Viscosity:

Viscosity of design:
design preserving methods are harder to employ than hacks.

Causes:

change in requirements that were not anticipated in the initial design.

changes that introduce new and unplanned for dependencies.

changes that need to be made quickly,
by developers unfamiliar with the original design philosophy.

Solution

Make code resilient to change

Create dependency firewalls

Redesigning the software is the wrong approach here,
because the old design continues to evolve and change,
and the new design must keep up.

Principles of Object Oriented Class Design

Open Closed Principle

we want to be able to change what the modules do,
without changing the source code of the modules.

Liskov Substitution Principle

LSP can be restated in terms of design by contract:

A derived class is substitutable for its base class if:

Its preconditions are no stronger than the base class method.

Its postconditions are no weaker than the base class method.

Derived methods should expect no more and provide no less.

Example of Liskov violation:
Circles are a type of ellipse,
but have a single focus.
If a Ellipse#set_foci(a, b) method exists,
Circle should also implement it, but would need to ignore one of the args.
This is a violation of the contract,
because circle.focus_b would return a, because b was ignored.

Dependency Inversion Principle

depending upon interfaces or abstract functions and classes,
rather than upon concrete functions and classes

Every dependency in the design should target an interface, or an abstract class.
No dependency should target a concrete class.

However, if you have tried and true modules
that are concrete, but not volatile,
depending upon them is not so bad

Interface Segregation Principle

If you have a class that has several clients,
rather than loading the class with all the methods that the clients need,
create specific interfaces for each client
and multiply inherit them into the class.

Principles of Package Architecture

Package Cohesion Principles:

Release Reuse Equivalency Principle:
The granule of reuse is the granule of release.

A reusable element (component, class, or a cluster of classes)
cannot be reused unless it is managed by a release system of some kind.

Abstractness metrics:

Abstractness A = Na/Nc

Na - # of classes in package

Nc - # of abstract classes in package

I should increase as A decreases

A position on the line (in the I vs A graph below) means that
the package is abstract in proportion to its incomming dependencies
and is concrete in proportion to its outgoing dependencies.

Distance metrics:

How far is a package from the main sequence?

Distance, D = |A + I - 1| / √2

Normalized distance D′ = | A + I – 1 |

1|\
| \
| \
↑ | \
A | \
| \
| \
|_______\_
0 I → 1

Patterns of Object Oriented Architecture

Abstract server

When a client depends directly on a server, the DIP is violated.
Changes to the server will propogate to the client,
and the client will be unable to easily use similar servers.

An abstract interface between the client and server solves this problem.

It becomes a “hinge point” upon which the design can flex.

Different server implementations can be bound
to an unsuspecting client.

Adapter

inserting an abstract interface is infeasible
when the server is third party software,
or is so heavily depended upon that it cannot easily be changed

An adapter can be used to bind the abstract interface to the server

It is n object that implements the abstract interface
to delegate to the server

Every method of the adpater simply translates and then delegates

Observer

Used when one element needs to take action
when another element detects something,
and we don’t want the detector to know about the actor.

Example:
A Sensor derives from Subject,
and Meter derives from an Observer interface.
Meter uses Subject#register to register itself
to Sensor’s list of observers.
When reading changes, Sensor calls Subject#notify,
which calls #update on each registered Observer.

Bridge

Creates a strong seperation between the interface and implementation

Abstract factory

allows that dependency upon the concrete class to exist in a single place.