Layers of Smalltalk Application

42
Dependence Management Bob Martin says “Object- oriented programming is dependence management.” See his “Design Principles and Design Patterns” at http://www.objectmentor.com/ resources/articles/ Principles_and_Patterns.PDF

Transcript of Layers of Smalltalk Application

Page 1: Layers of Smalltalk Application

Dependence Management

Bob Martin says “Object-oriented programming is dependence management.”

See his “Design Principles and Design Patterns” at

http://www.objectmentor.com/resources/articles/Principles_and_Patterns.PDF

Page 2: Layers of Smalltalk Application

Dependence

How can one package depend on another? Reuse a class

• By inheritance

• By instantiation (direct reference) Reuse a variable Reuse a method?

Page 3: Layers of Smalltalk Application

Dependence

If package A depends on package B then you can’t run the tests for A unless you also have B.

“A depends on B” means you can’t use A unless you have B.

“Package A depends on package B” means that something in A depends on something in B.

Page 4: Layers of Smalltalk Application

Cycles of dependence

If package A depends on package B then package B should NOT depend on package A.

If classes C and D both depend on each other, put them in the same package.

Page 5: Layers of Smalltalk Application

Eliminating dependence

The Observer pattern eliminates dependence.

Suppose that “FBIAgent” is an observer of Mobster. Mobster is a subclass of Model, so it can have observers. Class FBIAgent probably depends on class Mobster, but Mobster does not depend on FBIAgent.

Page 6: Layers of Smalltalk Application

Observer Pattern

ObserverObserver

update:update:

SubjectSubject

addDependent: addDependent: removeDependent: removeDependent: changed:changed:

MobsterMobsterrobBankrobBankdriveCardriveCar

FBIAgentFBIAgent

update:update:

observer/observer/dependentdependent

modelmodel

*

Page 7: Layers of Smalltalk Application

Smalltalk base library

GUI library Application

Application GUI SUnit tests

Page 8: Layers of Smalltalk Application

Abstract Server

Bob Martin’s name for “depend on an interface, not on a concrete class”.

Interface

ClientServer

Creation scriptConsumer <<interface>>

ResourceManager

ResrcMgr1

Page 9: Layers of Smalltalk Application

AdapterIntent: Convert the interface of a class into another interface

clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

AdapteeAdapterTarget

Page 10: Layers of Smalltalk Application

Adapter

Target

Request()

Client

AdapterRequest()

Adaptee

Page 11: Layers of Smalltalk Application

Adapter

Allows client and adaptee to be unchanged

Adapter is usually ugly

Client Adaptee

Adapter

Page 12: Layers of Smalltalk Application

Mediator

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Example: Insurance policies must be approved before they are issued. There is a procedure (which can change over time, and which is different for different kinds of policies) for approving a policy. This procedure must interact with work queues of managers and with the history that is kept on the customer. Instead of putting this procedure in the insurance policy, put it in a separate object that is easy to change. (This is a “business process”)

Page 13: Layers of Smalltalk Application

Not Mediator

CustomerHistory

InsurancePolicy

Worker

Page 14: Layers of Smalltalk Application

Mediator

Procedure

CustomerHistory

InsurancePolicy

Worker

Mediator

Colleagues

If interaction is main thing that changes, then make the interaction be an object.

Colleague classes become more reusable.

Mediator is the non-reusable part.

Page 15: Layers of Smalltalk Application

Mediator

Procedure

CustomerHistory InsurancePolicy Worker

Business Rule

Domain Objects

Mediator

Colleagues

Page 16: Layers of Smalltalk Application

Application Model

Mediator between widgets and domain model.

PayrollSystemInterface

ListView TextView EmployeePayrollSystem

Page 17: Layers of Smalltalk Application

Façade

Provide a unified interface to a set of interfaces in a subsystem. Define a higher-level interface that makes the subsystem easier to use.

Facade

Page 18: Layers of Smalltalk Application

The Compiler

Scanner

Return Expression

SmalltalkExpression

Compilercompileevaluate

CompiledMethod

AssignmentExpression

Message Expression

...

Parser

Page 19: Layers of Smalltalk Application

Creational Patterns

Factory Method

Factory Object

Abstract Factory

Builder

Prototype

Singleton

Page 20: Layers of Smalltalk Application

Factory MethodDon't (call constructor / send message to class)

directly.

Make a separate function / method to create object.

How to do it: Find every class name in “producer” Extract it (or perhaps “CN new”) into a

method

Page 21: Layers of Smalltalk Application

Factory Method

Results: Localizes dependencies Modules become less coupled Reduces coupling Can lead to parallel class hierarchies

Page 22: Layers of Smalltalk Application

Factory Method

Producer

doSomething

ConcreteProducer

createXXcreateXX

^XX new

doSomething …self createXX...

XX

Page 23: Layers of Smalltalk Application

Factory Object

Problem with factory method -- have to create subclass to parameterize.

Often end up with parallel class hierarchies.

Example: subclass of Tool for each figure you want to create

Alternative: parameterize CreationTool with object that creates figure

Smalltalk automatically creates a factory for every class, the Class!

(Note: Factory Object is generalization of Abstract Factory,Builder, and Prototype. It is not in the book.)

Page 24: Layers of Smalltalk Application

Applicability

Use factory objects:

when system creates them automatically

when more than one class needs to have product specified

when most subclasses only specialize to override factory method

Page 25: Layers of Smalltalk Application

FigureFactory new

LineFigureFactory

ElipseFigureFactory

RectangleFigureFactory

Figure

LineFigure ElipseFigure RectangleFigure

Page 26: Layers of Smalltalk Application

Prototype

Making a class hierarchy of factories seems wasteful.

The parameters of an object can be as important as its class.

Solution:

Use any object as a factory by copying it to make a new instance.

Advantages

Don't need new factory hierarchy.

Can make new "class" by parameterizing an object

Disadvantages

Requires robust copying

Page 27: Layers of Smalltalk Application

Making Prototype

You have a design in which objects are parameterized by passing in classes. You are making new classes just for their constructors, or you want to make “composite classes”.

Make sure “copy” works. Define “new” as an instance method that returns a copy. Change client to pass in instances instead of classes.

Page 28: Layers of Smalltalk Application

Abstract Factory

Sometimes a group of products are related -- if you change one, you might need to change them all.

Solution:

Make a single object that can make any of the products.

ScrollBar

MotifScrollBar PMScrollBar

WidgitFactoryCreateScrollBarCreateWindow

MotifWidgetFactoryCreateScrollBarCreateWindow

PMWidgetFactoryCreateScrollBarCreateWindow

Page 29: Layers of Smalltalk Application

Making Abstract Factory

Give Producer a component called “Factory” Create class Factory Add instance variable “factory” to Producer Change constructor to have line

factory:=Factory newMove factory methods to Factory

Copy factory method to Factory Change sends of createFoo to “factory

createFoo”

Page 30: Layers of Smalltalk Application

Builder

Complex objects require a lot of work to make.

Solution:

Factory must keep track of partly built product.

Client specifies product by performing series of operations on factory.

Client

WindowBuilderAddScrollBarAddButtonGetWindow

Page 31: Layers of Smalltalk Application

Implementing Builder

WidgitFactoryCreateScrollBarCreateWindow

WindowBuilderAddScrollBarAddButtonGetWindow

PMWidgetFactoryCreateScrollBarCreateWindow

MotifWidgetFactoryCreateScrollBarCreateWindow

Builder can make components using

Factory Method

Abstract Factory, or

Prototype

Page 32: Layers of Smalltalk Application

Making BuilderThere are several places in your system where a

complex object is built. These places need to mention a lot of classes, unless you use a pattern like Abstract Factory.

Constructors get complicated. Perhaps there are a lot of class methods that deal with construction. Construction needs temporary variables.

Make a class that builds the object for you. It hides the concrete classes that are used and temporary variables used during construction.

Result: Producers not coupled with Product. Builder is coupled with Product.

Page 33: Layers of Smalltalk Application

Summary of Factory Patterns

Factory method -- use in simple cases so that you can change product

Abstract factory -- use when there is a set of related products

Builder -- use when product is complex

Prototype -- use when Factory Method is awkward and when classes are not objects, or when you want to specify new "classes" by composition

Page 34: Layers of Smalltalk Application

Singleton

What if you want to make sure that a class has only one instance?

One possibility is global variables. Another is using class methods.

Best solution: store single instance in class variable.

Page 35: Layers of Smalltalk Application

Singleton

The singleton class has a class variable “Instance” and a class method

instance

Instance isNil ifTrue: [Instance := super new].

^Instance

Alternative: make “Instance” a class instance variable.

Page 36: Layers of Smalltalk Application

Managing dependences

Cost of eliminating dependences More abstract Harder to test Harder to understand

It is OK to depend on stable packages.

Stable = doesn’t change = has many dependents

Page 37: Layers of Smalltalk Application

Managing dependences

Subsystem2

Application

Library3

Library1

Library2

Subsystem1

Page 38: Layers of Smalltalk Application

Managing dependences

Application2

Subsystem2

Subsystem1

Application1

Suppose Application2 depends on only a small part of Subsystem1, and that part doesn’t depend on Subsystem2

Page 39: Layers of Smalltalk Application

Managing dependences

Application2

Subsystem2Subsystem3

Application1

Subsystem1

Page 40: Layers of Smalltalk Application

Dependence management

Determines Build times Difficulty of testing Frequency of rebuilding and retesting Ease of reuse

Design patterns help control dependences

Page 41: Layers of Smalltalk Application

Design patterns and refactoring

Patterns are most useful for complex systems.

Add them later by refactoring Keep system simple – no unnecessary

patterns Keep system flexible – all needed

patterns

Page 42: Layers of Smalltalk Application

Next time

More on Observer and creational patterns.