views:

201

answers:

1

I have been thinking about the Feature Envy smell lately. Suppose I have an object called DomainObject, that responds to a message "exportTo:someExport". This is basically the DomainObject's way to provide a copy of its internal state:

exportTo:someExport

    someExport setX:myX.
    someExport setY:myY.
    someExport setZ:myZ.

That way, in the data access layer, I could say something like this:

saveNew:someDomainObject

    |domainObjectExport|
    domainObjectExport := DomainObjectSQLWriter new.
    someDomainObject exportTo:domainObjectExport.
    db exec:(domainObjectExport generateInsertStatement).

This is an example of Feature Envy. In order to refactor, I should extract this code into a single message to someExport:

exportTo:someExport

    someExport setX:myX setY:myY setZ:myZ

However, now the setX:setY:setZ: message suffers from Long Parameter List (imagine 10 parameters instead of 3). Is there a way to have it both ways, or is Feature Envy only a bad smell if data is flowing out of the object you are envious of?

+2  A: 

The Feature Envy smell here arises from the fact that your object is exporting its guts to some other object, which isn't the most object-oriented thing to do in the first place. You also have structural duplication between the DomainObject and the DomainObjectSQLWriter. The direct resolution of the Feature Envy here is to move the generateInsertStatement method into DomainObject itself and eliminate the DomainObjectSQLWriter.

That said, such horrific disemboweling of an object is often a necessary evil for persistence, especially if multiple dissimilar persistence mechanisms are in play. If the separation must remain, the worst of the odor could be cleaned up by using ; instead of . to separate your setter messages:

exportTo:someExport
    someExport
        setX: myX;
        setY: myY;
        setZ: myZ.
Jeffrey Hantin
I think the exportation technique is better than accessors everywhere. The guts have to get out at some point by some method.You're right about the structural duplication; I wrote about it here: http://tinyurl.com/bb7hwu. You're also right about the least-sucky solution: http://tinyurl.com/dhves5
moffdub