Holistic Development

Nick Stogner | Mar 2018

As developers, we tend to focus on improving our craft through learning to write code that is either faster or more elegant. However, I have found that the top developers focus on something very different. What self-improvements are the rest of us leaving on the table?

Example 1: While helping a startup get their MVP out the door, I was tasked with implementing JSON Web Token authorization. The project was months behind schedule and the CEO was getting nervous. However the VP of engineering wanted full benchmarks written on the different available algorithms so that he could fully understand the performance impact of each option.

Example 2: One senior developer would flag any javascript chaining of .filter + .map and submit PR’s because it was less efficient than a single for loop. He would make sure to note that inefficient code will cause the company to pay more on their AWS bill.

Both of these examples involved extremely smart engineers and the result was indeed faster running code. But what slice of the total request time did we really shave off? 1/1000th? And at what cost?

Cost of Example 1: A day-long task turned into a 3-day long task because benchmarks needed to be written and the results needed to be reviewed and discussed. Due to the accumulation of premature optimizations, the project was now lagging further behind schedule.

Cost of Example 2: Avoiding the entire functional vs procedural debate, a performance-above-all mindset like this will lead to less understandable code. The “improved” code was faster but more error prone. Extrapolate out this methodology across the codebase, and yes you save some pennies on your AWS bill, but now you have to pay more for the added development/debugging hours.

As developers, we naturally want to write “efficient” code. The problem is that we tend to focus on the wrong level of efficiency. Some of us focus on the space the code takes up on our screen and we end up writing compact, esoteric code. Others of us tend towards writing the fastest code, even if it requires dense comments to explain what it is doing.

I would suggest that developers should optimize for the project as a whole. Most projects are constrained by development resources, not computing power. Keep in mind that slow code in production beats fast code sitting in your develop branch. This is what holistic development is about:

Optimize for other developers, so you don’t slow them down.

  • Prefer clear over clever.
  • Prefer concrete over abstract (abstractions carry a large cognitive overhead).
  • Prefer easily understood APIs over concise ones (it is better to have the user of your API expend a few more keystrokes than to dig through your code/documentation to grapple with unexpected behavior).
  • Avoid acronyms and abbreviations on global variables and function names.
  • Adhere to coding conventions appropriate for the language you are using.

Optimize for operating the application, so that your code is easy to run and debug in production.

  • Avoid building over-configurable apps.
  • When you have to add configuration options, prefer reasonable defaults over blank/required fields.
  • Avoid inconsistent logging and over-logging (metrics are best exposed outside of the log stream).
  • Always include health checks.

Optimize for security because nothing kills a project, a company, and your reputation faster than a security breach.

  • Prefer simpler solutions because complexity begets security flaws.
  • Do it now, not later, because // TODO: Security risk comments tend to sneak their way into production applications.

Finally, optimize for performance, but only if it becomes an issue.

  • Profile your app so that you can identify areas where you can get the most performance returns for your effort.
  • Write benchmarks before modifying working code.
  • Add comments explaining performance-driven blocks of code (link to benchmarks if possible).

Holistic development is about keeping a broad set of goals in mind while coding. It is about avoiding micro-optimizations and focusing on big-picture effectiveness. It is about taking responsibility for the costs associated with your design choices, even when they only affect other team members or even other teams. It is understanding that when it comes down to it, people, not computers drive overall project performance.