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

Improving Developer Experience Through Tools and Techniques 2022

Improving Developer Experience Through Tools and Techniques 2022

Krzysztof Zabłocki

June 24, 2022
Tweet

More Decks by Krzysztof Zabłocki

Other Decks in Programming

Transcript

  1. Improving Developer Experience
    or "How to save hours of development 4me each week?"
    by @merowing_ 1

    View Slide

  2. I've been focused on developer experience for more than a decade
    by @merowing_ 2

    View Slide

  3. Improving Developer Experience
    Is it one of the best investments we can make?
    by @merowing_ 3

    View Slide

  4. Good Developer Experience allows us to
    • Focus on user/business goals
    • Provide efficient workflows
    • Keeps us engaged with the work we are doing
    • Work smart, not hard
    • Limits human mistakes
    by @merowing_ 4

    View Slide

  5. How can we improve Developer Experience?
    by @merowing_ 5

    View Slide

  6. How can we improve Developer Experience?
    • App architecture
    • Removing required manual steps
    • Workflow and code automa;on
    • Building developer tools
    • Shortening feedback loops
    by @merowing_ 6

    View Slide

  7. How to gauge if you should invest 3me into tooling?
    • Is this inconvenient just for me?
    • Do other folks in my team run into the same kind of problems?
    • How o=en does it happen?
    • What's the total team @me per week wasted on this problem?
    by @merowing_ 7

    View Slide

  8. How to gauge if you should invest 3me into tooling?
    • NYT project used internal / 3rd party tools with each build
    • The total on each build adds about 6s, only 6s, right?
    • I measured that I build between 200-400 Dmes daily, and 90% of
    the Dmes we don't need those tools to run again
    • We had ~30 iOS developers touching the main app
    • Lower threshold = 200 $mes * 6s * 30 devs * 90% => 9 hours
    wasted per day
    by @merowing_ 8

    View Slide

  9. How to gauge if you should invest 3me into tooling?
    • This means we were was-ng 45 hours per week.
    • If we can improve that, it's almost like hiring a new full--me
    developer, except it's free.
    • Is it worth inves-ng -me to improve it?


    Definitely
    • How to do it? Custom pre-process script on pre-commit / CI
    • Read more @ my blog h4ps:/
    /bit.ly/3uwbqhL
    by @merowing_ 9

    View Slide

  10. Common Issues
    and things we can do to improve our projects
    by @merowing_ 10

    View Slide

  11. Issue - Manual Steps
    by @merowing_ 11

    View Slide

  12. Issue - Manual Steps
    Need to fill out some fields? e.g., login creden4als
    • Use user breakpoints
    • Data never leaves your machine
    • Easy to disable
    by @merowing_ 12

    View Slide

  13. Issue - Manual Steps
    Are you working on a long-running feature?
    by @merowing_ 13

    View Slide

  14. Issue - Manual Steps
    Are you working on a long-running feature?
    • Build-phase script that allows you to create #if branches per
    developer (e.g., h;ps:/
    /bit.ly/3mmfLRP)
    #if merowing
    showARExperience(StubARData(...))
    #endif
    by @merowing_ 14

    View Slide

  15. Issue - Retain Cycles
    by @merowing_ 15

    View Slide

  16. Issue - Retain Cycles
    Apple: Xcode Memory Graph Debugger + Leaks Instrument
    • Do you trust people will always run those tools and analyze their
    results before submi7ng Pull Requests?
    by @merowing_ 16

    View Slide

  17. Issue - Retain Cycles
    Open Source: Life'meTracker
    • How many instances of class X should
    ever be alive?
    • Works in Swi< and Objec?ve-C
    • Surface new retain cycle as you create
    them, not afeature
    by @merowing_ 17

    View Slide

  18. Issue - Retain Cycles
    Open Source: krzysztofzablocki/Life3meTracker
    Straigh(orward integra/on:
    class SectionFrontViewController: UIViewController, LifetimeTrackable {
    static var lifetimeConfiguration = LifetimeConfiguration(maxCount: 1, groupName: "SF VC")
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    /// ...
    trackLifetime()
    }
    }
    by @merowing_ 18

    View Slide

  19. Architecture integra-ons - e.g. TCA
    by @merowing_ 19

    View Slide

  20. Issue - Data dependencies
    by @merowing_ 20

    View Slide

  21. Issue - Data dependencies
    • Design your processing like a pipeline
    • Protocol at each stage, so it's easy to change
    by @merowing_ 21

    View Slide

  22. Issue - Data dependencies
    • Wri%ng tests for your ViewModel?
    • Bug report requires specific data?
    • Replace Model Converter with Fake Models
    by @merowing_ 22

    View Slide

  23. Issue - Data dependencies
    • Do you want to see how your whole applica3on reacts to specific
    data changes, but the backend isn't ready?
    • Easily load external data to the applica3on
    • In simulator ? loading from a local file would be preferred
    • On device? we need to load from a network server
    • We need real-3me updates
    by @merowing_ 23

    View Slide

  24. Issue - Data dependencies
    Open Source: KZFileWatchers
    • Works in Swi, and Objec4ve-C
    • FileWatcher.Local is useful for observing local file changes
    e.g., observing files on the developer desktop.
    • FileWatcher.Remote can be used to observe files on the
    web. Both Etag headers and Last-Modified-Date are
    supported.
    by @merowing_ 24

    View Slide

  25. Issue - Data dependencies
    -> Replace DataProvider with FileWatcher
    by @merowing_ 25

    View Slide

  26. by @merowing_ 26

    View Slide

  27. Issue - Data reproduc/on
    Can't reproduce bugs because your data changes o3en?
    • Every app deals with raw NSData at some point in the pipeline
    • Pipe it through (Identifier, Data) -> Data
    • Use only returned data:
    • If the app is in recording mode, it persist data in cache
    • If you are in reproduc=on mode, it loads data from the cache
    • Read more @ my blog h/ps:/
    /bit.ly/3mrna2i
    by @merowing_ 27

    View Slide

  28. by @merowing_ 28

    View Slide

  29. Need more power? Leverage unidirec3onal architecture/view state to implement 3me travel
    by @merowing_ 29

    View Slide

  30. Issue - Tes(ng Diffs
    Comparing objects is terrible.
    • Default Xcode results
    by @merowing_ 30

    View Slide

  31. Issue - Tes(ng Diffs
    Comparing objects is terrible.
    • Open Source Difference - Pure func.on Mirror based diffing
    by @merowing_ 31

    View Slide

  32. Issue - Boilerplate code
    and not thinking about Developer Experience
    by @merowing_ 32

    View Slide

  33. Sourcery
    • Sourcery is like a pre-processor
    • Sourcery(input: Swift) -> Either
    • Used in over 40 000 apps.
    • In massive code-bases like Airbnb, Bumble, etc.
    • Adds annota?on support to SwiA language
    • Allows fine-grained control over the genera?on
    • Sourcery can generate any code if you can describe the algorithm
    by @merowing_ 33

    View Slide

  34. by @merowing_ 34

    View Slide

  35. Example: Automa.c Se1ngs
    struct Calculation: AutomaticSettings {
    var text = ""
    var mode = Mode.linearRegression
    }
    // sourcery: injectFooter
    struct Smoothing {
    var dayPeriod = 7
    var algorithm = Algorithm.movingAverage
    struct Grouped {
    var level: Float = 1
    var prettyCool = true
    }
    var grouped: Grouped = .init()
    }
    by @merowing_ 35

    View Slide

  36. Example: A/B Tests
    struct ABTests {
    var meterLimit = Test(
    default: .control
    )
    var calendarReminder = Test(
    default: .control
    )
    ....
    }
    by @merowing_ 36

    View Slide

  37. Example: JS <-> Swi1 bridge
    // 1 case -> 1 command
    case nodesSetAutoFade(ids: [String], maxDistance: CGFloat)
    case nodesSetVisibility(showIds: [String]?, hideIds: [String]?)
    case materialSetProperties(
    id: String,
    material: String,
    properties: ARViewer.Model.MaterialProperties
    )
    // automatically bridges JS <-> Swift and provided as fully typed enum
    switch (command) {
    case let .materialSetProperties(id, materialName, properties):
    by @merowing_ 37

    View Slide

  38. But ... it's a dependency. I don't know if my
    team will want or can integrate it?
    by @merowing_ 38

    View Slide

  39. Sourcery Pro
    with Xcode Live templates
    by @merowing_ 39

    View Slide

  40. by @merowing_ 40

    View Slide

  41. by @merowing_ 41

    View Slide

  42. Sourcery Pro
    with Xcode Live templates
    by @merowing_ 42

    View Slide

  43. Issue - Tes(ng Mocks
    • Open Source Swi&yMocky - Sourcery based framework for
    powerful mocking DSL
    • Open Source Sourcery - AutoMockable template
    by @merowing_ 43

    View Slide

  44. Issue - Tes(ng Mocks
    • Sourcery Pro Live AST Templates
    by @merowing_ 44

    View Slide

  45. Issue - Long itera/on cycle
    by @merowing_ 45

    View Slide

  46. Issue - Long itera/on cycle
    by @merowing_ 46

    View Slide

  47. Issue - Long itera/on cycle
    First, we can split the project into many different modules.
    • Improves modular architecture design
    • Forces developers to think about public API and module boundaries
    • Each framework has its test suite that can run fast
    • Enables use of playgrounds or small projects
    • .dylib loading is no longer a significant concern, and we have staBc
    libs
    by @merowing_ 47

    View Slide

  48. Issue - Long itera/on cycle
    Open Source: KZPlayground
    • Both Swi* and Objec3ve-C
    • Custom DSL for exposing control variables (sliders, image
    pickers, trigger buEons).
    • It's easy to add the framework to exis3ng code-base
    • Works with Injec3onForXcode
    by @merowing_ 48

    View Slide

  49. by @merowing_ 49

    View Slide

  50. Not convinced yet?
    What if you only needed a maximum of two line change to hot-
    reloading your UIKit / AppKit / tvOS / Swi>UI project?
    UIKit/AppKit:
    // from
    let vc = MainViewController(...)
    // to
    let vc = Inject.ViewControllerHost(MainViewController(...))
    by @merowing_ 50

    View Slide

  51. by @merowing_ 51

    View Slide

  52. Not convinced yet?
    What if you only needed a maximum of two line change to hot-
    reloading your UIKit / AppKit / tvOS / Swi>UI project?
    Swi$UI:
    @ObservedObject private var iO = Inject.observer variable
    var body: some View {
    ...
    .enableInjection()
    }
    by @merowing_ 52

    View Slide

  53. by @merowing_ 53

    View Slide

  54. Issue - Long itera/on cycle
    What if you can't split up your project easily or it's s4ll too slow?
    • Open Source: Inject + Injec+onForXcode
    • Hot Reloading for Swi: and Objec+ve-C
    • No run+me involved, full Swi: support
    • Can be integrated as an SPM package
    by @merowing_ 54

    View Slide

  55. Summary
    • Crea&ng a good developer experience should be one of the main goals of your applica&on
    architecture design
    • Time invested into improving your team developer experience can yield huge ROI for your
    business
    • By enabling your developers to work on the features that maAer to the business
    • If a mythical 10x developer exists, it would be the person that makes ten team members more
    efficient.
    • Ask yourself if the problems you are facing are isolated or affect other devs?
    • Consider geHng Sourcery Pro to automate your workflows
    • Give Inject a try if you want to save hours of development :me per week
    by @merowing_ 55

    View Slide

  56. Ques%ons?
    by @merowing_ 56

    View Slide

  57. Contact
    Twi$er merowing_
    Github krzysztofzablocki
    Blog: h"ps:/
    /merowing.info
    by @merowing_ 57

    View Slide