1. How does inheritance conflict with encapsulation in OO
systems? Be sure and discuss the issue widely by including
design issues like allocation, dependency, control, and
Method: Short definition of encapsulation and why inheritance
violates this principle. Then a discussion of design issues in
regards to allocation, dependency, control and structure.
Answer: Encapsulation (information hiding) is a mechanism that
allows us to hide the implementation details of the object so
other components of the system cannot exploit the innards of the
object. Objects are cohesive units that bind together data and
function. This localizes changes and minimizes the impact of
changes to one object on other components of the system.
Inheritance is said to violate the principle of encapsulation
since objects that inherit from a superclass, inherit details
from the superclass. These subclasses are thus affected by
changes in the superclass, violating the principle of
When developing inheritance hierarchies one should have a clear
organizing principle for the hierarchy. Each object class should
have a clearly defined role or function. Object classes should
function like data types and follow the substitutability
principle.( the ability to substitute type S when object type T
is expected, guaranteeing the substituted object will support
the same operations of T. A User should not have to
distinguish between subclasses to use an operation. Inherited
operations must support the 'original contract' with superclass.
When developing OO software, we should concentrate of maximizing
reusability by localizing change (encapsulation). Use this
criteria for allocating operations to objects. Allocating
operations to objects not a natural thing to do and a design
should be verified by suggesting extensions or modifications to
the proposed object model and evaluating the impacts on the
system. If you find that the proposed extensions are affecting
a great number of objects, maybe the design needs to be
reworked. Keep the interfaces for an object small and
information in one spot, not across many objects.
When faced with some behavior that is spread amongst a couple of
classes, model this behavior with a control object. Control
objects, don't correspond to real world objects. They are used
to encapsulate some behavior that where we cannot easily
identify whose responsibility it would be. Control strategies
should be developed to localize change, taking either a
centralized or decentralized approach.
Minimize dependencies amongst objects, fewer dependencies stand
up better to change, less affected by change. The Law of
Demeter "the methods of a class should not depend in any way on
the structure of any class, except the immediate structure of
their own class. Further, each method should send messages to a
very limited set of classes only". Don't incorporate knowledge
of a structure in the methods.
2. Critically discuss the issue of control in a state (machine)
Method: To briefly discuss control in an OO system. The
architecture of the state machine pattern and its advantages and
disadvantages with regards to control will then be discussed.
Answer: In OO systems control is implemented using either a
process driven or event driven approach (or a combination of).
In the process driven approach, each operation is responsible
for it's own control. This results in highly nested control
structures for those objects with complex (or a high number of
states) life cycles. Making each operation responsible for its
own control can also affect the maintainability and
extendibility of the system. For example, if operations
contain the logic for control (moving from state to state), a
modification or change in control usually results in a lot of
CASE/IF-THEN clauses, which can have devastating effects on
maintaining, extending or reusing the system.
In an event driven system, state machines manage the flow of
control. You have the additional cost of implementing these
state machines, but the system is much more maintainable and
flexible. These machines are 'table-driven' which provide for
easy updates/modifications. State machines are particularly
good for user interfaces, since these interfaces must respond to
a large number of events.
The state machine pattern utilizes FIniteStateModel, Transition
and ActiveObject classes to implement a finite state machine and
control state transitions of a given object. The transitions
are usually represented in a table, making them easy to modify.
The fact that the object is using a FSM to control its
processing is hidden from the user. The user calls the object
with the event that needs to be processed (i.e.
modify,accept,cancel). The name of the event is different from
the internal method that is applied (action) in response to this
event. This object can then check any gaurd(if any) and then
utilizes the FSM to validate that the transition is legal, call
the appropriate internal method and update the objects state.
The use of this state machine in implementing control within OO
systems is a very powerful tool. It creates a highly flexible
and maintainable implementation for objects which have very
complex life cycles. This flexibility is gained at the cost of
developing and implementing the FSM.
One area of concern is the affect exception handling has on the
implementation of the FSM. Exception handling can add to the
complexity of implementing FSM. An exception that occurs within
the invocation of the internal method( action) may result in a
rollback from the updated state, or a return to the original or
a different state.
3. Write a critical analysis of how you think patterns can or
cannot achieve the goals that many have stated for OO systems
(see the guidelines for OO systems in Yourdon).
Method: Quickly recant Yourdon/Coad OO guidelines and address
them on how patterns may/may not satisfy these guidelines.
Focus on the clarity of design. programmers won't reuse
anothers work if they cannot understand the logical or physical
design. Use a Consistent vocabulary, manageable number of
messages and classes, and clear concise descriptions.
Keep protocols simple, complex messages represent excessive
coupling. Large number of parameters usually a sign of bad
design. Parameters should be free of computer science jargon
Keep operations simple. Code for operations should be small ( a
page for 3gl, < 25 lines for 4gl) A lot if if/then case
statements hints of bad class factorization. This is procedure
code being used for decisions that should be handled by the
Minimize volatility of design. Bad design is very volatile where
a small change has large ripple effect. Also evaluate design by
scenario. Use role playing to validate a design, this will show
weakness in responsibility of design.
Minimize overall size, small is beautiful.
** end guidelines **
Design patterns more useful than guidelines, they provide an
example of the solution. Patterns are very useful in conveying
knowledge and experiences from past systems development. They
can also assist in the creation of generalized classes that are
robust enough to support a wide variety of systems. I view them
as an important tool in system development in areas such as
providing documentation, for both user and programmers.
Supporting the creation of reusable systems, developing systems
based on a set of stable, well defined components (consistency)
to minimize the learning curve and increase reliability.
Patterns themselves do not do away with the guidelines, but
actually must follow the guidelines established above to be
useful. These guidelines should be used in the development as
well as implementation of the patterns. The patterns should be
developed using a consistent vocabulary, with a focus on
complexity and size.
What may be a problem/ concern is that systems usually consist
of a large number of patterns. A specific object or class may
actually utilize many patterns. Even though each pattern may
individually adhere to the above guidelines ( especially in
terms of size and complexity) the implementation of these
patterns may result in a highly complex system.
4. Discuss 3 patterns that help code be platform-independent.
are they for this purpose?
Method: Id the 3 patterns of platform independence.
Answer: Most of today's software is based upon a GUI, providing
some type of windowing system (Window, X Windows, Presentation
Mgr...). Designing and implementing systems that can be
platform independent must address three areas of concern:
The Windowing system.
The 'Look and Feel' of the system and
User operations of the system.
To achieve this independence we are looking for classes that
separate the abstract implementations from their concrete
classes, allowing platform independence. There are patterns
that address each one of these issues.
The BRIDGE Pattern decouples an abstraction from its
implementation. Inheritance could be used to provide the same
system independence, but inheritance 'binds' an implementation
to the abstraction permanently, making it difficult to extend or
modify. New subclasses for each new platform. Using the BRIDGE
Pattern, the client can create a window without committing to a
concrete class. The abstraction and the implementation are
separated and extensible independently of each other.
Achieving independence of the look and feel of the system can be
accomplished by using the ABSTRACT FACTORY pattern. Look and
feel refers to the appearance and behavior of user interface
widgets (controls) such as scroll bars, windows and buttons. The
Abstract Factory pattern can create and configure a particular
The COMMAND pattern lets objects (user interface objects such as
button) make requests of unspecified application objects by
turning the request itself into an object. By decoupling the
object that invokes the operation from the one that knows how to
perform it we can support platform independence. The commands
are first class objects, making it easy to add new commands,
define 'macro' commands.
The use of these patterns does support the platform
independence. It has been my experience, with multi-platfrom
development tools that achieving all the platform independence
goals (look and feel , windowing and command processing) is
difficult. Of these goals i feel the look and feel may be the
most difficult to achieve. If we take for example MS Windows,
Motif and the MAC interface there are very distinct differences
on how these user interfaces look and feel. This would create
very large, complex implementation to handle the variety of
actions. For example, windowing system A may support some type
of user interface functionality that is not supported in another
windowing system We make decisions then on how to implement
these special cases. The tools i am familiar with happen to
support some 'core' functionality that is the most common
amongst the platforms.
5. Discuss and analyze the prototype pattern from GOF. Give an
from an application domain (that is not in the book) that would
use this pattern.
Method: A brief statement on the usefulness of this pattern,
implementation issues, followed by an application from the
Answer: The prototype pattern is useful when a system should be
independent of how its products are created, composed and
represented. It allows the creation of new objects by specifying
a prototypical instance. The pattern is useful when the classes
to be instantiated are specified at runtime or to avoid building
a class hierarchy of factories that parallels the class
hierarchy of products. This type of pattern is extremely
beneficial to framework developers who are developing a very
generalized product (framework) that may not be aware of the
types of objects that it needs to create. This type of pattern
provides the greatest benefit in languages like C++ where
classes are not objects and the user does not have any type
information available at runtime.
Some issues when using this type pattern include the shallow vs.
deep copy issue when implementing the Clone operation. A
shallow copy message will create a new object that will instance
variables with identical values to that of the target object. A
deep copy message will create a new object that will have
instance variables with entirely new variables. Any
'sub-object' reachable from this newly created object will also
be a new object. The clone message itself can be difficult to
add when the classes already exist. It may also be difficult to
implement when their internals include objects that do not
support copying or have circular references.
This type of pattern is particularly useful in design tools that
used various classes of objects to build a finalized part. I
can see this pattern being used in any circumstance where an
engineer can experiment using different parts and running
simulations. I envision and engineer constructing the finalized
product (for example a car) built from many available components
that the car manufacture has available. The engineer could
assemble a car or any portion of a car that he/she wants to
design or test. from a list of available components.
Performance tests could be conducted. The engineer could than
swap out comparable components are rerun the simulation. Some
intelligence could be added to this process for selecting the
set of products that maximize efficiency and reduce cost.