How to survive a discussion of principles
There are so many Books about more or less ingenious design patterns, engineering guidelines, modularization, framework usage etc. no one could ever afford the time to actually read one of them. The main point in all of these efforts is widely the same:
I don’t want to do more work than I have to.
Which is, in fact, the principle of all technology, up to the point where having spent efforts in technology finally frees us from the efforts of the task itself, leaving us just with the efforts of fixing that technology when (if would be nice here, but is inappropriate) it breaks and the effort of finding something meaningful to do. It unfortunately implies “If I can drive a car with three wheels, why should I bother buying the fourth?”
So why the heck can’t I just…
I mean, you get a task. Say like “Write an online application”. What you want to do is get rid of it forever. What your company wants is to get rid of it soon.
So they order you to get it done as soon as possible and you will be spending time on it forever. Face the fact.
And the first solution that would come to your mind would be: “OK, if I do this as simple as possible, I won’t be doing complex errors and be done with it quickly.” Which is a correct assumption. For one, finite Task.
This is, where multiplicity comes into play. You won’t be doing one Task in one context. You won’t be done with it, ever, either. And the first one coming after you will most probably have to do it again in a slightly different fashion. And there is a word for multiplied simplicity: Chaos.
There is a certain amount of complexity that a System will always have, defined at least by the complexity of the tasks it has to perform. There is no way to eliminate this complexity, not even with Object orientation, 4GL and UML. So what happens if you seem to have eliminated complexity is that you actually shifted it somewhere else. Which can be a good thing, once that “elsewhere” is in the domain of your customer’s organization and they can live with it. Or inside some framework voodoo.
Calling things differently or avoiding to name them at all does not eliminate complexity either. It just takes away any possibility to handle them. If your application does not have explicit Tiers (Yay! We have a one-tier application! That is only a quarter of what a 4-Tier application would cost us!) it nonetheless has implicit ones, and usually more than you would imagine. If your application does not employ a model (saved efforts incoming!) it will have an implicit model nonetheless, and even better, it will have several models describing the same thing, once that thing is used in two contexts!
We have a developer here that spent much time painting tables with fields to find implicit models for which no classes exist.
So why bother with architecture, modularization or reuse at all? I mean, even if your system starts with minimum complexity, future evolution will soon drive it into entropy anyway! And yes, this is an effect that can not be avoided by any means we here possess. Any concept of reuse requires overhead, abstraction and configurability which makes the would-be reusable component even more complex. Any concept of modularization requires much work on how these modules interact, are composed, packaged, defined and you have to do much work just finding out where to put your stuff.
Fun, isn’t it? We actually add more complexity to an already complex system, to be able to view it in a more simple way. Isn’t that ridiculous? No.
What we can do, is shift complexity away from the evolving spots. We can move it out of the multiplying part of the system, which is usually defined by the features. Since complexity is there, and cannot be done away with, we have to face it somewhere and make sure that it is faced only once. So there are complex components, difficult to understand, cryptic, like many components of software tend to become when left alone for a couple of years, but we have them in their own biotope of complexity, and most important of all, we have their complexities separated, able to be handled one at a time by different people.
It is not the aim of modules to enable old, smelly code of old to work forever, but to have clear places to cut once parts of that code fall to the teeth of time and have to be replaced. Furthermore, we have Modules to enable composition of more than one product (or variation thereof, like a staging installation) while using the same, tested implementation with a different configuration. Featuresets and other terms known to multiply are allowed their own module to keep the multiplying stuff out of their dependencies. This ist costly, but it costs less than multiplying everything in every code.
We do not produce future code that handles all possibilities of future extendsions, but we provide valid rules for extending the system, at defined places, with defined terms and common basic functionality. So then the future code may multiply and change as much as it wants, as long as we are able to handle these multiplying components at all, our basic system remains stable, in fact, it gets even more stable with each new component that uses it, and it actually stays… simple.
So everytime I drop a design abstraction for the sake of simplicity, I should take a clear look where it actually went, because I can be sure it will bite me some time.
When I read a book about object orientation, the first argument for OO is “Encourages reuse of code”. No. It doesn’t. It enables you to do reusable components, but these do not besome reusable by just writing “Class” somewhere atop your old code.

Blurps