Don’t Let Perfect be the Enemy of Good
Hans Martin Steinbacher
IT & Agile Mercenary | Full-Stack Devloper, Scrum Master, Agilist | 6 Years of Experience Developing Software and Building Agile Teams
Last week I wrote about technical debt and how we should not compromise on quality when delivering increments in our iterative cycles. I stand behind what I wrote, but today I want to approach feature delivery from a different angle. There is a balance to be struck.
?
Trying to be Perfect
?
In the beginning of my career (I started out as a web developer) I had stumbled upon “SOLID”, five principles in object-oriented programming which will make your code more maintainable and expandable by improving readability and reducing tight coupling in your code. Awesome, I thought, this will get rid of all the technical debt we have in our code base!
?
If any of you developers are using SOLID as your design principle, you have probably already noticed how many classes it requires you to build. The simplest feature you want to build suddenly grows into 10 classes. You introduce complexity into your code, but it will be worth it. Once you need to get back into this area of your source code to change something, it will pay dividends.
?
Well, turns out that this day might never come. Your stakeholders need that feature now. That feature can already start earning money or improve your product as soon as it is done. That change you are anticipating by making sure each class has a single responsibility, is open to expansion but close to change, can be substituted by any other class with the same interface which in turn is perfectly segregated from other interfaces, that change might never come. YAGNI. You aren’t gonna need it.
?
The Thing with Technical Debt
?
I realized that by trying to make my code perfect, I inadvertently had worse outcomes. I felt that my code quality had improved (who knows if I even did the whole SOLID thing correctly? It looked good to me), but less of my code would reach production. Less of my code would be usable and used by customers. I slowly realized, that if I spend too much effort trying to anticipate changes in my code base that may never come, I will become less effective when the goal was to become more effective.
?
领英推荐
Technical debt only really shows up when there is a poorly written area of code which needs to change often. Regular changes imply a tight coupling so whenever software around the code changes it will need to change with it. If it takes a long time to do these changes (or if developer do not want to do them), this usually implies bad code quality. This is the monster of technical debt we speak about. This is where you jump in and refactor, because each day you leave it that way is a day that costs you. That small feature you’re building for the customer? It may never see a change, or it may not see changes for the foreseeable future at least. Write some tests, write your logic, and send that bad boy out into the world.
?
Only when your code starts to necessitate change is when you start refactoring. I’m not saying you should write the dirtiest code in existence either. You should still write clean code, make sure you do not have code duplications, have tests in place and extract functions to reduce complexity. I’m just saying there may not be a need to write an interface for a class which may never be implemented by any other class in the software.
?
In the Real World
?
My wife is a perfectionist. She is capable of many great things; she has extraordinary taste (especially in men!) and an attention to detail which I fail to even comprehend. That perfectionism has a very dark side, though. The very nature of trying to perfect something means that it will not get done. Perfection can be strived for, but never achieved. Not getting stuff done means more work in progress and lots of work in progress will reduce your structure and lead to stress. I see some of that perfectionism in myself: Sometimes I have to force myself to call something good enough and finish it. Just like this blog post here.
?
When the engineers at Toyota – the birthplace of all we call Lean or Agile these days – developed the Prius, it only took them 15 months from concept to delivery, faster than any other delivery in history. The way they managed that was by prototyping. They built cars long before they were ready to be sold to the public, but they had working cars in their design factories which the chief engineer would take out on test runs to improve on. I think if they waited for their cars to be perfect before they took them out for a spin, they would still be working on it. Feedback is incredibly important. You can only achieve feedback by giving people your product first, even if it is far from perfect.
?
Takeaway
?
It does not have to be perfect – chances are that it never will be, anyways. All that meticulous effort you have put into preparing for all these different eventualities which may never materialize, it’s nothing more than waste. Yes, the day may come where what you built may not be good enough anymore. Fix it then, not now. That is the beauty of the iterative process. Release, learn, improve. Do not let perfect be the enemy of good.
Data.Development. AWS. Python
1 年Well said ! Excellent work.