SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the...

21
SOLID PRINCIPLE

Transcript of SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the...

Page 1: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

SOLID PRINCIPLE

Page 2: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

OCP :Open/Closed Principle

Extension points

Page 3: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension PointsClasses that honor the OCP should be open to extension by

containing defined extension points where future functionality can hook into the existing code and provide new behaviors.

Code without extension points

Page 4: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension Points (cont’d)

f you allow changes to existing code where they have no client impact, you might not have to create an entirely new version of the TradeProcessor.

If the ProcessTrades method signature were to change, this would not simply be an implementation change for the class, it would also be an interface change.

All interface changes force client changes because clients are tightly coupled to the interfaces of their dependencies.

Page 5: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension Points: Virtual Methods

An alternative implementation for the TradeProcessor

class contains an extension point: the ProcessTrades

method is virtual.

Any class that marks one of its members as virtual

is open to extension

This type of extension is via implementation

inheritance.

When the requirement for a new feature in the

TradeProcessor class arrives, you can subclass the

existing TradeProcessor and—without modifying its

source code—alter the ProcessTrades method.

The TradeProcessorClient does not need to change in

this case. Because

It is possible to use polymorphism to supply the

client with the new version of the TradeProcessor

It is possible to call the subclass’s implementation

of the ProcessTrades method.

Page 6: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Virtual Methods (cont’d)

If we allow changes to existing code where they have no client impact, we might not have to create an entirely new version of the TradeProcessor.

If the ProcessTrades method signature were to change, this would not simply be an implementation change for the class, it would also be an interface change.

All interface changes force client changes because clients are tightly coupled to the interfaces of their dependencies.

Page 7: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension Points: Abstract Methods

A more flexible extension point that uses implementation inheritance is an abstract method.

The TradeProcessor is an abstract class that defines a public ProcessTradesmethod, which delegates the work of the processing algorithm to three protected abstract methods.

The client has no knowledge of these protected methods and, because they are abstract, no implementation is provided.

Page 8: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Abstract methods (Cont’d)

These methods need not be abstract; they could be virtual.

The difference here is mainly the granularity of what has been made extensible.

Rather than replacing the ProcessTrades method in its entirety, you can now replace select parts of the process by overriding the constituent methods.

Page 9: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Virtual Functions in Java

In Java, all non-static methods are by default "virtual functions."

Only methods marked with the keyword final cannot be overridden

The methods are private methods

The methods are not inherited,

The methods are non-virtual.

Page 10: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension Point: Interface Inheritance

The client depends on an interface rather than a class.

Interface inheritance is preferable to

implementation inheritance.

With implementation inheritance:

all subclasses are clients.

This prevents modification

subclasses depend on the

implementation

All implementation changes are

potentially client-aware changes.

The advice is to prefer composition over

inheritance and to keep inheritance

hierarchies shallow, with few layers of

subclassing.

If a change is made to add a member at

the top of the inheritance graph, that

change affects all members of the

hierarchy.

Page 11: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Extension Point: Interface Inheritance

Interfaces are better extension points because they can be decorated with rich object graphs of functionality

Object graphs of functionality touch upon many different contexts.

Object graphs are more flexible than classes.

The writer’s point of view (Gary McLean Hall- Adaptive Code:Agilecoding with design patterns and SOLID principles):

«I don’t mean that the virtual and abstract methods that form the

extension points of class inheritance are not useful, but that they do not provide quite the same level of adaptability as do interfaces»

Page 12: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

“Design for Inheritance or Prohibit it”

In his book Effective Java (Addison-Wesley, 2008), Joshua Bloch has this to say about inheritance:

Design and document for inheritance or else prohibit it.

If you choose to use implementation inheritance as an extension point, you must design and document the class properly so as to protect and inform future programmers who extend the class.

Inheritance of classes can be tricky

New subclasses can break existing code in unpredictable ways.

Page 13: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

OCP Principle: Protected Variation

«Identify points of predicted variation and create a stable interface

around them».

Alistair Cockburn, Pattern Languages of Program Design, vol. 2 , 1996)

The requirements of an individual class should be linked directly to a business client’s requirement.

If this link is ignored, there is a risk that the class will not serve any purpose that the business client requested.

In fact, user stories are taken from the sprint backlog, and developers and the product ownerHere, questions should be asked as to the potential for future, related

requirements.

This informs the predicted variation that can be translated into extension points.

Page 14: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

The Liskov Substitution Principle (LSP)

If S is a subtype of T, then objects of type T may be replaced with objects of type S, without breaking the program.

There are three code ingredients relating to the LSP

Base type The type (T) that clients have reference to.

Clients call various methods, any of which can be overridden—or partially specialized—by the subtype.

Subtype Any one of a possible family of classes (S) that inherit from the base type (T).

Clients should not know which specific subtype they are calling, nor should they need to.

The client should behave the same regardless of the subtype instance that it is given.

Context The way in which the client interacts with the subtype.

If the client doesn’t interact with a subtype, the LSP can neither be honored nor contravened.

Page 15: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

LSP RulesThe LSP rules can be split into two categories

Contract rules (relating to the expectations of classes)

Variance rules (relating to the types that can be substituted in code)

Page 16: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Contract Rules

Page 17: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

LSP Rules

Preconditions cannot be strengthened in a subtype

you cannot require more than the parent

Postconditions cannot be weakened in a subtype

You cannot guarantee less than the parent

Invariants of the supertype must be preserved in a subtype.

Page 18: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

Interface Contracts

Contravariant

Covariant

Invariant

covariance is a relationship where subtypes go with each other,

contravariance is a relationship where subtypes go against each other.

When we talk about covariance and contravariance then subtypes and supertypes comes first in discussion.Subtypes can substitute for Supertypes.

Page 19: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

CovarianceWhen function return values can changed to subtypes, covariance is

moving down the hierarchy.

class Product {

func calculateShippingCost() -> BaseShippingStrategy {

return BaseShippingStrategy()

} }

class PhoneProduct: Product {

// An instance of a subclass can always be substituted for an instance of

its superclass.

override func calculateShippingCost() -> WorldShippingStrategy {

return WorldShippingStrategy()

} }

Page 20: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

ContravarianceWhen function parameters can be changed to supertypes, contravariance is

moving up the hierarchy.

On modifying parameter type to subtype down the hierarchy, we get Method doesn't override error

class Product {

func order(strategy:

WorldShippingStrategy) {

} }

class PhoneProduct: Product {

override func order(strategy:

BaseShippingStrategy) {

} }

Page 21: SOLID PRINCIPLE · coding with design patterns and SOLID principles): «I don’t mean that the virtual and abstract methods that form the extension points of class inheritance are

FINALLY with No LLP Rule

Protocol LoginUseCase define method to be implemented by class.

Client who consumes use case should be able to work with both

DefaultLoginUseCase , MockLoginUseCase without any change in code.