+ All Categories
Home > Documents > Design Principles

Design Principles

Date post: 30-Dec-2015
Category:
Upload: shelly-golden
View: 27 times
Download: 0 times
Share this document with a friend
Description:
Design Principles. Hans Van Vliet, Software Engineering, Principles and Practice, 3 rd edition, John Wiley & Sons, 2008. Section 12.1. Robert C. Martin, Clean Code: A Handdbook of Agile Software Craftsmanship, Prentice Hall, 2008. - PowerPoint PPT Presentation
Popular Tags:
49
CS 4311 1 Design Principles Hans Van Vliet, Software Engineering, Principles and Practice, 3 rd edition, John Wiley & Sons, 2008. Section 12.1. Robert C. Martin, Clean Code: A Handdbook of Agile Software Craftsmanship, Prentice Hall, 2008. Joshua Bloch, Effective Java, 2 nd edition, Addition Wesley, 2008.
Transcript
Page 1: Design Principles

CS 4311 1

Design Principles

Hans Van Vliet, Software Engineering, Principles and Practice, 3rd edition, John Wiley & Sons, 2008. Section 12.1.Robert C. Martin, Clean Code: A Handdbook of Agile Software Craftsmanship, Prentice Hall, 2008.Joshua Bloch, Effective Java, 2nd edition, Addition Wesley, 2008.

Page 2: Design Principles

2CS 4311

Outline

Encapsulate what varies Minimize access of members Favor composition over inheritance Program to interface Open-closed principle Liskov substitution principle

Why?

Page 3: Design Principles

3CS 4311

Abstraction

“Abstraction arises from a recognition of similarities between certain objects, situations, or processes in the real world, and the decision to concentrate upon those similarities and to ignore for the time being the differences.” Tony Hoare

“An abstraction denotes the essential characteristics of an object that distinguish it from all other kinds of objects and thus provide crisply defined conceptual boundaries, relative to the perspective of the viewer.” Grady Booch

Q: Examples in programming/code? Q: Why abstraction?

Page 4: Design Principles

4CS 4311

Encapsulation

“Encapsulation is the process of compartmentalizing the elements of an abstraction that constitute its structure and behavior; encapsulation serves to separate the contractual interface of an abstraction and its implementation.” Grady Booch

“Encapsulation is a mechanism used to hide the data, internal structure, and implementation details of an object. All interaction with the object is through a public interface of operations.” Craig Larman

Q: Language constructs that support encapsulation? Q: Why encapsulation?

Page 5: Design Principles

5CS 4311

Minimize the Accessibility of Classes and Members Classes should be opaque Classes should not expose their internal implementation details Use getters and setters

Compare

public double speed;

vs

private double speed; public double getSpeed() { return speed; } public void setSpeed(double speed) { this.speed = speed; }

Page 6: Design Principles

6CS 4311

Minimize the Accessibility of Classes and Members Classes should be opaque Classes should not expose their internal implementation details Use getters and setters

Compare

public double speed;

vs.

private double speed; public double getSpeed() { return speed; } public void setSpeed(double speed) { this.speed = speed; }

Is this better?Why?

Page 7: Design Principles

7CS 4311

Advantages of Minimizing Accessibility

Centralized checking of constraints Add useful side-effects (monitoring) Decouple internal representation from

function: Improved encapsulationReduced coupling of components

Page 8: Design Principles

8CS 4311

Outline

Encapsulate what varies Minimize access of members Favor composition over inheritance Program to interface Open-closed principle Liskov substitution principle

Page 9: Design Principles

9CS 4311

Composition vs. Subclassing

Two different methods for code reuse Delegation (prototype) vs inheritance (OO) Black box vs. white/grey box reuse Q: pros and cons? which one to use?

A B A B

Page 10: Design Principles

10CS 4311

Composition

Method of reuse in which new functionality is obtained by creating an object composed of other objects New functionality obtained by delegating to objects being

composed Sometimes called aggregation or containment

Aggregation - when one object owns or is responsible for another object and both objects have identical lifetimes (GoF)

Aggregation - when one object has a collection of objects that can exist on their own (UML)

Containment - a special kind of composition in which the contained object is hidden from other objects and access to the contained object is only via the container object (Coad)

A B

Page 11: Design Principles

11CS 4311

Advantages of Composition

Contained objects are accessed by the containing class solely through their interfaces

"Black-box" reuse, since internal details of contained objects are not visible

Good encapsulation Fewer implementation dependencies Each class is focused on just one task (cohesion) The composition can be defined dynamically at run-time

through objects acquiring references to other objects of the same type

Page 12: Design Principles

12CS 4311

Disadvantages of Composition

Resulting systems tend to have more objects Interfaces must be carefully defined in order to

use many different objects as composition blocks

Page 13: Design Principles

13CS 4311

Inheritance

Method of reuse in which new functionality is obtained by extending the implementation of an existing object

The generalization class (superclass) explicitly captures the common attributes and methods

The specialization class (subclass) extends the implementation with additional attributes and methods

A B

Page 14: Design Principles

14CS 4311

Advantages of Inheritance

New implementation is easy, since most of it is inherited

Easy to modify or extend the implementation being reused

Page 15: Design Principles

15CS 4311

Disadvantages of Inheritance

Breaks encapsulation, since it exposes a subclass to implementation details of its superclass

"White-box" reuse, since internal details of superclasses are often visible to subclasses

Subclasses may have to be changed if the implementation of the superclass changes

Implementations inherited from superclasses can not be changed at runtime.

Page 16: Design Principles

16CS 4311

Example (from Effective Java by Bloch)

public class InstrumentedHashSet<E> extends HashSet<E> {

private int addCount = 0; // The number of attempted element insertions

public InstrumentedHashSet() { super(); }

public boolean add(E e) { addCount++; return super.add(e); }

public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }

public int getAddCount() { return addCount; }}

Variant of HashSet that tracks number of insertions

Page 17: Design Principles

17CS 4311

Example Variant of HashSet that tracks number of insertions

Keep track of insertions

Call super constructor

public class InstrumentedHashSet<E> extends HashSet<E> {

private int addCount = 0; // The number of attempted element insertions

public InstrumentedHashSet() { super(); }

public boolean add(E e) { addCount++; return super.add(e); }

public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }

public int getAddCount() { return addCount; }}

Page 18: Design Principles

18CS 4311

Example Variant of HashSet that tracks number of insertions

When we add, update the counter

public class InstrumentedHashSet<E> extends HashSet<E> {

private int addCount = 0; // The number of attempted element insertions

public InstrumentedHashSet() { super(c); }

public boolean add(E e) { addCount++; return super.add(e); }

public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }

public int getAddCount() { return addCount; }}

Page 19: Design Principles

19CS 4311

Example: Test It---Add!public class InstrumentedHashSetTest { private InstrumentedHashSet<String> set;

@Before public void setUp() { set = new InstrumentedHashSet<String>(); } @Test public void testAdd() { assertEquals(0, set.getAddCount()); set.add("CS4311"); assertEquals(1, set.getAddCount()); set.add("Fun"); assertEquals(2, set.getAddCount()); }

% java org.junit.runner.JUnitCore InstrumentedHashSetTest

JUnit version 4.10

.

Time: 0

OK (1 test)

Page 20: Design Principles

20CS 4311

Example: Test It---AddAll!public class InstrumentedHashSetTest { … @Test public void testAddAll() {

set.addAll(Arrays.asList(new String[] {"CS4311", "Fun"})); assertEquals(2, set.getAddCount()); }

% java org.junit.runner.JUnitCore InstrumentedHashSetTest

JUnit version 4.10

..E

Time: 0.015

There was 1 failure:

1) testAddAll(InstrumentedHashSetTest)

java.lang.AssertionError: expected:<2> but was:<4>

at …

FAILURES!!!

Tests run: 2, Failures: 1

Page 21: Design Principles

21CS 4311

Example: Test it---AddAll!public class InstrumentedHashSetTest { … @Test public void testAddAll() {

set.addAll(Arrays.asList(new String[] {"CS4311", "Fun"})); assertEquals(2, set.getAddCount()); }

% java org.junit.runner.JUnitCore InstrumentedHashSetTest

JUnit version 4.10

..E

Time: 0.015

There was 1 failure:

1) testAddAll(InstrumentedHashSetTest)

java.lang.AssertionError: expected:<2> but was:<4>

at …

FAILURES!!!

Tests run: 2, Failures: 1

Test success or failure?

What went wrong?

Page 22: Design Principles

22CS 4311

Example: Investigate It!

Look at the API document, e.g., JDK 8 says

public boolean addAll(Collection<? Extends E> c) of AbstractCollection

Adds all of the elements in the specified collection to this collection (optional operation). …This implementation iterates over the specified collection, and adds each object returned by the iterator to this collection, in turn. …

Look at the source code. The internal implementation of addAll() in the superclass

superclass invokes the add() method! First we add 2 to addCount in InstrumentedHashSet’s

addAll(). Then we invoke super’s addAll().

For each element, this addAll() invokes the add() method, which as overridden by InstrumentedHashSet adds one for each

element.

Page 23: Design Principles

23CS 4311

Example: Investigate It!

Look at the API document, e.g., JDK 7 says

public boolean addAll(Collection<? Extends E> c) of AbstractCollection

Adds all of the elements in the specified collection to this collection (optional operation). …This implementation iterates over the specified collection, and adds each object returned by the iterator to this collection, in turn.

Look at the source code. The internal implementation of addAll() in the superclass

superclass invokes the add() method! First we add 2 to addCount in InstrumentedHashSet’s

addAll(). Then we invoke super’s addAll().

For each element, this addAll() invokes the add() method, which as overridden by InstrumentedHashSet adds one for each

element.

Need to know the implementation

details to get this right!

Page 24: Design Principles

24CS 4311

Example: Fix It! Variant of HashSet that tracks number of insertions

public class InstrumentedHashSet<E> extends HashSet<E> {

private int addCount = 0; // The number of attempted element insertions

public InstrumentedHashSet() { super(c); }

public boolean add(E e) { addCount++; return super.add(e); }

public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }

public int getAddCount() { return addCount; }}

Page 25: Design Principles

25CS 4311

Example: Fix It! Variant of HashSet that tracks number of insertions

public class InstrumentedHashSet<E> extends HashSet<E> {

private int addCount = 0; // The number of attempted element insertions

public InstrumentedHashSet() { super(c); }

public boolean add(E e) { addCount++; return super.add(e); }

public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }

public int getAddCount() { return addCount; }}

Any concerns?

Hint: Program to interface

Page 26: Design Principles

26CS 4311

Example: Composition

Let’s write an InstrumentedSet class that is composed of a Set object.

Our InstrumentedSet class will duplicate the Set interface, but all Set operations will actually be forwarded to the contained Set object.

The contained Set object can be an object of any class that implements the Set interface (and not just a HashSet)

InstrumentedSet Set

Page 27: Design Principles

27CS 4311

Examplepublic class InstrumentedSet<E> implements Set<E> { private final Set<E> s;

private int addCount = 0;

public InstrumentedSet() { s = new HashSet<E>(); }

public boolean add(E e) { addCount++; return s.add(e); }

public boolean addAll(addAll(Collection<? Extends E> c) { addCount += c.size(); return s.addAll(c); }

public int getAddCount() { return addCount; }

Page 28: Design Principles

28CS 4311

Example: Forwarding methods

public void clear() { s.clear(); } public boolean contains(E e) { return s.contains(e); }public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator iterator() { return s.iterator(); } public boolean remove(E e) { return s.remove(e); }public boolean containsAll(Collection<? Extends E> c) { return s.containsAll(c); } public boolean removeAll(Collection<? Extends E> c) { return s.removeAll(c); } public boolean retainAll(Collection<? Extends E> c) { return s.retainAll(c); } public E[] toArray() { return s.toArray(); } public E[] toArray(E[] a) { return s.toArray(a); } public boolean equals(E e) { return s.equals(e); } public int hashCode() { return s.hashCode(); } public String toString() { return s.toString(); }

Page 29: Design Principles

29CS 4311

Coad's RulesUse inheritance only when all of the following criteria are satisfied:

A subclass expresses “is a special kind of” and not “is a role played by a.”An instance of a subclass never needs to become an object of another class.A subclass extends, rather than overrides or nullifies, the responsibilities of its superclass.A subclass does not extend the capabilities of what is merely a utility class.For a class in the actual Problem Domain, the subclass specializes a role, transaction or device.

Page 30: Design Principles

30CS 4311

Outline

Encapsulate what varies Minimize access of members Favor composition over inheritance Program to interface Open-closed principle Liskov substitution principle

Page 31: Design Principles

31CS 4311

Program to an Interface, not an Implementation Q: interface vs. implementation?

A sorted set class provides a “choose” operation that returns an arbitrary element contained in the set. You learned that the operation always returns the smallest element of the set. Is this an interface or implementation feature?

Why?

service provider

service user

Client <<interface>>List

<<uses>>

LinkedList ArrayList

X

Page 32: Design Principles

32CS 4311

Interface

Interfaces express types in a limited way. An interface is the set of methods one object knows that

it can invoke on another object. An object can have many interfaces. Different objects can have the same type and the same

object can have many different types. An object is known by other objects only through its

interface.

Page 33: Design Principles

33CS 4311

Example

public class InstrumentedSet<E> implements Set<E> { private final Set<E> s;

private int addCount = 0;

public InstrumentedSet(Set<E> s) { this.s = s; }

public boolean add(E e) { addCount++; return s.add(e); }

public boolean addAll(addAll(Collection<? Extends E> c) { addCount += c.size(); return s.addAll(c); }

public int getAddCount() { return addCount; }

Which lines?

Page 34: Design Principles

34CS 4311

Example

public class InstrumentedSet<E> implements Set<E> { private final Set<E> s;

private int addCount = 0;

public InstrumentedSet(Set<E> s) { this.s = s; }

public boolean add(E e) { addCount++; return s.add(e); }

public boolean addAll(addAll(Collection<? Extends E> c) { addCount += c.size(); return s.addAll(c); }

public int getAddCount() { return addCount; }

Which lines?

Page 35: Design Principles

35CS 4311

Advantages:

Clients are unaware of the specific class of the object they are using.

One object can be easily replaced by another. Object connections need not be hardwired to an object

of a specific class, thereby increasing flexibility Loosens coupling. Increases likelihood of reuse Improves opportunities for composition since contained

objects can be of any class that implements a specific interface

Page 36: Design Principles

36CS 4311

Outline

Encapsulate what varies Minimize access of members Favor composition over inheritance Program to interface Open-closed principle Liskov substitution principle

Page 37: Design Principles

37CS 4311

Open/Closed Principle

Software should be open for extension, but closed for modification

Page 38: Design Principles

38CS 4311

Open/Closed Principle

The Open-Closed Principle (OCP) says that we should attempt to design modules that never need to be changed.

To extend the behavior of the system, we add new code. We do not modify old code.

Modules that conform to the OCP meet two criteria: Open For Extension - The behavior of the module can be extended to meet new

requirements. Closed For Modification - the source code of the module is not allowed to

change.

How can we do this? Abstraction Polymorphism Inheritance Interfaces Design patterns such as template methods New programming paradigms or languages such as AOP and AspectJ

Page 39: Design Principles

39CS 4311

Open/Closed Principle Consider the following method that totals the price of each part in the

specified array of parts of some class:

public double totalPrice(Part[] parts) { double total = 0.0; for (Part p: parts) { total += p.getPrice(); } return total; }

If Part is a base class or an interface and polymorphism is being used, then this class can easily accommodate new types of parts without having to be modified!

It conforms to the OCP.

Page 40: Design Principles

40CS 4311

Open/Closed Principle Suppose the Accounting Department decrees that motherboard

parts and memory parts should have a premium applied when figuring the total price.

public double totalPrice(Part[] parts) { double total = 0.0; for (Part p: parts) { if (p instanceof Motherboard) total += (1.45 * p.getPrice()); else if (p instanceof Memory) total += (1.27 * p.getPrice()); else total += p.getPrice(); } return total; }

Page 41: Design Principles

41CS 4311

Open/Closed Principle Suppose the Accounting Department decrees that motherboard

parts and memory parts should have a premium applied when figuring the total price.

public double totalPrice(Part[] parts) { double total = 0.0; for (Part p: parts) { if (p instanceof Motherboard) total += (1.45 * p.getPrice()); else if (p instanceof Memory) total += (1.27 * p.getPrice()); else total += p.getPrice(); } return total; }

Is this OK?

Page 42: Design Principles

42CS 4311

Open/Closed Principle Suppose the Accounting Department decrees that motherboard

parts and memory parts should have a premium applied when figuring the total price.

public double totalPrice(Part[] parts) { double total = 0.0; for (Part p: parts) { if (p instanceof Motherboard) total += (1.45 * p.getPrice()); else if (p instanceof Memory) total += (1.27 * p.getPrice()); else total += p.getPrice(); } return total; }

Does not conform to OCP.

totalPrice() must be changed whenever Accounting changes pricing policy.

What could we do instead?

Page 43: Design Principles

43CS 4311

Open/Closed Principle

A better idea is to have a PricePolicy class which can be used to provide different pricing policies:

public class Part { private double price; private PricePolicy pricePolicy;

public void setPricePolicy(PricePolicy pricePolicy) { this.pricePolicy = pricePolicy; }

public void setPrice(double price) { this.price = price; } public double getPrice() { return pricePolicy.getPrice(price); } }

Part PricePolicy

Page 44: Design Principles

44CS 4311

Open/Closed Principle

/** * Class PricePolicy implements a given price policy. */ public class PricePolicy { private double factor; public PricePolicy (double factor) { this.factor = factor; } public double getPrice(double price) { return price * factor; } }

Page 45: Design Principles

45CS 4311

Open/Closed Principle

/** * Class PricePolicy implements a given price policy. */ public class PricePolicy { private double factor; public PricePolicy (double factor) { this.factor = factor; } public double getPrice(double price) { return price * factor; } }

Pricing policies can be set dynamically by changing the PricePolicy object.

Multiple pricing policy classes may exist.

Page 46: Design Principles

46CS 4311

Pair; 2 minutes

An example of OCP application from standard libraries or frameworks like JDK?

Page 47: Design Principles

47CS 4311

Outline

Encapsulate what varies Minimize access of members Favor composition over inheritance Program to interface Open-closed principle Liskov substitution principle

Page 48: Design Principles

48CS 4311

Liskov Substitution Principle

An object of a subtype may be substituted for an object of its supertypes. An object of a subtype should behave like an object of

its supertypes.

Q: Why? A program that uses supertypes must be able to use

objects of the subtypes.

Barbara Liskov, Turing Award 2008

Page 49: Design Principles

49CS 4311

Substitution Principle --- How?

Syntactically:If a method T1 m(T2 x) of class T is overridden in a subclass S,

T2_S is a superclass of T2_T (contra-variance of argument types)

T1_S is a subclass of T1_T (covariance of return type)

Q: Java rule?Q: How about exceptions that may be thrown?

Semantically:An overriding method should behave like an overridden methodPre_T Pre_S

Post_S Post_T


Recommended