Download Object-Oriented Analysis and Design: Classes, Objects, Identity, and Equality and more Thesis Object Oriented Analysis and Design in PDF only on Docsity!
Lecture Notes in
O BJECT -ORIENTED
A NALYSIS AND D ESIGN
Walid S. Saba
School of Computer Science
University of Windsor
Copyright 1999, 2000 Walid S. Saba
CS-322 Lecture Notes
OBJECT-ORIENTED A NALYSIS
AND DESIGN
Accompanying Material
- Object-Oriented Design Heuristics, Arthur Riel, Addison Wesley
- UML specification (any source is fine)
Other Recommended Material
- Design Patterns, Gamma et al.
- Object-Oriented Analysis and Design, Grady Booch, Benjamin Cummings.
- Introduction to Object-Oriented Software Engineering (Ivar Jacbson et al.)
NOTES
- Do not use object-oriented programming languages books (such as C++, CLOS/Scheme, Java or Smalltalk) as your introduction to object-oriented analysis and design since they typically introduce concepts from the vantage point of a single language while these concepts should be understood independent of any language. The only exception here (that I am aware of) is Coplien’s book (Advanced C++ Porgramming Syles and Idioms). This book reflects Coplien’s rich experience in theory and practical SW development on large scale projects at Bell Labs. He also discusses C++ and OOP in the larger context of how to deal with situations where symbolic or applicative/functional programming seems to be superior.
- The best way to learn OO analysis and design is to work in groups on trying to come up with a design for some real-life problem. The discussions (some sessions might go beyond ‘discussions’) you will have when deciding on the key abstractions, on the object model, on the various relationships, or on the various positions of centralized vs. distributed control will teach you more on what OO analysis and design involves than you might first realize. Make up some groups and work on different designs. I am willing to referee.
Walid S. Saba
School of Computer Science
University of Windsor
Introduction
Designing software for large applications is a very complex task. It could arguably be said that there is no limit to how complex software design could get. The reason for this is that we generally design software to model some real-world phenomenon. The more realistic we aim to make our model the more complex the design, since in general real-world phenomena can be very complex. Take, for example, the modeling of activities on the stock market. To accurately represent all the parameters (variables) that might affect the behavior of a certain stock a system must take into account various statistical data (trends), as well as a complicated set of interrelationships between various pieces of data (for example, political instability in the middle east might affect the price of oil, which in turn might affect the inflation rate, which again, incidentally, might affect the price of oil.) How can such complex relationships be modeled? There are several reasons for the complexity here. The main source of the complexity in the modeling of the stock market is the fact that this model involves two distinct set of rules: (i) a set of analytic rules that can be well specified by expert actuaries and statisticians; and (ii) a set of commonsense rules and a number of heuristics that represent the ”knowledge” of some experts. One challenge here is how to ultimately separate these two distinct sets of rules in the software, since the latter is a very dynamic set that could change on a daily basis.
If modeling the stock market is not complex enough, imagine the complexities involved in modeling the cognitive and reasoning capabilities of humans in building intelligent machines. Researchers in artificial intelligence (AI) are trying to emulate human perceptual, language, and reasoning capabilities. In addition to the conceptual breakthroughs, there are various computational challenges that arise when building such systems.
The fact that the logic of some applications can be very complex is one source of complexity in software design. The other source of complexity comes from the fact that software in the end is executed on machines and thus applications must be written with a computational environment in mind. While some of the constraints of the computational environment are not (and should not be) considered at the analysis phase, time and memory constraints, as well as issues that relate to concurrency, whether the system needs to be dynamic or static, add another level of complexity.
The point of all of this is that building large applications is a complex task and like engineers in other disciplines, software engineers need a good set of tools that can aid the analysis, the design and ultimately the implementation process. Indeed, over the years a number of programming tools, languages and paradigms where suggested. The aim of each paradigm was to help improve on one or more of the following:
- Rapid application development (RAD)
- Maintainability
- Performance
- Reuse
Among these, the most visible improvement is in the number of RAD tools that exist today. However, in many cases the tradeoff in using these tools is in performance
KNOW THE TECHNOLOGY
- As a software engineer, how do you make a case for a certain
technology, T?
Must say, T can help us … as opposed to, T …
build re-usable code supports inheritance build highly maintainable code supports data abstraction build concise and well-structured code is polymorphic, has templates build cross platform software compiles to a virtual machine modify online systems is dynamic build efficient code is multi-threaded in RAD and prototyping is high-level, is declarative ? is strongly-typed ? is reflective ? is higher-order etc. etc.
- A manager might not care if a certain language is dynamic, but you
should, if you had to build a system the behavior (logic) of which
might have to be updated at run-time.
- If you can not describe a feature (say, inheritance, polymorphism,
etc.) without any reference to a specific programming language, then
you probably do not fully understand (appreciate the value of) this
feature.
ANALYSIS VS. DESIGN
- S/W construction is an iterative process.
- The analysis and design tasks are not different, except for the level
of detail. This view minimizes the gap between “what” the system
must do and “how” it is done!
- Thus, analysis and design are best thought of as two special states in
a continuum.
- In the early stages we should pay little attention to implementation
details. The final stage (final design) should be “the realization of the
model within a certain (computing) environment.”
- In general the model at leveln should be more stable than the model
at leveln+1. For example, early analysis is not so sensitive to change
as a detailed design would be if the programming language, database
or other environmental variables changed.
1
2 3
4 5
1
2
4
3
5
Maintena nce
Testing
Coding
Design
Analysis
W HY DIFFERENT PROGRAMMING PARADIGMS?
- Different paradigms interpret the ‘program=data+control’
equation differently.
- Some paradigms try to achieve re-use by building re-usable
data objects, some by building re-usable modules.
- program = data + control (logic)
⇒ generic (program) = generic (data + logic)
Therefore, to build generic (re-usable) programs we can
generalize the data, the control, or, of course, both.
- Generic data objects are attained via data abstraction
Generic modules are attained via functional abstraction
data control / logic
program = data + control
W HAT’ S NEW IN THE OO PARADIGM?
- The procedural, functional, logic, etc programming
paradigms differ substantially in how control is attained:
function composition, procedure calls, rule-chaining, etc.
(they also differ in whether or not they are: strongly-typed,
high-order, reflective, static/dynamic, polymorphic,
lazy/strict, multithreaded, etc.)
- BUT, as far as the general philosophy of program design,
they all belong to the same class, i.e., they are all control-
centric (as opposed to data-centric)
- In the OO paradigm we structure our programs around data
objects and control (intelligence) is distributed as a set of
services that each data object promises to provide.
program
data control
messages functions procedures rules triggers
Obj 1 Obj 2
Obj 4 Obj 3
f ( )
g ( )
g ( ) f ( )
mainFunc ( )
and
or
S O WHAT IS THE S OFTWARE CRISIS?
- RAD (Rapid Application Development)
¾ Most programming paradigms emphasize the ease of
software development
¾ This technology has advanced tremendously (we can now
develop a prototype within hours and with minimal amount of
coding.)
¾ S/W Maintenance is more costly than S/W development!
¾ Maximizing cohesion of and minimizing coupling between
modules is the key to building highly maintainable code
¾ Different paradigms approach this problem in various ways.
¾ Design block-box modules (software chips?)
¾ Can we ever build generic (re-usable) business objects?
¾ Is there more hope in building generic (re-usable) functions?
T HE OBJECT-ORIENTED DESIGN P HILOSOPHY
- OO is NOT about polymorphism, encapsulation, inheritance,
etc. OO is a new strategy for distributing intelligence across
the system so as to maximize cohesion and minimize
coupling!
By distributing intelligence across the system in a data-centric fashion, we implicitly build highly cohesive (& thus re-usable) modules, without introducing unnecessary coupling.
- The question now is how do we best distribute
intelligence across the system? This is the object- oriented design problem!!!
T HE OBJECT-ORIENTED DESIGN P HILOSOPHY
- In structured programming there is a centralized control.
‘main’ controls the sequencing (and the control flow) and
owns all external and global data/information.
- In OOP, there is no centralized control. Ideally, all objects
are created equal and control is an interaction between
objects that collaborate to achieve a certain functionality.
- A First Example. An ATM machine.
Main()
while ( true )
acctNo = getAcctNo();
pinNo = getPIN();
if ( notValid(pinNo,acctNo) ) exit(CODE);
case (choice) of
1: deposit(amt,acctNo);
2: withdraw(amt,acctNo);
3: return checkBalance(acctNo);
void withdraw(amt,acctNo)
b = checkBalance(acctNo);
if ( b >= amt )
updateBalance(SUB,amt,acctNo);
giveMoney(amt);
E XERCISES FOR PART I
- A typical telecom company has many systems, some real-time
telephony systems that automate dialing, switching, etc. and some
backend systems that are used for network management, etc. In the
former performance is the main requirement, while in the latter it is
not as crucial. What kind of design tradeoffs you think the designers
of these systems have to make?
- Suggest examples where a dynamic environment is more suitable
than a static (compiled) environment.
- Discuss the tradeoff between maintainability and performance.
Think of the two extremes (say assembly languagevs. very high-level
declarative languages.)
- Give examples of details that should not be discussed in the analysis
phase, but should be left to design. Why?
- Should a programming language or the computing environment be
taken into consideration when in the design phase? Why, or why not?
- What makes the maintenance problem so critical? Is that what the
‘software crisis’ is? Or is development the main challenge? Discuss in
relation to very complex systems.
- Any program satisfies ‘program=control+data’. To build generic
programs, therefore, we can generalize the data, control (functions),
or both. Which of the two (data and control) is easier to generalize?
Discuss and give some examples of business objects and rules/logic.
- What are good examples of generic data objects that are used
everyday by software developers. What are good examples of generic
modules (functions)?
E XERCISES FOR PART I (CONT’ D )
- Define/describe without referring to any specific programming
language, and discuss with examples the advantages of each of
the following:
- Inheritance - polymorphism
- data abstraction - higher-order
- reflection
- How is the object-oriented paradigm different from all the other
paradigms with respect to program design? Discuss.
- In the SW life cycle, programming paradigms often make promises
regarding ease of development (RAD), and/or maintainability. Which
paradigms facilitate RAD and which make promises regarding
maintainability? In your opinion, where is the real problem in SW
engineering, and where do you think OO stands on that?
- What is ‘traceability’? How is it related to maintainability?
- What are multi-tier architectures? Why are they useful? How is all of
this related to maintainability and re-use?
- The main idea behind OO is a better distribution of logic across the
system to minimize coupling and maximize cohesion. This produces
highly maintainable and re-usable code. How is that? Discuss.
- How do structured (procedural) programs lend themselves to
centralized control while object-oriented programs are more easily
constructed with distributed control? How does that relate to
coupling, cohesion, and maintainability?
- Describe the data abstractions and functional abstractions that are
needed to write a sort function that sorts data of any type and in any
order. (can this be achieved with one kind of abstraction only?)
FOUNDATIONS OF THE OBJECT MODEL
Abstract Data Types (ADT)
- The basic idea is to design a data structure with a certain expected
behavior the details of which are hidden from its users.
- For example, a Stack object might be implemented in so many ways,
as an array, a list, etc. All users need to know is that the operations
they expect, namely Push(), Pop(),isEmpty()and isFull()are supported
and they behave as expected.
Information Hiding (Encapsulation)
- Users of a class should not be concerned with internal representation
of data members or implementation details of services. If any of
these have changed, users of the class should not be effected.
O N HIDING D ETAILS ….
Can you provide the services/behavior of a queue if you only had stacks?
class myQueue {
private: Stack stack1; private: Stack stack2;
Push(Object e) { if ( not stack1.isFull() ) { stack1.Push(e); return; } else CAN-NOT-ADD-ELEMENTS-TO-QUEUE; } Object Pop() { if ( not stack2.isEmpty() ) { return stack2.Pop(); } if ( stack1.isEmpty() ) { return QUEUE-EMPTY; } while ( (not stack1.isEmpty()) && (not stack2.isFull()) ) { stack2.Push( stack1.Pop() ); } stack2.Pop(); } Boolean IsEmpty() { return stack1.isEmpty(); } Boolean IsFull() { return stack2.isFull(); } }
T HE BUILDING BLOCKS OF THE OBJECT MODEL
A class is a data abstraction of some concept/entity (physical or
abstract). The abstraction is meant to capture the characteristics
(properties/attributes) and behavior common to all instances of the
class. For example, all ‘cars’ in the real world could be modeled by
the following data abstraction:
All cars have a make, a model, a year of make and a color. Also, we must be able to Start(), Drive(), ChangeSpeed(), Brake(), and Stop() all cars.
Car Make Model Year Color Start() Drive() ChangeSpeed() Brake()