Hotel mixin sample -- reservation mixin

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.

Reserve method

The verbal description of this method is "reserve a room for week week, for name name". Reserve

  • checks whether there is a free room and throws a NoRoomException if there isn't
  • checks whether there already is a reservation for the given name and week, because this constitute an error in our toy-world (see restrictions above) FIXME
  • if everything turns out well, a ReservationInfo instance with name and week is added to the repository

If 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;
    }
Find method

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 methods

Cancel is polymorphic, two versions exist:

  • IReservationInfo Cancel (IReservationInfo reservationInfo) is a thin wrapper around the repository's Remove method
  • IReservationInfo 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 parameters

Trying to cancel a reservation that does not exist in the repository is an error, of course.