You are on page 1of 87

Design Patterns

In Java

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Course overview

• Techniques to improve software


maintainability
• Creational patterns
• Structural patterns
• Behavioral patterns

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Software cost

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Software quality
• Goals:
 Correctness
 Robustness
 Extendibility
 Reusability
 Compatibility
 Efficiency
 Portability
 Ease of use
 Functionality

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
What is software design?
• Implement software solutions
• Transform user requirements
• Software design levels:
– Architectural Design
• Highest abstract version of a system
• Many components interacting with each other
– High-level Design
• Identifies sub systems and modules
• Interaction between modules
– Low-level Design
• Logical structure of each module
• Interfaces to communicate with other modules

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
What is good design?

• Need criteria to evaluate a design


• Need of principles and rules for creating good design

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Modularity

• Technique to divide a software system into multiple


independent modules
• Advantages
– Small components are easier to develop, test and maintain
– Reusability
– Enforces concurrent execution
• A modular system is one that's structured into identifiable
abstractions called components
 Components should possess well-specified abstract interfaces
 Components should have high cohesion and low coupling

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Modularity
• Criteria :
 Decomposability
• Are larger components decomposed into smaller components?
 Composability
• Are larger components composed from smaller components?
 Understandability
• Are components separately understandable?
 Continuity
• Do small changes to the specification affect a localized and limited
number of components?
 Protection
• Are the effects of run-time abnormalities confined to a small
number of related components?

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
1. Decomposability
• Decompose problem into smaller sub-
problems that can be solved separately
 Goal: Division of Labor
• keep dependencies explicit and minimal
 Example: Top-Down Design
 Counter-example: Initialization Module
 initialize everything for everybody

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
2. Composability
• Freely combine modules to produce new
systems
 Reusability in different environments ->
components
 Example: Math libraries; UNIX command & pipes
 Counter-example: use of pre-processors

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
3. Understandability
• Individual modules understandable by human
reader
 Counter-example: Sequential Dependencies (A | B
| C)
• contextual significance of modules

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
4. Continuity
• Small change in requirements results in:
– changes in only a few modules does not affect the
architecture
– Example: Symbolic Constants
– Counter-Example: static arrays

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
5. Protection
• Effects of an abnormal run-time condition is
confined to a few modules
 Example: Validating input at source
 Counter-example: Undisciplined exceptions

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Five Rules of Modularity
• Direct Mapping
 consistent relation between problem model and solution
structure
• Few Interfaces
 Every component should communicate with as few others as
possible
• Small Interfaces
 If any two components communicate at all, they should
exchange as little information as possible
• Explicit Interfaces
 Whenever two components A and B communicate, this must be
obvious from the text of A or B or both
• Information Hiding

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
1. Direct Mapping
• Keep the structure of the solution compatible
with the structure of the modeled problem
domain
 clear mapping (correspondence) between the two
• Impact on:
– Continuity
• easier to assess and limit the impact of change
– Decomposability
• decomposition in the problem domain model is a good
starting point for the decomposition of the software

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
2. Few Interfaces
• Every module should communicate with as
few others as possible
 rather n-1 than n(n-1)/ 2
 Continuity, Protection, Understandability,
Composability

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
3. Small Interfaces
• If two modules communicate, they should
exchange as little information as possible
 limited "bandwidth" of communication
 Continuity and Protection

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
4. Explicit Interfaces
• Whenever two modules A and B
communicate, this must be obvious from the
text of A or B or both.
 Decomposability and Composability
 Continuity, Understandability
• The issue of indirect coupling
 data sharing

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
5. Information Hiding
• Motivation: design decisions that are subject
to change should be hidden behind abstract
interfaces, i.e. components
 Components should communicate only through
well-defined interfaces
 Each component is specified by as little
information as possible
 Continuity: If internal details change, client
components should be minimally affected
• not even recompiling or linking

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Abstraction vs. Information Hiding

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
OO Design Heuristics

• Material for this lecture is taken from


 Object-Oriented Design Heuristics
• by Arthur J. Riel
• ISBN: 0-201-63385-X
 as such, it is copyright, © 1999, by Addison
Wesley

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
What’s next?

• Classes and Objects


• Topologies of Procedural versus Object
Oriented Applications
• Relationships between Classes and Objects
• The Inheritance Relationship
• Multiple Inheritance

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristics
– All data should be hidden within its class
• When a developer says
– “I need to make this piece of data public because…”
• They should ask themselves
– “What is it that I’m trying to do with the data and why doesn’t
the class perform that operation for me?”
– Users of a class must be dependent on its public
interface, but a class should not be dependent on
its users
• Why?

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Grade Calculator
• GradeCalculator class with 3 methods:
– readGradeInput
– computeGrades
– showGradeOutput
• if the 3 methods are not called in exactly this order,
GradeCalculator code crashes! Solutions?
• computeGrades or showGradeOutput call
their preceding methods if that hasn't been
done already
• combine these methods into only one public
method that calls all 3 in order

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Dependencies
• Class dependencies

• Interface Dependencies

• Method/Field dependencies

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristics
 Minimize the number of messages in the protocol
of a class
• The problem with large public interfaces is that you can
never find what you are looking for…smaller public
interfaces make a class easier to understand and
modify
• Example: LinkedList has too many methods, hard to find
a method for merge operation

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristics
 Do not put implementation details such as common code
“helper” functions into the public interface of a class
• Users of a class do not want to see operations in the public
interface that they are not supposed to use
• LinkedList class has add and remove methods that both
advance the list to the proper linked node to add/remove, then
performs the operation. How should we design this?
• use a common helper named getNodeAt(int index)
that advances the list to the proper node and returns
that node
• make the helper getNodeAt a private method so
client code does not see it and cannot call it

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristics
 A class should capture one and only one key abstraction
• (bad) example: PokerGame class that holds all the players, holds an
array representing the card deck, stores all bets and money, does the
logic for each betting round...
 Keep related data and behavior in one place
• example: Should a poker game's Player class remember whether
that player is in the game, what that player's current bet is, etc? Or
should the Game class remember who is in the game, the Bet class
remember every player's current bets, ...?
 Spin off non-related information into another class
• Similar to the “Extract Class” refactoring pattern
 Most of the methods defined on a class should be using most of
the data members most of the time
• All of these heuristics deal with class cohesion

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Action Oriented Topology
• Procedural topologies break an application down
according to function which then share data
structures
• It is easy to see which functions access which
data structures
• It is difficult to go the other way, to see which
data structures are used by which functions
• How to apply it correctly
– Put the data in the same file with the functions on it
– So why not make it a class

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Object Oriented Topology
• Collections of decentralized data
• Well defined interfaces

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Action vs. Object-Oriented
• There are two typical problems that arise
when developers familiar with procedural
techniques try to create an OO design
 The God Class
• A single class drives the application, all other classes
are data holders
 Proliferation of Classes
• When object-oriented design leads us to design a
system that has too many classes that are too small in
size and scope, making the system hard to use, debug,
and maintain

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
God Class
• Avoidance:
– Distribute system intelligence horizontally as uniformly as
possible, that is, the top-level classes in a design should
share the work uniformly
• Anticipate:
– Be very suspicious of a class whose name contains
“Driver”, “Manager”, “System”, or “Subsystem”
– Beware of classes that have many accessor methods
defined in their public interface. Having many implies that
related data and behavior are not being kept in one place
– Beware of classes whose methods operate on a proper
subset of the data members of a class. God classes often
exhibit this behavior

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
God Class Example
• A heat flow regulator needs to decide when to activate a furnace to keep a
room at a certain temperature
• Bad example

• Good example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Proliferation of Classes
• Bad example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Proliferation of Classes
• Good example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristics
 Minimize the number of classes with which another class
collaborates
• Look for situations where one class communicates with a group of
classes
– Ask if its possible to replace the group with a class that contains the
group
 Related Heuristics
• Minimize the number of message sends between a class and its
collaborator
• Minimize the amount of collaboration between a class and its
collaborator, that is, the number of different messages sent
• Minimize fanout in a class, that is, the product of the number of
messages defined by the class and the messages they send

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Classes and Objects
• Heuristic
 If a class contains objects of another class, then the
containing class should be sending messages to the
contained objects
• that is a containment relationship should always imply a uses
relationship
• Related
 Classes should not contain more objects than a
developer can fit in short-term memory.
 A class must know what it contains, but it should not
know its container (do not depend on your users)

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• Heuristics
 Inheritance should be used only to model a
specialization hierarchy
• Containment is black-box
• Inheritance is white-box
 Derived classes must have knowledge of their
base class by definition, but base classes should
not know anything about their derived classes
 All data in a base class should be private; do not
use protected data

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• Heuristics
 In theory, inheritance hierarchies should be
deep—the deeper, the better
• In practice, inheritance hierarchies should be no deeper
than an average person can keep in short-term
memory.
 All abstract classes must be base classes
 All base classes should be abstract classes
 Factor the commonality of data, behavior, and/or
interface as high as possible in a class hierarchy

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• A Second Heuristic
 Whenever there is inheritance in an object-oriented
design, ask yourself two questions:
 1) Am I a special type of the thing from which I’m
inheriting? 2) Is the thing from which I’m inheriting
part of me?
• A yes to 1) and no to 2) implies the need for
inheritance; A no to 1) and a yes to 2) implies the
need for composition
 Is an airplane a special type of fuselage? No
 Is a fuselage part of an airplane? Yes

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Multiple Inheritance
• Riel does not advocate the use of multiple
inheritance (its too easy to misuse it). As such,
his first heuristic is
 If you have an example of multiple inheritance in
your design, assume you have made a mistake and
prove otherwise!
• Most common mistake
 Using multiple inheritance in place of containment

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Effective Java by Bloch

• An example of a “design heuristics” book that


advocates “best practices”
 presents 57 best practices or rules of thumb and
shows how they were (or were not!) applied in the
design of the Java class libraries

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Examples from Bloch

• Consider static factory methods in place of


constructors
• Favor immutability
• Favor composition over inheritance
• Design and document for inheritance or else
prohibit it

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Static Factory Methods
• Typically an object is obtained from a class
constructor
public Boolean(boolean value) {
_value = value;
}
• but an alternative is to use a static factory
method
public static Boolean valueOf(boolean b) {
return (b ? Boolean.TRUE : Boolean.FALSE);
}

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Static Factory Methods
• Benefits
 static factory methods have names
• two constructors with same signatures not allowed
– factory methods can simply use different names
 static factory methods do not have to create a new
object each time they are invoked
• consider implementation of the flyweight pattern, no matter
how many times the factory method was invoked, only a
maximum of 26 objects could be created
 static factory methods can return an object of any
subtype of their return type; constructors cannot
• this method allows frameworks to return objects whose
classes are private; like Java’s ListIterator

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Static Factory Methods
• Benefits:
 Static factory methods reduce the verbosity of
creating parameterized type instances
 Instead of:

 Use:

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Static Factory Methods
• Disadvantages
 If a class provides only static factory methods, and
makes its constructor private, then the class
cannot be subclassed
 static factory methods are not readily
distinguishable from other static methods
• whereas constructors “stand out” since their name
matches the name of the class

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Builder
• Bad example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Builder
• Better example:

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Builder
• Best example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Immutability
• Consider creating immutable classes
 An immutable class is simply a class whose instances
cannot be modified
• Why?
 Immutable objects are simple
• they can be in only one state
 Immutable objects are thread-safe
• since they never change value, multiple threads can access
them without synchronization!
 Immutable objects can be shared freely
• one object can’t change the value of an immutable object
unexpectedly, because the value cannot change at all!

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Immutability
• To make a class immutable
 Do not provide mutator methods
• e.g. setName(String name)
 Ensure that methods cannot be overridden
• make constructor private, add factory method
 Make all fields final (e.g. const)
 Make all fields private
• you should do this anyway
 Ensure exclusive access to any mutable components
• Do not store a pointer to a mutable object provided from
the outside world, and do not return a pointer to any of your
mutable objects; perform defensive copies instead

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Immutability

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Immutability
• Disadvantage
 Immutable objects require a separate object for each
distinct value
• Turning lemons into lemonade
 use a static factory method to manage a pool of
objects for your immutable class
 if two objects with the same value are requested,
return the same object each time
• this lets the class ensure that a==b is equivalent to
a.equals(b)
– e.g. a logically equals b, only when a and b point to the same
object)
– the latter is typically much faster at run-time

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition
• Inappropriate use of inheritance leads to
fragile software
 Why? Because inheritance breaks encapsulation;
subclasses can see and access the internals of
their parents (unless protected by “private”)
• thus, a subclass may “break” due to a change in one of
its parents, even when the source code of the subclass
was not modified
– mainly because a subclass may have depended on the
implementation details of its parents

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition
• Bad example

 Extend a Set class to keep track of how many


elements have been added to the set since it was
created
 We start by creating a subclass of HashSet called
IHashSet (for instrumented hash set)
• see next slide

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition
IHashSet s = new IHashSet()
s. addAll(
Arrays.asList(
new String[] {“Snap”, “Crackle”, “Pop”}));

• We would hope addCount = 3, but it doesn’t, it equals 6! Why?


 because HashSet’s addAll makes use of the add routine to add elements to the
set; since we provided a method body for add, our method was invoked via
polymorphism and we incremented addCount twice for each element added
• We depended on our parent’s implementation not to “self invoke” its
other methods and we guessed wrong!
 To correct this problem, while still using inheritance, involves a lot of bad
design choices
• if we just override add, and not addAll, our class will break when Sun changes the
implementation of addAll to no longer call add!
• if we change our method to invoke add directly, then we ignore the method for addAll in
our parent (and we might make a mistake in our implementation)

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition
• Rather than subclass HashSet, lets wrap it,
furthermore, since HashSet implements the Set
interface, lets create a Wrapper that can handle
any class that implements the Set interface
 Our new class ISet will take a reference to an existing
Set, forward all Set related calls to it, and add our
instrumentation to the add and addAll operations
• now since we are delegating to a composed object, rather
than overriding inherited methods, polymorphism no longer
applies; HashSet’s addAll method is free to use HashSet’s
add method (or not) and our code still works
 See code next slide

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Favor Composition
• Now ISet can handle any class that implements
the Set interface, not just HashSet
Set s1 = new ISet(new TreeSet(list));
Set s2 = new ISet(new HashSet(20));
• ISet is an instance of the Decorator pattern, it
wraps other Set classes
• Disadvantages
– Hard to use in callback frameworks
• because wrapped objects do not know they are wrapped
– Writing forwarding methods is tedious

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Prohibit Inheritance
• How do you design and document a class for
inheritance
 if not done properly, problems can arise, as we saw in the
last example
• we did not know that HashSet.addAll invoked HashSet.add
• First, a class must document precisely the effects of
overriding any method
 including documenting its self-use of its own methods;
which methods and in what order
• Now, wait a minute! Does this violate the dictum that
good documentation should describe “what” a method
does not “how” it does it? Yes! Why? Because
inheritance breaks encapsulation!
Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• Second, to provide hooks to subclasses,
protected methods must be provided
 choose with care if your class is used by external
clients
• you are committing to these methods (and your self-use
documentation from the previous slide) forever!
• Third, constructors must not invoke overridable
methods
 since superclass constructors are invoked before
subclass constructors, use of an overridable method
may cause a subclass method to be invoked before
the subclass constructor has been invoked!

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• What is being printed on the screen?

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Inheritance
• By now it should be apparent that designing a
class for inheritance places substantial limitations
on the class
 hence this is not a decision to be taken lightly
• The best solution to this problem is to prohibit
subclassing in classes that are not designed and
documented to be safely subclassed
 Easiest way to do this is to make the constructors
private and provide only public static factory methods
• If this is not an option, consider designing your
class to eliminate self-use

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Principles and Rules of OOD
• Open Close Principle
• Dependency Inversion Principle
• Liskov Substitution Principle
• Single Responsibility Principle
• Interface Segregation Principle
• Law of Demeter

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Open Close Principle

• Be open for extension


 Module’s behavior can be extended
• Be closed for modification
 Source code for the module must not be changed

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Open Close Principle

• How to make the Car run efficiently with a


TurboEngine?
• Only by changing the Car!

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Open Close Principle

• A class must not depend on a concrete class!


• It must depend on an abstract class ...
...using polymorphic dependencies (calls)

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Open Close Principle

• What if we decide to change that only each


second character is written?
Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Open Close Principle

• Closure not complete but strategic.


1. Abstraction to gain explicit closure
 Provide class methods that can be dynamically
invoked
 To determine general policy decisions
 Design using abstract ancestor classes
2. Use “Data-Driven” approach to achieve closure
 Place volatile policy decision in a separate location
 E.g. a file or separate object
 Minimizes future change locations

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Dependency Inversion Principle

• High level modules


 Encapsulate complex logic
• Business flows
• Low level classes
 Basic and primary operations
• Disk accesses
• Network protocols

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Dependency Inversion Principle

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Design to an Interface
• Abstract classes/interfaces:
 tend to change less frequently
 abstractions are ‘hinge points’ where it is easier to
extend/modify
 shouldn’t have to modify classes/interfaces that represent the
abstraction (OCP)
• Exceptions
 Some classes are very unlikely to change (example: String class)
 In cases like this can use concrete class directly

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
DIP Bad Example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
DIP Good Example

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Liskov Substitution Principle
• Any code which can legally call another class’s
methods must be able to substitute any
subclass of that class without modification

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Square IS-A Rectangle?

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
LSP

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Single Responsibility Principle

• A Responsibility is a reason to change


• The Rectangle has 2 responsibilities ... due to the various clients

• The bad part: ComputationalGeometryApplication depends now on


• GUI!

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Single Responsibility Principle

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Interface Segregation Principle

• Many client-specific interfaces are better than


one general purpose interface

• Consequence:
 impact of changes to one interface aren’t as big if
interface is smaller
 interface pollution

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Law of Demeter
• Weak Form
Inside of a method M of a class C, data can be accessed in and
messages can be sent to only the following objects:
 this and super
 data members of class C
 parameters of the method M
 object created within M
 by calling directly a constructor
 by calling a method that creates the object
 global variables
• Strong Form:
In addition to the Weak Form, you are not allowed to access directly
inherited members

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Law of Demeter

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Law of Demeter

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania
To be Checked
• Class abstraction
• Functional requirements
• UML
• Coding style

Information Type: Working Standard, Disclosure Range: , Information Owner: iulia.jianu, NTT DATA Romania

You might also like