Just a quick rant this morning, something that occurred to me in the shower….
Object-oriented languages were hailed as a great advance in software engineering because they helped you create “generic and reusable components”…. great, but I call BS.
This little nugget of wisdom has been around for years and is still taught at many universities… and it’s also the cause of lots of pain and misery in software projects. Why? Because generic and reusable components suck.
If you’re working on some shrink-wrap product within a big company, and the same code-base has been around for years then yes… you may want to refactor some components into a more generic version, but please: also leave a few specific versions! Make them adapters, make them inherit from the generic one… but don’t let every user of your API have to mess around with your super-generic and flexible object. It’s like butting your toast with a Swiss Army knife… you can do it, but why would you want to?
Generic components are jacks of all trades but masters of none… they have to be to stay generic. This means that they can’t keep proper invariants since that would limit their wonderful genericness. So, you’re stuck with something that in theory could do everything, but in practice it can’t do anything: at least not without a lot of work and checks on the part of the person using the API.
Also: I work a lot on custom software. This means that each new project is for a new client, so I couldn’t even use any of those generic components from a previous project if I wanted to…
My point would be: make simple components that do 1 thing, and do it in the most simple way. Have 2 components that need to do the same thing slightly different? Refactor into a super-class and 2 subclasses… or add a few configuration parameters, but provide sensible defaults.
For the love of your-deity-of-choice’s sake: Keep It Simple Stupid!
Are you hinting at the Unix design filosophy?
What got me going writing this post was service-design with overly generified interfaces, but yes I am a big fan of the Unix design philosophy.
In the unix philosophy the emphasis is on re-use through composition: because each component has one well-defined function it’s easy to use them as building blocks for bigger components, building higher-level abstractions out of lower-level ones.
Personally I think this is the most effectice form of re-use, since it doesn’t require you to guess ahead of time what different types of use might happen. I’m not against re-use through generalization, but I consider it a form of premature optimization. You shouldn’t generalize until you have at least 2 components / classes that share a significant amount of shared function and even then I’d try to solve that through composition first.
Thanks for participating