Pattern: Code Layout


Context

When writing Smaltalk code a well formatted method will be easier to read and understand. The use of a consistent style also relieves a developer of the thought burden associated with code formatting.

Solution

Follow these guidelines to achieve a consistent readablecode layout.

Keep your methods short

Short methods are easier to write and easier to read. Perhaps more importantly, since they aggregate less function they are easier to override in new subclasses.

Method Header

Choose a selector and its parameter names according to Method Name. Keep the method header on one line unless it is too long to fit within a 'reasonable' width, in which case wrap it on keywords and indent the subsequent lines.

indexOfSubCollection:aSequenceableCollection startingAt: anInteger
	text: textString line: lineNumber range: anInterval
	selector: selector in: codeString for: aClass

Comments

Comment a method according to Comments. The method comment should start on the line immediately after the method header and it should be indented by one tab. If the comment is long, wrap it on word boundaries so that it will fit into a 'reasonable' width. Each line should be indented by one tab. There should be one blank line between the end of the comment and beginning of the code.

isEmpty
	"Answer whether the receiver contains no elements."
	^self size == 0
x: xCoord y: yCoord
	"Answer a new instance of the receiver with the specified
	x and y coordinates"
	^self basicNew x: xCoord y: yCoord

Message Send

Keep a message send on one line if it will fit. Split long keyword message sends over several lines with one parameter per line, indenting each subsequent line by one tab.

receiver shortSelector.
receiver
	long: ...
	keyword: ...
	message: ... 
receiver
	message1;
	cascadedMessage2;
	cascadedMessage3.

Blocks

Blocks are often passed as parameters. If the block is short, keep it on one line. Keep the block on the same line as the selector if it will fit. If the block can't fit on the same line, then start it on the next line and indent it by one tab. If the block is too long for one line, then format it as normal method source, keeping the square brackets on the same lines as the start and end of the block.

shortReceiver message: [shortBlock]
shortReceiver message: [ 
	long. 
	block 
long expression resulting in receiver
	message: [shortBlock]
long expression resulting in receiver
	message: [
		long.
		block] 
receiver
	ifTrue: [shortBlock1]
	ifFalse: [shortBlock2]
receiver
	 ifTrue: [ 
		long.
		block]
        ifFalse: [shortBlock] 

Guard Clause

In languages with long functions it is considered good practice to avoid multiple function exits. However, in Smalltalk the methods are generally short and the multiple exit restriction can be lifted in favour of reducing excessive nested testing.

actualClass
	"Answer the actual class selected in the receiver after taking account
	of instance or class mode. Answer nil if there is no class selected"

	| selectedClass |
	selectedClass := self basicClass.
	selectedClass isNil ifTrue: [^nil].
	^self isInstanceMode
		ifTrue: [ selectedClass ]
		ifFalse: [ selectedClass class ]

Related Patterns