OOP2

I'm pretty much done now.

Author
Maarten 'Vngngdn' Vangeneugden
Date
Dec. 16, 2016, 1:55 p.m.
Hash
cd8fef3ba559bf2ebfdb75e4d6dcedfbb6805718
Parent
5c90f8e84f1a4f2ae7feada51ba2e9104ea76a42
Modified files
Challenge 6/Main.java
Challenge 6/MainWindow.java
Challenge 6/SearchView.java
Challenge 6/ontwerpkeuzes2.md

Challenge 6/Main.java

7 additions and 1 deletion.

View changes Hide changes
1
1
import java.util.HashSet;
+
2
import java.util.HashSet;
2
3
import java.util.Random;
3
4
4
5
/**
5
6
 * The program starts here.
6
7
 * @author Maarten Vangeneugden - 1438256
7
8
 */
8
9
public class Main {
9
10
	public static void main(String[] args) {
10
11
		// Starting controllers and linking them together
11
12
		RoomController roc = new RoomController();
12
13
		ReservationController rc = new ReservationController(roc);
13
14
		WalkController wc = new WalkController(rc);
14
15
15
16
		addTestRooms(roc);
16
17
		addTestWalks(wc);
17
18
		MainWindow mainWindow = new MainWindow(rc, roc);
18
-
	}
+
19
	}
19
20
20
21
	/**
21
22
	 * Generates a series of Rooms to test the program.
22
23
	 * This method is mostly for debugging purposes.
23
24
	 * It features a set of constants in the front of the method, which you can
24
25
	 * edit to your heart's content. =)
25
26
	 * @param roc The Room Controller to which the Rooms will be added.
26
27
	 * @pre roc mustn't be null.
27
28
	 * @throws NullPointerException if roc is a null pointer.
28
29
	 */
29
30
	public static void addTestRooms(RoomController roc) {
30
31
		// Constants; edit to suit your needs
31
32
		final int ROOM_COUNT = 10; // Amount of Rooms that will be generated
32
33
		final int MAX_BEDS = 20; // The maximum amount of Beds in 1 Room
33
34
		final String[] POSSIBLE_FACILITIES = {"Shower", "Curtains", "Airco", "Bath", "Minibar"};
34
35
		final String[] POSSIBLE_TYPES = {"Male", "Female", "Mixed"};
35
36
36
37
		Set<Room> testRooms = new HashSet<>();
37
38
		for(int i=0; i<ROOM_COUNT; i++) {
38
39
			Random random = new Random();
39
40
			int beds = random.nextInt(MAX_BEDS) + 1; // +1, because it's in range [0, MAX_BEDS[
40
41
			String type = POSSIBLE_TYPES[random.nextInt(POSSIBLE_TYPES.length)];
41
42
			Set<String> facilities = new HashSet<>();
42
43
			for(String possibleFacility: POSSIBLE_FACILITIES) {
43
44
				if(random.nextBoolean()) {
44
45
					facilities.add(possibleFacility);
45
46
				}
46
47
			}
47
48
			testRooms.add(new Room(beds, type, facilities));
48
49
			// For debugging purposes, a human readable layout of the Rooms is
49
50
			// printed:
50
51
			System.out.println("ROOM");
51
52
			System.out.println("Beds: "+ beds);
52
53
			System.out.println("Type: "+ type);
53
54
			System.out.print("Facilities: ");
54
55
			for(String facility : facilities) {
55
56
				System.out.print(facility +", ");
56
57
			}
57
58
			System.out.println();
58
59
			System.out.println("-------------------------------");
59
60
		}
60
61
		roc.setRooms(testRooms);
61
62
	}
62
63
63
64
	public static void addTestWalks(WalkController wc) {
64
65
	}
+
66
		places.add("Lyon");
+
67
		places.add("Marseille");
+
68
		places.add("Paris");
+
69
		wc.addWalk(new Walk("Tour de France", 5, places));
+
70
	}
65
71
}
66
72

Challenge 6/MainWindow.java

20 additions and 1 deletion.

View changes Hide changes
1
1
 * Main window for the hostel program.
2
2
 * This class creates some sort of "main menu screen". It displays a concise set
3
3
 * of buttons, that allow the user to reach all parts of the program's GUI.
4
4
 * To be called as soon as the program is started (Essentially from the Main
5
5
 * class).
6
6
 * @author Maarten Vangeneugden - 1438256
7
7
 */
8
8
public class MainWindow {
9
9
10
10
	private ReservationController reservationController;
11
11
	private RoomController roomController;
12
12
	
+
13
	
13
14
	public MainWindow(ReservationController reservationController, RoomController roomController) {
14
-
		this.reservationController = reservationController;
+
15
		this.reservationController = reservationController;
15
16
		this.roomController = roomController;
16
17
+
18
17
19
		Window window = new Window("Main menu");
18
20
		window.createButton("New reservation", "", "addReservation", this);
19
21
		window.createButton("Search screen", "", "openSearchView", this);
+
22
		window.createButton("Search screen", "", "openSearchView", this);
20
23
	}
+
24
	}
21
25
22
26
	public void openSearchView() {
23
27
		SearchView sv = new SearchView(this.reservationController, this.roomController);
24
28
	}
25
29
	
26
30
	public void addReservation() {
27
31
		Reservation reservation = new Reservation();
28
32
		ReservationView rv = new ReservationView(reservation, this.reservationController, this.roomController);
29
33
	}
30
34
31
35
}
+
36
		WalkSearchView wsv = new WalkSearchView(this.reservationController, this.walkController);
+
37
	}
+
38
+
39
	/**
+
40
	 * Create a Walk Reservation creation screen.
+
41
	 * @pre walkController must have at least one Walk stored in it.
+
42
	 * @throws IndexArrayOutOfBoundsException is walkController has no Walks in
+
43
	 * it.
+
44
	 */
+
45
	public void addWalkReservation() {
+
46
		WalkReservation walkReservation = new WalkReservation();
+
47
		walkReservation.setWalk(this.walkController.getWalks().toArray(new Walk[1])[0]);
+
48
		WalkView wv = new WalkView(walkReservation, this.reservationController, this.walkController);
+
49
	}
+
50
}
32
51

Challenge 6/SearchView.java

4 additions and 10 deletions.

View changes Hide changes
1
1
import java.util.ArrayList;
2
2
import java.util.Date;
3
3
4
4
/**
5
5
 * Class for creating a screen that allows querying actions.
6
6
 * This program offers the ability to search in the program for Reservations,
7
7
 * Room status, etc.
8
8
 * This class creates a GUI for user interaction.
9
9
 * When matches are found, it will display them. In case of a unique match, that
10
10
 * match is immediately displayed.
11
11
 * @see ReservationView
12
12
 * @author Maarten Vangeneugden - 1438256
+
13
 * @author Maarten Vangeneugden - 1438256
13
14
 */
14
15
public class SearchView {
15
16
	private ReservationController rc;
16
17
	private RoomController roc;
17
18
	private Window window;
18
19
19
20
	private JTextField groupNameField;
20
21
	private JTextField reservationIDField;
21
22
	private JTextField bedDateField;
22
23
	private JTextField breakfastDayField;
23
24
24
25
	public SearchView(ReservationController rc, RoomController roc) {
25
26
		this.rc = rc;
26
27
		this.roc = roc;
27
28
28
29
		this.window = new Window("Search screen");
29
30
		this.addFields();
30
31
	}
31
32
	
32
33
	private void addFields() {
33
34
		// TODO: Add fields to private members!
34
-
		this.window.createLabel("Search reservations:");
+
35
		this.window.createLabel("Search reservations:");
35
36
		this.groupNameField = this.window.createTextField("Search by group name");
36
37
		this.reservationIDField = this.window.createTextField("Search by reservation ID");
37
38
		this.window.createButton("Search reservation", "", "queryReservations", this);
38
39
		this.window.createLabel("Search reserved beds on given day:");
+
40
		this.window.createLabel("Search reserved beds on given day:");
39
41
		this.bedDateField = this.window.createTextField(new Date().toGMTString());
40
42
		this.window.createButton("Get reserved beds", "", "queryBeds", this);
41
43
		this.window.createLabel("Find amount of breakfasts:");
+
44
		this.window.createLabel("Find amount of breakfasts:");
42
45
		this.breakfastDayField = this.window.createTextField(new Date().toGMTString());
43
46
		this.window.createButton("Get breakfasts on given day", "", "queryBreakfasts", this);
44
47
	}
45
48
46
49
	public void queryReservations() {
47
50
		ArrayList<Reservation> foundReservations = new ArrayList<>();
48
51
		String nameQuery = this.groupNameField.getText();
49
52
		String IDQuery = this.reservationIDField.getText();
50
53
		for(Reservation activeReservation : this.rc.getReservations()) {
51
54
			if(activeReservation.getGroupName().contains(nameQuery) &&
52
55
				String.valueOf(activeReservation.getReservationID()).contains(IDQuery)) {
53
56
				foundReservations.add(activeReservation);
54
57
				}
55
58
		}
56
59
		// After collecting all results, offer the user the choice about which
57
60
		// one to take:
58
61
		String[] reservationNames = new String[foundReservations.size()];
59
62
		for(int i=0; i<foundReservations.size(); i++) {
60
63
			String text = foundReservations.get(i).getGroupName() +" ("+
61
64
				String.valueOf(foundReservations.get(i).getReservationID()) +")";
62
65
			reservationNames[i] = text;
63
66
		}
64
67
		int choice = this.window.choiceDialog("Multiple results were found. Specify which one you want to view:", reservationNames);
65
68
		if(choice == -1) { // No result found
66
69
			this.window.messageDialog("No reservations matched the given details.");
67
70
		}
68
71
		else {
69
72
			new ReservationView(foundReservations.get(choice), this.rc, this.roc);
70
73
		}
71
74
	}
72
75
73
76
	/**
74
77
	 * Search and display the reservation of Beds in Rooms.
75
78
	 * This method takes the given begin and end dates from the GUI, and lists
76
79
	 * for each Room, how many Beds are reserved, and by whom.
77
80
	 */
78
81
	public void queryBeds() {
79
82
		// The amount of reserved Beds is determined by the Reservations.
80
83
		// If a Reservation (partially) overlaps with the given time, then this
81
84
		// Bed is reserved in the given period.
82
85
		final Date date = new Date(this.bedDateField.getText());
83
86
		// endDate is required as it has to be strictly later than date.
84
87
		final Date endDate = new Date(date.getTime() + 1);
85
88
		String result = "";
86
89
87
90
		for(Room room: this.roc.getRooms()) {
88
91
			// XXX: The Java Object class provides a "hashcode()" method, to
89
92
			// retrieve an object's hashcode. I'm using that to identify the
90
93
			// different rooms.
91
94
			int usedBeds = room.getBeds().size() - room.getEmptyBeds(date, endDate).size();
92
95
			result = result + "Room "+ String.valueOf(room.hashCode()) +": "+ String.valueOf(usedBeds) +" reserved beds.\n";
93
96
		}
94
97
		this.window.messageDialog(result);
95
98
		/*for(Reservation reservation: this.rc.getReservations()) {
96
99
			if(!
97
100
				(reservation.getBeginDate().before(beginDate) && reservation.getEndDate().before(beginDate)) ||
98
101
				(reservation.getBeginDate().after(endDate) && reservation.getEndDate().after(endDate)))
99
102
			{ // This block is only reached if the valid options didn't match.
100
103
				String name = reservation.getGroupName();
101
104
				String beds = String.valueOf(reservation.getReservedBeds().size());
102
105
				String begin = reservation.getBeginDate().toGMTString();
103
106
				String end = reservation.getEndDate().toGMTString();
104
107
				result = result +
105
108
					name +" reserved "+ beds +" between "+ begin +" and "+ end +".\n";
106
109
			}
107
110
		}*/
108
111
	}
109
112
110
113
	/**
111
114
	 * Queries and displays breakfast reservations.
112
115
	 * After the user has entered a day in the corresponding field, this method
113
116
	 * can be called to search for breakfast reservations on that day.
114
117
	 * Breakfasts are ordered by Reservation, accompagnied by the amount of
115
118
	 * people in that Reservation.
116
119
	 * // TODO finish this javadoc
117
120
	 */
118
121
	public void queryBreakfasts() {
119
122
		Date date = new Date(this.breakfastDayField.getText());
120
123
		// Breakfast is only served at 9 o'clock, so set that time for easy
121
124
		// reference during querying:
122
125
		date.setHours(8);
123
126
		date.setMinutes(0);
124
127
		date.setSeconds(0);
125
128
		String response = "";
126
129
		for(Reservation reservation: this.rc.getReservations()) {
127
130
			if(reservation.getBreakfastDays().contains(date)) {
128
131
				String name = reservation.getGroupName();
129
132
				String amount = String.valueOf(reservation.getPeople());
130
133
				response = response +
131
134
					"Reservation "+ name +" ordered breakfast for "+ amount +" people.\n";
132
135
			}
133
136
			// else block is DEBUG CODE
134
-
			else {
135
-
				System.out.println("No match!");
136
-
				System.out.println("Query: "+date.toGMTString());
137
-
				System.out.println("Tests:");
138
-
				for(Date bfd: reservation.getBreakfastDays()) {
139
-
					System.out.println(bfd.toGMTString());
140
-
				}
141
-
			}
142
-
		}
143
137
		if(!response.isEmpty()) {
144
138
			this.window.messageDialog(response);
145
139
		}
146
140
		else {
147
141
			this.window.messageDialog("There are no breakfasts ordered for this day.");
148
142
		}
149
143
	}
150
144
}
151
145

Challenge 6/ontwerpkeuzes2.md

47 additions and 10 deletions.

View changes Hide changes
1
1
2
2
## GRASP
3
3
Om zoveel mogelijk tegemoet te komen aan de GRASP-richtlijnen, heb ik volgende
4
4
ontwerpkeuzes toegepast voor de verschillende richtlijnen.
5
5
6
6
### High cohesion & Low coupling
7
7
- Veel classes zijn totaal van elkaar losgekoppeld. Een goed voorbeeld hiervan
8
8
  is Bed; Bed weet niet over dat er Reservaties bestaan, zelfs niet in welke
9
9
  Room het 'staat'.
10
10
- Als er toch gekoppeld moet worden, dan blijft dit tot een minimum beperkt; Een
11
11
  Room weet wel welke Bedden het heeft, maar niet hoe deze gebruikt worden, een
12
12
  Reservation weet wel welke Bedden voor hem gereserveerd zijn, maar heeft geen
13
13
  weet van welke kamer dat deze staat.
14
14
- Uitzondering op deze regel vormen de Controller-classes; omwille van hun taken
15
15
  zijn deze vaak verplicht om van veel verschillende classes op de hoogte te
16
16
  zijn.
17
17
18
18
### Indirectie
19
19
- In plaats van functionaliteit toe te wijzen aan class X om met class Y te
20
20
  interageren, wordt er vaak gebruik gemaakt van een class Z, die deze
21
21
  verantwoordelijkheid op zich neemt.
22
22
- Dit wordt toegepast d.m.v. een MVC-structuur, waarin de \*Controller-classes
23
23
  als 'tussenpersoon' werken.
24
24
- Dit komt ook tegemoet aan de eigenschappen van Information Expertise.
25
25
26
26
### Creator
27
27
- Controllers staan ook in als zgn. Creators van de models die ze beheren. Ze
28
28
  voldoen dan ook aan de eigenschappen zoals
29
29
  [hier](https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator)
30
30
  opgesomd wordt.
31
31
32
32
33
33
## SOLID
34
-
35
-
### Single Responsibility
36
-
37
-
## Veranderingen t.o.v. Challenge 1
38
-
39
-
- Verkrijgen van een vrije kamer is verplaatst van ReservationView naar
+
34
- Verkrijgen van een vrije kamer is verplaatst van ReservationView naar
40
35
  RoomController
41
-
- Toevoeging van veel documentatie, vooral in de vorm van Javadoc, maar ook
+
36
- Toevoeging van veel documentatie, vooral in de vorm van Javadoc, maar ook
42
37
  _inline commenting_ waar nodig/gewenst.
43
38
+
39
  voorbeeld incluis).
+
40
- Nieuw zoekvenster, speciaal gericht op het behandelen van wandelingen.
+
41
- Zoekvensters zijn nu haast volledig operationeel, en geven bruikbare
+
42
  antwoorden en data terug.
+
43
- Eerder gemaakte reservaties/wandelreservaties kunnen later aangepast en/of
+
44
  verwijderd worden.
+
45
- Prijsberekening op orde gesteld.
+
46
- Toevoeging van een automatische _room generator_ in Main, om snel en met
+
47
  willekeurige data het programma te testen.
+
48
- Toepassing van contractueel programmeren in vele methods; vaak wordt de method
+
49
  nog niet uitgevoerd als het contract niet 100% wordt nageleefd.
+
50
44
51
### Vereiste aanpassingen
45
52
De aanpassingen die ik heb moeten doorvoeren om wandelingen toe te voegen, zijn
46
53
grotendeels beperkt gebleven tot de plekken in de code die sowieso van meerdere
47
54
onderdelen van het programma op de hoogte zijn;
48
55
Zo is er niks veranderd aan Reservation of Room, maar WalkController en
49
56
ReservationController hebben elkaar nu wel als member.
50
57
51
58
Aan de GUI-kant was het slechts 1 knopje toevoegen in het hoofdmenu.
52
59
53
60
Ik heb het zo opgesteld dat een groepsnaam die overeenkomt met een
54
61
hostelreservering, wordt aanzien als een reservering van dezelfde persoon.
55
62
Als de namen niet overeen komen, dan zijn het verschillende groepen.
56
63
57
64
Deze conventie laat mij toe om het programma veel beter te laten voldoen aan
58
65
high cohesion/low coupling, zonder daarvoor veel voordelen voor hoeven in te
59
66
leveren.
60
67
61
68
## Algemene keuzes ter bevordering codekwaliteit
62
-
+
69
zoekvenster te plaatsen, maar ik vond dat dat nogal onduidelijk ging worden. Ik
+
70
heb dus voor wandelmanagement een apart zoekvenster gemaakt, te bereiken vanuit
+
71
het hoofdmenu.
+
72
+
73
Uiteindelijk ben ik blij van de beperkte aanpassingen in het eerste gedeelte van
+
74
de challenge. Ik heb slechts hier en daar een extra member moeten toevoegen, en
+
75
het geheel is nog steeds degelijk gesplitst.
+
76
+
77
# Algemene keuzes ter bevordering codekwaliteit
+
78
63
79
## Strings, integers, ... i.p.v. Enums/Eigen classes
64
80
In het programma zijn er sommige members die doen vermoeden dat ze beter als
65
81
Enums aangeduid kunnen worden; Het type van een kamer, faciliteiten, ...
66
82
67
83
In plaats van een speciale class hiervoor te maken, heb ik gekozen om deze
68
84
gewoon te behandelen als simpele Strings in lijsten.
69
85
70
86
Het voordeel aan deze werkwijze, is dat Strings in Java SE quasi universeel
71
87
voorkomen; data kunnen geconverteerd worden naar Strings (en vice versa), veel
72
88
gebruikte GUI-libraries (waaronder Swing, JavaFX, ...) gebruiken Strings voor
73
89
tekst voor te stellen in de GUI-widgets, ...
74
90
Daarnaast weet iedereen die ook maar een beetje geschoold is in Java, direct hoe
75
91
deze members behandeld kunnen worden. Had ik een class gemaakt die bv.
76
92
RoomFacilities heette, dan is die parate kennis over de taal zelf nutteloos.
77
93
78
94
Strings zijn ook voorzien van extreem veel methods, en zijn dus zeer flexibele
79
95
classes om te gebruiken. Het feit dat ze zo makkelijk doorheen het programma te
80
96
gebruiken zijn is dus een groot pluspunt.
81
97
82
98
Als dat nog niet genoeg is: Het gebruiken van de hulpmiddelen uit de _standard
83
99
library_ is niet enkel waarvoor libraries überhaupt bestaan, het beperkt ook
84
100
het benodigde aantal classes in de eigen software, waardoor het geheel
85
101
uiteindelijk veel overzichtelijker blijft, en bijgevolg, makkelijk uit te
86
102
breiden, te testen, te begrijpen, ...
87
103
88
104
Al deze voordelen graan grotendeels verloren als ik beslis om zelf
89
105
gespecialiseerde classes op te stellen.
90
106
Men kan misschien stellen dat "de voordelen die het schrijven van eigen
91
107
classes veel beter tegemoet komt aan de essentie van object-georiënteerd
92
108
programmeren, dan zich _beperken_ tot slechts een handvol generieke classes, die
93
109
misschien niet volledig aan de benodigdheden beantwoorden".
94
110
95
111
Toch laat ik mijn afweging overslaan in het voordeel van minder classes, en meer
96
112
uniformiteit. _Sometimes, less is more._ Meer classes betekent ook:
97
113
- Meer onderhoud
98
114
- Meer kans op bugs
99
115
- Groter programma
100
116
101
117
En al die problemen resulteren op lange termijn in:
102
118
- Slechtere uitbreidbaarheid
103
119
- Slechtere onderhoudbaarheid
104
120
- Slechtere schaalbaarheid
105
121
106
122
Zijn al die problemen de moeite van een (zogezegd) "beter object-georiënteerd
107
123
design" wel waard?
108
124
Veel mensen stellen juist dat OOP net voordelig is als men op zoek is naar
109
125
- Uitbreidbaarheid
110
126
- Onderhoudbaarheid
111
127
- Modulariteit
112
128
- Schaalbaarheid
113
129
114
130
Als de voordelen van het paradigma verdwijnen als ik dat "beter design" volg,
115
131
is dat design dan wel echt beter?
116
132
117
133
118
134
**Conclusie: Uniforme classes zijn volgens mij soms beter dan een stel
119
135
gespecialiseerde classes. Daarom dat ik mij soms behelp met Strings, intergers,
120
136
... i.p.v. zelf een oplossing te schrijven.**
121
137
122
138
123
139
### Null pointers
124
140
Het valt misschien op dat ik doorheen mijn programma in veel contracten eis dat
125
141
geen enkele parameter een zgn. *null pointer* is.
126
142
127
143
Het gebruik van null pointers staat garant voor een overvloed aan moeilijk te
128
144
vinden bugs die (door het design van objectgeörienteerd programmeren) enorm diep
129
-
kunnen doorpropageren.
+
145
kunnen doorpropageren.
130
146
131
147
Ik maak er een kerntaak van dat, als er aan mijn programma gewerkt wordt, de
132
148
programmeur zichzelf steeds kan garanderen dat **alle** data die hij
133
149
ontvangt, valide data is, tenzij dat expliciet anders wordt aangegeven.
134
150
Op deze manier valt er een hele last van de schouders van de programmeur; een
135
151
reeks fouten worden voorkomen, simpelweg door een strikt schema aan te houden.
136
152
137
153
Het controleren op null pointers wordt op 2 manieren gedaan:
138
154
- Gebruik van *methods* aanwezig in het gegeven type. Als de gegeven variabele
139
155
  een null pointer is, zal het programma direct crashen, en een
140
156
  NullPointerException geven.
141
157
- Expliciet testen of *var == null*. Wordt toegepast op parameters die direct
142
158
  als members opgeslagen dienen te worden.
143
159
144
160
Een uitzondering op het vermijden van null pointers vormen sommige methods die
145
161
slechts 1 object teruggeven. In deze gevallen kan het voorvallen dat het te
146
162
zoeken object niet gevonden wordt. Om de ontwikkelaar hiervan op de hoogte te
147
163
stellen, wordt dan soms een null teruggestuurd.
148
164
Dit wordt steeds expliciet vermeld.
149
165
150
166
Deze (contractuele) controle laat toe dat, mocht er een null pointer gebruikt
151
167
worden, het programma de programmeur hiervan direct op de hoogte stelt, en dit
152
168
op het laagst mogelijke niveau (namelijk de eerste method waar deze waarde
153
169
gebruikt wordt).
154
170
155
171
### Cloning
156
172
members 'private' maken (encapsuleren) is volledig nutteloos als men getters en
157
173
setters op deze members toepast; In Java worden references doorgegeven (m.u.v.
158
174
primitives), die de hele notie van encapsulatie voorbijgaan (bij sommige types).
159
175
Een voorbeeld hiervan is het privatiseren van een Set<T>-member: men kan daar
160
176
een 'getSet()'-method op plaatsen, en dan toch de inhoud van deze 'private'
161
177
aanpassen.
162
178
163
179
Ik heb geopteerd om, waar van toepassing, deze variabelen te 'clonen', om zo
164
180
exacte kopieën terug te geven.
165
181
Deze manier van werken brengt enkele voordelen teweeg:
166
182
- Zeer defensief programmeren; De ontwikkelaar kan geen members aanpassen als
167
183
  dat niet de bedoeling was
168
184
- Duidelijkheid code: getSet().clear() zal de member niet meer leegmaken. Om dat
169
185
  te doen, moet men gebruikmaken van de method die daarvoor bedoeld is:
170
186
  setSet(clearedSet)
171
187
172
188
### Inheritance
173
189
Overerving is een goed concept over het algemeen, maar **niet** in OOP.
174
190
De problemen omtrent impliciet gedrag en onnodige *state* zijn al te vaak
175
191
beschreven met OOP-inheritance.
176
192
177
193
Ik heb in mijn programma geen gebruik gemaakt van inheritance, exact omwille van
178
194
de problemen die het voortbrengt, zeker in termen van herbruikbaarheid en
179
195
robuustheid, wat toch zware vereisten waren voor deze opdracht.
180
196
181
197
Ik heb al mijn problemen makkelijk kunnen oplossen d.m.v. compositie.
182
198
183
199
### Benaming variabelen
184
200
Doorheen mijn programma maak ik heel veel gebruik van dezelfde benamingen.
185
201
Bijvoorbeeld: Een variabele van het type Reservation zal haast altijd
186
202
'reservation' heten, een Set van een bepaald type zal de naam van datzelfde type
187
203
dragen, in het meervoud, ...
188
204
189
205
Sommige programmeurs gebruiken liever afkortingen (bv. 'reservation' -->
190
206
'resv'), omdat dit sneller schrijft.
191
207
192
208
Naar mijn mening moet men bij deze werkwijze inleveren aan leesbaarheid, vooral
193
209
wanneer iemand die nog nooit met de code gewerkt heeft, dit programma moet
194
210
overnemen.
195
211
196
212
Daarnaast zorgt de consistentie van woordgebruik ervoor dat een andere
197
213
programmeur, doorheen het hele programma dezelfde context in zijn/haar gedachten
198
214
kan gebruiken.
199
215
200
216
+
217
code in zijn geheel moeilijker leesbaar wordt.
+
218
Een voorbeeld van hoe dit uitmondt is Objective-C. Haast **alles** wordt voluit
+
219
genoteerd, waardoor van de eigenlijke essentie van het programma haast niks
+
220
overblijft.
+
221
201
222
+
223
afgekort. Ik vond dat het verlies aan expressiviteit meer dan goed gemaakt werd
+
224
door het winnen aan leesbaarheid.
+
225
202
226
203
227
------------------------------------------------------------ TODO
204
-
## Toepassing types/classes
205
228
Doorheen het programma heb ik getracht zoveel mogelijk gebruik te maken van
206
229
types/classes die
207
230
- Veelvoorkomend zijn in de Java STL (Zoals String, Set, List, ...)
208
231
- primitief zijn (ints, ...), omdat deze operatoren hebben en de code
209
232
  leesbaarder maken
210
233
211
234
Een goed voorbeeld hiervan zijn bv. de faciliteiten:
212
235
I.p.v. een aparte "Facility"-class te maken, heb ik de verschillende
213
236
faciliteiten voorgesteld door een simpele String. De voordelen van deze aanpak
214
237
zijn ook direct duidelijk:
215
238
- Betekenis is direct duidelijk; de faciliteit letterlijk in de code vernoemd
216
239
- Makkelijke interactie met GUI, die sowieso Strings vraagt voor bv. JLabel
217
240
- Uitbreidbaarheid wordt bekomen door simpelweg een nieuwe String te
218
241
  introduceren
219
242
220
243
## View en GUI
221
244
Werken met GUI's is vaak tijdrovend en veroorzaakt snel errors, zeker met bv.
222
245
anonieme methods, exceptions, ...
223
246
Alhoewel mijn programma grotendeels in een MVC-stijl is geschreven, maken de
224
247
view-classes (RegistrationView, SearchView, ...) achterliggend gebruik van een
225
248
zelfgemaakt framework om makkelijk vensters te maken.
226
249
Dit kleine framework is een persoonlijk hobbyproject dat ik JSugar noem.
227
250
Het biedt een heleboel voordelen, vergeleken met elk GUI-venster zelf opstellen:
228
251
- Vaak gebruikte GUI-widgets (zoals een label, textfield) worden aangemaakt en
229
252
  toegevoegd door slechts 1 method op te roepen
230
253
- JSugar maakt gebruik van reflectie om op een leesbare en uitbreidbare manier
231
254
  knoppen te activeren:
232
255
  public JButton createButton(String text, String action, String methodName, Object triggerObject)
233
256
  'methodName' is een simpele String, en 'triggerObject' is het object waar deze
234
257
  method moet worden opgeroepen.
235
258
- Automatische uitlijning van widgets
236
-
Voor meer informatie kunt u JSugar-readme.md raadplegen.
+
259
Voor meer informatie kunt u JSugar-readme.md raadplegen.
237
260
238
261
## java.util.Date
239
262
240
263
Doorheen het programma maak ik vaak gebruik van de Date-class uit de Java STL,
241
264
om de volgende redenen:
242
265
- Uitbreidbaarheid: Door overal eenzelfde type te gebruiken, is het gemakkelijk
243
266
  om nieuwe modules toe te voegen, zonder dat daarvoor abstractielagen etc.
244
267
  nodig zijn.
245
268
- Uniformiteit: Eenzelfde type uit de STL laat de ontwikkelaar toe om door het
246
269
  hele programma heen hetzelfde denkpatroon aan te houden; een
247
270
  Stringvoorstelling hier, een integer daar, ... veroorzaken problemen en bugs,
248
271
  die met deze class voorkomen worden.
249
272
250
273
### Ontbijtdata
+
274
Geef data in in hetzelfde formaat, en de achtergrond doet de rest.
+
275
+
276
### Deprecation
+
277
Ik besef dat ik in java.util.Date veel gebruik maak van _deprecated methods_.
+
278
Nu, deze methods bieden mij wel de kans om snel en gemakkelijk met data om te
+
279
kunnen gaan.
+
280
Zeker het tijdsgebrek dat komt kijken bij de challenges zorgen ervoor dat ik
+
281
mijn niet de luxe kan veroorloven om een speciaal voor mij gemaakte dataclass te
+
282
maken.
+
283
+
284
### Ontbijtdata
251
285
252
286
Het moeilijkste om te implementeren waren de data voor ontbijt.
253
287
Er wordt voor de reservaties steeds een set bijgehouden van de data waarop
254
288
ontbijt besteld is.
255
289
Op zich is dit niet zo moeilijk. Het moeilijke hieraan, is de gebruiker van het
256
290
programma op een begrijpelijke manier deze data te laten invoeren.
257
291
Data worden ingevoerd via tekstvelden, omdat Swing geen zgn. "DatePicker" heeft.
258
292
259
293
+
294
+
295
260
296
### GUI
261
297
262
298
Swing biedt geen widget die zich specialiseert in het weergeven van informatie
263
299
over een datum (een zgn. _calendar widget_).
264
300
265
301
In de opdracht stond dat we geen "visueel aantrekkelijke GUI" hoeven te
266
302
ontwerpen, maar wel een die "alle functionaliteit ondersteunt".
267
303
268
304
Wegens het tijdsgebrek en de tekortkoming van Swing, heb ik besloten om data
269
305
weer te geven in een simpel JTextField.
270
306
Het biedt de beste oplossing voor wat gevraagd wordt in deze opdracht, en wegens
271
307
de tijdslimiet tijdens de challenges zelf vormen ze een goede
272
308
"kortetermijnoplossing".
273
309
274
310
## Bedden
275
311
276
312
Ik heb voor bedden een aparte class aangemaakt, omdat deze een bepaalde state
277
313
bijhouden, nml. wanneer ze gereserveerd zijn.
278
314
279
315
280
316
## Reservation
281
317
Voor de reservaties heb ik besloten om enkel die data bij te houden die inherent
282
318
gerelateerd is aan die reservatie:
283
319
- Enkel gereserveerde bedden i.p.v. gereserveerde kamers. Qua uitbreidbaarheid
284
320
  heeft dit tot gevolg dat men gemakkelijk kan uitbreiden naar reservaties,
285
321
  gespreid over verschillende kamers.
286
322
287
323
288
324
## ReservationView / WalkView
289
325
Merk op hoe in ReservationView de data van de Reservation direct in de GUI wordt
290
326
geplaatst.
291
327
Dit staat toe om zeer gemakkelijk deze class te hergebruiken voor zowel het
292
328
**aanmaken** als het **updaten** van de reservatie.
293
329
294
330
Dezelfde werkwijze wordt toegepast ook WalkView.
295
331
296
332
297
333
## Opmerkingen
298
334
299
335
- Door het gebruik van de FlowLayout in de GUI, is het mogelijk dat sommige
300
336
  gedeelten van de GUI niet direct worden weergegeven, daar ze verborgen worden
301
337
  door de hoogte van het venster. Men kan deze tevoorschijn halen door zelf het
302
338
  venster in de hoogte te verstellen.
303
339