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

Frameworks for Coding Confidence

Frameworks for Coding Confidence

As a mobile codebase grows and evolves, it becomes increasingly difficult to make large changes with confidence and speed. Unintended side effects, strange lifecycles, memory leaks, error-cases, and poor code cohesion work together to quickly make a mess of many applications as they grow. This talk will cover some of the techniques Uber has used to allow for changes in a tightly integrated application with confidence, including tools like Dagger 2, static analysis, and annotation processing. We’ll show you how these techniques and tools reinforce each other by demonstrating some concrete anti-patterns that have scaled poorly in the past, as well as how you can combine these new techniques to prevent entire classes of issues in the future.

Luke St.Clair

March 20, 2016
Tweet

Other Decks in Programming

Transcript

  1. Frameworks for
    Coding Confidence
    Luke St.Clair, Engineering Manager
    March 18, 2016

    View full-size slide

  2. • How do you make big changes?
    • What did Uber do?
    • What worked?
    • Key point: How do these frameworks and tools work
    together?
    Rapid Change
    A good problem to have

    View full-size slide

  3. What helps you move fast?
    Code grows fast
    Safety/Confidence
    This should be controversial, but
    consider where development
    time goes.
    Compilers
    Make the compiler do as much
    for you as possible, then the
    linter, then testing.

    View full-size slide

  4. • Very key way to express developer intent.
    • Where do you pass around an integer?
    • Basis of many other mechanisms for safety.
    Annotations
    Much @. So Java.

    View full-size slide

  5. Validation
    Natural consequence of annotation
    More than just IDE hint
    You did the work to tell Java
    what your code does - why isn’t
    it helping more?
    Enforcement
    What does any of this do? Is it
    just for the IDE?

    View full-size slide

  6. RAVE
    Runtime Annotation Validation Engine
    Enforces Annotations
    At runtime, you can tell if the
    state of the program is the state
    your annotations describe.
    Enforcement
    Annotations express intent,
    annotation processors can help
    you verify this intent.

    View full-size slide

  7. Validation (continued)
    Natural consequence of annotation
    Can go further
    First step is to boil this down to
    arbitrary conditions.
    Can be complicated
    Most apps have implicit
    dependencies and data
    relationships (imperfect APIs).

    View full-size slide

  8. Infer is a static analysis tool from Facebook
    that detects a pretty wide variety of bugs,
    from resource/context leaks, to some security
    violations.
    The most common use case, however, is for
    null pointer exceptions.
    Static Analysis
    Brought to you by Infer

    View full-size slide

  9. http://fbinfer.com/docs/eradicate-
    warnings.html
    Yeah, this one is obvious.
    Null Field Access
    Brought to you by Infer

    View full-size slide

  10. If a subclass or interface
    implementation doesn’t return the
    correct nullability, Infer will complain.
    Subclasses don’t annotate correctly

    View full-size slide

  11. If you forget to annotate a parameter or a
    return value, Infer will catch this.
    Infer catches missed annotations
    Brought to you by Infer

    View full-size slide

  12. Some engineering is required to use Infer.
    • Homebrew
    • Gradle
    • Build times
    - Caching
    Infer in Practice

    View full-size slide

  13. This is sample output from an Infer run.
    • Multiple types of issues.
    • Automatically analyzes every diff
    Sample
    Example Infer Run

    View full-size slide

  14. • Scopes - high-concept
    • Dependency resolution
    - It becomes harder to introduce a weird relationship
    • Helps prevent things like weird circular dependencies
    • Touch points to help you think about what you’re
    exposing
    • If it compiles, it runs.
    Dagger 2
    Compile time scoping and safety

    View full-size slide

  15. • Easy to add another dependency
    • Hard to mess up the scoping
    • Can’t mess up the dependency relationship
    - Well, mostly
    • There are not many tools to help with lifecycles.
    Dagger 2
    Compile time scoping and safety

    View full-size slide

  16. • You pay the price for Dagger 2
    • Verbosity
    • Testing
    Dagger 2
    Not all easy

    View full-size slide

  17. Other tools
    There is so much here
    Lint Checkstyle
    Extension points help guide
    consistency in the code base, and
    make it easy to ensure new code
    doesn’t accidentally skip some of
    these important checks.
    Gradle
    If you haven’t looked at all possible
    lint rules, do so.
    Custom lint is extremely powerful.
    There’s nothing like a 2 vs 4 space
    flamewar to slow you down.

    View full-size slide

  18. How do these combine?
    Better together
    Rave Infer Dagger
    Fills in the gaps, helps
    ensure Android-isms are
    enforced across libraries.
    Lint
    Establishes a baseline set
    of constraints that you
    know is satisfied in
    production.
    Because RAVE tells you
    the starting point for data,
    you know that it will
    continue to be enforced
    throughout the lifecycle of
    the application.
    Generated objects in DI
    don’t break the analysis
    chain.
    Dagger 1 >> Dagger 2.

    View full-size slide

  19. • @Inject supported
    • @Bind even supported
    • Establishes constraints even in the lifecycle of
    injection.
    Dagger + Infer

    View full-size slide

  20. • Remember the infer modes from a few slides ago?
    • Catch missing annotations
    • Those are now enforced with RAVE when they
    terminate in parts of your mobile app.
    Infer + RAVE

    View full-size slide

  21. Let’s say we find a new way to prevent a
    systematic problem.
    • Remember String.format?
    • Custom grade plugins apply this over all our code.
    • Can apply across many teams.
    • If it doesn’t get applied widely, it doesn’t matter.
    Tying it all together
    Gradle to the rescue

    View full-size slide

  22. Lots of fragments here, and
    other Droidcon talks. Hope to
    have more to share soon.
    View Based Development
    Easy to understand, lifecycle is
    complicated, fast testing.
    Stick with POJOs
    By paying attention to testing
    at the start, we make it much
    easier to separate and isolate
    code.
    Testability
    And more…

    View full-size slide

  23. Luke St.Clair
    Android Platform, Uber
    [email protected]
    Thank you

    View full-size slide