-
Notifications
You must be signed in to change notification settings - Fork 0
Description
What’s our biggest problem?
In 2006, Microsoft in collaboration with Carnegie Mellon University published a paper called “Maintaining Mental Models: A Study of Developer Work Habits.” The authors conducted a survey among programmers working at Microsoft. And one of the questions they asked was whether a particular task was seen as a problem.
The problem reported most often by these programmers was understanding the rationale behind a piece of code. How did the programmers try to overcome this?
Mostly, just by reading. Reading took over 40% of the time spent on solving this problem. When this was not enough, they tried running a debugger, adding print statements, and so on. If those also failed, they tried to get to the original author and ask them for an explanation.
-> Readability is crucial for understanding code. It makes a real impact on how we work.
programs must be written for people to read, and only incidentally for machines to execute
Readability Quest
Level 1-1: comments
/// Splits the email into username and domain.
/// - Parameter email: A string that possibly
/// contains the email address value.
/// - Returns: Either:
/// - Tuple with username as first element
/// and domain as second
/// - Nil when passed argument cannot be split
func split(email: String) → (String, String)?Level 1-2: symbols
typealias SplitEmail = (username: String,
domain: String)
struct SplitEmail {
let username: String
let domain: String
}
func split(email: String) → SplitEmail?Level 1-3: wrapper
enum SplitEmail {
case valid(username: String, domain: String)
case invalid
init(from email: String) {
let components = email.components(separatedBy: "@")
if /* same checks as before */ {
self = .valid(username: username, domain: domain)
} else {
self = .invalid
}
}
}Level 1-4: concepts
protocol Splitter {
associatedtype Splitting
associatedtype Splitted
func split(value: Splitting) → (Splitted, Splitted)?
}
struct EmailSplitter: Splitter {
func split(value: String) → (String, String)? {
let components = value.components(separatedBy: "@")
guard /* same checks as before */ else { return nil }
return (first, second)
}
}World 2: Delegation
Level 2-1: Initializer injection
struct Announcing {
private weak var delegate: Delegate?
init(to delegate: Delegate) {
self.delegate = delegate
}
}
let announcing = Announcing(to: delegate)
Level 2-2: Weak closure
struct Announcing {
private let delegate: () → Delegate?
init(to delegate: @escaping () → Delegate?) { ... }
}
let announcing = Announcing(to: {
[weak delegate] in delegate
})Level 2-3: Weak function
func weak<T: AnyObject>(_ object: T) → () → T? {
return { [weak object] in object }
}
struct Announcing {
private let delegate: () → Delegate?
init(to delegate: @escaping () → Delegate?) { ... }
}
let announcing = Announcing(to: weak(delegate))Level 2-4: Weak wrapper
struct Weak<T: AnyObject> {
private let internalValue: () → T?
init(_ value: T) {
internalValue = { [weak value] in value }
}
}
struct Announcing {
private let delegate: Weak<Delegate>
init(to delegate: Weak<Delegate>) { ... }
}ref: https://academy.realm.io/posts/a-neatly-typed-message-improving-code-readability/