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

Being for the Benefit of Future Developer

John Pignata
February 15, 2013

Being for the Benefit of Future Developer

Talk given at DUMBODevs (http://www.meetup.com/dumbo-developers) on 2/15/13.

A successful software project will pass between the hands of many different developers in its lifetime. What we sometimes bitterly refer to as "legacy code" is often the bread and butter of our organizations and "brownfield development" is the bulk of software development. Just as we've inherited projects from other developers, we leave our projects to Future Developer when we move on. His or her success and job satisfaction will be in large part dictated by the quality of what we've left behind. How do we keep our fields as green as possible for these future generations of developers? The practices we employ to deliver our projects define the genetics that guide their evolution both now and far beyond our last commit. In this talk we'll look at some practices we can use in all aspects of our day-to-day work to setup Future Developer for success and happiness.

John Pignata

February 15, 2013
Tweet

More Decks by John Pignata

Other Decks in Programming

Transcript

  1. Being for the Benefit of
    Future
    Developer

    View full-size slide

  2. tx.pignata.com
    @jpignata

    View full-size slide

  3. Launched: May, 2010
    1.6 Billion Messages Delivered Monthly
    Acquired by Skype: August, 2011

    View full-size slide

  4. 45 Main Street 20 Jay Street

    View full-size slide

  5. a successful software project will likely
    be passed down to many different
    developers in its lifetime

    View full-size slide

  6. we’re a link in the chain

    View full-size slide

  7. our work will outlast our
    involvement

    View full-size slide

  8. our decisions will be inherited

    View full-size slide

  9. our decisions will be inherited
    laziness
    misunderstandings
    inconsistencies
    inattentiveness
    shortcuts
    procrastination
    sloppiness
    dirty laundry

    View full-size slide

  10. (ϊಠӹಠ)ϊኯᵲᴸᵲ

    View full-size slide

  11. (ϊಠӹಠ)ϊኯ OMFG.

    View full-size slide

  12. (ϊಠӹಠ)ϊኯ BIG
    REWRITE!

    View full-size slide

  13. how can we work toward a
    better future?

    View full-size slide

  14. we’re in the best
    possible position to
    e m p a t h i z e w i t h
    future developer

    View full-size slide

  15. we can anticipate
    their needs

    View full-size slide

  16. our codebase is an
    organism

    View full-size slide

  17. nature and nurture

    View full-size slide

  18. every contribution to
    our project in part
    defines its genetics

    View full-size slide

  19. the artifacts we leave
    behind signal to future
    contributors how to
    best build upon them

    View full-size slide

  20. Refactor toward Consistency
    Prune Dead Code
    Polish Your Interfaces
    Write Documentation

    View full-size slide

  21. Refactor
    toward
    Consistency

    View full-size slide

  22. what is technical debt?

    View full-size slide

  23. learnings not yet reflected in
    the codebase

    View full-size slide

  24. technical debt is desirable

    View full-size slide

  25. it means we’re shipping our
    code to the real-world to learn
    more about it

    View full-size slide

  26. what the technical debt
    metaphor isn’t

    View full-size slide

  27. it’s not a
    loophole

    View full-size slide

  28. it’s not a license to do our
    jobs poorly by writing a
    check against future
    productivity

    View full-size slide

  29. we do the best we can with
    the information we have

    View full-size slide

  30. “A developer's obligation is
    to make sure that the code as
    written makes the clearest
    possible statement as to how
    the solution was understood
    at the time of writing.”
    — Ward Cunningham
    http://c2.com/cgi/wiki?TechnicalDebt

    View full-size slide

  31. but we’ll learn more

    View full-size slide

  32. our understanding will evolve

    View full-size slide

  33. technical debt is the gap
    between what we thought and
    what we now know

    View full-size slide

  34. these learnings must be
    accumulated and reflected in
    our codebase

    View full-size slide

  35. what kinds of learnings?

    View full-size slide

  36. domain model

    View full-size slide

  37. design patterns

    View full-size slide

  38. invoking ‘technical debt’
    doesn’t allow us to cut corners

    View full-size slide

  39. this isn’t a moral or ethical
    argument

    View full-size slide

  40. rather it’s a statement about
    the nature of software

    View full-size slide

  41. cutting corners isn’t simply a
    disservice to the future

    View full-size slide

  42. more importantly it’s a
    disservice to the present

    View full-size slide

  43. tense deploys

    View full-size slide

  44. resistence to change

    View full-size slide

  45. you’ll feel the pain immediately

    View full-size slide

  46. technical debt is more subtle

    View full-size slide

  47. if we don’t pay the debt,
    the interest payments will
    overtake progress

    View full-size slide

  48. we won’t be able to ship

    View full-size slide

  49. REFACTOR
    REFACTOR
    REFACTOR

    View full-size slide

  50. remodel aspects of the domain
    that we now know more
    precisely

    View full-size slide

  51. ensure consistency in domain
    concept naming

    View full-size slide

  52. graduate patterns and
    conventions into standards

    View full-size slide

  53. standardize on tools and
    approaches

    View full-size slide

  54. refactorings are retcons for
    your codebase

    View full-size slide

  55. not perfectionist wankery

    View full-size slide

  56. if you could go back in time,
    how would you build it?

    View full-size slide

  57. refactor and pretend you
    knew the right way all along

    View full-size slide

  58. consistency will
    h e l p f u t u r e
    developer

    View full-size slide

  59. conventions help clarify how
    to add new features to a
    system

    View full-size slide

  60. conventions hint where to
    look when troubleshooting
    an aspect of the system

    View full-size slide

  61. experiment liberally, ship
    often, and learn

    View full-size slide

  62. take those learnings and
    refactor the system

    View full-size slide

  63. don’t tolerate bad neighborhoods

    View full-size slide

  64. the interest payments are valuable
    feedback

    View full-size slide

  65. Prune Dead
    Code

    View full-size slide

  66. dead code is a parasitic
    barnacle on your
    codebase

    View full-size slide

  67. it provides no business value

    View full-size slide

  68. it creates mental overhead

    View full-size slide

  69. it is noise in a system down
    emergency

    View full-size slide

  70. it slows down your test suite

    View full-size slide

  71. yet you carry it around like a
    boat anchor

    View full-size slide

  72. the “turn it back on” fallacy

    View full-size slide

  73. misconception that a dead
    feature can be trivially re-
    enabled

    View full-size slide

  74. unfortunately, dead code
    erodes quickly

    View full-size slide

  75. turning it back on will involve
    more than flicking a switch

    View full-size slide

  76. some amount of work will be
    required

    View full-size slide

  77. it’s not free

    View full-size slide

  78. neither is carrying around the
    defunct implementation

    View full-size slide

  79. this is the sunk cost fallacy in
    action

    View full-size slide

  80. the “may need it later” false
    dilemma

    View full-size slide

  81. var article = CMS.retrieve(articleId);
    //if (article.state === PUBLISHED) {
    article.render($ele);
    //}

    View full-size slide

  82. var article = CMS.retrieve(articleId);
    if (false)
    article.render($ele);

    View full-size slide

  83. is this a remnant from a
    debugging session?

    View full-size slide

  84. is it a hint of a future
    requirement?

    View full-size slide

  85. is it a warning about a
    possible bug?

    View full-size slide

  86. ..****......*...........****.................*..**.
    *.........***......*..........*...*............**..
    ......*......**
    Finished in 2.62 seconds
    117 examples, 0 failures, 24 pending

    View full-size slide

  87. they’d be providing more
    value as red tests

    View full-size slide

  88. there’s no context provided

    View full-size slide

  89. entangled concerns

    View full-size slide

  90. brittleness sometimes
    discourages us from good
    hygiene

    View full-size slide

  91. “I removed the old header
    styles and now nobody can
    log in.”

    View full-size slide

  92. “if it ain’t broke, don’t fix it”

    View full-size slide

  93. large swathes of dead code is broke

    View full-size slide

  94. your codebase must communicate
    clearly

    View full-size slide

  95. that’s its most important job

    View full-size slide

  96. a mix of “real” and “old” code
    does not communicate clearly

    View full-size slide

  97. understanding these parts will
    require software archaeology

    View full-size slide

  98. every line of code should be signal

    View full-size slide

  99. extricate the productive parts of
    your system from the cruft

    View full-size slide

  100. use this as an opportunity to fortify
    brittle components in your system

    View full-size slide

  101. de-cluttering
    will help future
    developer

    View full-size slide

  102. r e d u c e y o u r
    codebase to its
    minimum

    View full-size slide

  103. to amplify what
    it communicates

    View full-size slide

  104. DEAD CODE
    DELETE

    View full-size slide

  105. relax! it’ll be in source control

    View full-size slide

  106. in case you’re feeling nostalgic

    View full-size slide

  107. Polish Your
    Interfaces

    View full-size slide

  108. a restaurant kitchen has many
    responsibilities

    View full-size slide

  109. sourcing ingredients

    View full-size slide

  110. preparing meals

    View full-size slide

  111. table service

    View full-size slide

  112. we don’t need to anything
    about how or what the
    kitchen does

    View full-size slide

  113. the menu is our interface to
    the kitchen

    View full-size slide

  114. “lol, I dunno.”

    View full-size slide

  115. “check the kitchen, I’m sure
    you can find some food back
    there.”

    View full-size slide

  116. that’s what every shapeless
    component says to future
    developer

    View full-size slide

  117. comprehension

    View full-size slide

  118. we describe our systems
    macroscopically by their
    interactions

    View full-size slide

  119. Web
    Transport Google
    Apple
    Windows
    PostgreSQL memcached
    Stripe
    Sendgrid

    View full-size slide

  120. put it under the microscope
    and magnify

    View full-size slide

  121. method junk drawers

    View full-size slide

  122. bad fences, bad neighbors

    View full-size slide

  123. User
    Payment
    Sale
    Processor

    View full-size slide

  124. User Payment
    Sale
    Processor
    #have_credit_card?
    #card_valid?(card_number)
    #bill(sale)
    #user_details)
    #address
    .last_payment_for(user)
    #account_number
    #renew!(user)
    #elapsed?
    #active?

    View full-size slide

  125. murky interfaces

    View full-size slide

  126. “private? whatever. we’re all
    adults.”

    View full-size slide

  127. method visibility helps us
    reduce the surface area of an
    object

    View full-size slide

  128. less surface area means we
    can change the innards of an
    object with less fear

    View full-size slide

  129. having a small, well-defined
    public interface communicates
    what it does

    View full-size slide

  130. and how it’s supposed to be
    used

    View full-size slide

  131. o u r s y s t e m s a r e
    defined by their
    interactions

    View full-size slide

  132. t h e s h a r p e r a
    c o m p o n e n t ’ s
    interface, the clearer
    your intent

    View full-size slide

  133. extensibility

    View full-size slide

  134. class Cache
    def initialize(storage)
    @storage = storage
    end
    def fetch(key)
    get(key) || set(key, yield)
    end
    private
    def get(key)
    @storage.get(key)
    end
    def set(key, data)
    @storage.set(key, data)
    data
    end
    end

    View full-size slide

  135. >> cache = Cache.new(Redis.new)
    => #127.0.0.1:6379/0>>
    >> cache.fetch(“key”) { some_expensive_operation }
    => :some_expensive_operation_result

    View full-size slide

  136. class Cache
    def initialize(storage)
    @storage = storage
    end
    def fetch(key)
    get(key) || set(key, yield)
    end
    private
    def get(key)
    @storage.get(key)
    end
    def set(key, data)
    @storage.set(key, data)
    data
    end
    end

    View full-size slide

  137. wire it up at runtime with a
    storage backend that responds
    to #get and #set

    View full-size slide

  138. cache = Cache.new(memcache)

    View full-size slide

  139. cache = Cache.new(redis)

    View full-size slide

  140. cache = Cache.new(CustomCacheBackend.new)

    View full-size slide

  141. redis = Redis::Distributed.new(ENV[“REDIS_URLS”])
    cache = Cache.new(redis)

    View full-size slide

  142. naming a concept helps us
    reason about it

    View full-size slide

  143. Cache represents a conceptual
    border

    View full-size slide

  144. we can’t predict future needs
    accurately

    View full-size slide

  145. speculative generality

    View full-size slide

  146. reuse in the small vs. reuse in
    the large

    View full-size slide

  147. build components that can be
    easily reasoned about

    View full-size slide

  148. apply a little design

    View full-size slide

  149. clarity, extensibility, and
    reuse will follow

    View full-size slide

  150. Write
    Documentation

    View full-size slide

  151. we demand it from our
    open source projects

    View full-size slide

  152. but we have different
    standards for our
    projects

    View full-size slide

  153. oral tradition and lore

    View full-size slide

  154. graveyard wikis

    View full-size slide

  155. comments are lies
    waiting to be told to the
    future

    View full-size slide

  156. # Return a NullUser if not logged in
    return true if logged_in?

    View full-size slide

  157. inline documentation

    View full-size slide

  158. documentation is exposition

    View full-size slide

  159. commit messages

    View full-size slide

  160. your commit messages
    comprise your project’s
    changelog

    View full-size slide

  161. breadcrumbs of context
    for the future

    View full-size slide

  162. $ git commit -am “fixes some stuff”

    View full-size slide

  163. $ git commit -am “Decompose RequestLogger
    The request logger middleware was responsible for mainipulating HTTP
    response headers for New Relic logging, sending measurement probes
    to StatsD, and outputting debugging information about a random
    sample of requests to the application log.
    This change splits up its responsibilities into three components:
    NewRelicHeader, StatsdTimer, DebugLogWriter.
    * Added coverage for middleware components
    * Minor consistency fixes in application config

    View full-size slide

  164. $ git rebase -i origin/master
    reword 0a8a3f6 Only sample for production
    pick d3d0250 Pass X-Proxy-Start as milliseconds
    squash 331c23f wip
    squash 1ee49de checkpoint: green
    reword b89e605 wip raise timeout if DB unavailable
    squash b2ed91f Speed up populate task
    pick db84969 Populate in a downtime migration
    # Rebase af190fb..10c3493 onto af190fb

    View full-size slide

  165. leave behind a coherent
    paper trail

    View full-size slide

  166. compare your projects to the
    standards to which you hold
    open source software

    View full-size slide

  167. fight software entropy

    View full-size slide

  168. fix broken windows

    View full-size slide

  169. work toward
    consistency

    View full-size slide

  170. leave behind what you
    hope to find

    View full-size slide

  171. build a better tomorrow
    for future developer

    View full-size slide

  172. and a better today for
    yourself

    View full-size slide

  173. Thanks!
    @jpignata tx.pignata.com

    View full-size slide

  174. Sup?
    @jpignata tx.pignata.com

    View full-size slide