Principles and patterns of object oriented design. answering the most common questions faced when designing a system, e.g., how to model the domain? how to prepare the code for modification? how to handle an object's life cycle?
Size: 1.2 MB
Language: en
Added: Apr 10, 2014
Slides: 43 pages
Slide Content
Object Oriented Design
is mainly about
behaviour, not
structure.
2
What to ask when designing
0Which class should a responsibility be assigned to?
0How to organize the system’s responsibilities?
0How to model the domain?
0How to handle an object’s lifecycle?
0How to prepare the code for modification?
3
Which class should a
responsibility be assigned to?
4
0Information Expert [GRASP]
0A responsibility dealing with X should be
assigned to the object holding X
0Single Responsibility Principle [SOLID]
0Each class should have one and only one
responsibility
0Interface Segregation [SOLID]
0Favour small specific interfaces so clients don’t
depend on interfaces they don’t use
5
Corollary of Information Expert
Getters and setters are Evil
(don’t ask for data, delegate as much as possible)
6
Procedural thinking
7
Object thinking
8
How to organize the system’s
responsibilities?
9
Layers pattern
0You are designing a system whose dominant
characteristic is a mix of low- and high-level issues,
where high-level operations rely on the lower-level
ones.
0Therefore
0Structure your system into an appropriate number of
layers and place them on top of each other, each
providing a specific level of abstraction.
10
GoF
Common architecture
Source: domain driven design , Eric Evans 11
0Low coupling [GRASP]
0Keep coupling of elements to a minimum.
Avoid circular dependencies.
0High Cohesion [GRASP]
0Keep related elements close together
0Indirection [GRASP]
0Avoid tight coupling by creating an
indirection layer
13
Façade
0Work is actually performed by a series of subsystem
but this level of complexity must be hidden from the
client
0Therefore
0Create a facade object offering a simpler, high level
interface which delegates work in the actual subsystems
14
GoF
Controller
0You need to coordinate application activity - the
interactions of a use case with the UI or external
systems
0Therefore
0Assign the responsibility of use case coordination to a
dedicated use case controller which exposes a business
API (application layer) and performs no business logic
but delegates to the right domain objects instead
15
GRASP
How to model the domain?
16
Look at your domain model’s
ubiquitous language
17
Entity
0Some objects in the domain have a thread of
continuity which we need to track by its identity.
0Therefore
0Model objects in the real world as entities, assigning
each object one or more identities. Equality of
references is done comparing the identity of the object.
18
DDD
Entity: example
Class Account{
public Account(AccountNumber accn) {…}
public boolean equals(Object other) {
if (other==this) return true;
if (!(other instanceof Account)) return false;
return (this.getID() == (Account)other.getID());
}
public void withdraw(Money amount) {
if (hasEnoughBalance(amount)
|| overdraftAllowed(amount)) {
// business logic for withdrawing
// and updating balances
}
}
}
19
Value Object
0Not everything needs an identity; some things matter
for the value of its attributes.
0Therefore
0Create immutable objects whose equality is
determined by the equality of its attributes.
20
DDD
Value object: example
Class Balance{
public Balance(Money amount, Calendar asOf) {…}
// getters (but no setters)
public Money amount() {…}
public Calendar asOf() {…}
// creates a new Balance object
// keeping this and the other object unchanged
public Balance add(Money some) {…}
public Balance add(Money some, Calendar effectiveOn) {…}
public Balance subtract(Money some) {…}
...
public boolean equals(Object other) {…}
}
21
Service
0Some business operations are not naturally placed
in a certain domain object
0Therefore
0Create a service object that handles only that operation
and coordinates the necessary domain objects.
23
DDD
Service: example
class TransferService {
public void transfer(Money amount,
Account from, Account to) {
if (isAllowedToTransfer(from, amount, to) {
from.withdraw(amount);
to.deposit(amount);
}
}
private boolean isAllowedToTransfer(Account from,
Money amount,
Account to) {
// rules specific to account transfers
// (e.g., maximum allowed amount to transfer for
// international account)
}
}
24
An Example
25
N-to-M
relationships
are hard
A pragmatic design
26
•Remove
unnecessary
associations
•Force traversal
direction of
bidirectional
associations
•Reduce
cardinality by
qualification of
the association
we are still left
with a tangle of
interconnected
objects...
Aggregate
0Some objects are closely related together and we need
to control the scope of data changes so that invariants
are enforced
0Therefore
0Keep related objects with frequent changes bundled in
an aggregate
0control access to the “inner” objects thru one single
“root” object
27
DDD
A more pragmatic design
28
Legend:
•Account
aggregate
•Customer
aggregate
Address is a value
object so it can be
freely shared among
several aggregates
How to handle an object’s
lifecycle?
29
Object’s lifecycle
1.An object is created
2.The object is used
3.It must be persisted for later use
4.Later, the object is reconstructed from persistence
5.It is used (provably changed)
6.It is stored back again for later use
7.…
30
Separate use from
construction
31
Factories
0Creating a (large) object might be a complex task
and/or the client must be decoupled from the actual
type of the created object.
0Therefore
0Place construction logic in a dedicated factory which
encapsulates object creation for all clients.
32
DDD
0Creator [GRASP]
0Assign class A creation responsibility to the class which
either (1) contains A’s instances; or (2) holds the data
for initializing an A’s instance
0Factory Method [GoF]
0A class method that simplifies the creation of different
implementations of the same interface
0Simple Factory [GoF]
0A class made up of only factory methods
0Abstract Factory [GoF]
0Handles the creation of related or dependent product
families
33
Repository
0Client code needs to obtain a reference to an object in
order to use it (sometimes, the desired object needs to
be reconstructed from persistence). After using it the
client wants the object to be persisted again.
0Therefore
0Encapsulate the logic needed for obtaining object
references in a Repository. The repository handles all
the persistence logic and abstracts the client code from
such details.
34
DDD
35
Repository example
Repositories and layers
36
How to prepare the code for
modification?
37
Protected Variation
0You need to design objects, components or systems so
that variations in those elements don’t impact other
elements
0Therefore
0Identify points of predicted variation and create a stable
interface around them.
38
GRASP
0Open/Close Principle [SOLID]
0A class should be open for extension and
adaption and closed for modification
0Dependency Inversion Principle [SOLID]
0Clients should depend on abstractions, not
concretions. I.e., program to an interface not
a realization.
39
0Polymorphism [GRASP]
0When behaviour varies depending on type
0Template Method [GoF]
0Define the skeleton of an algorithm in an
operation, deferring some steps to subclasses.
0Liskov Substitution Principle [SOLID]
0Any method expecting A should work
properly with any object derived from A
40
Liskov Substitution Principle’s Corollary
Derived classes should adhere strictly to the semantics
of the contract
see also, Design by Contract:
Pre-conditions
Post-conditions
Invariants
41
Strategy
0Sometimes there is a business policy (expressed in
the domain) that must be enforced but it actually may
have different variations of concrete policies
0Therefore
0Define a common interface for the policy and provide
different implementations decoupling the client from
the actual policy and allowing for permutation and
independent evolution.
42
GoF
Topic Principles and patterns
Which class should a responsibility be
assigned to?
Information Expert
Single Responsibility Principle
Interface Segregation Principle
How to organize the system’s
responsibilities?
Layers
Façade
Controller
How to model the domain? Entity
Value Object
Service
Aggregate
How to handle an object’s lifecycle? Factories
Repositories
How to prepare the code for
modification?
Protected Variation
Open/Close Principle
Dependency Inversion Principle
Liskov Substitution Principle
Template Method
Strategy
44
References
0Domain Driven Design. Eric Evans
0Why getters and setters are Evil. Allan Holub.
http://www.javaworld.com/article/2073723/core-
java/why-getter-and-setter-methods-are-evil.html
0Design Principles and Design Patterns. Robert Martin.
http://www.objectmentor.com/resources/articles/Princip
les_and_Patterns.pdf
0Design Patterns-Elements of Reusable Object-oriented
Software, Gamma et al. (Gang of Four)
0Applying UML and Patterns; Craig Larman; (2nd ed.); 2002.