I'm not really a fan of the term "overengineered." I often find it is a direct translation of "Something I don't understand quickly."
In my experience (including my own development), overly complex designs accrete, as opposed to start off complex.
They usually seem to begin with "This is simple, let me just do this...", then, when we run into Roadblock A, we design in a mitigation, and so on...
Eventually, we have a ghastly chimera.
Other times, it comes from trying to coerce software written for one purpose, into another, and the glue code is kinda messy.
Also, there was an article mentioned here, about "Don't design a general-purpose framework."
I can concur with that. The app I'm releasing now, has a server component that is, in my opinion, way too complex. I designed it, and implemented it, so I get to say that.
The deal was that I originally developed it as a general-purpose framework. It has a layered architecture, and I did heavy-duty unit testing of each layer, as I was writing it.
It works very well, is fast, and secure.
But way too complex, as this app is its only implementation. It handles a lot of stuff this app never touches, like trees of user permissions. I have a very simple, rather "flat" permission structure, so a whole shitton of code never gets used. It was tested heavily, works well, but will never be used. I don't like having unused code paths, but I don't have the luxury of time to remove it (I have removed some, but there's plenty more, where that came from).
If I were to rewrite it (I won't -see "works very well", above), it would be much simpler.
In my experience (including my own development), overly complex designs accrete, as opposed to start off complex.
They usually seem to begin with "This is simple, let me just do this...", then, when we run into Roadblock A, we design in a mitigation, and so on...
Eventually, we have a ghastly chimera.
Other times, it comes from trying to coerce software written for one purpose, into another, and the glue code is kinda messy.
Also, there was an article mentioned here, about "Don't design a general-purpose framework."
I can concur with that. The app I'm releasing now, has a server component that is, in my opinion, way too complex. I designed it, and implemented it, so I get to say that.
The deal was that I originally developed it as a general-purpose framework. It has a layered architecture, and I did heavy-duty unit testing of each layer, as I was writing it.
It works very well, is fast, and secure.
But way too complex, as this app is its only implementation. It handles a lot of stuff this app never touches, like trees of user permissions. I have a very simple, rather "flat" permission structure, so a whole shitton of code never gets used. It was tested heavily, works well, but will never be used. I don't like having unused code paths, but I don't have the luxury of time to remove it (I have removed some, but there's plenty more, where that came from).
If I were to rewrite it (I won't -see "works very well", above), it would be much simpler.