Slide 1

Slide 1 text

A Neatly Typed Message Krzysztof Siejkowski

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

What’s our biggest problem? “Maintaining Mental Models: A Study of Developer Work Habits”

Slide 4

Slide 4 text

Understanding the rationale behind a piece of code

Slide 5

Slide 5 text

Understanding the rationale behind a piece of code Switching tasks because of requests from my teammates

Slide 6

Slide 6 text

“Story of my life”

Slide 7

Slide 7 text

Readability is crucial for understanding

Slide 8

Slide 8 text

programs must be written for people to read, and only incidentally for machines to execute — Structure and Interpretation of Computer Programs book

Slide 9

Slide 9 text

the essential material (are) techniques used to control the intellectual complexity of software systems. — Structure and Interpretation of Computer Programs book

Slide 10

Slide 10 text

Complexity • intrinsic • incidental

Slide 11

Slide 11 text

Readability quest [Press start]

Slide 12

Slide 12 text

World 1:
 API design

Slide 13

Slide 13 text

func split(email: String) -> (String, String)? { let components = email.components(separatedBy: "@") guard components.count == 2, let username = components.first, let domain = components.last, !username.isEmpty && !domain.isEmpty else { return nil } return (username, domain) } let splitEmail = split(email: ”[email protected]")

Slide 14

Slide 14 text

func split(email: String) -> (String, String)? { let components = email.components(separatedBy: "@") guard components.count == 2, let username = components.first, let domain = components.last, !username.isEmpty && !domain.isEmpty else { return nil } return (username, domain) } let splitEmail = split(email: ”[email protected]")

Slide 15

Slide 15 text

func split(email: String) -> (String, String)? { let components = email.components(separatedBy: "@") guard components.count == 2, let username = components.first, let domain = components.last, !username.isEmpty && !domain.isEmpty else { return nil } return (username, domain) } let splitEmail = split(email: ”[email protected]")

Slide 16

Slide 16 text

func split(email: String) -> (String, String)?

Slide 17

Slide 17 text

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)?

Slide 18

Slide 18 text

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)?

Slide 19

Slide 19 text

Level 1-2: symbols typealias SplitEmail = (username: String, domain: String) struct SplitEmail { let username: String let domain: String } func split(email: String) -> SplitEmail?

Slide 20

Slide 20 text

Costs of symbols • fixed discoverability • marginal recognition

Slide 21

Slide 21 text

Either a lot
 or not at all

Slide 22

Slide 22 text

Level 1-2: symbols func split(email: String) -> SplitEmail ?

Slide 23

Slide 23 text

Level 1-3: wrappers 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 }

Slide 24

Slide 24 text

Level 1-3: wrappers func split(email: String) -> SplitEmail

Slide 25

Slide 25 text

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) }

Slide 26

Slide 26 text

Level 1-4: concepts enum Split where S.Splitting == Value, S.Splitted == Value { case splitted(Value, Value) case invalid init(_ value: Value, using splitter: S) { if let (first, second) = splitter.split(value: value) { self = .splitted(first, second) } else { self = .invalid } See https://github.com/Ben-G/Validated/ by Benjamin Encz

Slide 27

Slide 27 text

Level 1-4: concepts func split(email: String) -> Split // result: Split // value: String // transform: EmailSplitter

Slide 28

Slide 28 text

Is complexity justified?

Slide 29

Slide 29 text

End of World 1

Slide 30

Slide 30 text

World 2:
 Delegation

Slide 31

Slide 31 text

protocol Delegate: class { func foo() } struct Announcing { open weak var delegate: Delegate? } var announcing = Announcing() announcing.delegate = delegate 

Slide 32

Slide 32 text

Conventions are HP for readability

Slide 33

Slide 33 text

Level 2-1: Initializer injection struct Announcing { private weak var delegate: Delegate? init(to delegate: Delegate) { self.delegate = delegate } } let announcing = Announcing(to: delegate)

Slide 34

Slide 34 text

Level 2-2: Weak closure struct Announcing { private let delegate: () -> Delegate? init(to delegate: @escaping () -> Delegate?) { … } } let announcing = Announcing(to: { [weak delegate] in delegate })

Slide 35

Slide 35 text

Level 2-3: Weak function func weak(_ 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))

Slide 36

Slide 36 text

Level 2-4: Weak wrapper struct Weak { private let internalValue: () -> T? init(_ value: T) { internalValue = { [weak value] in value } } } struct Announcing { private let delegate: Weak init(to delegate: Weak) { ... } }

Slide 37

Slide 37 text

Readability is contextual

Slide 38

Slide 38 text

There is no castle
 with a princess inside

Slide 39

Slide 39 text

Empathy is the god mode

Slide 40

Slide 40 text

Who are we 
 writing for?

Slide 41

Slide 41 text

No such thing as the readability

Slide 42

Slide 42 text

How do we win?

Slide 43

Slide 43 text

May 
 the feedback
 be with you

Slide 44

Slide 44 text

Thank you! @_siejkowski siejkowski.net