When I started off as a developer, I remember the lead architect lamenting the fact that he hadn’t been on a“greenfield” project in a while - as he was scrolling through 30,000 lines of CSS code in one file…
7 years later, I ask myself the question, “Have I learned how to keep a greenfield project ‘green’?”
In the software world, the term “greenfield” refers to a brand new project, a lush undisturbed land, clean and un-trampled. In this place, a coder can lay down new laws, foundation, and ideals. He hopes people will come and view its beauty, maintainability, and scalability for years to come. Unfortunately, in one or two years time, reality comes crashing in with a vengeance. The project is no longer a “green field”, but rather a muddy mess.
So what causes this? Here’s my opinion from my experience:
- Narrow deadlines provide easy excuses to compromise on code quality.
- Tests fall behind because they’re hard to write and there’s not enough time.
- Team leads are too embarrassed or not skilled enough for code reviews.
- Scope creep messes up the most well-laid abstractions.
So how do you combat “muddy mess” syndrome? Ideally, you handle it BEFORE the technical debt accrues, but that hardly ever realistically happens. First of all, accept the fact that you WILL have to let go of some of your rules. Regardless, enumerate the most important ones (like testing) and hold fast to them. Communicate those principles. Don’t be afraid to say “that code is not very good”. Do these things, and next thing you know, you’ll be promoted to engineering lead, and you can slowly melt into middle management.
This is original content from snaptest.io, made because I needed to get tests made quickly and easily for many “muddy mess” projects.
Top comments (6)
There is really one overriding principle that I violated when things become messy: Separation of Concerns. Parts of code have improper responsibilities either out of convenience (carelessness). Or because of over-abstracting to shoehorn different-but-similar things into a single concept (idealism). Or because of forcing conformity to my abstraction to gain the functionality (opinionated / inflexible, aka frameworky). Or coding my pre-conceived notions rather than listening to what users are telling me (hubris). I have messed up in all of these ways.
In a seeming paradox, I find Separation of Concerns is often at odds with how people normally apply the DRY (Don't Repeat Yourself) principle. Just because two pieces of code or data are similar does not mean they should be abstracted into a single thing. I always ask myself: Are these literally doing the same thing? Could they conceivably diverge in functionality? If these are the same concept, could they be two different expressions of it? (I.e. the way sales perceives a customer versus the way support does.)
I used to commonly way over-abstract things. But nowadays when it is not clear I am much more likely to duplicate first. Then wait for that day when I need to change them both in the same way for the same reason. And then apply DRY (which may just mean extracting common parts between them).
I also used to take the framework approach to hide all the details I could. Ostensibly so in the future I could just concentrate on the new requested feature, not the plumbing. But it always happened that there would be a new feature that I could not have foreseen, and the framework could not do it without a refactor. After a few rounds of this, the value of the framework approach becomes greatly diminished.
Even when you are on guard for it, some SoC violations always creep in. So it is important to refactor when they become obvious.
I think that most of the time is about that, the DRY principle wrong implemented. I work in this project, that every time that two functions share at couple of lines, they would refactor into a single one. This was a nightmare, and it only improved difficult to understand the function.
You know I have been thinking hard about this. I came to the conclusion that the only way to reduce technical debt is to give developers "free time", that means a reserved amount of time each week (or sprint) where the developer can do whatever he wants as long as it improves code quality. Not just in the project's own database but also fixing a bugs or adding a features to an open source dependency. I would say that this time should be 1 day per week (20%). Of course this doesn't help for large scale refactors, but if you do this from the start large scale refactors shouldn't be necessary.
This is a good idea! We actually did this at my current company for about a year. There needs to be a little structure to this "free time", meaning it's helpful for people to state what they're going to be working on, so there's a little accountability. Regardless, it helped us keep our code base much cleaner.
The important part is that the developer should not have to haggle with their manager about the amount of time spent. In a previous job it was extremely hard for our team to be able to work on refactoring because of that
Robert "Uncle Bob" Martin wrote an entire book on the subject of not making a mess, and if/when necessary, how to clean up a mess.
Clean Code a handbook of agile software craftsmanship, by Robert Martin.
I give that book two thumbs up.