The Dopefly Tech Blog

<< The Dopefly Tech Blog Main page

Extends is not a form of include!

posted under category: ColdFusion on October 25, 2007 at 7:00 pm by MrNate

This is one I never thought I'd see, but unfortunately I have seen it a few times.

Think twice when you extend a class/component! In ColdFusion, that would be with the extends attribute of the cfcomponent tag.

When you extend a component, you are saying that that component, the one you are writing the "extends" text into, is a type of the component you are extending.

Ok, let's have an example.

Let's say we have a logging component. We say: myLoggingService.log(message); and it does it for us. Easy enough.
Also, we have a user component. User.setName(form.name); User.save();, and it saves it somehow. Basic stuff, easy to grasp.
Now, how do you write a log message after you save a user? There are, of course, dozens of ways to do this.

The way you should NOT, EVER under ANY circumstances do, is say that the user extends the logging service. That doesn't make any sense. Is a user a type of logging device? I certainly don't think so. A user doesn't write logs, a user has a name and probably knows what object to call to persist itself. The logging service writes logs. That logging service needs to be its own separate entity. It just doesn't make sense any other way. You can call it from within the user object, or better yet, from some kind of controller or service layer, but don't integrate it too deeply within an object that it doesn't need to be deeply coupled with.

Oh I know, it's a matter of convenience, you can just say log(message);. Oh wow, it saved you 17 characters, but you missed the point entirely.

The correct way is to leave the logging service by itself, then call myLoggingService.log(message). I think it's somewhat a matter of style where you call that from, of course be consistent. The rule is this: Favor composition over inheritance. Your User object can be composed of a logging service (among other things), and you should do this whenever possible.

Now, if you have a database logging service, this is a prime candidate to extend a more generic logging service. Or how about an error logging service? Those are types of logging services. Inherit up from a generic implementation, down to a specific one.

Too old to comment!
On Oct 25, 2007 at 7:00 PM Sean Corfield (seancorfield who hates gmail.com) said:
Whilst I agree with the overall thrust of your post, I don't agree that "a user has a name and probably knows what object to call to persist itself". Business objects should know nothing of persistence. Even if you're using the Active Record pattern, it's still someone else's responsibility to actually call the save() method. Other than that, good post and it's sad that it even needs saying... Like you I've seen some monstrous abuses of inheritance :(

On Oct 27, 2007 at 7:00 PM John C. Bland II (http://www.johncblandii.com) said:
Haha...I can see you sitting there fuming over someone's code as you write this. :-)

Good points though.
Too old to comment!