Acme Travel Agency Case Study: Design

039 - Simplifications <p><script> function OpenWin(url, w, h) { if(!w) w = 400; if(!h) h = 300; window. open (url, "_new", "width=" + w + ",height=" + h + ",menubar=no,toobar=no,scrollbars=yes", true); } function Print() { window.focus(); if(window.print) { window.print(); window.setTimeout('window.close();',5000); } } </script></p>
Team-Fly    

 
Application Development Using Visual Basic and .NET
By Robert J. Oberg, Peter Thorsteinson, Dana L. Wyatt
Table of Contents
Chapter 5.  Inheritance and Exceptions in VB.NET


The Acme Travel Agency provides various services, including the booking of hotel, plane, and car rental reservations. We will use this simple theme of booking reservations to illustrate various features of .NET throughout the book. In this chapter we design the architecture of a general system for booking different kinds of reservations . We illustrate the reservation system with an implementation of a hotel broker system that supports the following basic features:

  • Add a hotel to the list of hotels.

  • Show all the hotels.

  • Show all the hotels in a particular city.

  • Reserve a hotel room for a range of dates.

  • Show all the reservations.

  • Show all the reservations for a particular customer.

The system also maintains a list of customers. Customers may register by giving their name and email address, and they will be assigned a customer ID. The following features are supported in the basic customer management subsystem:

  • Register as a customer.

  • Change the email address of a customer.

  • Show a single customer or all the customers.

In this chapter various lists, such as hotels, reservations, and customers, will be maintained as arrays. In the next chapter we will use .NET collections in place of arrays, and we will implement more features, such as the ability to delete a hotel, cancel a reservation, and the like. In later chapters we will extend the case study in various ways, such as providing a graphical user interface, storing all data in a database, deploying as a Web application, and so on.

graphics/codeexample.gif

The code for our case study is in the CaseStudy folder for this chapter.

Designing the Abstractions

Bearing in mind that eventually we want to implement not only a hotel reservation system, but also a system for other kinds of reservations, including plane and car rental, it behooves us at the beginning to look for appropriate abstractions. The more functionality we are able to put in base classes, the less work we will have to do in order to implement a particular kind of reservation system. On the other hand, having more functionality in the base classes can reduce the range of problems to which they are applicable . Good design is a balancing act.

Another attribute of well-designed abstractions is that they will survive major changes in implementation. As we shall see later in this book, our VB.NET abstractions of the hotel reservation system remain intact as we implement the system on an SQL Server database.

These abstractions will be represented in VB.NET by abstract classes (classes declared with the MustInherit keyword), defined in the file Broker.vb in the CaseStudy folder for this chapter.

Reservable

Our first abstraction is the thing we are looking to reserve. We will denote this abstraction as simply Reservable . The basic issue in reservations is resource usage. There are a limited number of reservable resources. Hence the key attribute of a Reservable is Capacity . For example, a hotel may have 100 rooms. A flight may have 250 seats. We will also want a unique identifier for a Reservable , which we will denote by m_unitid . (The shorter name m_unitid is used in preference to the longer, more awkward name m_reservableid . Later we will see other use of the terminology "unit." For example, the method to add a reservable is called AddUnit .)

For our applications, we are going to introduce an additional attribute, Cost . There is a room rate for a hotel, a ticket cost for a flight, and so on. Note that this attribute may not be applicable to all things that are being reserved. For example, a conference room within a company may not have a cost assigned to it. However, our applications are for commercial customers, so we choose to include Cost in our model.

Simplifications

Because our case study is designed to illustrate concepts in VB.NET and the .NET Framework, we will choose many simplifications in our design so that we do not become bogged down in detailed design issues. For example, in real life a hotel has several different kinds of rooms, each having a different rate. Similarly, an airplane flight will have different classes of seats. Here the situation in real life is even more complicated, because the price of a seat may vary wildly depending on when the reservation is made, travel restrictions, and so on. To make life simple for us, we are assuming that each instance of a particular reservable will have the same cost.

In VB.NET we will represent a Reservable by an abstract class with the MustInherit keyword.

 Public MustInherit Class Reservable    Private Shared m_nextid As Integer = 0    Protected m_unitid As Integer    Protected Friend Capacity As Integer    Protected Friend Cost As Decimal    Public Sub New(_     ByVal capacity As Integer, _     ByVal cost As Decimal)       Me.Capacity = capacity       Me.Cost = cost       m_unitid = m_nextid       m_nextid += 1    End Sub End Class 

A constructor allows us to specify the capacity and cost when the object is created. The m_unitid is initialized with a shared variable named m_nextid that is automatically incremented. This ID starts out at 0, because it is also going to be used in our implementation as an index into a two-dimensional array to track the number of customers having a reservation at a given reservable on a given date.

We will discuss the role of the Private , Protected , Public , and Friend access control specifiers later.

Reservation

When a customer books a reservation of a reservable, a record of the reservation will be made. The Reservation class holds the information that will be stored.

 Public MustInherit Class Reservation    Public ReservationId As Integer    Public UnitId As Integer    Public DateTime As DateTime    Public NumberDays As Integer    Private Shared m_nextReservationId As Integer = 1    Public Sub New()       ReservationId = m_nextReservationId       m_nextReservationId += 1    End Sub End Class 

The ReservationId is automatically generated by incrementing a shared member named m_nextReservationId , starting with the value 1. The UnitId member identifies the reservable that was booked. DateTime is the starting date of the reservation, and NumberDays specifies the number of days for which the reservation was made.

Broker

Our third abstraction, Broker , models a broker of any kind of reservable and is also represented by an abstract class. It maintains a list of reservables, represented by the array m_units , and a list of reservations, represented by the array m_reservations . The two-dimensional array m_numCust keeps track of the number of customers having a reservation at a given reservable on a given day.

 Public MustInherit Class Broker     Private m_maxDay As Integer     Private Const m_MAXRESERVATION As Integer = 10     Private Shared m_nextReservation As Integer = 0     Private Shared m_nextUnit As Integer = 0  Private m_numCust(,) As Integer   Protected m_reservations() As Reservation   Protected m_units() As Reservable  Public Sub New(_      ByVal MaxDay As Integer, _      ByVal MaxUnit As Integer)        m_maxDay = MaxDay        m_numCust = New Integer(MaxDay, MaxUnit) {}        m_units = New Reservable(MaxUnit) {}        m_reservations = _           New Reservation(m_MAXRESERVATION) {}     End Sub ... 
ReservationResult

A simple structure is used for returning the result from making a reservation.

 Public Structure ReservationResult    Public ReservationId As Integer    Public ReservationCost As Decimal    Public Rate As Decimal    Public Comment As String End Structure 

The Rate is the cost for one day, and ReservationCost is the total cost, which is equal to the number of days multiplied by the cost for one day. The ReservationId is returned as -1 if there was a problem, and an explanation of the problem is provided in the Comment field. This structure is created so that result information can be passed in distributed scenarios, such as Web services, where you cannot throw exceptions.

Base Class Logic

The base class Broker not only represents the abstraction of a broker of any kind of reservable, it also contains general logic for booking reservations and maintaining a list of reservations. Our ability to capture this logic abstractly gives power to this base class and will make implementing reservations in a derived class relatively simple.

Reserve

The core method of the Broker class is Reserve .

 Protected Function Reserve(_  ByRef res As Reservation) As ReservationResult    Dim unitid As Integer = res.UnitId    Dim dt As DateTime = res.DateTime    Dim numDays As Integer = res.NumberDays    Dim result As ReservationResult = _         New ReservationResult()    ' Check if dates are within supported range    Dim day As Integer = dt.DayOfYear - 1    If (day + numDays > m_maxDay) Then       result.ReservationId = -1       result.Comment = "Dates out of range"       Return result    End If    ' Check if rooms are available for all dates    Dim i As Integer    For i = day To day + numDays - 1       If m_numCust(i, unitid) >= _        m_units(unitid).Capacity Then          result.ReservationId = -1          result.Comment = "Room not available"          Return result       End If    Next    ' Reserve a room for requested dates    For i = day To day + numDays - 1       m_numCust(i, unitid) += 1    Next    ' Add res to reservation list and return result    AddReservation(res)    result.ReservationId = res.ReservationId    result.ReservationCost = _       m_units(unitid).Cost * numDays    result.Rate = m_units(unitid).Cost    result.Comment = "OK"    Return result End Function 

The Reserve method is designed to implement booking several different kinds of reservations. Thus the Reservation object, which will be stored in the list of reservations, is created in a more specialized class derived from Broker and is passed as a parameter to Reserve . For example, a HotelBroker will book a HotelReservation , and so on. The UnitId , DateTime , and NumberDays fields are extracted from the Reservation object, and a ReservationResult object is created that is returned.

 Protected Function Reserve(_  ByRef res As Reservation) As ReservationResult    Dim unitid As Integer = res.UnitId    Dim dt As DateTime = res.DateTime    Dim numDays As Integer = res.NumberDays    Dim result As ReservationResult = _       New ReservationResult()    ... 

Next we check that all the dates requested for the reservation are within the supported range (which for simplicity we are taking as a single year). We make use of the DateTime structure from the System namespace. We return an error if a date lies out of range.

 ' Check if dates are within supported range Dim day As Integer = dt.DayOfYear - 1 If (day + numDays > m_maxDay) Then    result.ReservationId = -1    result.Comment = "Dates out of range"    Return result End If  ... 

Now we check that space is available for each date, using the m_numCust array that tracks how many customers currently have reservations for each day and comparing against the capacity. The first dimension of this two-dimensional array indexes on days, and the second dimension indexes on the unit ID. (Note that for simplicity we have given our fields and methods names suitable for our initial application, a HotelBroker .)

 ' Check if rooms are available for all dates Dim i As Integer For i = day To day + numDays - 1    If m_numCust(i, unitid) >= _     m_units(unitid).Capacity Then       result.ReservationId = -1       result.Comment = "Room not available"       Return result    End If Next ... 

Next, we actually reserve the unit for the requested days, which is implemented by incrementing the customer count in m_numCust for each day.

 ' Reserve a room for requested dates For i = day To day + numDays - 1    m_numCust(i, unitid) += 1 Next  ... 

Finally, we add the reservation to the list of reservations and return the result.

 ' Add res to reservation list and return result    AddReservation(res)    result.ReservationId = res.ReservationId    result.ReservationCost = _       m_units(unitid).Cost * numDays    result.Rate = m_units(unitid).Cost    result.Comment = "OK"    Return result End Function 
Lists of Reservations and Reservables

The Broker class also maintains lists of Reservation and Reservable objects. For our simple array implementation, we only implement methods for adding elements. In a later version, we will provide logic to add and remove elements from lists.

 Private Sub AddReservation(ByRef res As Reservation)    m_reservations(m_nextReservation) = res    m_nextReservation += 1 End Sub Protected Sub AddUnit(ByRef unit As Reservable)    m_units(m_nextUnit) = unit    m_nextUnit += 1 End Sub 

Designing the Encapsulation

In our current implementation of Broker all lists are represented by arrays. Since this implementation may not (and in fact will not) be preserved in later versions, we do not want to expose the arrays themselves or the subscripts that are used for manipulating the arrays. We provide public properties NumberUnits and NumberReservations to provide read-only access to the private variables m_nextUnit and m_nextReservation .

 Public ReadOnly Property NumberUnits() As Integer    Get       Return m_nextUnit    End Get End Property Public ReadOnly Property NumberReservations() _  As Integer    Get       Return m_nextReservation    End Get End Property 

In our Reservation class the simple fields ReservationId , UnitId , DateTime , and NumberDays are not likely to undergo a change in representation, so we do not encapsulate them. Later, if necessary, we could change some of these to properties without breaking client code. For now, and likely forever, we simply use public fields.

 Public MustInherit Class Reservation    Public ReservationId As Integer    Public UnitId As Integer    Public DateTime As DateTime    Public NumberDays As Integer    ... 

Team-Fly    
Top
 


Application Development Using Visual BasicR and .NET
Application Development Using Visual BasicR and .NET
ISBN: N/A
EAN: N/A
Year: 2002
Pages: 190

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net