A lot of general refactoring on Challenge 6. Also added a new design choices document, which will be constructed as I go.
- Author
- Vngngdn
- Date
- Nov. 24, 2016, 8:45 p.m.
- Hash
- e71d5ec3ad9dcfde04b78d5772529e5d0f0ff601
- Parent
- e58905458bfca974a57ba52df51b22014fa68ec8
- Modified files
- Challenge 6/Bed.java
- Challenge 6/Reservation.java
- Challenge 6/ReservationController.java
- Challenge 6/Room.java
- Challenge 6/RoomController.java
- Challenge 6/ontwerpkeuzes2.md
Challenge 6/Bed.java ¶
8 additions and 0 deletions.
View changes Hide changes
1 |
1 |
import java.util.Map; |
2 |
2 |
import java.util.HashMap; |
3 |
3 |
|
4 |
4 |
/** |
5 |
5 |
* Class representing a bed in the hostel. |
6 |
6 |
* Even though beds in a hostel could simply be an integer in a Room, these Beds |
7 |
7 |
* need to remember on what dates they are reserved. |
8 |
8 |
* @author Maarten Vangeneugden - 1438256 |
9 |
9 |
*/ |
10 |
10 |
public class Bed { |
11 |
11 |
|
12 |
12 |
/* Rationale: |
13 |
13 |
* I know that a mapping is not necessarily the best solution for storing |
14 |
14 |
* periods, because it doesn't offer built-in protection yadda yadda. |
15 |
15 |
* However, that's Java's fault, as it doesn't provide a Pair<L,R> thing in |
16 |
16 |
* the STL. |
17 |
17 |
* The best solution is actually a collection of tuples: (Begin, End), but |
18 |
18 |
* that doesn't exist in Java, and thus requires a custom implementation. |
19 |
19 |
* All things considered, a Map is the least bad choice. |
20 |
20 |
*/ |
21 |
21 |
private Map<Date, Date> reservedPeriods; |
22 |
22 |
|
23 |
23 |
public Bed() { |
24 |
24 |
this.reservedPeriods = new HashMap<>(); |
25 |
25 |
} |
26 |
26 |
|
27 |
27 |
/** |
28 |
28 |
* Reserves this Bed for the given period. |
29 |
29 |
* This method will mark the given period for this Bed as "reserved", which |
30 |
30 |
* can then be cancelled or queried later. |
31 |
31 |
* @param begin The time where the reservation begins. |
32 |
32 |
* @param end The time where the reservation ends. |
33 |
33 |
* @pre No parameter may be a null pointer. |
34 |
34 |
* @pre The given period mustn't overlap with a period already marked as |
35 |
35 |
* reserved. |
36 |
36 |
* @pre begin must come before end. |
37 |
37 |
* @pre begin and end mustn't be equal. |
38 |
38 |
* @post The given period will be marked as "Reserved", and will have to be |
39 |
39 |
* manually cancelled/removed in order to reserve again. |
40 |
40 |
* @throws NullPointerException if any parameter is a null pointer. |
41 |
41 |
* @throws IllegalArgumentException if begin is equal to, or comes after |
42 |
42 |
* end. |
43 |
43 |
* @throws DateTimeException if the given period overlaps with an already |
44 |
44 |
* reserved period. |
45 |
45 |
*/ |
46 |
46 |
public void reservePeriod(Date begin, Date end) { |
47 |
47 |
if(!begin.before(end)) { |
48 |
48 |
throw IllegalArgumentException("The begin date occurs after the end date."); |
49 |
49 |
} |
50 |
50 |
if(!this.isFree(begin, end)) { |
51 |
51 |
throw DateTimeException("This period overlaps with a reserved period."); |
52 |
52 |
} |
53 |
53 |
// Contract validated, execute method |
54 |
54 |
this.reservedPeriods.put(begin, end); |
55 |
55 |
} |
56 |
56 |
|
57 |
57 |
/** |
58 |
58 |
* Remove a previous registration from this Bed. |
59 |
59 |
* This method will remove/cancel the given reservation period from the |
60 |
60 |
* Bed, opening it up for reservation again. |
61 |
61 |
* @param begin The time where the reservation begins. |
62 |
62 |
* @param end The time where the reservation ends. |
63 |
63 |
* @pre No parameter may be a null pointer. |
64 |
64 |
* @pre The given period must already be marked as "Reserved" in this Bed. |
65 |
65 |
* @pre begin must come before end. |
66 |
66 |
* @pre begin and end mustn't be equal. |
67 |
67 |
* @post The given period will lose its "Reserved" mark, allowing the period |
68 |
68 |
* to be reserved again. |
69 |
69 |
* @throws NullPointerException if any parameter is a null pointer. |
70 |
70 |
* @throws IllegalArgumentException if begin is equal to, or comes after |
71 |
71 |
* end; or, if the given period is not reserved. |
72 |
72 |
*/ |
73 |
73 |
public void removeReservationPeriod(Date begin, Date end) { |
74 |
74 |
if(!begin.before(end)) { |
75 |
75 |
throw IllegalArgumentException("The begin date occurs after the end date."); |
76 |
76 |
} |
77 |
77 |
if(!this.isFree(begin, end)) { |
78 |
78 |
throw DateTimeException("This period overlaps with a reserved period."); |
79 |
79 |
} |
80 |
80 |
// Contract partially validated; further validation occurs while looking |
81 |
81 |
// for the reservation. |
82 |
82 |
// XXX: Check if Java correctly handles equality: 2 different Date |
83 |
83 |
// objects with the same date representation should be equal! |
84 |
84 |
boolean reservationFound = this.reservedPeriods.remove(begin, end); |
85 |
85 |
if(!reservationFound) { |
86 |
86 |
throw IllegalArgumentException("The given period was not marked as reserved."); |
87 |
87 |
} |
88 |
88 |
} |
89 |
89 |
|
90 |
90 |
/** |
91 |
91 |
* Checks whether this Bed can be reserved in the given period. |
92 |
92 |
* Use this method whenever you need to inform yourself about any |
93 |
93 |
* conflicting reservation period. |
94 |
94 |
* @param begin The time where the reservation begins. |
95 |
95 |
* @param end The time where the reservation ends. |
96 |
96 |
* @pre No parameter must be a null pointer. |
97 |
97 |
* @pre begin must come before end. |
98 |
98 |
* @pre begin and end mustn't be equal. |
99 |
99 |
* @throws NullPointerException if any parameter is a null pointer. |
100 |
100 |
* @throws IllegalArgumentException if begin is equal to, or comes after |
101 |
101 |
* end. |
102 |
102 |
* @return True if the given period does not overlap with any reservation, false otherwise. |
103 |
103 |
*/ |
104 |
104 |
public boolean isFree(Date begin, Date end) { |
105 |
105 |
if(!begin.before(end)) { |
106 |
106 |
throw IllegalArgumentException("The begin date occurs after the end date."); |
107 |
107 |
} |
108 |
108 |
if(!this.isFree(begin, end)) { |
109 |
109 |
throw DateTimeException("This period overlaps with a reserved period."); |
110 |
110 |
} |
111 |
111 |
// Contract validated, execute method |
112 |
112 |
for(Map.Entry<Date, Date> reservedPeriod: this.reservedPeriods.EntrySet()) { |
113 |
113 |
Date reservedBegin = reservedPeriod.key(); |
114 |
114 |
Date reservedEnd = reservedPeriod.value(); |
115 |
115 |
/* Forbidden possibilities: |
116 |
116 |
* (A,B = reserved; X,Y = requested) |
117 |
117 |
* X-A-Y-B / A-X-B-Y - Begins or ends in a reserved period |
118 |
118 |
* X-A-B-Y - Complete overlapping of reserved period |
119 |
119 |
* Allowed possibilities: |
120 |
120 |
* A-B-X-Y / X-Y-A-B - No overlapping |
121 |
121 |
*/ |
122 |
122 |
if((begin.after(reservedBegin) && begin.before(reservedEnd)) || |
123 |
123 |
(end.after(reservedBegin) && end.before(reservedEnd))) { |
124 |
124 |
// Triggered if any forbidden structure is detected |
125 |
125 |
return false; |
126 |
126 |
} |
127 |
127 |
} |
128 |
128 |
return true; // No overlapping found |
129 |
129 |
} |
130 |
130 |
} |
+ |
131 |
/** |
+ |
132 |
* Checks whether this Bed has open reservation periods. |
+ |
133 |
* @return True if this Bed has reserved periods, false otherwise. |
+ |
134 |
*/ |
+ |
135 |
public boolean hasReservations() { |
+ |
136 |
return !this.reservedPeriods.isEmpty(); |
+ |
137 |
} |
+ |
138 |
} |
131 |
139 |
Challenge 6/Reservation.java ¶
34 additions and 28 deletions.
View changes Hide changes
1 |
1 |
import java.util.HashSet; |
2 |
2 |
import java.util.Date; |
3 |
3 |
|
4 |
4 |
/** |
5 |
5 |
* Represents a reservation in a hostel. |
6 |
6 |
* Reservation is a simple class that allows one to store reservation |
7 |
7 |
* information, request it when necessary, and so on. |
8 |
8 |
* Certain methods are provided for interaction, which use contracts to assert |
9 |
9 |
* proper functioning. |
10 |
10 |
* @author Maarten Vangeneugden - 1438256 |
11 |
11 |
*/ |
12 |
12 |
public class Reservation { |
13 |
13 |
|
14 |
14 |
// Members |
15 |
15 |
private String groupName; |
16 |
16 |
private Date beginDate; |
17 |
- | private Date endDate; |
18 |
- | private Set<Bed> reservedBeds; |
+ |
17 |
private Date end; |
+ |
18 |
private Set<Bed> reservedBeds; |
19 |
19 |
private int reservationID; |
20 |
20 |
private String roomType; // Room type requested by group |
21 |
21 |
private Set<String> roomFacilities; // Requested room facilities |
22 |
22 |
private Set<Date> breakfastDays; // Set of days the group wants breakfast |
23 |
23 |
// Controllers |
24 |
24 |
private RoomController roomController; |
25 |
25 |
private ReservationController reservationController; |
26 |
26 |
|
27 |
27 |
/** |
28 |
28 |
* Create a new Reservation. |
29 |
29 |
* Be aware about the limitations of a Reservation: it's not the |
30 |
30 |
* Reservation's duty to check whether the provided Beds are properly |
31 |
31 |
* reserved; take care of this accordingly. |
32 |
32 |
* |
33 |
33 |
* Some information is implicit. For example: The size of the set of |
34 |
34 |
* reserved Beds implies the amount of people in the group; no breakfast |
35 |
35 |
* days implies no breakfast, ... |
36 |
36 |
* @param groupName The name of the group. |
37 |
37 |
* @param begin The date that the Reservation begins. |
38 |
38 |
* @param end The date that the Reservation ends. |
39 |
39 |
* @param reservedBeds The set of Beds reserved and assigned to this |
40 |
40 |
* Reservation. |
41 |
41 |
* @param roomType The requested room type. |
42 |
42 |
* @param roomFacilities The set of all requested room facilities. |
43 |
43 |
* @param breakfastDays A set of all days that the group wants breakfast. |
44 |
44 |
* @param reservationID An ID for this reservation, to differentiate from |
45 |
45 |
* other Reservations. |
46 |
46 |
* @pre No parameter must be a null pointer. |
47 |
47 |
* @pre begin must come before end. |
48 |
48 |
* @pre All dates in breakfastDays must fall between begin and end. |
49 |
49 |
* @pre No string parameter may be empty. |
50 |
50 |
* @post The amount of people in the Reservation is determined by the amount |
51 |
51 |
* of reserved Beds. |
52 |
52 |
* @throws NullPointerException if any parameter is a null pointer. |
53 |
53 |
* @throws IllegalArgumentException if any of the other preconditions is not |
54 |
54 |
* met. |
55 |
55 |
*/ |
56 |
56 |
public Reservation(String groupName, Date begin, Date end, Set<Bed> reservedBeds, String roomType, Set<String> roomFacilities) { |
57 |
57 |
// Contract validation: |
58 |
58 |
if(!begin.before(end)) { |
59 |
59 |
throw IllegalArgumentException("The begin date occurs after the end date."); |
60 |
60 |
} |
61 |
61 |
if(groupName.isEmpty() || roomType.isEmpty()) { |
62 |
62 |
throw IllegalArgumentException("groupName and/or roomType were empty strings."); |
63 |
63 |
} |
64 |
64 |
for(String roomFacility: roomFacilities) { |
65 |
65 |
if(roomFacility.isEmpty()) { |
66 |
66 |
throw IllegalArgumentException("One of the room facilities was an empty string."); |
67 |
67 |
} |
68 |
68 |
} |
69 |
69 |
for(Date breakfastDay : breakfastDays) { |
70 |
70 |
if(breakfastDay.before(begin) || breakfastDay.after(end)) { |
71 |
71 |
throw IllegalArgumentException("One of the breakfast days occurs before/after the reservation period."); |
72 |
72 |
} |
73 |
73 |
} |
74 |
74 |
// Contract validated, execute constructor |
75 |
75 |
this.groupName = groupName; |
76 |
76 |
this.beginDate = begin; |
77 |
77 |
this.endDate = end; |
78 |
78 |
this.reservedBeds = reservedBeds; |
79 |
79 |
this.reservationID = reservationID; |
80 |
80 |
this.roomType = roomType; |
81 |
81 |
this.roomFacilities = roomFacilities; |
82 |
82 |
this.breakfastDays = breakfastDays |
83 |
83 |
} |
84 |
84 |
|
85 |
85 |
/** |
86 |
86 |
* Creates an empty Reservation. |
87 |
- | * This constructor is espcially useful for adding a new reservation. |
88 |
- | */ |
+ |
87 |
* @param groupName The new group name. |
+ |
88 |
* @pre groupName mustn't be empty, or a null pointer. |
+ |
89 |
* @post The group name is changed to the given name. |
+ |
90 |
* @throws NullPointerException if groupName is a null pointer. |
+ |
91 |
* @throws IllegalArgumentException if groupName is an empty String. |
+ |
92 |
*/ |
89 |
93 |
public Reservation(ReservationController reservationController, RoomController roomController) { |
90 |
- | this( |
91 |
- | "", |
92 |
- | new Date(), |
93 |
- | new HashSet<>(), |
94 |
- | "", |
95 |
- | new HashSet<>(), |
96 |
- | 1, |
97 |
- | new int[0], |
98 |
- | reservationController, |
99 |
- | roomController |
100 |
- | ); |
101 |
- | } |
102 |
- | |
103 |
- | public void setGroupName(String groupName) { |
104 |
94 |
this.groupName = groupName; |
+ |
95 |
throw IllegalArgumentException("groupName is an empty String."); |
+ |
96 |
this.groupName = groupName; |
105 |
97 |
} |
106 |
98 |
|
107 |
99 |
public String getGroupName() { |
108 |
100 |
return groupName; |
109 |
101 |
} |
110 |
102 |
|
111 |
103 |
public void setDate(Date date) { |
112 |
- | this.date = date; |
113 |
- | } |
+ |
104 |
* Set the begin date for this Reservation. |
+ |
105 |
* @param begin The new begin date. |
+ |
106 |
* @pre begin mustn't be a null pointer. |
+ |
107 |
* @pre begin must come strictly before the end date. |
+ |
108 |
* @post The begin date is updated accordingly. |
+ |
109 |
* @throws NullPointerException if begin is a null pointer. |
+ |
110 |
* @throws IllegalArgumentException if begin comes after the end date. |
+ |
111 |
*/ |
+ |
112 |
public void setBegin(Date begin) { |
+ |
113 |
if(!begin.before(this.getEnd())) |
+ |
114 |
throw IllegalArgumentException("begin comes after the end date.") |
+ |
115 |
this.begin = begin; |
+ |
116 |
} |
114 |
117 |
|
115 |
118 |
public Date getDate() { |
+ |
119 |
|
+ |
120 |
/** |
+ |
121 |
* Set the end date for this Reservation. |
+ |
122 |
* @param end The new end date. |
+ |
123 |
* @pre end mustn't be a null pointer. |
+ |
124 |
* @pre end must come strictly after the begin date. |
+ |
125 |
* @post The end date is updated accordingly. |
+ |
126 |
* @throws NullPointerException if end is a null pointer. |
+ |
127 |
* @throws IllegalArgumentException if end comes after the end date. |
+ |
128 |
*/ |
+ |
129 |
public Date getDate() { |
116 |
130 |
return date; |
117 |
131 |
} |
118 |
132 |
|
119 |
133 |
public void setReservedBeds(Set<Bed> reservedBeds) { |
120 |
134 |
this.reservedBeds = reservedBeds; |
121 |
135 |
} |
122 |
136 |
|
123 |
137 |
public Set<Bed> getReservedBeds() { |
124 |
138 |
return reservedBeds; |
125 |
139 |
} |
126 |
140 |
|
127 |
141 |
public void setReservationID(int reservationID) { |
128 |
142 |
this.reservationID = reservationID; |
129 |
143 |
} |
130 |
144 |
|
131 |
145 |
public int getReservationID() { |
132 |
146 |
return reservationID; |
133 |
147 |
} |
134 |
148 |
|
135 |
149 |
public void setRoomType(String roomType) { |
136 |
150 |
this.roomType = roomType; |
137 |
151 |
} |
138 |
152 |
|
139 |
153 |
public String getRoomType() { |
140 |
154 |
return roomType; |
141 |
155 |
} |
142 |
156 |
|
143 |
157 |
public void setRoomFacilities(Set<String> roomFacilities) { |
144 |
158 |
this.roomFacilities = roomFacilities; |
145 |
159 |
} |
146 |
160 |
|
147 |
161 |
public Set<String> getRoomFacilities() { |
148 |
162 |
return roomFacilities; |
149 |
163 |
} |
150 |
164 |
|
151 |
165 |
public void setNights(int nights) { |
152 |
- | this.nights = nights; |
153 |
- | } |
154 |
- | |
155 |
- | public int getNights() { |
156 |
- | return nights; |
157 |
- | } |
158 |
- | |
159 |
- | /** |
160 |
166 |
* Calculates the price of the Reservation, based on its current state. |
161 |
167 |
* Price table: |
162 |
168 |
* - 20/person/day |
163 |
169 |
* - 5 less in low season, 5 more in high season |
164 |
170 |
* - 4/breakfast ordered |
165 |
171 |
* - If room is fully booked by the group --> 10% discount |
166 |
172 |
* @return The price in euros. |
167 |
173 |
*/ |
168 |
174 |
public int getPrice() { |
169 |
175 |
int totalPrice = 0; |
170 |
176 |
// Jan - Apr: Mid |
171 |
177 |
// May - Aug: High |
172 |
178 |
// Sep - Dec: Low |
173 |
179 |
|
174 |
180 |
// Calculate bed prices |
175 |
181 |
int month = this.getDate().getMonth(); |
176 |
182 |
int bedPrice = 20; |
177 |
183 |
if(month >=8) { // From September: |
178 |
184 |
bedPrice -= 5; |
179 |
185 |
} else if(month >=4) { // From May: |
180 |
186 |
bedPrice += 5; |
181 |
187 |
} |
182 |
188 |
totalPrice += (this.getReservedBeds().size() * this.getNights() * bedPrice); |
183 |
189 |
// Calculate price for breakfasts |
184 |
190 |
int breakfasts = this.getBreakfastDays().length; |
185 |
191 |
totalPrice += breakfasts * this.getReservedBeds().size(); |
186 |
192 |
// Check if eligible for discount |
187 |
193 |
for(Room room: roomController.getRooms()) { |
188 |
194 |
Set<Bed> roomBeds = room.getBeds(); |
189 |
195 |
if(roomBeds.containsAll(this.reservedBeds)) { |
190 |
196 |
double discount = (double)totalPrice * 0.1; |
191 |
197 |
totalPrice -= (int)discount; |
192 |
198 |
} |
193 |
199 |
} |
194 |
200 |
return totalPrice; |
195 |
201 |
} |
196 |
202 |
|
197 |
203 |
|
198 |
204 |
|
199 |
205 |
|
200 |
206 |
|
201 |
207 |
|
202 |
208 |
|
203 |
209 |
public void setBreakfastDays(int[] breakfastDays) { |
204 |
210 |
this.breakfastDays = breakfastDays; |
205 |
211 |
} |
206 |
212 |
public int[] getBreakfastDays() { |
207 |
213 |
return this.breakfastDays; |
208 |
214 |
} |
209 |
215 |
|
210 |
216 |
} |
211 |
217 |
Challenge 6/ReservationController.java ¶
105 additions and 15 deletions.
View changes Hide changes
1 |
1 |
import java.util.HashSet; |
2 |
2 |
import java.util.Date; |
3 |
3 |
|
4 |
4 |
/** |
5 |
5 |
* Controller class for the Reservations of this program. |
6 |
6 |
* Since this program handles a youth hostel, it's imperative that it holds a |
7 |
7 |
* number of Reservations. |
8 |
8 |
* |
9 |
9 |
* ReservationController takes the responsibility of handling the addition, |
10 |
10 |
* cancelling, editing, ... of Reservations, and the related tasks inherent to |
11 |
11 |
* these responsibilities, such as reserving beds, generating IDs, ... |
12 |
12 |
* @author Maarten Vangeneugden - 1438256 |
13 |
13 |
*/ |
14 |
14 |
public class ReservationController { |
15 |
15 |
|
16 |
16 |
private Set<Reservation> reservations; |
17 |
- | |
+ |
17 |
* Normally I'd put this as an interface (Set), but an interface does not |
+ |
18 |
* inherit from Object, and thus, does not provide clone(). This is |
+ |
19 |
* necessary, because otherwise, there's no point in having private |
+ |
20 |
* members. |
+ |
21 |
*/ |
+ |
22 |
private HashSet<Reservation> reservations; // Holds all Reservations |
+ |
23 |
|
18 |
24 |
public ReservationController() { |
+ |
25 |
* Creates the ReservationController. |
+ |
26 |
*/ |
+ |
27 |
public ReservationController() { |
19 |
28 |
this.reservations = new HashSet<>(); |
20 |
29 |
} |
21 |
30 |
|
22 |
31 |
public void setReservations(Set<Reservation> reservations) { |
23 |
- | this.reservations = reservations; |
24 |
- | } |
25 |
- | |
26 |
- | public Set<Reservation> getReservations() { |
+ |
32 |
* Returns a copy of all Reservations. |
+ |
33 |
* Emphasis on "copy"; There is no setReservations() for a reason, using |
+ |
34 |
* this to edit the pointer variable would omit the use of 'private'. |
+ |
35 |
* @return A verbatim copy of all Reservations. |
+ |
36 |
*/ |
+ |
37 |
@SuppressWarnings("unchecked") |
+ |
38 |
public Set<Reservation> getReservations() { |
27 |
39 |
return reservations; |
28 |
- | } |
+ |
40 |
} |
29 |
41 |
|
30 |
42 |
public int generateReservationID() { |
+ |
43 |
* Generates a unique ID for a new Reservation. |
+ |
44 |
* This method is to be called when a new Reservation is to be stored. |
+ |
45 |
* As every Reservation carries an ID, this method searches for a unique |
+ |
46 |
* one, and returns it. |
+ |
47 |
* @return An integer, different from all other stored Reservation IDs. |
+ |
48 |
*/ |
+ |
49 |
public int generateReservationID() { |
31 |
50 |
int ID = 0; |
+ |
51 |
* Instead of starting from 0, and incrementing until it's unique, it |
+ |
52 |
* will take the amount of stored Reservations, and test that as an ID. |
+ |
53 |
* This may still overlap (by removing an older Reservation), but may be |
+ |
54 |
* much faster. Consider implemting and testing for effectiveness if |
+ |
55 |
* generating an ID takes too long. |
+ |
56 |
*/ |
+ |
57 |
int ID = 0; |
32 |
58 |
while(true) { |
33 |
- | for(Reservation reservation: this.reservations) { |
+ |
59 |
do { |
+ |
60 |
ID++; |
+ |
61 |
isUnique = true; |
+ |
62 |
for(Reservation reservation: this.reservations) { |
34 |
63 |
if(reservation.getReservationID() == ID) { |
35 |
- | ID++; |
36 |
- | continue; |
37 |
- | } |
+ |
64 |
isUnique = false; |
+ |
65 |
} |
38 |
66 |
} |
39 |
67 |
break; |
40 |
- | } |
41 |
- | // Test: |
+ |
68 |
// Test: |
42 |
69 |
for(Reservation reservation: this.reservations) { |
43 |
70 |
assert reservation.getReservationID() != ID : "Duplicate ID generated!"; |
44 |
71 |
} |
45 |
72 |
return ID; |
46 |
73 |
} |
47 |
74 |
|
+ |
75 |
/** |
+ |
76 |
* Check if Reservation can be made. |
+ |
77 |
* Call this method whenever you're planning on adding a new Reservation. It |
+ |
78 |
* will check the provided requirements (Room facilities, for example), and |
+ |
79 |
* return whether this Reservation can continue. |
+ |
80 |
* @param reservation The Reservation to check for possible addition. |
+ |
81 |
* @pre reservation mustn't be null. |
+ |
82 |
* @throws NullPointerException if reservation is null. |
+ |
83 |
* @return True if reservation can be added, False otherwise. |
+ |
84 |
*/ |
+ |
85 |
public boolean checkReservation(Reservation reservation) { |
+ |
86 |
if(reservation == null) { |
+ |
87 |
throw NullPointerException("reservation was a null pointer."); |
+ |
88 |
} |
+ |
89 |
if(this.getRoomController().getQualifiedRooms(reservation).size() == 0) { |
+ |
90 |
return null; |
+ |
91 |
} |
+ |
92 |
|
48 |
93 |
/** |
49 |
94 |
* Adds and confirms the reservation. |
50 |
95 |
* By calling this method, the given reservation will be stored in the |
51 |
96 |
* system, and the given room will be filled. |
52 |
97 |
* @pre room must have enough empty beds |
53 |
- | * @pre no parameter may be null |
54 |
- | */ |
+ |
98 |
* this Room! If there are not enough Beds available, an exception will be |
+ |
99 |
* thrown. |
+ |
100 |
* @param reservation The Reservation to add. |
+ |
101 |
* @param room The Room in which the people will reside. |
+ |
102 |
* @pre room must have enough empty beds. |
+ |
103 |
* @pre room must accomodate the Reservation's requirements. |
+ |
104 |
* @pre No parameter must be null. |
+ |
105 |
* @post reservation is stored in the active Reservations. |
+ |
106 |
* @post The Beds in the provided Room are reserved for the Reservation's |
+ |
107 |
* period. |
+ |
108 |
* @throws IllegalArgumentException if the given Room can't fulfill the |
+ |
109 |
* requirements of the Reservation. |
+ |
110 |
* @throws NullPointerException if any parameter is a null pointer. |
+ |
111 |
*/ |
55 |
112 |
public void addReservation(Reservation reservation, Room room) { |
56 |
113 |
// TODO: Add reservation to the set, and add the reserved days to the |
+ |
114 |
|
+ |
115 |
// TODO: Add reservation to the set, and add the reserved days to the |
57 |
116 |
// beds in the given room. |
58 |
117 |
} |
59 |
118 |
public void cancelReservation(Reservation reservation) { |
+ |
119 |
* Cancels and removes the given Reservation. |
+ |
120 |
* If you want to remove a Reservation, use this method, and provide the |
+ |
121 |
* Reservation up for removal. |
+ |
122 |
* This method will take care of related actions, such as releasing Beds. |
+ |
123 |
* @param reservation The Reservation to be removed. |
+ |
124 |
* @pre reservation mustn't be null. |
+ |
125 |
* @pre reservation must be contained in the active Reservations. |
+ |
126 |
* @post The Reservation is removed from the active Reservations. |
+ |
127 |
* @post The Beds, previously reserved for this Reservation, are now |
+ |
128 |
* released, and can be reserved for another Reservation. |
+ |
129 |
* @throws NullPointerException if reservation is a null pointer. |
+ |
130 |
* @throws IllegalArgumentException if reservation is not contained in the |
+ |
131 |
* active Reservations. |
+ |
132 |
*/ |
+ |
133 |
public void cancelReservation(Reservation reservation) { |
60 |
134 |
// TODO: Remove from controller list; release beds, ... |
61 |
- | } |
+ |
135 |
if(!this.getReservations().contains(reservation)) { |
+ |
136 |
throw IllegalArgumentException("The given Reservation was not contained in the active Reservations."); |
+ |
137 |
} |
+ |
138 |
if(reservation == null) { |
+ |
139 |
throw NullPointerException(); |
+ |
140 |
} |
+ |
141 |
// Contract validated, execute method |
+ |
142 |
this.reservations.remove(reservation); // Remove from active Reservations |
+ |
143 |
for(Bed bed: reservation.getReservedBeds()) { // Release reserved Beds |
+ |
144 |
bed.removeReservationPeriod(reservation.getBegin(), reservation.getEnd()); |
+ |
145 |
} |
+ |
146 |
// Asserting post conditions are met |
+ |
147 |
assert !this.getReservation().contains(reservation) : "The reservation is still part of the active Reservations."; |
+ |
148 |
for(Bed bed: reservation.getReservedBeds()) { |
+ |
149 |
assert bed.isFree(reservation.getBegin(), reservation.getEnd()) : "One or more of the Beds are still reserved."; |
+ |
150 |
} |
+ |
151 |
} |
62 |
152 |
|
63 |
153 |
} |
64 |
154 |
Challenge 6/Room.java ¶
132 additions and 11 deletions.
View changes Hide changes
1 |
1 |
import java.util.HashSet; |
2 |
2 |
import java.util.Date; |
3 |
3 |
|
4 |
4 |
/** |
5 |
5 |
* A room in a hostel. |
6 |
6 |
* Room represents just that: A room. |
7 |
7 |
* A room contains a set of Beds, facilities that can be used, etc. |
8 |
8 |
* It's highly decoupled: Apart from holding a set of Beds, the only members |
9 |
9 |
* types consist of those that are available in every OpenJDK implementation. |
10 |
10 |
* @author Maarten Vangeneugden - 1438256 |
11 |
11 |
*/ |
12 |
12 |
public class Room { |
13 |
13 |
|
14 |
14 |
private Set<Bed> beds; |
15 |
- | private String type; |
+ |
15 |
private String type; |
16 |
16 |
private Set<String> facilities; |
17 |
- | |
+ |
17 |
|
18 |
18 |
public Room(Set<Bed> beds, String type, Set<String> facilities) { |
19 |
- | this.beds = beds; |
20 |
- | this.type = type; |
21 |
- | this.facilities = facilities; |
22 |
- | } |
+ |
19 |
* Create a new Room. |
+ |
20 |
* @param beds The amount of Beds that will be placed in this Room. |
+ |
21 |
* @param type The type of this Room. (for example: Male, Female, Mixed, |
+ |
22 |
* ...) |
+ |
23 |
* @param facilities A Set of facilities this Room provides ("Shower", |
+ |
24 |
* "Radio", "Overpriced WiFi", ...) |
+ |
25 |
* @pre No parameter must be a null pointer. |
+ |
26 |
* @pre beds must be at least 1. |
+ |
27 |
* @pre Type mustn't be an empty String. |
+ |
28 |
* @pre No facility may be an empty String. |
+ |
29 |
* @post The Room will receive the provided amount of Beds, which are all |
+ |
30 |
* completely released. |
+ |
31 |
* @throws IllegalArgumentException if the amount of Beds is less than 1, or |
+ |
32 |
* one of the facilities is an empty String. |
+ |
33 |
* @throws NullPointerException if one of the parameters is a null pointer. |
+ |
34 |
*/ |
+ |
35 |
public Room(int beds, String type, Set<String> facilities) { |
+ |
36 |
// Contract validation happens in the setter methods |
+ |
37 |
this.setFacilities(facilities); |
+ |
38 |
this.setType(type) |
+ |
39 |
if(beds < 1) { |
+ |
40 |
throw IllegalArgumentException("Beds was less than 1."); |
+ |
41 |
} |
+ |
42 |
// Contract validated, execute constructor |
+ |
43 |
this.beds = new HashSet<>(); |
+ |
44 |
for(int i=0; i<beds; i++) { |
+ |
45 |
this.beds.add(new Bed()); |
+ |
46 |
} |
+ |
47 |
} |
23 |
48 |
|
24 |
49 |
public void setBeds(Set<Bed> beds) { |
25 |
- | this.beds = beds; |
26 |
- | } |
+ |
50 |
* Remove a Bed from this Room. |
+ |
51 |
* This method will remove the given Bed from this Room. |
+ |
52 |
* However, make sure that this Bed is free of any reservations, as you |
+ |
53 |
* can't delete a Bed with a reserved period. |
+ |
54 |
* @see Bed |
+ |
55 |
* @param bed The Bed to be removed. |
+ |
56 |
* @pre bed mustn't be null. |
+ |
57 |
* @pre bed mustn't be the last Bed in this Room. |
+ |
58 |
* @pre bed must be in this Room. |
+ |
59 |
* @pre bed mustn't have any reserved periods. |
+ |
60 |
* @post The amount of Beds in this Room is decremented by 1. |
+ |
61 |
* @throws IllegalArgumentException if bed is not in this Room, or has |
+ |
62 |
* reserved periods, or this is the last Bed in the Room. |
+ |
63 |
* @throws NullPointerException if bed is a null pointer. |
+ |
64 |
*/ |
+ |
65 |
public void removeBed(Bed bed) { |
+ |
66 |
// Contract validation |
+ |
67 |
if(!this.getBeds().contains(bed)) { |
+ |
68 |
throw IllegalArgumentException("The given Bed is not in this Room."); |
+ |
69 |
} |
+ |
70 |
if(bed.hasReservations()) { |
+ |
71 |
throw IllegalArgumentException("The given Bed still has reserved periods."); |
+ |
72 |
} |
+ |
73 |
if(this.getBeds().size() == 1) { |
+ |
74 |
throw IllegalArgumentException("Deleting this Bed would empty the Room."); |
+ |
75 |
} |
+ |
76 |
// Contract validated, execute method |
+ |
77 |
this.beds.remove(bed); |
+ |
78 |
// Assert post conditions |
+ |
79 |
assert !this.getBeds().contains(bed) : "The given Bed was not removed from this Room."; |
+ |
80 |
} |
27 |
81 |
|
28 |
82 |
public Set<Bed> getBeds() { |
+ |
83 |
* Add a Bed to this Room. |
+ |
84 |
* @post The amount of Beds in this Room increments with 1. |
+ |
85 |
*/ |
+ |
86 |
public void addBed() { |
+ |
87 |
this.beds.add(new Bed()); |
+ |
88 |
} |
+ |
89 |
|
+ |
90 |
/** |
+ |
91 |
* Returns a copy of all Beds. |
+ |
92 |
* @return A verbatim copy of all Beds. |
+ |
93 |
*/ |
+ |
94 |
@SuppressWarnings("unchecked") |
+ |
95 |
public Set<Bed> getBeds() { |
29 |
96 |
return beds; |
30 |
- | } |
+ |
97 |
} |
31 |
98 |
|
32 |
99 |
public void setType(String type) { |
+ |
100 |
* Set the type of this Room. |
+ |
101 |
* @param type The new type of the Room. |
+ |
102 |
* @pre type mustn't be an empty String, or a null pointer. |
+ |
103 |
* @post The Room's type is changed to the given type. |
+ |
104 |
* @throws IllegalArgumentException if type is an empty String. |
+ |
105 |
* @throws NullPointerException if type is a null pointer. |
+ |
106 |
*/ |
+ |
107 |
public void setType(String type) { |
33 |
108 |
this.type = type; |
+ |
109 |
throw IllegalArgumentException("type is an empty String."); |
+ |
110 |
} |
+ |
111 |
this.type = type; |
34 |
112 |
} |
35 |
113 |
|
36 |
114 |
public String getType() { |
+ |
115 |
* Returns the type of this Room. |
+ |
116 |
* @return The secret launch codes of the USS Nimitz, granting access to |
+ |
117 |
* nuclear warheads so big, you'll lose faith in humanity. |
+ |
118 |
*/ |
+ |
119 |
public String getType() { |
37 |
120 |
return type; |
38 |
121 |
} |
39 |
122 |
|
40 |
123 |
public void setFacilities(Set<String> facilities) { |
+ |
124 |
* Set the facilities available in this Room. |
+ |
125 |
* @param facilities The set of facilities in this Room. |
+ |
126 |
* @pre No facility must be an empty String or a null pointer. |
+ |
127 |
* @post The Room will have the newly provided facilities. |
+ |
128 |
* @throws IllegalArgumentException if one of the facilities is an empty String. |
+ |
129 |
* @throws NullPointerException if any given variable is a null pointer. |
+ |
130 |
*/ |
+ |
131 |
public void setFacilities(Set<String> facilities) { |
41 |
132 |
this.facilities = facilities; |
+ |
133 |
if(facility.isEmpty()) { |
+ |
134 |
throw IllegalArgumentException("A facility was an empty String."); |
+ |
135 |
} |
+ |
136 |
} |
+ |
137 |
this.facilities = facilities; |
42 |
138 |
} |
43 |
139 |
|
44 |
140 |
public Set<String> getFacilities() { |
+ |
141 |
* Returns a copy of all facilities. |
+ |
142 |
* @return A verbatim copy of all facilities. |
+ |
143 |
*/ |
+ |
144 |
@SuppressWarnings("unchecked") |
+ |
145 |
public Set<String> getFacilities() { |
45 |
146 |
return facilities; |
46 |
- | } |
+ |
147 |
} |
47 |
148 |
|
48 |
149 |
public Set<Bed> getEmptyBeds(Date begin, Date end) { |
+ |
150 |
* Search for Beds that can be reserved. |
+ |
151 |
* This method will look through all Beds, and check whether they can be |
+ |
152 |
* reserved in the given period. You will receive all Beds that can be |
+ |
153 |
* reserved. |
+ |
154 |
* @param begin The begin date. |
+ |
155 |
* @param end The end date. |
+ |
156 |
* @pre No parameter must be null. |
+ |
157 |
* @pre begin must strictly come before end. |
+ |
158 |
* @throws IllegalArgumentException if begin comes after end, or both are |
+ |
159 |
* equal. |
+ |
160 |
* @throws NullPointerException if any given parameter is a null pointer. |
+ |
161 |
* @return A Set of all Beds that can be reserved, or an empty Set if no Bed |
+ |
162 |
* can be reserved in the given period. |
+ |
163 |
*/ |
+ |
164 |
public Set<Bed> getEmptyBeds(Date begin, Date end) { |
49 |
165 |
Set<Bed> emptyBeds = new HashSet<>(); |
+ |
166 |
if(!begin.before(end)) { |
+ |
167 |
throw IllegalArgumentException("begin does not come strictly before end"); |
+ |
168 |
} |
+ |
169 |
// Validated |
+ |
170 |
Set<Bed> emptyBeds = new HashSet<>(); |
50 |
171 |
for(Bed bed: this.beds) { |
51 |
- | if(bed.isFree(begin, end)) { |
+ |
172 |
if(bed.isFree(begin, end)) { |
52 |
173 |
emptyBeds.add(bed); |
53 |
174 |
} |
54 |
175 |
} |
55 |
176 |
return emptyBeds; |
56 |
177 |
} |
57 |
178 |
|
58 |
179 |
} |
59 |
180 |
Challenge 6/RoomController.java ¶
21 additions and 10 deletions.
View changes Hide changes
1 |
1 |
import java.util.Date; |
2 |
2 |
import java.util.HashSet; |
3 |
3 |
|
4 |
4 |
/** |
5 |
5 |
* Holds all Rooms in the hostel. |
6 |
6 |
* The hostel contains a set of Rooms, with facilities and stuff. |
7 |
7 |
* This class takes care of storing all those Rooms, and provides methods to |
8 |
8 |
* manage this, like removing Rooms, adding Rooms, ... |
9 |
9 |
* @author Maarten Vangeneugden - 1438256 |
10 |
10 |
*/ |
11 |
11 |
public class RoomController { |
12 |
12 |
|
13 |
13 |
private Set<Room> rooms; |
14 |
14 |
|
15 |
15 |
public RoomController() { |
16 |
16 |
this.rooms = new HashSet<>(); |
17 |
17 |
} |
18 |
18 |
|
19 |
19 |
public void setRooms(Set<Room> rooms) { |
20 |
- | this.rooms = rooms; |
21 |
- | } |
22 |
- | |
23 |
20 |
public Set<Room> getRooms() { |
24 |
21 |
return rooms; |
25 |
22 |
} |
26 |
23 |
|
27 |
24 |
/** |
28 |
25 |
* Returns all rooms that meet the given requirements. |
29 |
26 |
* This method will search through all rooms, and check which rooms qualify. |
30 |
27 |
* @return A set of all rooms that meet the requirements, or an empty set if |
+ |
28 |
* - Is the requested type available? |
+ |
29 |
* - Does the Set of requested facilities form a subset of the Room's |
+ |
30 |
* facilities? |
+ |
31 |
* - Are there any Beds in the Room that can be reserved in the given |
+ |
32 |
* period? |
+ |
33 |
* @param reservation The Reservation for which to find eligible rooms. |
+ |
34 |
* @pre reservation mustn't be null. |
+ |
35 |
* @throws NullPointerException if reservation is a null pointer. |
+ |
36 |
* @return A set of all rooms that meet the requirements, or an empty set if |
31 |
37 |
* none were found. |
32 |
38 |
*/ |
33 |
39 |
public Set<Room> getQualifiedRooms(Date begin, int duration, String type, Set<String> facilities) { |
34 |
- | Set<Room> qualifiedRooms = new HashSet<>(); |
+ |
40 |
Set<Room> qualifiedRooms = new HashSet<>(); |
35 |
41 |
long beginDate = begin.getTime(); |
36 |
- | long endDate = beginDate + (duration * 24 * 60 * 60 * 1000); |
37 |
- | Date end = new Date(endDate); |
38 |
- | |
39 |
- | // TODO: Loop through all rooms that qualify, collect them, and return |
40 |
- | // that set. |
41 |
- | return qualifiedRooms; |
+ |
42 |
if(room.getType().equals(reservation.getType())) |
+ |
43 |
continue; |
+ |
44 |
if(!room.getFacilities().containsAll(reservation.getFacilities())) |
+ |
45 |
continue; |
+ |
46 |
if(room.getEmptyBeds(reservation.getBegin(), reservation.getEnd()).isEmpty()) |
+ |
47 |
continue; |
+ |
48 |
// The Room fulfills all requirements at this point, so add it to |
+ |
49 |
// the set |
+ |
50 |
qualifiedRooms.add(room); |
+ |
51 |
} |
+ |
52 |
return qualifiedRooms; |
42 |
53 |
} |
43 |
54 |
} |
44 |
55 |
Challenge 6/ontwerpkeuzes2.md ¶
176 additions and 0 deletions.
View changes Hide changes
+ |
1 |
|
+ |
2 |
## GRASP |
+ |
3 |
Om zoveel mogelijk tegemoet te komen aan de GRASP-richtlijnen, heb ik volgende |
+ |
4 |
ontwerpkeuzes toegepast voor de verschillende richtlijnen. |
+ |
5 |
|
+ |
6 |
### High cohesion & Low coupling |
+ |
7 |
- Veel classes zijn totaal van elkaar losgekoppeld. Een goed voorbeeld hiervan |
+ |
8 |
is Bed; Bed weet niet over dat er Reservaties bestaan, zelfs niet in welke |
+ |
9 |
Room het 'staat'. |
+ |
10 |
- Als er toch gekoppeld moet worden, dan blijft dit tot een minimum beperkt; Een |
+ |
11 |
Room weet wel welke Bedden het heeft, maar niet hoe deze gebruikt worden, een |
+ |
12 |
Reservation weet wel welke Bedden voor hem gereserveerd zijn, maar heeft geen |
+ |
13 |
weet van welke kamer dat deze staat. |
+ |
14 |
|
+ |
15 |
### Indirectie |
+ |
16 |
- In plaats van functionaliteit toe te wijzen aan class X om met class Y te |
+ |
17 |
interageren, wordt er vaak gebruik gemaakt van een class Z, die deze |
+ |
18 |
verantwoordelijkheid op zich neemt. |
+ |
19 |
- Dit wordt toegepast d.m.v. een MVC-structuur, waarin de \*Controller-classes |
+ |
20 |
als 'tussenpersoon' werken. |
+ |
21 |
- Dit komt ook tegemoet aan de eigenschappen van Information Expertise. |
+ |
22 |
|
+ |
23 |
### Creator |
+ |
24 |
- Controllers staan ook in als zgn. Creators van de models die ze beheren. Ze |
+ |
25 |
voldoen dan ook aan de eigenschappen zoals |
+ |
26 |
[hier](https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator) |
+ |
27 |
opgesomd wordt. |
+ |
28 |
|
+ |
29 |
|
+ |
30 |
## SOLID |
+ |
31 |
|
+ |
32 |
### Single Responsibility |
+ |
33 |
|
+ |
34 |
## Algemene keuzes ter bevordering codekwaliteit |
+ |
35 |
|
+ |
36 |
### Null pointers |
+ |
37 |
Het valt misschien op dat ik doorheen mijn programma in veel contracten eis dat |
+ |
38 |
geen enkele parameter een zgn. *null pointer* is. |
+ |
39 |
|
+ |
40 |
Het gebruik van null pointers staat garant voor een overvloed aan moeilijk te |
+ |
41 |
vinden bugs die (door het design van objectgeörienteerd programmeren) enorm diep |
+ |
42 |
kunnen doorpropageren. |
+ |
43 |
|
+ |
44 |
Ik maak er een kerntaak van dat, als er aan mijn programma gewerkt wordt, de |
+ |
45 |
programmeur zichzelf steeds kan garanderen dat **alle** data die hij |
+ |
46 |
ontvangt, valide data is. |
+ |
47 |
Op deze manier valt er een hele last van de schouders van de programmeur; een |
+ |
48 |
reeks fouten worden voorkomen, simpelweg door een strikt schema aan te houden. |
+ |
49 |
|
+ |
50 |
Het controleren op null pointers wordt op 2 manieren gedaan: |
+ |
51 |
- Gebruik van *methods* aanwezig in het gegeven type. Als de gegeven variabele |
+ |
52 |
een null pointer is, zal het programma direct crashen, en een |
+ |
53 |
NullPointerException geven. |
+ |
54 |
- Expliciet testen of *var == null*. Wordt toegepast op parameters die direct |
+ |
55 |
als members opgeslagen dienen te worden. |
+ |
56 |
|
+ |
57 |
Deze (contractuele) controle laat toe dat, mocht er een null pointer gebruikt |
+ |
58 |
worden, het programma de programmeur hiervan direct op de hoogte stelt, en dit |
+ |
59 |
op het laagst mogelijke niveau (namelijk de eerste method waar deze waarde |
+ |
60 |
gebruikt wordt). |
+ |
61 |
|
+ |
62 |
### Cloning |
+ |
63 |
members 'private' maken (encapsuleren) is volledig nutteloos als men getters en |
+ |
64 |
setters op deze members toepast; In Java worden references doorgegeven (m.u.v. |
+ |
65 |
primitives), die de hele notie van encapsulatie voorbijgaan (bij sommige types). |
+ |
66 |
Een voorbeeld hiervan is het privatiseren van een Set<T>-member: men kan daar |
+ |
67 |
een 'getSet()'-method op plaatsen, en dan toch de inhoud van deze 'private' |
+ |
68 |
aanpassen. |
+ |
69 |
|
+ |
70 |
Ik heb geopteerd om, waar van toepassing, deze variabelen te 'clonen', om zo |
+ |
71 |
exacte kopieën terug te geven. |
+ |
72 |
Deze manier van werken brengt enkele voordelen teweeg: |
+ |
73 |
- Zeer defensief programmeren; De ontwikkelaar kan geen members aanpassen als |
+ |
74 |
dat niet de bedoeling was |
+ |
75 |
- Duidelijkheid code: getSet().clear() zal de member niet meer leegmaken. Om dat |
+ |
76 |
te doen, moet men gebruikmaken van de method die daarvoor bedoeld is: |
+ |
77 |
setSet(clearedSet) |
+ |
78 |
|
+ |
79 |
### Inheritance |
+ |
80 |
Overerving is een goed concept over het algemeen, maar **niet** in OOP. |
+ |
81 |
De problemen omtrent impliciet gedrag en onnodige *state* zijn al te vaak |
+ |
82 |
beschreven met OOP-inheritance. |
+ |
83 |
|
+ |
84 |
Ik heb in mijn programma geen gebruik gemaakt van inheritance, exact omwille van |
+ |
85 |
de problemen die het voortbrengt, zeker in termen van herbruikbaarheid en |
+ |
86 |
robuustheid, wat toch zware vereisten waren voor deze opdracht. |
+ |
87 |
|
+ |
88 |
Ik heb al mijn problemen makkelijk kunnen oplossen d.m.v. compositie. |
+ |
89 |
|
+ |
90 |
### Benaming variabelen |
+ |
91 |
Doorheen mijn programma maak ik heel veel gebruik van dezelfde benamingen. |
+ |
92 |
Bijvoorbeeld: Een variabele van het type Reservation zal haast altijd |
+ |
93 |
'reservation' heten, een Set van een bepaald type zal de naam van datzelfde type |
+ |
94 |
dragen, in het meervoud, ... |
+ |
95 |
|
+ |
96 |
Sommige programmeurs gebruiken liever afkortingen (bv. 'reservation' --> |
+ |
97 |
'resv'), omdat dit sneller schrijft. |
+ |
98 |
|
+ |
99 |
Naar mijn mening moet men bij deze werkwijze inleveren aan leesbaarheid, vooral |
+ |
100 |
wanneer iemand die nog nooit met de code gewerkt heeft, dit programma moet |
+ |
101 |
overnemen. |
+ |
102 |
|
+ |
103 |
Daarnaast zorgt de consistentie van woordgebruik ervoor dat een andere |
+ |
104 |
programmeur, doorheen het hele programma dezelfde context in zijn/haar gedachten |
+ |
105 |
kan gebruiken. |
+ |
106 |
|
+ |
107 |
|
+ |
108 |
|
+ |
109 |
|
+ |
110 |
------------------------------------------------------------ TODO |
+ |
111 |
## Toepassing types/classes |
+ |
112 |
Doorheen het programma heb ik getracht zoveel mogelijk gebruik te maken van |
+ |
113 |
types/classes die |
+ |
114 |
- Veelvoorkomend zijn in de Java STL (Zoals String, Set, List, ...) |
+ |
115 |
- primitief zijn (ints, ...), omdat deze operatoren hebben en de code |
+ |
116 |
leesbaarder maken |
+ |
117 |
|
+ |
118 |
Een goed voorbeeld hiervan zijn bv. de faciliteiten: |
+ |
119 |
I.p.v. een aparte "Facility"-class te maken, heb ik de verschillende |
+ |
120 |
faciliteiten voorgesteld door een simpele String. De voordelen van deze aanpak |
+ |
121 |
zijn ook direct duidelijk: |
+ |
122 |
- Betekenis is direct duidelijk; de faciliteit letterlijk in de code vernoemd |
+ |
123 |
- Makkelijke interactie met GUI, die sowieso Strings vraagt voor bv. JLabel |
+ |
124 |
- Uitbreidbaarheid wordt bekomen door simpelweg een nieuwe String te |
+ |
125 |
introduceren |
+ |
126 |
|
+ |
127 |
## View en GUI |
+ |
128 |
Werken met GUI's is vaak tijdrovend en veroorzaakt snel errors, zeker met bv. |
+ |
129 |
anonieme methods, exceptions, ... |
+ |
130 |
Alhoewel mijn programma grotendeels in een MVC-stijl is geschreven, maken de |
+ |
131 |
view-classes (RegistrationView, SearchView, ...) achterliggend gebruik van een |
+ |
132 |
zelfgemaakt framework om makkelijk vensters te maken. |
+ |
133 |
Dit kleine framework is een persoonlijk hobbyproject dat ik JSugar noem. |
+ |
134 |
Het biedt een heleboel voordelen, vergeleken met elk GUI-venster zelf opstellen: |
+ |
135 |
- Vaak gebruikte GUI-widgets (zoals een label, textfield) worden aangemaakt en |
+ |
136 |
toegevoegd door slechts 1 method op te roepen |
+ |
137 |
- JSugar maakt gebruik van reflectie om op een leesbare en uitbreidbare manier |
+ |
138 |
knoppen te activeren: |
+ |
139 |
public JButton createButton(String text, String action, String methodName, Object triggerObject) |
+ |
140 |
'methodName' is een simpele String, en 'triggerObject' is het object waar deze |
+ |
141 |
method moet worden opgeroepen. |
+ |
142 |
- Automatische uitlijning van widgets |
+ |
143 |
Voor meer informatie kunt u JSugar-readme.md raadplegen. |
+ |
144 |
|
+ |
145 |
## java.util.Date |
+ |
146 |
|
+ |
147 |
Doorheen het programma maak ik vaak gebruik van de Date-class uit de Java STL, |
+ |
148 |
om de volgende redenen: |
+ |
149 |
- Uitbreidbaarheid: Door overal eenzelfde type te gebruiken, is het gemakkelijk |
+ |
150 |
om nieuwe modules toe te voegen, zonder dat daarvoor abstractielagen etc. |
+ |
151 |
nodig zijn. |
+ |
152 |
- Uniformiteit: Eenzelfde type uit de STL laat de ontwikkelaar toe om door het |
+ |
153 |
hele programma heen hetzelfde denkpatroon aan te houden; een |
+ |
154 |
Stringvoorstelling hier, een integer daar, ... veroorzaken problemen en bugs, |
+ |
155 |
die met deze class voorkomen worden. |
+ |
156 |
|
+ |
157 |
## Bedden |
+ |
158 |
|
+ |
159 |
Ik heb voor bedden een aparte class aangemaakt, omdat deze een bepaalde state |
+ |
160 |
bijhouden, nml. wanneer ze gereserveerd zijn. |
+ |
161 |
|
+ |
162 |
|
+ |
163 |
## Reservation |
+ |
164 |
Voor de reservaties heb ik besloten om enkel die data bij te houden die inherent |
+ |
165 |
gerelateerd is aan die reservatie: |
+ |
166 |
- Enkel gereserveerde bedden i.p.v. gereserveerde kamers. Qua uitbreidbaarheid |
+ |
167 |
heeft dit tot gevolg dat men gemakkelijk kan uitbreiden naar reservaties, |
+ |
168 |
gespreid over verschillende kamers. |
+ |
169 |
|
+ |
170 |
|
+ |
171 |
## ReservationView |
+ |
172 |
Merk op hoe in ReservationView de data van de Reservation direct in de GUI wordt |
+ |
173 |
geplaatst. |
+ |
174 |
Dit staat toe om zeer gemakkelijk deze class te hergebruiken voor zowel het |
+ |
175 |
**aanmaken** als het **updaten** van de reservatie. |
+ |
176 |