0% found this document useful (0 votes)
70 views47 pages

Software Reengineering P3: OO Design Principles and Violations

This document discusses several object-oriented design principles and violations, including: - Design smells that can indicate problems like rigidity, fragility, and opacity. - The SOLID principles of single responsibility, open/closed, Liskov substitution, interface segregation, and dependency inversion. - Additional principles like the law of Demeter and DRY (Don't Repeat Yourself). - Examples are provided to illustrate violations and proper implementations of these principles to improve flexibility, reusability and understandability of object-oriented software designs.

Uploaded by

ramvvugt12
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
70 views47 pages

Software Reengineering P3: OO Design Principles and Violations

This document discusses several object-oriented design principles and violations, including: - Design smells that can indicate problems like rigidity, fragility, and opacity. - The SOLID principles of single responsibility, open/closed, Liskov substitution, interface segregation, and dependency inversion. - Additional principles like the law of Demeter and DRY (Don't Repeat Yourself). - Examples are provided to illustrate violations and proper implementations of these principles to improve flexibility, reusability and understandability of object-oriented software designs.

Uploaded by

ramvvugt12
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 47

Software Reengineering

P3: OO Design Principles


and Violations

Martin Pinzger
Delft University of Technology

Slides adapted from the presentation by Steve Zhang


Outline

Design Smells

Object-Oriented Design Principles

Conclusions

2
The Reengineering Life-Cycle

(1) requirement New


analysis Requirements

(3) problem
detection (4) problem
resolution

Designs

(2) model
capture

Code

3
Design Smells

The Odors of Rotting Software


Rigidity – The design is hard to change
Fragility – The design is easy to break
Immobility – The design is hard to reuse
Viscosity – It is hard to do the right thing
Needless complexity – Overdesign
Needless Repetition – Copy/paste
Opacity – Disorganized expression

4
The Broken Window Theory

A broken window will


trigger a building into a
smashed and abandoned
derelict

So does the software

Don’t live with the broken


window

5
S.O.L.I.D. Design Principles
S.O.L.I.D Design Principles

SRP – The Single Responsibility Principle

OCP – The Open-Closed Principle

LSP – The Liskov Substitution Principle

ISP – The Interface Segregation Principle

DIP – The Dependency Inversion Principle

7
SRP: The Single-Responsibility Principle

A class should have a single purpose and only one reason to


change
If a class has more than one responsibility, then the responsibilities
becomes coupled

SRP is one of the simplest of the principles, and the one of the
hardest to get right

8
SRP heuristics

Describe the primary responsibility in a single sentence

Group similar methods

Look at hidden methods (private, protected)


Many of them indicate that there is another class in the class tying to get
out

Look for decisions that can change (not “if-statements”)


They should go into separated classes

Look for internal relationships


Are certain variables used by some methods and not others?

9
Exercise: SRP
RuleParser
- current: String
- variables: HashMap
- currentPosition: int
+ evaluate(String rule) : int
- branchingExpression(Node left, Node right) : int
- causualExpression(Node left, Node right) : int
- variableExpression(Node node) : int
- valueExpression(Node node) : int
- nextTerm() : String
- hasMoreTerms() : boolean
+ addVariable(String name, int value)

10
Example: SRP (possible) solution

TermTokenizer
+ nextTerm() : String
+ hasMoreTerms() : boolean

RuleEvaluator
RuleParser
+ evaluate(String rule)
+ parse(String rule) : Expression
+ addVariables(String, int)

creates

{abstract}
SymbolTable
Expression
+ addVariable(String, int)
+ evaluateWith(SymbolTable table)

11
OCP: The Open-Closed Principle

Software entities( classes, modules, functions, etc.) should be


open for extension, but closed for modification
“Open for extension”
The behavior of the module can be extended (e.g., by subclassing)
“Closed for modification”
Extending the behavior of a module does not result in changes to the existing source code
or binary code of the module

12
Example: OCP – Strategy Pattern

OCP cannot be fully achieved


E.g.,

13
OCP heuristics

Look for duplicated code

Look at the change history


Classes that frequently change together

Apply potential change scenarios


Which classes would be affected by the change?

14
LSP: Liskov Substitution Principle

Subtypes must be substitutable for their base types


LSP defines the OO inheritance principle
If a client uses a base class, then it should not differentiate the base class
from derived class

In terms of design by contract


Precondition equal or weaker
Must accept anything the base class could accept
Postcondition equal or stronger
Must not violate the post-condition of the base class

15
LSP violation example
public enum ShapeType {square, circle};
Violate OCP
public class Shape {
public static void DrawShape(Shape s) {
if(s.type == ShapeType.square)
(s as Square).Draw();
else if(s.type == ShapeType.circle) Not
substitutable
(s as Circle).Draw();
}
}
public class Circle : Shape {
public void Draw() {/* draws the circle */}
}
public class Square : Shape{
public void Draw() {/* draws the square */}
}
16
Another LSP violation example
void g(Rectangle r)
Square is not
{ Rectangle!
r.setWidth(5);
r.setHeight(4);
if(r.getArea() != 20)
throw new Exception("Bad area!");
}

Square’s behavior is
changed, so it is not
IS-A Relationship substitutable to
Rectangle

17
LSP heuristics

Check the contracts of base and sub classes


Every LSP violation is a violation of OCP but not vice versa

18
DIP: The Dependency Inversion Principle

High-level modules should not depend on low-level modules


Both should depend on abstractions

Abstractions should not depend on details


Details should depend on abstractions

DIP is at the very heart of framework design

19
A DIP example
DIP

DIP violation

20
DIP heuristics

Depend on abstractions
No variable should hold a reference to a concrete class
No class should derive from a concrete class
No method should override an implemented method of any of its base
classes

Heuristic is typically violated at least once


Somebody has to create the instances of the concrete classes
-> No reason to strictly follow this heuristic for classes that are concrete
but non-volatile

21
ISP: The Interface Segregation Principle

Clients should not be forced to depend on methods they do


not use
Design cohesive interfaces and avoid "fat" interfaces
The dependency of one class to another one should depend on the
smallest possible interface
The interfaces of the class can be broken up into groups of methods
Each group serves a different set of clients

22
An violation of ISP example

ISP violation

23
An ISP Violation example: solution

Segregated
interface

24
ISP heuristics

Check classes with a high number of public methods


Group clients according to their calls of the public methods
Check for methods that frequently change together

25
LoD - Law of Demeter

Principle of Least Knowledge

Only talk to your immediate friends

Don’t talk to strangers

Write “shy” codes

Minimize coupling

26
LoD formal definition

A method M of an object O may only invoke the methods of


the following kinds of objects
O itself
M's parameters
Any objects created/instantiated within M
O's direct component objects

27
Example LoD
class Demeter {
public A a;
public int func() {
// do something
}
public void example(Arg arg) {
C c = new C();
int f = func(); // functions belonging to itself
arg.invert(); // to passed parameters
a = new A();
a.setActive(); // to any objects it has created
c.print(); // to any held objects
}
}

28
LoD violation example
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

a.getB().getC().doSomething()

29
DRY – Don’t Repeat Yourself

Every piece of knowledge must have a single, unambiguous,


authoritative representation within a system

Following DRY will make software systems easier to


understand and maintain

30
More information on Design Principles

Agile Software Development: Principles Patterns, and Practices


Robert C. Martin, Prentice Hall, 2002

31
Intensive Coupling(120), Shotgun Surgery(133)
Classification Disharmonies (Chapter 7): Refused Parent Bequest(145),
Tradition Breaker(152)
Design Disharmonies

32
Collaboration
Disharmonies
Collaboration Disharmonies

Limit collaboration intensity


Operations should collaborate (mainly unidirectional) with a limited
number of services provided by other classes

Limit collaboration extent


Operations (and consequently their classes) should collaborate with
operations from a limited number of other classes

Limit collaboration dispersion


An entity should collaborate closely only with a selected set of entities,
preferable located in the
same abstraction
same hierarchy
same package (or sub- system)

34
provider classes is excessively verbose. Therefore, we named this de-
sign disharmony Intensive Coupling.
Intensive Coupling

Fig. 6.2. Illustration of Intensive Coupling


35
6.3 Intensive Coupling 12

The detection strategy is based on two main conditions that mus


be fulfilled simultaneously: the function invokes many methods an
Intensive Coupling: Detection Strategy the invoked methods are not very much dispersed into many classe
22 6 Collaboration Disharmonies (Fig. 6.3).
Additionally, based on our practical experience, we impose a min
imal complexity condition on the function, to avoid the case of config
uration operations (e.g., initializers, or UI configuring methods) tha
Operation calls too many
methods call many other methods. These configuration operations reveal a les
harmful (and hardly avoidable) form of coupling because the depen
CINT > Short Memory Cap dencies can be much easily traced and solved.
AND The detection strategy is composed of the following heuristics (se
Class are "dispersed" in Fig. 6.3):
few classes

CDISP < HALF


Operation
Method calls methods
calls too many too from
OR manyfewmethods
unrelatedfrom few
classes
and unrelated classes
Operation calls more than Intensive
AND
a few methods Coupling
Method has few nested
CINT > FEW conditionals

AND MAXNESTING > SHALLOW


Calls are "dispersed" in
very few classes
Fig. 6.3. Intensive Coupling detection strategy.
CDISP < A QUARTER

1. Operation calls too many methods from a few unrelated classe


Fig. 6.4. In Intensive Coupling operation calls too many
Themethods from a for
basic condition fewa method or function to be considered a
unrelated classes having an Intensive Coupling is to call many methods belongin
to a few classes (Fig. 6.4). By “unrelated classes” we mean tha
the provider classes are belonging to the the same class hierarch
36
Intensive Coupling: Example
124 6 Collaboration Disharmonies

37
Intensive Coupling: Class Blueprint
6.3 Intensive Coupling 125

Fig. 6.6. The class ClassDiagramLayouter is intensively coupling with a few


classes, especially ClassDiagramNode.
38
ch class.

Dispersed Coupling

39
conditionals

MAXNESTING > SHALLOW

Dispersed Coupling: Detection Strategy


128 6 Collaboration
Fig. 6.9. Dispersed Coupling detection strategy Disharmonies

Detection The detection rule is defined in the same terms as the the one define
for Intensive Coupling(120), with only one complementary differenc
we capture only those operations that have a high dispersion of the
coupling (Fig. 6.9). The detection strategy in detail is:

Operation calls too many


methods
Operation calls a few methods from
CINT > Short Memory Cap each of a largecalls
Operation number
a few
AND of unrelated
methods from classes
each of a large
Calls are dispersed in number of unrelated classes Dispersed
AND
many classes Operation has few nested Coupling
conditionals
CDISP  HALF
MAXNESTING > SHALLOW

ig. 6.10. In Dispersed Coupling operation calls a few methods from each of
Fig. 6.9. Dispersed Coupling detection strategy
large number of unrelated classes.

. Operation calls a few methods from each of a large number


of unrelated classes. This term of the Operation
detection rules
calls too many imposes
two conditions: an intensive coupling, i.e., the methods
invocation of many
methods from other classes (CINT - Coupling Intensity),
CINT > Short Memory Cap and a Operation calls a few
40
large dispersion among classes of these invoked operations (CDISP AND methods from each of a lar
should have a non-trivial nesting level, to make sure that irrele-
vant cases (like initializer functions) are skipped.
Dispersed Coupling: Example

41
pling strength but also the coupling dispersion.
Shotgun Surgery

42
dependencies caused by function calls. In order to reveal especially
those cases where dependencies are harder to trace, we will count
Shotgun Surgery:
only those operations Detection
(and classes) Strategy
that are neither belonging to the
same class nor to the same class hierarchy with the measured oper-
ation.

Operation is called by too many


other methods

CM > Short Memory Cap


AND Shotgun Surgery
Incoming calls are from
many classes

CC > MANY

Fig. 6.14. Shotgun Surgery detection strategy

Based on all the considerations above, the detection technique is


43
detected.
Shotgun Surgery: Example

Fig. 6.15. Project provides an impressive example of a class with several


methods affected by Shotgun Surgery(133). Due to these methods, Project is
coupled with 131 classes (ModelFacade has been elided from the screen-
shot). Furthermore, the class has cyclic invocation dependencies with Pro-44
Tool to Detect Collaboration Disharmonies

inCode
http://loose.upt.ro/incode/pmwiki.php/

45
More info on Detection Strategies

Object-Oriented Metrics in Practice


Michele Lanza and Radu Marinescu, Springer 2006
http://www.springer.com/computer/swe/book/
978-3-540-24429-5

46
Summary

The OO design principles help us:


As guidelines when designing flexible, maintainable and reusable
software
As standards when identifying the bad design
As laws to argue when doing code review

Keep the design of a system as simple, clean, and expressive as


possible
Don’t allow broken windows
Apply them in iterations (not to a big, up-front design)
Sometimes you have to make trade-offs

47

You might also like