Complexity in Software
Notes I made from a talk by @zachdennis at Path to Craftsmanship 2012
Past habits dictate future behavior. The things you have done in the past, you will probably keep on doing. If you're tacking on stuff today, you'll probably be tacking on stuff tomorrow. If you're writing tests today, you'll probably be writing tests tomorrow. If you're refactoring today, probably you will be tomorrow as well.
- Gut feel
- Peer review
Software complexity is not linear. As the size of a project grows linearly, the number of potential relationships grow exponentially. Little changes made one at a time can add up to big complexities.
Consider a pile of sand. You take a handful of sand, and slowly drop it out of your hand into a sandpile. The sandpile grows taller and taller, but eventually it reaches a critical point of stress, and a landslide starts that makes the pile shorter and broader.
Software is similarly attracted to a critical point of complexity. Small changes are added individually until the critical point is reached. When it reaches it, development must stop until cleanup occurs, like the landslide. This pushes the software temporarily away from the critical point, but then complexity is added again until the same thing happens.How do you measure the stress? Being able to predict when the critical point is reached might be a huge advantage - bf
Teams start out at a rapid pace, quickly adding features. But then they gradually slow down as the complexity reaches the critical point. At that point, the team might try to refactor to remove complexity, which causes bouncing up and down off the critical point. It's a vicious stop-go cycle. Is rewriting the only way to break it? Most rewriting of software ends up being much more difficult and costly than anticipated, in my experience. - bf
There is a misconception of pragmatism, where it's easiest to add the little bit of code that makes everything more complex. But in doing that, you do more work to move back from the critical point than you do working towards it.
So how do you avoid reaching the critical point?
There's a similarity here to the principle of re-understanding in Domain-Driven Design, where the idea is that when your understanding of the model is sufficiently complete, you may be able to refactor it to a completely different, and simpler, form. -- bf
- fall in love with simplicity
- loathe (unnecessary) complication
- Don't focus on Perfection
But note that refactoring can be good or bad. If you have complicated code in a controller, just moving that code to a model object doesn't do anything to fix the issue. Of course, 'anything' can be good or bad.
- Practices are important but values (missed what he said here)
- Values help determine where we drop our grains of sand
- What we're really fighting against is complexity
I asked him if the example of complex code he gave was fixed by rewriting or refactoring. He said it was rewritten with careful examination of existing code to copy existing functionality and make sure nothing was lost.