Avoid Null Checks Damien Cassou, Stphane Ducasse and Luc Fabresse - - PowerPoint PPT Presentation

avoid null checks
SMART_READER_LITE
LIVE PREVIEW

Avoid Null Checks Damien Cassou, Stphane Ducasse and Luc Fabresse - - PowerPoint PPT Presentation

Avoid Null Checks Damien Cassou, Stphane Ducasse and Luc Fabresse W7S07 http://www.pharo.org Anti If Campaign Main >> showHappiness: animal animal isDog ifTrue: [ animal shakeTail ]. animal isDuck ifTrue: [ animal quack ]. animal


slide-1
SLIDE 1

Avoid Null Checks

Damien Cassou, Stéphane Ducasse and Luc Fabresse

W7S07

http://www.pharo.org

slide-2
SLIDE 2

Anti If Campaign

Main >> showHappiness: animal animal isDog ifTrue: [ animal shakeTail ]. animal isDuck ifTrue: [ animal quack ]. animal isCat: [ ... ]. Branching (with if) based on the type of an object is bad:

adding a new type requires modifying all such code methods will become very long and full of details

Send messages instead

W7S07 2 / 12

slide-3
SLIDE 3

Anti If Campaign

Dog >> showHappiness self shakeTail Duck >> showHappiness self quack Cat >> showHappiness ... Branching (with if) based on the type of an object is bad

adding a new type requires modifying all such code methods will become very long and full of details

Send messages instead

W7S07 3 / 12

slide-4
SLIDE 4

Do Not Return Nil

Inferencer >> rulesForFact: aFact self noRule ifTrue: [ ^ nil ] ^ self rulesAppliedTo: aFact

ifTrue: [ ^ nil ] forces every client to check for nil:

(inferencer rulesForFact: 'a') ifNotNil: [ :rules | rules do: [ :each | ... ]

W7S07 4 / 12

slide-5
SLIDE 5

Return Polymorphic Objects

When possible, replace if by polymorphic objects:

when returning a collection, return an empty one when returning a number, return 0

Inferencer >> rulesForFact: aFact self noRule ifTrue: [ ^ #() ] ^ self rulesAppliedTo: aFact Your clients can just iterate and manipulate the returned value (inferencer rulesForFact: 'a') do: [:each | ... ]

W7S07 5 / 12

slide-6
SLIDE 6

For Exceptional Cases, Use Exceptions

For exceptional cases, replace nil by exceptions:

avoid error codes because they require if in clients exceptions may be handled by the client, or the client’s

client, or ... FileStream >> nextPutAll: aByteArray canWrite ifFalse: [ self cantWriteError ]. ... FileStream >> cantWriteError (CantWriteError file: file) signal

W7S07 6 / 12

slide-7
SLIDE 7

Initialize Your Object State

Avoid nil checks by initializing your variables

by default instance variables are initialized with nil

Archive >> initialize super initialize. members := OrderedCollection new

W7S07 7 / 12

slide-8
SLIDE 8

Use Lazy Initialization if Necessary

You can defer initialization of a variable to its first use: FreeTypeFont >> descent ^ cachedDescent ifNil: [ cachedDescent := (self face descender * self pixelSize // self face unitsPerEm) negated ]

W7S07 8 / 12

slide-9
SLIDE 9

Sometimes you have to check...

Sometimes you have to check before doing an action

if you can, turn the default case into an object

ToolPalette >> nextAction self selectedTool ifNotNil: [ :tool | tool attachHandles ] ToolPalette >> previousAction self selectedTool ifNotNil: [ :tool | tool detachHandles ]

W7S07 9 / 12

slide-10
SLIDE 10

Use NullObject

NoTool >> attachHandles ^ self NoTool >> detachHandles ^ self ToolPalette >> initialize self selectedTool: NoTool new ToolPalette >> nextAction self selectedTool attachHandles ToolPalette >> previousAction self selectedTool detachHandles

a null object proposes a polymorphic API and embeds

default actions/values

Woolf, Bobby (1998). "Null Object". In Pattern Languages

  • f Program Design 3. Addison-Wesley.

W7S07 10 / 12

slide-11
SLIDE 11

Conclusion

A message acts as a better if Avoid null checks, return polymorphic objects instead Initialize your variables If you can, create objects representing default behavior W7S07 11 / 12

slide-12
SLIDE 12

A course by and in collaboration with

Inria 2016 Except where otherwise noted, this work is licensed under CC BY-NC-ND 3.0 France https://creativecommons.org/licenses/by-nc-nd/3.0/fr/