se2_lec 19_design principles and design patterns

70
1 رَ ـدْ ـقِ ن،،، لماننا نصدق اْ قِ ن رَ د رَ ـدْ ـقِ ن،،، لماننا نصدق اْ قِ ن رَ د

Upload: amr-e-mohamed

Post on 06-Apr-2017

119 views

Category:

Software


0 download

TRANSCRIPT

1َدرِنقْْنصدق اننالما،،، ِنـْقـَدر َدرِنقْْنصدق اننالما،،، ِنـْقـَدر

2

Design bridges that gap between knowing what is needed

(software requirements specification) to entering the code

that makes it work (the construction phase).

Design is both a verb and a noun.

3

During the design phase, software engineers apply their

knowledge of the problem domain and implementation

technologies in order to translate system specifications

into plans for the technical implementation of the

software.

The resulting design expresses the overall structure and

organization of the planned implementation. It captures

the essence of the solution independent of any

implementation language.

4

There is a famous cartoon showing

two professors at a chalkboard

examining a proof that includes the

step “then a miracle occurs”.

At times it seems like this is the

most that can be hoped for during

software design.

5

There is a process for design but not an algorithm.

Software design is a heuristic rather than deterministic

process.

No reliable process for conjuring up a design

6

Poorly designed programs are difficult to understand and

modify.

The larger the program, the more pronounced are the

consequences of poor design.

Cost of adding the ith feature to a well-designed and poorly designed program

7

To better understand how good design can minimize

technical complexity, it’s helpful to distinguish between

two major types of complexity in software:

Essential complexities – complexities that are inherent in

the problem.

Accidental/incidental complexities – complexities that are

artifacts of the solution.

The total amount of complexity in a software solution is:

ESSENTIAL COMPLEXITIES + ACCIDENTAL COMPLEXITIES

8

Design is the primary tool for managing essential and

accidental complexities in software.

Good design doesn't reduce the total amount of essential

complexity in a solution but it will reduce the amount of

complexity that a programmer has to deal with at any

one time.

A good design will manage essential complexities

inherent in the problem without adding to accidental

complexities consequential to the solution.

9

MODULARITY – subdivide the solution into smaller

easier to manage components. (divide and conquer)

INFORMATION HIDING – hide details and complexity

behind simple interfaces

10

ABSTRACTION – use abstractions to suppress details in

places where they are unnecessary.

HIERARCHICAL ORGANIZATION – larger components

may be composed of smaller components. Examples: a

complex UI control such as tree control is a hierarchical

organization of more primitive UI controls. A book

outline represents the hierarchical organization of ideas.

11

Design is difficult because design is an abstraction of the

solution which has yet to be created

12

The term wicked problem was first used to describe

problems in social planning but engineers have

recognized it aptly describes some of the problems they

face as well.

A wicked problem is one that can only be clearly defined

by solving it.

Need two solutions. The first to define the problem, and

the second to solve it in the most efficient way.

Fred Brooks could have been talking about wicked

problems when he advised: “Plan to throw one away;

you will anyhow.”

13

Any product that is an aggregate of more primitive

elements, can benefit from the activity of design.

14

Standard Levels of Design

15

Non-deterministic – A deterministic process is one that

produces the same output given the same inputs. Design

is non-deterministic. No two designers or design

processes are likely to produce the same output.

Heuristic – because design is non-deterministic design

techniques tend to rely on heuristics and rules-of-thumb

rather than repeatable processes.

Emergent – the final design evolves from experience and

feedback. Design is an iterative and incremental process

where a complex system arises out of relatively simple

interactions.

16

Good design reduces software complexity which makes the

software easier to understand and modify. This facilitates

rapid development during a project and provides the

foundation for future maintenance and continued system

evolution.

It enables reuse. Good design makes it easier to reuse

code.

It improves software quality. Good design exposes defects

and makes it easier to test the software.

Complexity is the root cause of other problems such as

security. A program that is difficult to understand is more

likely to be vulnerable to exploits than one that is simpler.

17

1. Understand the problem (software requirements).

2. Construct a “black-box” model of solution (system specification).

System specifications are typically represented with use cases

(especially when doing OOD).

3. Look for existing solutions (e.g. architecture and design patterns)

that cover some or all of the software design problems identified.

4. Design not complete? Consider using one or more design techniques

to discover missing design elements

Noun-verb analysis, CRC Cards, step-wise refinement, etc.

Take final analysis model and pronounce a first-draft design

(solution) model

5. Consider building prototypes

6. Document and review design

7. Iterate over solution (Refactor) (Evolve the design until it meets

functional requirements and maximizes non-functional

requirements)

18

User requirements and system specification (including

any constraints on design and implementation options)

Domain knowledge (For example, if it’s a healthcare

application the designer will need some knowledge of

healthcare terms and concepts.)

Implementation knowledge (capabilities and limitations

of eventual execution environment)

19

Patterns play an important role in the design methods of

today

20

Methods and patterns are the principle techniques for

dealing with the challenges of design

They are useful for:

Creating a design

Documenting and communicating a design

Transferring design knowledge and experience between

practitioners

21

A design pattern is a reusable solution to a commonly

occurring design problem

Design patterns are adapted for the unique

characteristics of the particular problem

Just as there are levels of design, there are levels of

design patterns:

Architecture Styles/Patterns

Design Patterns

Programming Idioms

22

23

Robert Martin

"AGILE SOFTWARE DEVELOPMENT: PRINCIPLES,

PATTERNS, AND PRACTICES“

“CLEAN CODE”

24

Design is generally

“THE DECISIONS WE TAKE TO BUILD SOMETHING”

Design + implementation = Product

If we apply this to software:

DESIGN

+

PROGRAMMING / CODING

=

SOFTWARE PRODUCT

25

CHANGEis

The only constant in software

26

if

CHANGEis

The only constant in software

Then

MODIFIABILITYIs a vital design consideration

27

Increased difficulty to adapt and maintain

Causes

Communication/Documentation breakdown

• Maintainers not fully familiar with the original design

principles -> change works, but…

Design is not resilient in the face of change

28

Characteristics of a bad design:

RIGIDITY - It is hard to change because every change affects

too many other parts of the system.

FRAGILITY - When you make a change, unexpected parts of

the system break.

IMMOBILITY - It is hard to reuse in another application

because it cannot be disentangled from the current

application.

VISCOSITY: The law of least resistance when faced with a

choice

• Design viscosity: Hacks are easier/faster than preserving the

design

• Environment viscosity: Slow cycle time -> fastest choice

29

SOLID

Single Responsibility Principle

Open Closed Principle

Liskov Substitution Principle

Interface Segregation Principle

Dependency Inverison Principle

Code becomes more Testably (remember TDD is not only

about testing, more important its about Design)

30

"There should never be more than one reason for a class

to change." — Robert Martin, SRP paper linked from The

Principles of OOD

My translation: A class should concentrate on doing one

thing and one thing only

31

Two resposibilities

Connection Management + Data Communication

interface Modem {

public void dial(String pno);

public void hangup();

public void send(char c);

public char recv();

}

32

Separate into two interfaces

interface DataChannel {

public void send(char c);

public char recv();

}

interface Connection {

public void dial(String phn);

public char hangup();

}

33

"Software entities (classes, modules, functions, etc.)

should be open for extension, but closed for

modification." — Robert Martin paraphrasing Bertrand

Meyer, OCP paper linked from The Principles of OOD

My translation: Change a class' behavior using

inheritance and composition

34

// Open-Close Principle - Bad example

class GraphicEditor {

public void drawShape(Shape s) {

if (s.m_type==1)

drawRectangle(s);

else if (s.m_type==2)

drawCircle(s);

}

public void drawCircle(Circle r) {....}

public void drawRectangle(Rectangle r) {....}

}

class Shape {

int m_type;

}

class Rectangle extends Shape {

Rectangle() {

super.m_type=1;

}

}

class Circle extends Shape {

Circle() {

super.m_type=2;

}

}

35

Impossible to add a new Shape without modifying

GraphEditor

Important to understand GraphEditor to add a newShape

Tight coupling between GraphEditor and Shape

Difficult to test a specific Shape without involvingGraphEditor

If-Else-/Case should be avoided

36

// Open-Close Principle - Good example

class GraphicEditor {

public void drawShape(Shape s) {

s.draw();

}

}

class Shape { //super class

abstract void draw();

}

class Rectangle extends Shape {

public void draw() {

// draw the rectangle

}

}

37

"Functions that use pointers or references to base

classes must be able to use objects of derived classes

without knowing it." — Robert Martin, LSP paper linked

from The Principles of OOD.

My translation: Subclasses should behave nicely when

used in place of their base class

38

// Violation of Liskov's Substitution Principle

class Rectangle

{

int m_width;

int m_height;

public void setWidth(int width){

m_width = width;

}

public void setHeight(int ht){

m_height = ht;

}

public int getWidth(){

return m_width;

}

public int getHeight(){

return m_height;

}

public int getArea(){

return m_width * m_height;

}

}

class Square extends Rectangle

{

public void setWidth(int width){

m_width = width;

m_height = width;

}

public void setHeight(int height){

m_width = height;

m_height = height;

}

}

39

class LspTest{private static Rectangle getNewRectangle(){

// it can be an object returned by some factory ... return new Square();

}

public static void main (String args[]){

Rectangle r = LspTest.getNewRectangle();r.setWidth(5);r.setHeight(10);

// user knows that r it's a rectangle. It assumes that he's able to set the width and height as for the base class

System.out.println(r.getArea());// now he's surprised to see that the area is 100 instead of 50.

}}

40

"Clients should not be forced to depend upon interfaces

that they do not use." — Robert Martin, ISP paper linked

from The Principles of OOD

My translation: Keep interfaces small

41

Don’t force classes so implement methods they can’t

(Swing/Java)

Don’t pollute interfaces with a lot of methods

Avoid ’fat’ interfaces

42

//bad example (polluted interface)

interface Worker {

void work();

void eat();

}

ManWorker implements Worker {

void work() {…};

void eat() {30 min break;};

}

RobotWorker implements Worker {

void work() {…};

void eat() {//Not Appliciable

for a RobotWorker};

}

43

Solution

- split into two interfaces

interface Workable {

public void work();

}

interface Feedable{

public void eat();

}

44

"A. High level modules should not depend upon low

level modules. Both should depend upon abstractions.

B. Abstractions should not depend upon details. Details

should depend upon abstractions." — Robert Martin, DIP

paper linked from The Principles of OOD

My translation: Use lots of interfaces and abstractions

45

//DIP - bad example

public class EmployeeService {

private EmployeeFinder emFinder //concrete class, not abstract. Can access a SQL DB for instance

public Employee findEmployee(…) {

emFinder.findEmployee(…)

}

}

46

Now its possible to change the finder to be a

XmlEmployeeFinder, DBEmployeeFinder,

FlatFileEmployeeFinder, MockEmployeeFinder….

//DIP - fixed

public class EmployeeService {

private IEmployeeFinder emFinder //depends on an abstraction, no an implementation

public Employee findEmployee(…) {

emFinder.findEmployee(…)

}

}

47

http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

http://www.oodesign.com

http://www.slideshare.net/enbohm

48

49

In software engineering, a design pattern is a general

repeatable solution to a commonly occurring problem in

software design.

A design pattern isn't a finished design that can be

transformed directly into code. It is a description or

template for how to solve a problem that can be used in

many different situations.

50

A design pattern

Design Patterns are time-tested common solutions to

recurring design problems.

Are the answer to a question that commonly arises “How

can I … ?”

Abstracts a recurring design structure

Comprises class and/or object

• Dependencies

• Structures

• Interactions

• Conventions

Names & specifies the design structure explicitly

Distils design experience

51

52

Can reuse solutions

Gives us a head start (mostly design, but implementation

too)

Avoids unanticipated results as we are using time-tested

solutions

No need to reinvent the wheel

Establish common terminology

Design patterns provide a common point of reference

53

Design patterns gained popularity in computer

science after a certain book was published in

1994 by four authors, commonly know as Gang

of Four or GOF

Gang of Four (GoF) Gamma, Helm, Johnson,

Vlissides, - founders of movement.

Gamma et al, Design Patterns: Elements of

Reusable Object-Oriented Software,

Addison Wesley, 1995.

They offer advice and help for developing

quality software

An object-oriented design pattern

systematically names, explains and evaluates

an important and recurring design in object-

oriented systems.

54

A design pattern has 4 basic parts:

1. Pattern Name

2. Problem

3. Solution

4. Consequences and trade-offs of application

Language- and implementation-independent

A “micro-architecture”

Adjunct to existing methodologies (Unified, OMT, etc.)

No mechanical application

The solution needs to be translated into concrete terms in the

application context by the developer

55

Codify good design

Distil and disseminate experience

Aid to novices and experts alike

Abstract how to think about design

Give design structures explicit names

Common vocabulary

Reduced complexity

Greater expressiveness

Capture and preserve design information

Articulate design decisions succinctly

Improve documentation

Facilitate restructuring/refactoring

Patterns are interrelated

Additional flexibility

56

Patterns

Creational

BehavioralStructural

57

Ensure a class only has one instance, and provide a

global point of access to it.

Singleton

58

Motivation

How to cleanly provide access to a global variable?

Structure

Output

59

There must be exactly one instance of a class, and it

must be accessible to clients from a well-known access

point.

When the sole instance should be extensible by

subclassing, and clients should be able to use an

extended instance without modifying their code.

60

Controlled access to sole instance.

Reduced name space.

Permits refinement of operations and representation

Permits a variable number of instances.

61

Hayes

Modem

USR Modem

Zoom

Modem

Modem< ? >

File Sync

Dedicated Modem

Send ()

Receive()

Dial () {}

Hangup () {}

Send ()

Receive()

Dial ()

Hangup ()

62

Hayes

Modem

USR Modem

Zoom

Modem

Modem

File Sync

Send ()

Receive()

Dial ()

Hangup ()

Dedicated Modem

Send ()

Receive()

Dedicated Modem

Adapter

Send ()

Receive()

Dial () {}

Hangup () {}

ADAPTER(wrapper)

Convert the interface of a class into

another interface clients expect. Adapter

lets classes work together that couldn't

otherwise because of incompatible

interfaces.

64

Motivation:

Reuse of existing codebase in a situation that it did

not anticipate.

structure:

65

Applicability:

You want to use an existing class, and its interface does

not match the one you need

Consequences:

The amount of adapting is needed

Conceptual distance between adapter and adaptee can

cause undesirable side effects

Observer(Publish-Subscribe)

Define a one-to-many dependency between

objects so that when one object changes

state, all its dependents are notified and

updated automatically.

68

Motivation:

Maintain consistency between collaborating objects

while maintaining loose coupling

Structure:

69

Applicability:

When an abstraction has two aspects, one dependent on

the other.

When a change to one object requires changing others,

and you don't know how many objects need to be changed.

When an object should be able to notify other objects

without making assumptions about who these objects are.

Consequences:

Abstract coupling between Subject and Observer

Support for broadcast communication

Unexpected updates

Dangling References

Memory Issues

70