35
Naming in Swift Part 3: Boundary Words
With the introduction of async/await to Swift, this article may have already aged poorly.
In fact I wrote the first draft of this for Objective-C, before Swift even existed!
In fact I wrote the first draft of this for Objective-C, before Swift even existed!
There are some words that appear in pairs through Swift APIs:
start
and stop
start
and finish
begin
and end
I am calling these boundary words, as they delimit the boundarys of certain actions, events or processes.
Although theses words are considered synonyms of each other in plain English,
they take on distinct semantics and should no longer be considered synonyms in Swift.
they take on distinct semantics and should no longer be considered synonyms in Swift.
Furthermore, due to this specialisation, there are certain pairings that make sense and some pairings that you don't see as often.
For example, you typically won't see
For example, you typically won't see
start()
paired with end()
, nor begin()
with finish()
even though these constructs would be perfectly fine in ordinary English.APIs use start and stop to convey a long-running task that is happening in human-perceivable time.
Here are some examples:
URLProtocol
has startLoading()
and stopLoading()
AVCaptureSession
has startRunning()
and stopRunning()
UIImageView
has startAnimating()
and stopAnimating()
Things that can be stopped can usually be started again. This means the object will have state.
Where you see
Where you see
startPerformingTask
and stopPerformingTask
you often also see isPerformingTask
.Sometimes start is paired with finish.
Here are some examples:
AVAssetWriter
has startWriting()
and finishWriting(completionHandler:)
PHContentEditingController
has startContentEditing(…)
and finishContentEditing(completionHandler:)
Unlike stop, finish is not simply the opposite of start.
It specifically denotes that there is some sort of final phase to the task.
For example, flushing the contents of a buffer, writing to the disk, or cleaning up resources.
It specifically denotes that there is some sort of final phase to the task.
For example, flushing the contents of a buffer, writing to the disk, or cleaning up resources.
You see APIs with complete when they have completion handlers.
The concept of completion specifically denotes the boundary of the task between the caller and callee.
The concept of completion specifically denotes the boundary of the task between the caller and callee.
Here are some examples with both finish and complete:
AVAssetWriter.finishWriting(completionHandler:)
HKWorkoutBuilder.finishWorkout(completion:)
In these APIs, finish is refering to the final phase of the task that needs to be performed before control is transferred back to the caller in the completion handler.
These pairs normally appear within the same lexical code block, and are used to group operations into batches, transactions or other constructs.
Here are some examples:
UITableView
has beginUpdates
and endUpdates
MTLCaptureScope
has begin
and end
OSSignposter
has beginInterval
and endInterval
These APIs were much more common in Objective-C prior to the introduction of block syntax.
In Swift these would be good candidates to improve using closures.
In Swift these would be good candidates to improve using closures.
When writing this I did find a lot of examples in Apple's APIs that contradicted my definitions above.
For one, in the Swift Standard Library, collections have a start index and end index.
These definitions aren't hard rules, but I believe they are more consistent than not and that makes them worthwhile to know.
Many design patterns that have corresponding vocabulary already defined.
If possible, why not use a common vocabulary — it will only make your APIs feel more at home.
Many design patterns that have corresponding vocabulary already defined.
If possible, why not use a common vocabulary — it will only make your APIs feel more at home.
35