Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Being correct, quicker

Being correct, quicker

Alex Curran

August 07, 2018
Tweet

More Decks by Alex Curran

Other Decks in Technology

Transcript

  1. Being correct, quicker

    View full-size slide

  2. @amlcurran
    Where’s the assumption?
    class TodoItem {
    var id: String?
    var title: String?
    var dueDate: Date?
    var tasks: [String]?
    var completed: Bool
    }

    View full-size slide

  3. @amlcurran
    Where’s the assumption?
    class TodoItem {
    var id: String?
    var title: String?
    var dueDate: Date?
    var tasks: [String]?
    var completed: Bool
    }
    when is this nil?
    is this object valid without an ID?
    Is this property thread safe?
    does this change?

    View full-size slide

  4. let idToDelete = todo.id!

    View full-size slide

  5. @amlcurran
    Timeline of messing up
    Immediate End of the
    world
    You
    caught it
    QA
    caught it
    A user
    told you
    let idToDelete = todo.id!
    Merged
    code
    Released
    app

    View full-size slide

  6. @amlcurran
    Timeline of messing up
    Immediate End of the
    world
    Unit test
    crashed
    UI test
    failed
    Crash
    reporting
    caught it
    let idToDelete = todo.id!
    Merged
    code
    Released
    app

    View full-size slide

  7. @amlcurran
    How can we improve?
    class TodoItem {
    var id: String?
    var title: String?
    var dueDate: Date?
    var tasks: [String]?
    var completed: Bool
    }
    Immediate End of the
    world

    View full-size slide

  8. @amlcurran
    How can we improve?
    class TodoItem {
    let id: String = ""
    let title: String = ""
    let dueDate: Date?
    let tasks: [String] = []
    let completed: Bool = false
    }
    Immediate End of the
    world

    View full-size slide

  9. @amlcurran
    How can we improve?
    class TodoItem {
    let id: String
    let title: String
    let dueDate: Date?
    let tasks: [String]
    let completed: Bool
    init(...) { }
    }
    Immediate End of the
    world

    View full-size slide

  10. @amlcurran
    Removing guesswork
    • Code didn’t give us enough information, we had to assume

    • An assumption is either right or wrong

    • Removing the assumption removes the guesses

    • Still assuming the API is stable, but talk to your API developers ;)

    View full-size slide

  11. @amlcurran
    Reducing a feedback loop
    Immediate End of the
    world
    A user
    told you
    Merged
    code
    Released
    app

    View full-size slide

  12. @amlcurran
    Reducing a feedback loop
    Immediate End of the
    world
    QA
    found it

    View full-size slide

  13. @amlcurran
    Time is money
    • Releases are time-expensive

    • The longer until an issue is found, the more work has to be done

    • Code review, pairing, type-safety all reduce this time

    View full-size slide

  14. @amlcurran
    Closing a feedback loop
    Immediate End of the
    world
    QA
    found it
    Merged
    code
    Released
    app

    View full-size slide

  15. @amlcurran
    Closing a feedback loop
    Immediate End of the
    world
    UI test
    failed
    Merged
    code
    Released
    app

    View full-size slide

  16. @amlcurran
    • “Definite” happens more often than “maybe"

    • Prefer to encode expectations into code and tools, rather than knowledge

    • An open loop requires knowledge to close — can you guarantee this
    happens?
    Definite is better than maybe

    View full-size slide

  17. Have you ever forgotten to set
    a dataSource or delegate?

    View full-size slide

  18. @amlcurran
    Forgetting a delegate
    let pairInputView = AddPairView()
    class AddPairView: UIVisualEffectView, UITextFieldDelegate {
    var delegate: AddPairViewDelegate?
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    delegate?.addPairView(self, didFinishCreating: request())
    return true
    }
    }
    Immediate End of the
    world

    View full-size slide

  19. @amlcurran
    Forgetting a delegate
    let pairInputView = AddPairView()
    pairInputView.delegate = self
    class AddPairView: UIVisualEffectView, UITextFieldDelegate {
    var delegate: AddPairViewDelegate?
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    delegate?.addPairView(self, didFinishCreating: request())
    return true
    }
    }
    Immediate End of the
    world

    View full-size slide

  20. @amlcurran
    Forgetting a delegate
    let pairInputView = AddPairView()
    class AddPairView: UIVisualEffectView, UITextFieldDelegate {
    var delegate: AddPairViewDelegate?
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    delegate!.addPairView(self, didFinishCreating: request())
    return true
    }
    }
    Immediate End of the
    world

    View full-size slide

  21. @amlcurran
    Forgetting a delegate
    let pairInputView = AddPairView(delegate: self)
    class AddPairView: UIVisualEffectView, UITextFieldDelegate {
    let delegate: AddPairViewDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    delegate!.addPairView(self, didFinishCreating: request())
    return true
    }
    }
    Immediate End of the
    world

    View full-size slide

  22. @amlcurran
    Forgetting a delegate
    let pairInputView = AddPairView(delegate: self)
    class AddPairView: UIVisualEffectView, UITextFieldDelegate {
    let delegate: AddPairViewDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    delegate!.addPairView(self, didFinishCreating: request())
    return true
    }
    }
    Immediate End of the
    world

    View full-size slide

  23. @amlcurran
    Using the compiler
    • A compile-time error is guaranteed to happen

    • A runtime crash is not (and is worse for the user!)

    • Flexible is not guaranteed to be safe

    View full-size slide

  24. @amlcurran
    Compile time vs runtime
    Compile
    time
    Compile
    Runtime Compile Launch Navigate Hit issue

    View full-size slide

  25. @amlcurran
    Swift (generally) helps
    • Stronger typing in Swift vs Obj-C makes compiler more important
    • Look at your optionals, mutables, and your implicitly unwrapped optionals

    • IUOs you’ve written can often be written in a less-crashy way

    • Don’t make things mutable/optional if it doesn’t make sense

    • Verify (and fail) early

    View full-size slide

  26. @amlcurran
    Strong typing helps
    • Use generics for common behaviour, not convenience

    • Don’t circumvent the compiler using Any

    • Think whether a primitive type really makes sense

    • Forcing a strong type can prevent bugs

    View full-size slide

  27. Quicker feedback is not always
    about crashes

    View full-size slide

  28. @amlcurran
    Tools to reduce feedback
    • SwiftGen and R.swift reduce runtime failures or undefined behaviour to
    compile errors — much faster!

    • SwiftLint makes compile time warnings from style guides

    View full-size slide

  29. @amlcurran
    “The code doesn’t match our style”
    Immediate End of the
    world
    App released
    Code
    review

    View full-size slide

  30. @amlcurran
    Immediate End of the
    world
    App released
    Pair with
    dev
    “The code doesn’t match our style”

    View full-size slide

  31. @amlcurran
    Immediate End of the
    world
    App released
    Swiftlint +
    compile
    “The code doesn’t match our style”

    View full-size slide

  32. @amlcurran
    Immediate End of the
    world
    App released
    Swiftlint +
    compile
    PR
    review
    “The code doesn’t match our style”

    View full-size slide

  33. @amlcurran
    Immediate End of the
    world
    App released
    Swiftlint +
    compile
    PR
    review
    Not open to interpretation
    Newer members of the team
    get neutral feedback
    “The code doesn’t match our style”

    View full-size slide

  34. @amlcurran
    Preventing accidents
    • Removing ability to undo a decision that was already made unconsciously

    • You can still change the rules, but not accidentally

    • If you have rules that you want people to follow, make it as easy as
    possible

    • Don’t add rules around things you can accept changing!

    View full-size slide

  35. @amlcurran
    class ServiceLocator {
    private var references = [String: Any]()
    func register(_ object: T) {
    references["\(type(of: T.self))"] = object
    }
    func retrieve() -> T {
    let identifier = "\(type(of: T.self))"
    guard let object = references[identifier] as? T else {
    preconditionFailure("Didn't register an object of \(type(of: T.self))")
    }
    return object
    }
    }

    View full-size slide

  36. @amlcurran
    let locator = ServiceLocator()
    locator.register(UserDefaults.standard)
    // Works
    let userDefaults: UserDefaults = locator.retreive()
    // Crashes
    let urlSession: URLSession = locator.retreive()

    View full-size slide

  37. @amlcurran
    class Dependencies {
    lazy var userDefaults: UserDefaults = .standard
    lazy var urlSession: URLSession = .shared
    }
    let dependencies = Dependencies()
    // Works
    let userDefaults = dependencies.urlSession
    // immediately doesn't compile
    let application = dependencies.application

    View full-size slide

  38. @amlcurran
    When is this stuff useful?
    • Old codebase, with weak coding practises

    • Teams with inexperienced developers

    • Teams with opinionated developers

    • Teams with high turnover

    • But really, its always useful

    View full-size slide

  39. @amlcurran
    Summing up
    • Reducing feedback loop time reduces the time to realise a mistake

    • Closing open feedback loops guarantees you feedback

    • Third-party tools can close Apple’s feedback loops

    • Think about aiming for certainty, not convenience

    • If something doesn’t make sense, make it impossible to happen

    View full-size slide

  40. @amlcurran
    Agile development
    • Reducing the time to feedback

    • Ensuring feedback is guaranteed

    • It is NOT about standups and retros and meetings!

    View full-size slide