Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
A Starting Point
As a general rule, aiming for systems
whose components exhibit high cohesion
and low coupling is a very good thing, as it
results in systems that readily reusable,
testable, maintainable, modifiable etc.
This applies regardless of what we are
designing e.g. electronic devices, cars,
houses or (especially) software.
Of course, there will be times when the rule
needs to be broken, as when performance
requirements can not be achieved any
other way.
Coupling and Cohesion
Lethbridge and Laganiere (2004) provide the following
definitions:
Coupling:
“A measure of the extent to which interdependencies
exist between software modules. An important design
principle is to reduce coupling”
Cohesion:
“A measure of the extent to which related aspects of a
system are kept together in the same module, and
related aspects are kept out”
Cohesion:
○ The number of responsibilities that a class has
@Override
public void deposit( int d ) {
balance += d;
System.err.println("Savings account
balance now $"+balance);
}
}
// closed for modification public class OCP {
class Account { public static void main(String[] args) {
private AccountType _a; AccountType savingsAccount =
new SavingsAccount();
public Account(AccountType a) { Account account =
_a = a; new Account(savingsAccount);
} account.deposit( 1000 );
public void deposit(int d) {
_a.deposit( d ); }
} }
}
Note that
In the preceding example, we could have
used an interface instead of an abstract
class
OCP also underpins a number of common
design patterns, such as the State and
Strategy patterns
Dependency Inversion Principle
Definition:
“Depend on abstractions. Do not depend on
concretions” or in the Java world, “Design to
interfaces”
Application:
Couple at the abstract level (ie to an abstract
class or interface, rather than to a concrete
class). Inject the dependency via the class
constructor or an explicit method.
Consequence:
Looser coupling
An Example
In the OCP example, Account is
dependent on the abstract class
AccountType and not on the concrete
classes, ChequeAccount and
SavingsAccount. Not only does this
weaken the dependency, it also facilitates
OCP.
Liskov Substitution Principle
Definition:
“Subclasses should be substitutable for their base classes”. More
specifically substitutability means that a caller that communicates with an
abstraction, i.e. a base class or an interface, should not be aware of and
should not be concerned with the different concrete types of those
abstractions. The client should be able to call BaseClass.DoSomething()
and get a perfectly usable answer regardless of what the concrete class
is in place of BaseClass
Application:
For LSP to work the derived class must also “behave well”, meaning it
must not
1. remove any base class behaviour
2. violate base class invariants i.e. the rules and constraints of a class,
in order to preserve its integrity.
Consequence:
In effect, LSP refines the IS-A relationship with ‘IS-SUBSTITUTABLE-FOR’,
meaning that an object is substitutable with another object in all situations without
running into exceptions and unexpected behaviour.
http://dotnetcodr.com/2013/08/19/solid-design-principles-in-net-the-liskov-substitution-
principle/
An Example: Bennett et al., p.409
ChequeAccount
Account
Disinheritance of
debit() means that accountName
balance accountName
the left-hand hierarchy
balance
is not Liskov compliant Restructuring
credit() to
debit() satisfy LSP credit()
MortgageAccount
MortgageAccount ChequeAccount
interestRate
interestRate
calculateInterest() debit()
- debit() calculateInterest()
24
© 2010 Bennett, McRobb and Farmer
Note that in Java, inherited methods
cannot be disinherited, so either debit()
1. has to be removed from ChequeAccount or
2. is overridden in MortgageAccount with a
method that does nothing / throws a
NotImplementedException
Interface Segregation Principle
Definition:
“Many specific interfaces are better than a
single, general interface”
Application:
Apply SRP to interface design
Consequence:
highly cohesive interfaces
An Example: Knoernschild, p. 328
Definition:
“Don’t talk to strangers”
http://en.wikipedia.org/wiki/Law_of_Demeter
Application:
A method m of an object O may only invoke the methods
of the following kinds of objects:
1. O’s
2. M’s parameters
3. Any objects instantiated within M
4. O’s direct component objects
5. Any global variables accessible by O
Consequence:
Objects are less dependent on the internal structure of
other objects, which is a good thing.
Don’t Repeat Yourself
Definition:
“Every piece of knowledge must have a single,
unambiguous, authoritative representation within a
system”
http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
Application:
Self evident?
Consequence:
Self evident?