YAGNI: You Ain't Gonna Need It and Cake models

YAGNI is a principle that arose from extreme programming which states you should not add functionality until you need it. I learned about this from a recent elm radio episode:

This leads us to two approaches to programming:

The Layered Cake Approach

  • implement things from the ground up in layers
  • every layer is completed and perfected before you start the next layer
  • if you think you might need something, implement it now while you are thinking about it as that might be most efficient rather than coming back later
  • product is only functional near the end of the project
  • end-to-end testing starts late in the process
  • code is not easy to refactor
  • refactoring is not common as previous layers are locked in and not modified
  • roles are often fixed
  • Just in Case
  • also referred to as the water-fall methodology

The Sliced Cake Approach

  • functionality is implemented in end-to-end slices
  • nothing is implemented until it is needed
  • unused code is identified and removed from the codebase using automated linting tools
  • the goal of each slice is to have some end-user functionality that can be demoed or tested.
  • end-to-end testing can start early once a slice is completed
  • stake-holders use the product and provide feedback
  • this feedback is used to refactor existing slices and adjust the approach for future slices.
  • focus is on iteration and learning
  • code is easy to refactor and refactoring is a common activity
  • roles are flexible and people do whatever is needed to complete a slice – often working all up and down the software stack
  • Just in Time
  • also referred to as the lean or agile methodology

Efficiency

Efficiency in programming is a tricky topic as it is very difficult to measure. Most of us are biased to be a bit conservative – take the careful approach – never throw anything away. We like to polish and perfect. The argument that we “should implement something we may need as we are in the code anyway and it will be most efficient” has some validity, but it ignores other costs, such as maintaining the code. As one person said, Code is a liability, not an asset. Aim to have as little of it as possible. It also ignores the reality that software projects are very difficult to completely specify up front. The sooner we get something implemented end-to-end, the quicker we can start learning the things we need to know. And we’ll likely end up someplace different than where we started based on the feedback received.

Principles

  • code should be easy to read and maintain. If it is not, it is likely too complex and clever – simplify it! This diminishes the need to “implement something now while I’m in the code” as it is easy to add later.
  • it is difficult to fully specify a software project upfront
  • you will encounter problems that require changing your approach, so the quicker these problems are identified, the better off you are
  • the faster you can iterate, the faster you will learn about the problem domain you are solving.
  • end-to-end testing is where the real learning occurs and problems are discovered.
  • feedback from users is extremely valuable
  • failure is fine as long as you are “fast at failing.”

So, I had only listened to about 1/2 the elm-radio episode when I wrote the above. When I picked up listening, the following comment was made:

I think a lot of it comes down to – do you want to work in horizontal slices or vertical slices?

A few more comments:

In Lean they call this push vs pull. Push being I think I’m going to need this. So I’m going to set all these things up that I think I’m going need later and pull being hey once you need something, then you grab it.

Just In Case vs Just In Time

This podcast about unused code is a very well-done and cleverly disguised lecture on Lean Development Philosophy.