The following are the notes from Object Oriented Analysis and Design 3rd edition.
The physical building
block of a programming language is a module which consists of a logical
collection of classes and objects. If procedures and functions are verbs and
data is noun, object-oriented program is organized around noun. Thus, medium
software applications look like graph with minimum global data.
A complex system consists of clusters of abstraction consisting of classes, objects and modules built on top of each other. At each layer objects are collaborating to deliver high level behavior. Inside each cluster, yet another set of cooperative abstractions can be found.
Object oriented
programming is a method of implementation where modules consist of a set of collaborating
objects (“part of”) to deliver higher behavior; each object is based on a class
(“is a”) which might be a member of a hierarchy of classes.
Objects have
integrity that cannot be violated. in other words, object’s invariant property
cannot be altered. For example, an elevator can travel up and down.
Object oriented analysis focuses on the building real world models from object-oriented view of the world by examining the requirements to identify classes and objects in the vocabulary of the problem domain. The models will be the input for object-oriented design whose output will be blueprint for implementing the application using object-oriented programming languages.
Elements of the Object
Model
- Abstraction
- Encapsulation
- Modularity
- Hierarchy
- Type
- Concurrency
- Persistence
Abstraction
Abstraction is
the fundamental way to cope with the complexity.
Abstraction means
identifying and focusing on similarities between objects, processes and
situations in problem domain ignoring differences for time being. A concept is
called abstraction only if it can be described, understood and analyzed
independently of the mechanism that will be used to realize it. An abstraction denotes
essential characteristics of the object and provides crisply defined conceptual
boundaries from other objects focusing only on the perspective of the viewer.
Abstraction
focusses only on outside view of its behavior so serves to separate an objects
essential behavior from its implementation.
Deciding on the right set of abstractions for a given domain is the central problem in object-oriented design.
|
Abstraction Type |
Description |
|
Entity abstraction |
An object that represents a useful model of a problem domain or
solution domain entity |
|
Action abstraction |
An object that provides a generalized set of operations, all of
which perform the same kind of function |
|
Virtual machine abstraction |
An object that groups operations that are all used by some
superior level of control, or operations that all use some junior-level
set of operations |
|
Coincidental abstraction |
An object that packages a set of operations that have no relation
to each other |
In abstractions,
state invariants should be preserved pre and post operation. All abstractions
have static and dynamic properties.
No object stands
alone; they collaborate with others to achieve higher behavior. The design decisions
decide boundaries, behaviors and protocols of each object.
Encapsulation
Abstraction
should precede implementation and implementation details should be hidden from
clients.
Abstraction and
encapsulation are complimentary. Encapsulation is achieved through information
hiding apart from data hiding. Information hiding is the process of hiding non-essential
characteristics of an object.
By providing
explicit barriers to abstractions, encapsulation ensures clear separation of concerns.
For abstraction
to work in a class, its implementation should be encapsulated. In other words,
a class should have two parts – an interface and implementation.
Abstraction is
comprised of only outside view of a class common to all instances whereas
implementation includes both abstraction and its implementation.
Modularization
Dividing a program
into components attempts to reduce its complexity and also creates well defined
and documented boundaries within the program. Modules comprises of a set of
classes thus are multiple abstractions, to create an application’s physical
architecture. In a large application comprising of hundreds of classes, modules
are necessary.
Modularization
means dividing an application into multiple modules that can be compiled
separately but modules will have interconnections.
Modules serve as physical containers of
classes and objects of our logical design.
The goal of modular
decomposition is to save cost where each module can be designed and revised
independently such that it will not alter the abstraction upon which other
modules are dependent. The cost of compiling a single module is less but the
cost is high if its abstraction is changed as it will affect dependent module
as well.
In other words,
modules should be cohesive by grouping logically related abstraction and loosely
coupled by reducing inter module dependency. The concepts of abstraction,
encapsulation and modularity are synergistic.
Hierarchy
Often
abstractions form hierarchy. Identifying these greatly during design simplifies
understanding the problem domain. Hierarchy is basically ranking or ranking of
abstractions.
Single Inheritance
Inheritance
implies a generalization / specialization of hierarchy where derived classes
inherit structures and behavior of base classes and often redefines certain
behaviors. The litmus test is if the class
B is not type of class A, it should not inherit from class A.
Base classes are generalized abstraction and
derived classes are specialization where members of the base classes are added,
modified, and hidden. Therefore ignoring “is a” hierarchy leads to inelegant
and bloated designs.
There is a
healthy tension between abstraction, encapsulation and hierarchy. Abstraction
creates an opaque barrier where data and methods are hidden; inheritance tries
to open this interface and may allow accessing these without abstraction. Thus, for a class there are two kinds of
clints – an external object consuming its methods or its derived class.
Inheritance can
violate encapsulation in three ways – access base class’s fields or methods,
access base class’s base class directly. In C++ access to base class’s member
in its derived class can be configured flexibly.
Multiple Inheritance
Multiple
inheritance is the better way to express abstractions to eliminate redundancy.
For example, two standalone base classes are created to capture unique
properties of flowering plants as well as fruits and vegetables. These are
called mixin classes as they are used to create derived classes by mixing
together.
The Rose Class,
Which Inherits from Multiple base classes
The Carrot Class, Which Inherits from Multiple base classes
The CherryTree
Class, Which Inherits from Multiple Base classes
Multiple inheritance is straight forward but it introduces two practical problems:
- Clash when the same names are used for methods and fields in multiple base classes.
- Repeated inheritance of same base class where the inheritance lattice will be diamond shaped.
The Repeated Inheritance Problem
Aggregation
In case of “is a”
hierarchy, higher level abstraction is generalized and lower-level abstraction
is specialized. Example, Flower class is at higher level of abstraction than
the plant class. Similarly, in “part of” hierarchy, a class is at higher level
of abstraction than the classes that makes it up its implementation. Example, Garden
is at higher level than plants.
Aggregation
introduces issues of ownership and lifetime. For example, when a car’s tires
are changed, car’s identity is not changed. Similarly, when a car is recycled
its tires are removed so that their lifetimes are not tied or tires can exist
independent of the car. Whereas, lifetime of the chassis of the car is tied to
it. In other words, chassis cannot exist independent of the car.
Typing
Typing lets
expression of abstractions such that the programming used for implementation
can make design decisions. A programming language can be strongly typed, weakly
typed or even untyped. The idea of conformance is central to the notion of
typing. In strong typed languages may
allow only certain combination of abstractions. In other words, strong typing restricts
mixing of abstractions. However strong typing introduces semantic restrictions
where single change in the base class require recompilation of the derived
classes.
- Without type checking most application would crash
- Better documentation
- Better code generation
- Value of type in Safety offered is more than flexibility from untyped languages
Polymorphism is a
concept where dynamic binding and inheritance meet. In C++, polymorphism enables
the methods decorated as virtual in derived classes to override base class
implementation of the same method. It uses vtables to achieve it.
Opposite of polymorphism
is monomorphism. Polymorphism is central to object-oriented design.
Concurrency
A multithreaded
application suffers from livelock, deadlock, thread starvation mutual exclusion
and race condition. Concurrency can be avoided by hiding it in reusable
abstraction in most cases.
While Object
oriented programming focusses on data abstraction, encapsulation and inheritance,
concurrency focusses on process abstraction and concurrency. An object concept
unifies two viewpoints: an object drawn from abstraction of the real-world acts
as a thread control (process abstraction.) such objects are called as active objects.
Thus, world can
be viewed as set of cooperative objects where some of them are active and serve
as center of independent activity. Concurrency is the property that distinguishes
active from non-active.
Once concurrency
is introduced, key point is how two active objects synchronize with each other
as well as sequential objects. For example, when two objects are sending
message to a third object concurrency ensures mutual exclusion such that the
state of the object is not corrupted.
This is where
ideas of concurrency, abstraction, encapsulation interact. The semantics of
defined methods should be preserved in presence of multiple threads of control.
The synergy
between objects and concurrency leads to concurrent object-oriented programming
languages.
Persistence
An object takes
certain amount of space and lives for certain about of time. The duration can
vary from transitionary in an expression to durable in a database.
This spectrum of
object persistence encompasses the following:
■ Transient results in expression evaluation
The first three
are addressed by programming languages and the last three are the domain of the
database that can lead to clash of cultures. There is also a hybrid model such
as ADO.NET where an application can stay disconnected from database.
The synergy
between object-oriented programming and persistence leads to object-oriented
databases. These are based on exiting database technologies such as relational
database but provide object-oriented interface through which database queries
are performed in terms of objects whose lifetime transcend its application’s
life time. This allows same design methods to database and non-database
segments of an applications. EJB and ORM software support object-oriented
databases.
Persistence saves the state and class of an object across time or space.
Persistency is
the characteristic of an object where it transcends time (i.e., it continues to
live after its host application terminates) and/or space (i.e., moves to
another address space on the same machine or different machine).
Benefits of object model
First, the object
model helps exploit the expressive power of object-oriented languages. Significant
improvement in productivity and code quality has been achieved by applying data
abstraction where it’s needed. Further improvements are achieved by using
inheritance. Therefore, without using the elements of the object model, the
powerful features of the object-oriented language are ignored or misused.
Second, the
object model enables reuse of the software but also entire designs leading to
creation of software frameworks. Thus, the code in object-oriented model will
be less than non-object-oriented model.
Third, object
model creates systems that are based on stable intermediate stable forms that
are resilient to changes. Thus, they evolve over time instead of abandoned or
completely redesigned when major changes are needed.
Finally, object
mode appeals to human cognition.
Summary
■ The maturation of software engineering has led to the development of object-oriented analysis, design, and programming methods, all of which address the issues of programming-in-the-large.
No comments:
Post a Comment