I love coming back to a feature that was developed a couple of months ago and seeing that extending it is just a walk in a park. When thinking abou...
For further actions, you may consider blocking this person and/or reporting abuse
Could leave yourself a breadcrumb for work not done, that maybe wasn't needed, maybe will never be needed.
Picking JavaScript today, rather than my usual C++.
I like the idea of leaving breadcrumbs! It's self-documenting and pretty straightforward.
Great article!
I agree that over-engineering produces a lot of bad code. Especially over-abstraction for code that can have one, and only one, implementation.
Though, one should never reject forward-thinking system design, if there is a clear notion that the functionality would be extended and if it takes comparable amount of time to implement it.
I couldn't agree more!
Forward-thinking is one of the most fun and important part of being a software developer. The problem occurs when that clear notion is not so clear and when you find yourself solving problems that don't and might never exist.
Good post.
One useful suggestion by Martin Fowler is to imagine making the change at a future point. This tends to lead to two things. Firstly, realising that the cost at a future point may not be as bad as first thought. And, secondly, coming up with some small changes that would make the change easier at a future point without adding much complexity.
Thank you!
As usual, Martin Fowler is on point. This is really useful how-to.
When I would like to implement something but suspect that now it is not the time.. i write a comment // TODO write a method for... . That helps me feel better and I never do anything from those TODOs :-D
I usually write down what ifs in my notes, but I really like idea of documenting it in code!
This VSCode plugin gathers all project TODOs
marketplace.visualstudio.com/items...
It's one of the advantages of Test-Driven Development (actually Behaviour Driven Development is what I do, but the idea is similar).
Because you start with an executable specification, all you do is the bare minimum to make the tests pass. I have found that making the tests pass looks like an insurmountable mountain for ages - then suddenly everything works and you're really surprised as how simple the resulting code is. (Although, now you have tests you're also safe to refactor if it does need tidying up)
And because all you're concerned with is making the tests pass, all the YAGNI stuff gets put on the back-burner until it, too, is included in a specification.
This is a great approach. You're right, tests ensure that you've done a good enough job and they would also help you enormously when (or if) refactor is needed.
In a team environment, recommending retros vs what-iffs, let alone bread-crumbs or adding comments. I do inline a comment here and there, and I think the edge case is when writing code that's obviously fragile, because time is lacking to write it well.
Here's why.
The tomorrow you is smarter than the today you.
The tomorrow you understands the problem better.
What-iffs are you talking to yourself; they're a likely waste of your time, and more importantly (team environment) hardly anybody will take the time to figure what you possibly intended; they likely will solve the problem a different way and leave your stubs/breadcrumbs sitting here, feeling unsure what the stubs/comments intended; then what? Bloat.
A variant of what-iffs consists in endorsing as many best practices as possible, without an understanding of the context.
Finally, a thing I often see is developers getting reluctant to delete code produced by misunderstood (or mis-stated) requirements.
Travel light!
You made a few excellent points. You are right, just as all code comments, leaving breadcrumbs can result in mess.
And yes, deleting code is hard, especially if you've done something you're proud of. We should all remind ourselves that it's just a code and has one and only purpose: to solve problems, not to boost our egos.
I had to work with code of a guy that tried to solve each future problem. Of course the next problem was not solved and from there on life was hell. Adapting an overdesigned framework immediately leads to crap. change my mind
xkcd.com/974/
Oh yeah, overdesigned frameworks are just evil.
Well, you seem to be mashing together a couple of somewhat related things but not in a way that seems to connect logically.
You start with over engineering, which is about code design and implementation and then go about features (not sure if there's a word for it, perhaps over-productization?).
Overengineering, basically engineering things a certain way just for the sake of it, is a bit of weird case. It's weird because there will always be a moment when you're doing things to preempt problems. When you're just beginning a project, you make decisions that solve potential issues you know about from experience which you might hit (but then again, might not - experience is never 100% replicable). While it's natural to happen, people tend to forget that different people come with different experiences and different takes which they will try to apply all at once in that stage.
Point 2, which is more a rule-of-thumb kind of guideline, is to never engineer extensibility before it's needed. Don't design a contract that's currently used once. Design it when you have at least two uses in mind, which are needed right now.
On the second matter, features (which is what Ron Jeffries specifically refers to) are no longer a development decision. Nowadays we have (generally, unless you're a garage startup - though even then ...) product designers that describe features. It's still a great thing to not implement something unless it's needed (and particularly in startups people avoid it like fire when going for an MVP) but it's beyond the domain of pure development. Overengineering a product (in the sense of taking a convoluted approach to feature implementation for the sake of opening up future options) would probably get you skinned alive in a time-pressed startup (but unless you double it with hurried spaghetti code, it won't kill anyone except probably accountants). Overengineering an implementation (architecture, code) is a more immediate development issue that's guaranteed to come haunt you in many different ways.
Thanks for this comment, it really made me think. When I talk about overengineering a feature, I don’t talk about defining scope of it. For me, as a developer, overengineering a feature is adding unnecessary complexity to code only because of a fear of the future problems. It’s all about that thin line between building right amount of flexibility into a code and overengineering.
This is completely spot on. I deal with overengineering myself and I'm learning to have a more realistic approach to the solutions I code. One approach I'm trying is that, when I'm not sure if something is going to be really needed, then I put a short time limit to implement it. If it takes too long, I quit and continue with the rest of the code.
I only want to add one thing: you can do overengineering in personal projects to learn. I have a lot of code that I never use, but I try to have it heavily commented and its common that I revisit it to see how I thought that certain problem could be solved.
However, the focus of this code is not quality, but experimentation and learning, so its important to keep it separated from real code!
Great post, Lina :)
Thank you!
I like the idea of overengineering personal projects. It really can be a great way to fully grasp some concepts and find out what is going on under the hood. In the worst case scenario, you learn how not to do something, which is also a great thing!
Im agree with your post and the importance using YAGNI, but every new feature is different depending the project you are working on. Let's say that you have to code a new big feature, but you have to deliver it in steps, in order to let the client to see how is it working and put these functionality in the table letting the rest of the team to see how is this working for example. In that case, you can save a lot of time by doing every step in flexible way because you have the certainty that you are going to need it, which doesn't violate YAGNI principle.
If there is certainty, absolutely!