“The client keeps changing requirements!”
“This deadline is unrealistic!”
“This legacy code is too hard to work with!”
Things like these are legitimate problems that are often used as excuses to write bad code. You feel pressure to go faster, so maybe you skip the tests. Maybe you write very long functions. Maybe you let the conditionals get nested into a web of complexity that works for now but will be impossible to untangle later.
You do what you have to do, but don’t fall into the trap of thinking it was totally out of your hands why the code is now hard to maintain. The truth is, when you felt the pressure, you fell back on what was comfortable so you could go faster. If writing bad code is comfortable, you need to practice until writing bad code is uncomfortable.
A professional sports team practices so they don’t fall back on bad form when the pressure is on. A professional programmer should do the same. Your goal should be for good code to be your comfort zone.
That doesn’t mean you can never cut corners when you have to, but do it mindfully. Don’t use one of those excuses to justify your lack of skill. Notice it, and then work on fixing it.
I like to use abstractions that lead to lots of small objects that do little jobs communicating with each other to do bigger jobs. The common argument I hear against this is that it makes the code hard to change, for two reasons:
1. “The work is spread out into too many places”
The Single Responsibility Principle says that a class should have only one reason to change. The inverse of that is that if multiple things will change for the same reason, they should probably be in the same place. If you are making a change that requires editing lots of things in lots of different places, you’re either making a very high-level change – in which case, this is expected – or your design needs work – those things probably should have been in the same place.
This doesn’t contradict “lots of little objects”, it provides a counter-balance for taking it too far.
2. “It’s hard to find where I need to make my change”
“I’ll start in my view… ok that’s calling a method in this file… oh that’s calling a method in this file…” and so on.
This is sometimes true, but I prefer it to the alternative of everything happening in this one method so it’s easy to find, but when I want to make the change I’m terrified because this method does so much.
I’m willing to trade that anxiety and potential for bugs for the cost of a bit more upfront time looking for the right place to make the change. Because when I find it, it’s only doing one small thing. I can change it with confidence.
This is the main reason I think using lots of small objects enables change. And ability to change is the best indicator of a good design.
Sandi Metz has a great talk on this subject.