Being for the Benefit of Future Developer

Being for the Benefit of Future Developer

Talk given at DUMBODevs ( 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


  1. Being for the Benefit of Future Developer

  2. @jpignata

  3. None
  4. None
  5. Launched: May, 2010 1.6 Billion Messages Delivered Monthly Acquired by

    Skype: August, 2011
  6. 45 Main Street 20 Jay Street

  7. a successful software project will likely be passed down to

    many different developers in its lifetime
  8. we’re a link in the chain

  9. our work will outlast our involvement

  10. our decisions will be inherited

  11. our decisions will be inherited laziness misunderstandings inconsistencies inattentiveness shortcuts

    procrastination sloppiness dirty laundry
  12. legacy code

  13. legacy code

  14. None
  15. (ϊಠӹಠ)ϊኯᵲᴸᵲ

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

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

  18. how can we work toward a better future?

  19. we’re in the best possible position to e m p

    a t h i z e w i t h future developer
  20. we can anticipate their needs

  21. our codebase is an organism

  22. nature and nurture

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

  24. the artifacts we leave behind signal to future contributors how

    to best build upon them
  25. Refactor toward Consistency Prune Dead Code Polish Your Interfaces Write

  26. Refactor toward Consistency

  27. what is technical debt?

  28. learnings not yet reflected in the codebase

  29. technical debt is desirable

  30. it means we’re shipping our code to the real-world to

    learn more about it
  31. what the technical debt metaphor isn’t

  32. it’s not a loophole

  33. it’s not a license to do our jobs poorly by

    writing a check against future productivity
  34. we do the best we can with the information we

  35. “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
  36. but we’ll learn more

  37. our understanding will evolve

  38. technical debt is the gap between what we thought and

    what we now know
  39. these learnings must be accumulated and reflected in our codebase

  40. what kinds of learnings?

  41. domain model

  42. design patterns

  43. conventions

  44. tooling

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

  46. this isn’t a moral or ethical argument

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

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

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

  50. tense deploys

  51. hot fixes

  52. resistence to change

  53. you’ll feel the pain immediately

  54. technical debt is more subtle

  55. if we don’t pay the debt, the interest payments will

    overtake progress
  56. we won’t be able to ship


  58. remodel aspects of the domain that we now know more

  59. ensure consistency in domain concept naming

  60. graduate patterns and conventions into standards

  61. standardize on tools and approaches

  62. refactorings are retcons for your codebase

  63. not perfectionist wankery

  64. if you could go back in time, how would you

    build it?
  65. refactor and pretend you knew the right way all along

  66. consistency will h e l p f u t u

    r e developer
  67. conventions help clarify how to add new features to a

  68. conventions hint where to look when troubleshooting an aspect of

    the system
  69. experiment liberally, ship often, and learn

  70. take those learnings and refactor the system

  71. don’t tolerate bad neighborhoods

  72. the interest payments are valuable feedback

  73. Prune Dead Code

  74. dead code is a parasitic barnacle on your codebase

  75. it provides no business value

  76. it creates mental overhead

  77. it is noise in a system down emergency

  78. it slows down your test suite

  79. yet you carry it around like a boat anchor

  80. the “turn it back on” fallacy

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

  82. unfortunately, dead code erodes quickly

  83. turning it back on will involve more than flicking a

  84. some amount of work will be required

  85. it’s not free

  86. neither is carrying around the defunct implementation

  87. this is the sunk cost fallacy in action

  88. the “may need it later” false dilemma

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

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

  91. is this a remnant from a debugging session?

  92. is it a hint of a future requirement?

  93. is it a warning about a possible bug?

  94. ..****......*...........****.................*..**. *.........***......*..........*...*............**.. ......*......** Finished in 2.62 seconds 117 examples, 0

    failures, 24 pending
  95. they’d be providing more value as red tests

  96. there’s no context provided

  97. entangled concerns

  98. brittleness sometimes discourages us from good hygiene

  99. “I removed the old header styles and now nobody can

    log in.”
  100. “if it ain’t broke, don’t fix it”

  101. large swathes of dead code is broke

  102. your codebase must communicate clearly

  103. that’s its most important job

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

  105. understanding these parts will require software archaeology

  106. every line of code should be signal

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

  108. use this as an opportunity to fortify brittle components in

    your system
  109. de-cluttering will help future developer

  110. r e d u c e y o u r

    codebase to its minimum
  111. to amplify what it communicates


  113. relax! it’ll be in source control

  114. in case you’re feeling nostalgic

  115. Polish Your Interfaces

  116. a restaurant kitchen has many responsibilities

  117. sourcing ingredients

  118. preparing meals

  119. table service

  120. sanitation

  121. we don’t need to anything about how or what the

    kitchen does
  122. the menu is our interface to the kitchen

  123. “lol, I dunno.”

  124. “check the kitchen, I’m sure you can find some food

    back there.”
  125. that’s what every shapeless component says to future developer

  126. comprehension

  127. we describe our systems macroscopically by their interactions

  128. Web Transport Google Apple Windows PostgreSQL memcached Stripe Sendgrid

  129. put it under the microscope and magnify

  130. method junk drawers

  131. User

  132. bad fences, bad neighbors

  133. User Payment Sale Processor

  134. 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?
  135. murky interfaces

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

  137. method visibility helps us reduce the surface area of an

  138. less surface area means we can change the innards of

    an object with less fear
  139. having a small, well-defined public interface communicates what it does

  140. and how it’s supposed to be used

  141. o u r s y s t e m s

    a r e defined by their interactions
  142. 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
  143. extensibility

  144. 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
  145. >> cache = => #<Cache:0x007f9170822e28 @storage=#<Redis client v3.0.2 for

    redis://>> >> cache.fetch(“key”) { some_expensive_operation } => :some_expensive_operation_result
  146. 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
  147. wire it up at runtime with a storage backend that

    responds to #get and #set
  148. cache =

  149. cache =

  150. cache =

  151. redis =[“REDIS_URLS”]) cache =

  152. naming a concept helps us reason about it

  153. Cache represents a conceptual border

  154. code reuse

  155. we can’t predict future needs accurately

  156. speculative generality

  157. reuse in the small vs. reuse in the large

  158. build components that can be easily reasoned about

  159. apply a little design

  160. clarity, extensibility, and reuse will follow

  161. Write Documentation

  162. RTFM

  163. RTFM

  164. WTFM

  165. WTF

  166. we demand it from our open source projects

  167. but we have different standards for our projects

  168. oral tradition and lore

  169. graveyard wikis


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

  172. # Return a NullUser if not logged in return true

    if logged_in?
  173. inline documentation

  174. None
  175. None
  176. None
  177. documentation is exposition

  178. commit messages

  179. your commit messages comprise your project’s changelog

  180. breadcrumbs of context for the future

  181. git blame

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

  183. $ 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
  184. $ 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
  185. leave behind a coherent paper trail

  186. compare your projects to the standards to which you hold

    open source software
  187. TL;DR

  188. fight software entropy

  189. fix broken windows

  190. work toward consistency

  191. leave behind what you hope to find

  192. build a better tomorrow for future developer

  193. and a better today for yourself

  194. Thanks! @jpignata

  195. Sup? @jpignata