My purpose is to get this first bit done. I don't understand it and it is only worth 10% of the marks which I have got most of the first part done it just needs the tests etc done which are probably worth around 5% but it needs to be done to move on to the next part of it. I have got the GUI done myself it is just this part of the Assignment that I do not understand at all.
I do want to learn how to understand this part and would go back and look at my lecture notes and learn it from the start again but because it has took me so long to get other parts of the Assignment done I have not got time to do that as the assignment has to be in for the 20th.
I just need this part done as soon as I can so I have got time to get as much of the other parts of the Assignment done as possible which are worth more marks.
I appreciate I may be asking stupid/obvious questions and may not have understood fully what has been said in other posts in this thread but that is because I am new to Java. Not everybody can just look at something straight away and full understand it that is why I was asking more questions to get clarification.
I appreciate that programming is difficult. OOP can be hard to grasp, perhaps even more so if you've worked with none-OOP languages in the past. It's not that your questions are stupid. It's that you're not really asking the right ones. People are usually more than happy to answer even basic questions but they won't do your homework for you.
"Getting it done" will not work. You need to understand the concepts before you can do it. That's not just the preferred approach; it's the only one that will work. The way I learned was by studying the idea, then try and code an assignment. If I had difficulties, I would go back to the concepts and see if I'd misunderstood something. Then back to the code, etc.
As stated, I think your approach is wrong. 9 days should be enough to do it using the right approach. If you keep going about it as you do, I suspect 9 days will not be enough.
However, it's not really fair to tell someone their approach is wrong without at least sketching out the right one. Actually, there are a number of "right" approaches. The one students usually take is writing the code, then writing the test code because they are told to do so, and that approach usually works if the assignment is fairly simple and they have a good understanding on what's going on. However, there is a approach that gives you more control and hopefully more insight into what you're trying to do.
Obviously, I haven't followed the course so I don't know if the following is the way your professor wants you to go about it, but it will certainly work. It is known as Test Driven Development and is well described in the literature. You can Google it to find more info. In real life, people use more advanced tools but the basic concepts are not so difficult and would seem to be more than enough to ace this assignment.
First of all, forget that the tests only account for a certain percentage of the grade. The tests are there to ensure that the application code is correct and I would imagine
that is a substantial part of the grade.
What we are trying to accomplish is a correct implementation of the Room class and its subclasses. At this stage, we don't care about the GUI. The GUI will be built on top of the correctly implemented Room, BedRoom, and MeetingRoom classes. So lets begin...
Step 1. Implementing the UML description.
I'm assuming the UML diagram is part of the handout. We can implement the description in a so called stub class in order for our test class to have something to work with. This is what the Room class should look like:
Code:
public class Room {
private int roomNumber;
private double rate;
private String customer;
public Room() {
//TODO
}
public Room(int n, double t) {
//TODO
}
public void bookRoom(String cust) {
//TODO
}
public void clearBooking() {
//TODO
}
public String getCustomer() {
//TODO
return null;
}
public double getRate() {
//TODO
return -1;
}
public int getRoomNumber() {
//TODO
return -1;
}
public String toString() {
//TODO
return null;
}
}
This is a minimal implementation of the Room class. It obviously won't work but it is the bare minimum that follows the UML diagram and that the Java compiler will accept.
Step 2. Writing a test
Now let's write a test case.
Code:
public class TestRoom {
public static void main(String[] args) {
// The method to bookRoom(String) will set the customer name.
Room room = new Room(1, 2);
room.bookRoom("foo");
if (!"foo".equals(room.getCustomer())) {
throw new RuntimeException("bookRoom did not set customer name. Expected: foo. Actual: " + room.getCustomer());
}
System.out.println("All tests passed :-)");
}
}
If you compile and run, this is what is outputted:
Code:
Exception in thread "main" java.lang.RuntimeException: bookRoom did not set customer name. Expected: foo. Actual: null
This is perhaps not so surprising but at least we have a running program. What now?
Step 3. Fixing the code.
What we want to do now is fix our Room class to avoid the test failing. This is what our new Room class looks like:
Code:
public class Room {
private int roomNumber;
private double rate;
private String customer;
public Room() {
//TODO
}
public Room(int n, double t) {
//TODO
}
public void bookRoom(String cust) {
customer = cust;
}
public void clearBooking() {
//TODO
}
public String getCustomer() {
return customer;
}
public double getRate() {
//TODO
return -1;
}
public int getRoomNumber() {
//TODO
return -1;
}
public String toString() {
//TODO
return null;
}
}
Running the code again gives us this:
Our Room class now gives us the correct behaviour but it's still incomplete. What to do?
Step 4. Write another test.
This is actually just step 2 again. We want to write another test that expresses the behaviour that Room should have:
Code:
public class TestRoom {
public static void main(String[] args) {
// The method to bookRoom(String) will set the customer name.
Room room = new Room(1, 2);
room.bookRoom("foo");
if (!"foo".equals(room.getCustomer())) {
throw new RuntimeException("bookRoom did not set customer name. Expected: foo. Actual: " + room.getCustomer());
}
// The method clearBooking() will set the customer to null
room.clearBooking();
if (room.getCustomer() != null) {
throw new RuntimeException("clearBooking did not set customer name to null. Expected: null. Actual: " + room.getCustomer());
}
System.out.println("All tests passed :-)");
}
}
Running this code gives us:
Code:
Exception in thread "main" java.lang.RuntimeException: clearBooking did not set customer name to null. Expected: null. Actual: foo
Again, our test fails. You might have guessed the next step.
Step 5. Fixing the code (again)
Code:
public class Room {
private int roomNumber;
private double rate;
private String customer;
public Room() {
//TODO
}
public Room(int n, double t) {
//TODO
}
public void bookRoom(String cust) {
customer = cust;
}
public void clearBooking() {
customer = null;
}
public String getCustomer() {
return customer;
}
public double getRate() {
//TODO
return -1;
}
public int getRoomNumber() {
//TODO
return -1;
}
public String toString() {
//TODO
return null;
}
}
If we run this, we get
---
So the approach here is to keep doing step 2 and step 3 until all the tests pass. When they do, we can be fairly convinced that the class is correctly implemented. Then we move on to BedRoom and MeetingRoom. Note that this depends on the quality of the tests. You have to try and break your code in the test phase so don't focus on writing tests that passes but instead write tests that fail and elucidate possible problems with the code. Also, create new Room classes whenever possible instead of using the old ones. I actually cheated slightly in the above and reused a Room object to make the code shorter. A longer version that is more to the point would look like this:
Code:
public class TestRoom {
public static void main(String[] args) {
testThatTheMethodBookRoomWillSetTheCustomerName();
testThatTheMethodClearBookingWillSetTheCustomerToNull();
System.out.println("All tests passed :-)");
}
private static void testThatTheMethodBookRoomWillSetTheCustomerName() {
Room room = new Room(1, 2);
room.bookRoom("foo");
if (!"foo".equals(room.getCustomer())) {
throw new RuntimeException("bookRoom did not set customer name. Expected: foo. Actual: " + room.getCustomer());
}
}
private static void testThatTheMethodClearBookingWillSetTheCustomerToNull() {
Room room = new Room(1, 2);
room.bookRoom("foo");
room.clearBooking();
if (room.getCustomer() != null) {
throw new RuntimeException("clearBooking did not set customer name to null. Expected: null. Actual: " + room.getCustomer());
}
}
}
I hope this will be enough to get you started. Feel free to ask questions but understand that people will respond more constructively to well thought out questions about the concepts that are difficult instead of "I did this. It didn't work. Why?".
In closing, this ought to be fun and if you do it the way I've described, you should get a lot of small victories along the way. One of the reasons for this approach is that it actually gives you a sense of accomplishment along the way instead of just getting a "works? yes/no" in the end. Another reason is that if you want to modify or expand your code later on, you can keep your tests in the code base and it will give you a lot of feedback, making sure that you don't accidentally break something along the way. This is, of course, not that relevant here but in real life it is a very important concern. You might have heard the term "If it ain't broke, don't fix it". Sometimes code have been patched for such a long time that it becomes impossible to understand and/or manage. Unit tests, when done right, give developers the confidence to change the code without too much fear of the consequences.
When I come across code that works but is unmaintainable I actually write tests to try an get an idea of the expected behaviour. Then I pull the code apart and back again (this is known as 'refactoring') trying to make it more clear what is going on. Because I have tests I can be fairly certain that this doesn't completely mess up the application.
So try to have fun with it and realize that there are very valid reasons for the way your professor wants you to go about the assignment.