stoop ed-lod

22
Stéphane Ducasse 1 Stéphane Ducasse [email protected] http://stephane.ducasse.fr ee.fr/ Design Points - Law of Demeter Stéphane Ducasse --- 2005

Upload: the-world-of-smalltalk

Post on 29-Nov-2014

557 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Stoop ed-lod

Stéphane Ducasse 1

Stéphane [email protected]://stephane.ducasse.free.fr/

Design Points - Law of Demeter

Stéphane Ducasse --- 2005

Page 2: Stoop ed-lod

S.Ducasse 2

About Coupling• Why coupled classes is fragile design?• Law of Demeter• Thoughts about accessor use

Page 3: Stoop ed-lod

S.Ducasse 3

Coupling hampers...

ReuseI cannot reuse this component in another application

SubstitutionI cannot substitute easily this component for another one

EncapsulationWhen a far away change happens, I get impacted

Page 4: Stoop ed-lod

S.Ducasse 4

The Core of the Problem

Page 5: Stoop ed-lod

S.Ducasse 5

The Law of Demeter

You should only send messages to:an argument passed to you instance variablesan object you createself, superyour classAvoid global variablesAvoid objects returned from message sends other than self

Page 6: Stoop ed-lod

S.Ducasse 6

Correct Messages

someMethod: aParameterself foo.super someMethod: aParameter.self class foo.self instVarOne foo.instVarOne foo.aParameter foo.thing := Thing new.thing foo

Page 7: Stoop ed-lod

S.Ducasse 7

In other words• Only talk to your immediate friends. • In other words:

• You can play with yourself. (this.method())• You can play with your own toys (but you can't

take them apart). (field.method(), field.getX())• You can play with toys that were given to you.

(arg.method())• And you can play with toys you've made

yourself. (A a = new A(); a.method())

Page 8: Stoop ed-lod

S.Ducasse 8

Halt!

Page 9: Stoop ed-lod

S.Ducasse 9

To not skip your intermediate

Page 10: Stoop ed-lod

S.Ducasse 10

Solution

Page 11: Stoop ed-lod

S.Ducasse 11

Transformation

Page 12: Stoop ed-lod

S.Ducasse 12

Heuristic of Demeter

Not a lawKnow when you can bend it or not apply itEncapsulating collections may produce large interfaces so not applying the LoD may help.

Page 13: Stoop ed-lod

S.Ducasse 13

Collections

Object subclass: #AinstVar: myCollection

A>>do: aBlock myCollection do: aBlock

A>>collect: aBlock ^ myCollection collect: aBlock

A>>select: aBlock ^ myCollection select: aBlock

A>>detect: aBlock ^ myCollection detect: aBlock

A>>isEmpty ^ myCollection isEmpty

…………………

Page 14: Stoop ed-lod

S.Ducasse 14

About the Use of Accessors

Some schools say: “Access instance variables using methods”

In such a caseBe consistent inside a class, do not mix direct access and accessor useThink accessors as protected methods (not invoked by clients)in ST: put them in accessing only when public

Page 15: Stoop ed-lod

S.Ducasse 15

Accessors

Accessors are good for lazy initialization

Scheduler>>tasks tasks isNil ifTrue: [task := ...]. ^ tasks

BUT accessors methods should be Protected by default at least at the beginning

Page 16: Stoop ed-lod

S.Ducasse 16

Example

Scheduler>>initializeself tasks: OrderedCollection new.

Scheduler>>tasks^ tasks

But now everybody can tweak the tasks!

Page 17: Stoop ed-lod

S.Ducasse 17

Accessors open Encapsulation

The fact that accessors are methods doesn’t support a good data encapsulation. You could be tempted to write in a client:

ScheduledView>>addTaskButton...model tasks add: newTask

What’s happen if we change the representation of tasks?

Page 18: Stoop ed-lod

S.Ducasse 18

Tasks

If tasks is now an array, it will break

Take care about the coupling between your objects and provide a good interface!

Schedule>>addTask: aTasktasks add: aTask

ScheduledView>>addTaskButton...model addTask: newTask

Page 19: Stoop ed-lod

S.Ducasse 19

About Copy Accessor

Should I copy the structure?

Scheduler>>tasks ^ tasks copy

But then the clients can get confused...

Scheduler uniqueInstance tasks removeFirstand nothing happens!

Page 20: Stoop ed-lod

S.Ducasse 20

You will read code

Code that others wrote

Code that you wrote and forgot

Page 21: Stoop ed-lod

S.Ducasse 21

Use intention revealing names

Probably Better

Scheduler>>taskCopy or copiedTasks “returns a copy of the pending tasks”

^ task copy

Page 22: Stoop ed-lod

S.Ducasse 22

Provide a Complete Interface

Workstation>>accept: aPacketaPacket addressee = self name…

It is the responsibility of an object to offer a complete interface that protects itself from client intrusion.Shift the responsibility to the Packet objectPacket>>isAddressedTo: aNode

^ addressee = aNode nameWorkstation>>accept: aPacket

(aPacket isAddressedTo: self)ifTrue:[ Transcript show: 'A packet is accepted by the

Workstation ', self name asString]ifFalse: [super accept: aPacket]