Best Practices & Common Pitfalls
Keep each project in Git with a baseline and rebuild images from scratch regularly; write tests first and run them constantly; use the debugger as a development tool; prefer refactorings over manual edits; learn the system with Spotter, senders, and impleme…
43.1 Style
Intention-revealing names: includes:, isEmpty, totalBalance, addAccount:; argument names describe roles or types (anInteger, aCollection).
Small methods (often 1–7 lines); one level of abstraction per method; *Composed Method* (Kent Beck).
Tell, don't ask: send a message to the object that has the data rather than pulling data out.
Replace type checks (isKindOf:, class =) with polymorphism.
Return self implicitly; use ^ only to return something meaningful or exit early.
Use cascades and yourself in constructors; keep instance creation on the class side.
Comment classes (CRC style), not every method; write executable examples and tests.
Format with the built-in formatter; follow *Pharo with Style* conventions.
43.2 Common pitfalls
Expecting arithmetic precedence Parenthesize: 2 + (3 * 4) Forgetting yourself in a cascade
OrderedCollection new add: 1; add: 2 → 2 Add ; yourself Two keyword messages without parentheses dict at: #k put: list at: 1 dict at: #k put: (list at: 1) Using == to compare strings 'abc' == 'abc'
Use = (identity is for symbols, small integers, singletons) Overriding = without hash Sets/Dictionaries lose objects Always override both Forgetting super initialize Superclass state left nil Call it first in initialize Modifying a collection while iterating oc do: [:x | oc remove: x ] Iterate over a copy, or use reject: detect: without ifNone: NotFound error at runtime Use detect:ifNone:
Expecting add: to return the collection x:= oc add: 3 add: returns the element Treating nil as false nil ifTrue: [...] Test isNil / notNil explicitly Mutating literal arrays/strings #(1 2) at: 1 put: 0 Send copy first Blocking the UI process 5 seconds wait in a button action fork long work; defer: UI updates Non-local return from a dead method storing a block with ^ and running it later Avoid ^ in stored blocks Redefining a system class by accident Object << #Rectangle...
Prefix or check Smalltalk globals includesKey: first Code only in the image Image corrupted, work lost Commit to Git via Iceberg often
printString vs displayString confusion 'abc' printString → '''abc'''
Use displayString for user-facing text perform: with computed selectors everywhere Prefer explicit messages Forgetting to unsubscribe announcements Memory leaks, ghost updates unsubscribe: or weak subscriptions
43.3 Working practices
Keep each project in Git with a baseline and rebuild images from scratch regularly; write tests first and run them constantly; use the debugger as a development tool; prefer refactorings over manual edits; learn the system with Spotter, senders, and implementors — read the source, it's all there; prefix class names in shared libraries (Zn, Sp, RS) since Pharo has one global namespace; run CI with smalltalkCI on several Pharo versions.