880 likes | 1.19k Views
Object-Oriented Design. Lesson #13. Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised by M. Deek. Activities in Software Development. Problem Analysis Solution Design Coding Documenting Testing Maintenance. Strategy.
E N D
Object-Oriented Design Lesson #13 Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised by M. Deek
Activities in Software Development • Problem Analysis • Solution Design • Coding • Documenting • Testing • Maintenance
Strategy • One basic way to deal with complexity: Divide and Conquer. • Systems can be divided into modules (Objects or Classes). • The challenge is to ensure effective communication between different parts of the program without destroying the divisions.
Objectives • We are concerned with producing software that satisfies user requirements. • The primary means to do so is to produce software with a clean internal structure.
The Tasks of OO Design We need to specify: • The needed classes • The public interface • The protected interface
The Need for a Clean Internal Structure To simplify: • Testing • Porting • Maintenance • Extension • Re-organization • Understanding
Characteristics of Successful Software It has an extended life where it might be: • worked on by a succession of programmers and designers • ported to new hardware • adapted to unanticipated uses
The Development Cycle • Create an overall design • Find standard components and then customize the components for this design. • Create new standard components and then customize the components for this design. • Assemble design.
Design for Change • The system must be designed to remain as simple as possible under a sequence of changes. • Aim for: • flexibility • extensibility • portability • OOD can support the above.
Design Steps of OOD • Find the Concepts/Classes and their fundamental relationships. • Refine the Classes by specifying the sets of Operations on them • classify these operations: constructors, destructors, etc. • consider minimalism, completeness, and convenience
Design Steps • Refine the classes by specifying their dependencies on other classes: • Inheritance • Use dependencies • Specify the interfaces for the classes: • separate functions into public and protected operations • specify the exact type of the operations on the classes.
Finding Classes • Good design must capture and model some aspects of reality. • Look at the application rather than the abstractions. • Usually nouns correspond to classes and verbs represent functions.
Example • When ordering new videotapes from a supplier, the store manager creates a purchase order, fills in the date, the supplier’s name , address, and enters a list ofvideotapes to be ordered. The purchase order is added to a permanent list of purchases. When one or more video tapes are received from a supplier, a clerk locates the original purchase order and makes a record of each tape that was received. A record of the videotape is then added to the store’s inventory. When all tapes listed on a particular purchase order have been received, the manager sends a payment to the supplier and the purchase order is given a completion date.
Specifying operations • Consider how an object of the class is constructed, copied, and destroyed. • Define the minimal set of operations required by the concept the class is representing. • Consider which operations could be added for notational convenience and include only important ones.
Specifying Operations • Consider which operations are to be virtual. • Consider what commonality of naming and functionality can be achieved across all the classes of the component.
Operations on a Class • Foundation: • Constructors, destructors, and copy operators • Selectors: • Operations that do not modify the state of an object. • Modifiers: • Operations that modify the state of an object.
Operations on a Class • Conversion Operators: • Operations that produce an object of another type based on the value (state) of the object to which they are applied. • Iterators: • Operations that process data members containing collections of objects.
Specifying Dependencies • The key dependencies to consider in the context of design are inheritance and use relationships. • Overuse can lead to inefficient and incomprehensible designs.
Specifying Interfaces • Private functions are not considered at this stage. • The interface should be implementation independent (more than one implementation should be possible). • All operators in a class should support the same level of abstraction.
Reorganizing the Class Hierarchy • Typically, initial organization of classes may not be adequate and therefore, may have to be reorganize to improve the design and/or implementation. • The two most common reorganizations of a class hierarchy are: • factoring of two classes into a new class. • splitting a class into two new ones.
Use of Models • Whenever possible, design and programming should be based on previous work. • This allows the designer to focus on a the important issues at any given time.
Experimentation and Analysis • Prototyping is frequently used for experimenting. • Different aspects of a system may be prototyped independently, such as the graphical user interface. • Analysis of a design and/or implementation can be an important source of insight.
Example:Doctor’s office scheduling • Specification: • The program allows to schedule appointments for patients. • The office has multiple doctors, each with a daily schedule divided into 15-minute appointment slots beginning from 8:00am to 6:00pm. • We also want to print out separate daily schedules for each doctor, listing the time and patient name of each appointment. • All output directed to the screen, except for the doctors’ schedules, which will be written to a file for later printing. • For simplicity: Each doctor has only one appointment day.
Analysis • Finding classes: • Doctor • Patient • DailySchedule • Appointment • Scheduler (Interface to the user)
Scenario of the process • Scheduler requests the patient’s name; • Patient chooses a doctor; • Scheduler displays doctor’s schedule, showing available appointment slots; • Patient requests the specific slot; • Scheduler adds the appointment to the doctor’s schedule, and adds the appointment to the patient’s record; • Scheduler confirms the appointment.
Class dependencies Scheduler Fstring(LastName) Patient Doctor Fstring(FirstName) DailySchedule Appointment :composite(contains) :link(requests, send messages)
Operations • Doctor 1. AddToSchedule: Add an appt. to the Dr’s Sch. 2. ShowAppointment:Display the sch • Patient 1.InputName: 2.ChooseDoctor: 3.ChooseTimeSlot: 4.SetAppointment: Schedule an Appt.
Operations • DailySchedule 1.SetAppointment: Add an appt to the sch. 2.IsTimeSlotFree:Find out if a particular slot is available 3.ShowAppointments: Display the schd appt • Appointment 1.Constructor: 2.IsScheduled: Find out if an appt schd for the current Appt • Scheduler 1.ScheduleOneAppointment: p-appt-d 2.ScheduleAllAppointments:input p, request d, update d 3.PrintAllAppointment: print all the schd appt for all Ds
Additional Classes • TimeSlot: • Handles the translation and formatting of appointment times. • FString: • Deals with string data members.
The TimeSlot class class TimeSlot { public: TimeSlot( const unsigned n = 0 ); unsigned AsInteger() const; friend istream & operator >>(istream & inp, TimeSlot & T); friend ostream & operator <<(ostream & os, const TimeSlot & T); private: static unsigned StartHour; static unsigned ApptLen; unsigned intValue; };
The Appointment class class Appointment { public: Appointment(); Appointment ( const TimeSlot & aTime, unsigned docNum, const Patient & P); const FString & GetPatientName() const; const TimeSlot & GetTime() const; int IsScheduled() const; void SetTime( const unsigned n ); friend ostream & operator <<( ostream & os,const Appointment & A ); private: enum { NoDoctor = 9999 }; unsigned doctorNum; TimeSlot timeSlot; FString patientName; };
The Patient class class Patient { public: Patient(); void InputName(); unsigned ChooseDoctor() const; TimeSlot ChooseTimeSlot(const Doctor & D) const; const Appointment & GetAppointment() const; const FString & GetFirstName() const; const FString & GetLastName() const; int IsScheduled() const; void SetAppointment( const Appointment & A ); friend ostream & operator <<( ostream & os, const Patient & P ); private: FString lastName; FString firstName; Appointment nextVisit; };
The DailySchedule class class DailySchedule { public: DailySchedule(); int IsTimeSlotFree( const TimeSlot & T ) const; void SetAppointment( const Appointment & A ); void ShowAppointments( ostream & os ) const; friend ostream & operator <<( ostream & os, const DailySchedule & DS ); private: enum { MaxTimeSlots = 40 }; Appointment appointments[MaxTimeSlots]; };
The Doctor class class Doctor { public: Doctor(); int AddToSchedule( const Appointment & A ); const DailySchedule & GetSchedule() const; void SetId( const unsigned ); void SetLastName( const FString & L ); const FString & GetLastName() const; void ShowAppointments( ostream & ) const; static const FString & GetDoctorName( unsigned index ); static void SetDoctorName(unsigned, const FString & nam); private: unsigned id; FString lastName; DailySchedule schedule; static FString doctorName[NumDoctors]; };
The Scheduler class class Scheduler { public: Scheduler( Doctor * docs ); void PrintAllAppointments( const char * fileName); int ScheduleOneAppointment(); void ScheduleAllAppointments(); private: Doctor * doctors; };
The main Program #include "doctors.h" static Doctor doctorArray[NumDoctors]; int main() { cout << "Doctors Office Scheduling Program\n\n"; Scheduler officeSchedule( doctorArray ); officeSchedule.ScheduleAllAppointments(); officeSchedule.PrintAllAppointments( "appts.txt" ); return 0; }
The Implementation • The Time Slot • h : hour value • sa: the starting appointment time • aph: appointments per hour • m: minute value • al: the appointment length in minutes timeslot = (h-sa)*aph+m/al E.g: timeslot = (12-8)*4+20/15=17 The 17th slot.
The TimeSlot class unsigned TimeSlot::StartHour = 8; unsigned TimeSlot::ApptLen = 15; istream & operator >>( istream & inp, TimeSlot & T ) { char buf[20]; inp.getline( buf, 20 ); // get a line of input istrstream aStream( buf, 20 ); unsigned h, m; char ch; aStream >> dec >> h >> ch >> m; unsigned aph = 60 / TimeSlot::ApptLen; if( h < T.StartHour ) // afternoon hour? h += 12; // add 12 to hours T.intValue = ((h - TimeSlot::StartHour)* aph) + (m / TimeSlot::ApptLen); return inp; }
The TimeSlot class ostream & operator <<( ostream & os, const TimeSlot & T ) { unsigned aph = 60 / T.ApptLen; // 4 = 60 / 15 unsigned h = (T.intValue / aph ) + T.StartHour; // (S / 4) + 8 unsigned m = (T.intValue % aph ) * T.ApptLen; // (S % 4) * 15 char oldfill = os.fill('0'); os << setw(2) << h << ':' << setw(2) << m; os.fill( oldfill ); return os; }
The Appointment class Appointment::Appointment ( const TimeSlot & aTime, unsigned docNum, const Patient & aPatient ) { timeSlot = aTime; doctorNum = docNum; patientName = aPatient.GetLastName(); patientName.Append( ", " ); patientName.Append( aPatient.GetFirstName() ); }
The Appointment class ostream & operator <<( ostream & os, const Appointment & A ) { os << "Dr. " << Doctor::GetDoctorName(A.doctorNum) << ", " << "Time: " << A.timeSlot; return os; }
The Patient class void Patient::InputName() { cout << "Patient's last name: "; cin >> lastName; cout << "Patient's first name: "; cin >> firstName; }
The Patient class unsigned Patient::ChooseDoctor() const { for(unsigned i = 0; i < NumDoctors; i++) cout << i << ": " << Doctor::GetDoctorName(i) << '\n'; unsigned n = 0; int ok = 0; do { cout << "Enter a doctor number: "; cin >> n; cin.ignore(255,'\n'); if( n >= NumDoctors ) cout << "Number out of range!\n"; else ok = 1; } while( !ok ); return n; }
The Patient class TimeSlot Patient::ChooseTimeSlot( const Doctor & D ) const { cout << '\n' << "Daily Schedule of Dr. " << D.GetLastName() << '\n' << "........................................" << '\n' << D.GetSchedule() << '\n' << "Enter a time (format hh:mm): "; TimeSlot aSlot; cin >> aSlot; return aSlot; }
The Patient class ostream & operator <<( ostream & os, const Patient & P ) { os << "Patient " << P.firstName << ' ' << P.lastName << '\n' << "has been scheduled as follows:" << '\n' << P.nextVisit << endl; return os; }
The DailySchedule class DailySchedule::DailySchedule() { for(unsigned i = 0; i < MaxTimeSlots; i++) appointments[i].SetTime( i ); } int DailySchedule::IsTimeSlotFree( const TimeSlot & aTime ) const { unsigned n = aTime.AsInteger(); return !appointments[n].IsScheduled(); } void DailySchedule::SetAppointment( const Appointment & app ) { unsigned n = app.GetTime().AsInteger(); appointments[n] = app; }
The DailySchedule class void DailySchedule::ShowAppointments( ostream & os ) const { for(unsigned i = 0; i < MaxTimeSlots; i++) { if( appointments[i].IsScheduled()) os << appointments[i].GetTime() << " " << appointments[i].GetPatientName() << endl; } }
The DailySchedule class ostream & operator <<( ostream & os, const DailySchedule & DS ) { for(unsigned i = 0; i < DS.MaxTimeSlots; i++) { os << DS.appointments[i].GetTime(); if( DS.appointments[i].IsScheduled()) os << " *** "; else os << " "; if( i % 4 == 3 ) os << '\n'; } return os; }
The Doctor class FString Doctor::doctorName[NumDoctors]; //Static member. Doctor::Doctor() { id = 0;} int Doctor::AddToSchedule( const Appointment & app ) { if( schedule.IsTimeSlotFree( app.GetTime())) { schedule.SetAppointment( app ); return 1; } return 0; }
The Doctor class void Doctor::ShowAppointments( ostream & os ) const { os << "Appointments for Dr. " << lastName << '\n' << ".................................." << '\n'; schedule.ShowAppointments( os ); os << endl; }//cis601source/chap5/doctors/