包含所有需要的单词,以避免人们在阅读调用处的代码时感到困惑。
譬如,有一个方法,要在集合(collection)中移除指定位置的元素。
推荐:
extension List {
public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)
如果我们删掉方法签名中的at,那就给人一种该方法是搜索并删除集合中等于x 的元素的感觉,而不是用x来指示元素在集合中的位置,并把该位置的元素删除。
不推荐:
employees.remove(x) // unclear: are we removing x?
删除不需要的单词。名字中的每个单词都应该在调用处传达出重点信息。
更多的单词或许能澄清意图和消除歧义,但是那些读者已经知道的冗余信息都可以删掉,尤其是那些仅仅重复了类型信息的单词。
不推荐:
public mutating func removeElement(member: Element) -> Element?
allViews.removeElement(cancelButton)
上述情况下,Element在调用处没有提供任何要点信息,如下 API 会更好。
推荐:
public mutating func remove(member: Element) -> Element?
allViews.remove(cancelButton) // clearer
个别情况下,重复类型信息对于消除歧义是必要的,但一般来说,用一个表明参数角色(role)而不是类型的词,会更好一些。详情请参看下一条。
基于变量、参数、关联类型的角色来对它们进行命名,而不是基于它们的类型。
不推荐:
var string = "Hello"
protocol ViewController {
associatedtype ViewType : View
}
class ProductionLine {
func restock(from widgetFactory: WidgetFactory)
}
像这样重申一遍类型名并不能最大程度提升明确性和表现力。相反,我们应该尽量选用那些表明实体角色的名字。
推荐:
var greeting = "Hello"
protocol ViewController {
associatedtype ContentView : View
}
class ProductionLine {
func restock(from supplier: WidgetFactory)
}
如果某个关联类型和它的协议联系非常紧密,以至于它的协议名就是它的角色名,那就给关联类型的名字加上Type避免冲突:
protocol Sequence {
associatedtype IteratorType : Iterator
}
为弱类型信息的参数添加补充信息以表明参数的角色
当参数类型是NSObject、Any、 AnyObject或者像Int、String这样的基本类型的时候,调用处的类型信息和上下文环境可能不能完全表明函数的意图。如下这个例子,它的声明可能是明确的,但在调用的地方就显得意图不明了。
不推荐:
func add(observer: NSObject, for keyPath: String)
grid.add(self, for: graphics) // vague
为了恢复明确性,在每个弱类型参数前加一个名词用来描述它的角色。
推荐:
func addObserver(_ observer: NSObject, forKeyPath path: String)
grid.addObserver(self, forKeyPath: graphics) // clear