Tuesday, January 29, 2008

Car != Frying Pan

One of the first things you learn in software engineering is that duplication is bad and reuse is good. As generalized concepts applied to specific situations, both statements are true and are good ideas to keep in mind. However, if applied without discretion or thinking ... they can be worse than the alternative.

Let me paint a picture for you .....

You have a job. You buy a car to get you to work. You don't care exactly how every piece of your car works "under the hood" so long as it gets you to work.

You get married.

Your spouse wants to cook dinner. Neither of you owns a stove. When you get home from work, your spouse notices that the car's engine is very hot to the touch and immediately thinks: "stove = hot, hot = engine, therefore, stove = engine". Later that night you get a dinner that has been cooked on the top of the car engine. Why buy a stove when the car engine works (and the food isn't too terrible).

One day the car starts making funny noises and you take it to a shop. In order to fix the car, you need a new engine. The new engine has all the latest features including an engine that doesn't get hot to the touch.

Well, now your screwed. When you get home and your spouse tries to cook dinner on the car's engine, nothing cooks and you go to bed hungry and frustrated because you have to go buy a new stove now anyway (and you ate 5 years of meals tasting like motor oil for nothing).
I have run into this problem a lot lately (with the code base I am working on, not my car, Em is a good cook). The analogy is a bit crude and longer than I would have liked, but I think it demonstrates my point.

Without any formal testing in place, well defined components and ever changing feature changes ... the code is a mess of intermingled requirements and coding by coincidence. Large amounts of code have been reused b/c "reuse is good" and "code duplication is bad". Well the problem with this is that the real rule should be "reuse is good, when the component you are reusing is well defined and you are reusing it in the same manor as it was intended". Past developers have relied on reusing old components in new and unique ways (often by subsclassing, copying some long methods again while changing random lines in the middle, and ignoring others) which leaves the code base a mess. There is no order to the code. Components that started out as well defined thoughts have been bastardized into doing many things they were not designed for and without any documentation. Things are held together by random side-effects which only work b/c of random implementation specifics. If the specifics ever change, random new problems pop up.

Just because there exists a component that "could" do what you want "if you make certain changes" and if "you add undocumented desired behavior" ... doesn't mean you should.

If we are going to try and write code in an object oriented way ... we need to know the difference between the different types of object relations ships:
  • has-a
  • is-a
  • looks-like-a-from-across-the-room-but-up-close-isn't-a-and-never-was-a
  • mutant-asexually-spawned-offspring-of-a
... and which ones to avoid.

[this post is mostly to help me vent some of my frustration before trying to tackle the current task at hand again, thanks for listening]

2 comments:

Kevin Berridge said...

I enjoyed your analogy.

I'm curious, where did you come across the Open/Closed Principle? I've been reading lots of good stuff like that in Agile Principles, Patterns, and Practices in C#. I was just curious where you'd gotten it from.

Benjamin P Lee said...

I don't remember exactly.

I know we talked about it in a TDD class I went to a few months ago (along with the Liskov Substitution Principle and the Law of Demeter). I know I knew them before this but can't put my finger on exactly where I first saw them.

Some or all may have been in the Pragmatic Programmer as side-tips and/or in one of Head-First series of books. Good question.

Someone blogged recently about most of the famous (and often incorrectly used) quotes and principles around software engineer, but I can't find it.