First Indicators of Overengineering in Your Project
- You start to use terms like "potentially", "in future" or "scalable".
- You spend more time thinking of "encapsulation", "abstraction" and "decoupling", than the actual problem.
- You believe, that the with amount of frameworks, libraries, and languages (better polyglot projects), the qualitity of the software will improve.
- You are able to replace every single concept, class and layer - but this feature actually cannot be derived from the client's requirements.
- Just looking at the code - you do not understand what happens - you need addtional tools, products and consultants :-) to understand it.
- You hate monolithic structures - so everything is configurable, replacable - of course at runtime. If it becomes too complex, go to point 5.
- You start to implement a generator to tackle the complexity.
- Your configuration file is getting slightly bigger, than your code.
- Your interface is so fluent, that only domain experts understand the code :-)
The problem with patterns, best practices and idioms is the overuse of a single principle. Regardless what you are considering: overuse of DRY can lead to "fat" layers and classes, overuse of Separation Of Concerns to many fine grained units, overuse of modularization to jar, plugin or just governance hell. Common sense and the balance between concepts and idioms are the solution- but it's hard to find in real world :-).
[I expanded the thoughts above in the book "Real World Java EE Patterns"]
Well, that's really interested list.
However, it's hard to say whether overengeneering is always bad thing - the question there is rather finding proper balance.
Just couple of my comments:
1) What's wrong if you consider futher evolution of the system as possible scalability issues? If we'll ignore them and consider only current situation you'll simply could have problems in the future - so that problem is just moved to later time.
From the other side, it's not required to support every case that could be required in the future - however, I suppose that at least generic architecture of the system should be pretty flexible for futher evolution.
2) Internal architecture vs actual tasks - also, not sure that composition should be negleted in favor of today solution - again, there should be balance since solving particular problem without proper decomposition/coupling, on the later stages you can have issues with support, maintenance and changes.
6) well, non-monolitic system is hot bad - but again, there should be proper balance.
7)Writing generator - why not? Especially if one could be used for several similar projects - sorry, but that's perfect solution if it could save time and automate routine coding. And in some cases, generated code will obviously work faster than one executed on runtime.
Posted by Andrew Sazonov on June 22, 2008 at 12:12 AM CEST #
Thats about the best and most concise blog entry I've ever read. You should re-post it every week. That wouldn't be too often.
Posted by Eirik on June 22, 2008 at 02:18 AM CEST #
thanks! And it was one of the fastest (it took about 10 minutes - the idea came after an architecture review),
so - stay underengineered :-)!,
Posted by Adam Bien on June 22, 2008 at 07:32 PM CEST #
"...1) What's wrong if you consider futher evolution of the system as possible scalability issues?..."
You can take them into account. The question is: how much time will you have to spend now to implement the infrastructure - and how much later? Often it is hard to start with the perfect solution immediately. On the other hand, certain decign decisions are obvious (like extensible platforms or frameworks)
"...2) Internal architecture vs actual tasks..."
It doesn't mean you should hack your project - you should just stop discussing, start and improve the design incrementally.
"6) well, non-monolitic system is hot bad"
Right - monolithic systems are not always "bad" - sometimes even a best practice - it depends on the requirements.
"7)Writing generator - why not? "
If you have many similar projects - product line engineering is perfect. A transformator shouldn't be introduced just to fix the architectural flaws. Often it is better to refactor your system :-).
Thank you very much for your comment!!!
Posted by Adam Bien on June 23, 2008 at 01:18 PM CEST #
10) Your architects use all GoF patterns for a single "Hello World". Seriously: I've seen a few times that patterns need to be introduced in a program - just because they exist and not because they are needed at a certain point in the code/architecture.
Posted by Heiko Rupp on June 23, 2008 at 02:26 PM CEST #