Write code as if you are going to remove it tomorrow.
I get a lot of questions about this. What do I mean by that?
When you write code for a new feature, you want it to be decoupled from other parts of your system. Put it in its own bucket - namespace, module, directory, etc. (depending on the technology). This makes the code easier to test and reduces the risk it will break existing functionality.
I have found that a good way to tell how decoupled some code is to find out how much work it would be to remove the feature it is powering. If removing a feature is just remove a folder + 2~3 integration points - that's good code.
Because of this, I prefer to organize code based on domain than on type.
But how often you remove features? 🤨
At Product Hunt, we do this quite often 😅 , and this is a good thing. When you do product development, you discover what works and what doesn't via experimentation.
But I spent so much work on this feature, and now my work goes to waste? 🙄
Not really. On the product level, you learned something, and hopefully, this will give you a better direction for future work.
Product logic gets simpler. Think about losing body fat.
But I had some really, really cool code there? 🥺
When I write code, I make a clear distinction between Plumbing vs. Domain. I have found that plumbing utilities are often where the "elegant" and "cool" code is.
This often happens to me. I build a feature and separate its plumbing utilities and domain. Then, for another feature, either me or a teammate use the utilities. Later, the original feature is removed, and the utilities stay.
If utilities are isolated, they are often re-used in different domains. So this cool code stays after the feature.
For any questions or comments, you can ping me on Twitter.