The first slice of the software manages reservations, essentially built around a repository of ReservationInfo
instances. ReservationInfo
is modeled around Babara's and Manuela's index cards with names, weeks and room numbers.
When receiving a reservation request by phone or fax, Babs or Manu enters the name and week into the program, the program checks if it can find a free room for that week; if so, the room is reserved. If not, the system throws a NoRoomException
.
The top-level data structure is an instance of type Hotel
, implementing the IHotel
, but it can't do much by itself.
The basic Hotel
class is extended by the mixin ReservationsMixin
, implementing the IReservationsMixin
interface. This mixin holds an instance of the Repository<IReservationInfo>
and exposes the following simple methods. They don't need much discussion:
- bool IsRoomFree (int number, int week) - int? FindFreeRoom (int week) // returns null if none is found |
(The two methods
- CountReservations () - ClearReservations () |
are not part of the interface. They are used only for testing. More about this in FIXME.)
We find out whether a given room is free by trying to find it in a reservation in the repository. If we can't find it, the room is free. FindFreeRoom
iterates over all room numbers (two in the current implementation – 0 and 1, configurable by changing Base.Hotel.NumberOfRooms
) and calls IsRoomFree
. If true, the room number is returned to signal a free room.
The following methods are more elaborate:
- IReservationInfo Reserve (string name, int week) - IReservationInfo Cancel (IReservationInfo reservationInfo) - IReservationInfo Cancel (string name, int week) - IReservationInfo Find (string name, int week) // null if none is found |
These methods map more or less exactly to typical activities of Babara and Manuela when reserving a room or canceling a reservation. The following paragraphs discuss each of these methods.
The verbal description of this method is "reserve a room for week week
, for name name
". Reserve
NoRoomException
if there isn'tReservationInfo
instance with name and week is added to the repositoryIf the checks give green light,
Reserve
returns the freshly minted IReservationInfo
instance.
In code:
public virtual IReservationInfo Reserve (string name, int week) { var found = FindFreeRoom (week); if (found == null) { throw new NoRoomException (string.Format ("no room for week {0}", week)); } var foundNames = _reservationInfoRepository.Find ().Count<IReservationInfo> (resInfo => resInfo.Name == name && resInfo.Week == week); if (foundNames > 0) { throw new NameAlreadyInReservationsException (string.Format ("name already in reservations: {0}", name)); } var reservationInfo = new ReservationInfo (name, found.Value, week); _reservationInfoRepository.Add (reservationInfo); return reservationInfo; } |
The Find
method is useful for browsing the reservation repository. After all, Babara and Manuela can't be expected to remember all entries in the reservation repository. If someone calls, the concierge on duty can unearth a reservation with Find
. Find
is also a crucial component for the next method, Cancel
.
Cancel
is polymorphic, two versions exist:
IReservationInfo Cancel (IReservationInfo reservationInfo)
is a thin wrapper around the repository's Remove
methodIReservationInfo Cancel (string name, int week)
is the more convenient relative that does error checking and creates the IReservationInfo
instance for you, from the name
and week
parametersTrying to cancel a reservation that does not exist in the repository is an error, of course.