>This speaks to object cohesion.  Why should your object have 
>to care how it will be used?  
>In fact, why should the object have any idea about the
>outside world at all?
>
  Firstly, as i understand it, cohesion is a measure of how well the
methods in an object stick together, how closely related they are to
what the object is and does - i don't understand how an object with
get/set methods is inherently "more cohesive" than an object without
such methods. What i will argue, below, is that an object _with_ such
methods will tend to become more tightly coupled with other objects over
time.
  Secondly, an object shouldn't have any idea about the outside world,
but an object _does_ care about how it is used: this is why objects have
both public and private methods, this is where the whole concept of an
object's interface comes from, this is one of the fundamental tenets of
object orientation: an object interface embodies a contract that says
"if you use me in these very specific ways (list of methods and
arguments) i will work for you."

>In general, I'd argue that the opposite is true - that most of 
>the time this approach will _add_ methods.  It's a user object.  
>It shouldn't care that it will be used to generate XML.  It 
>shouldn't even care that it will ever be persisted in any way.  
>By this argument, I should try to predict everything that anyone 
>will ever want to do with my object and provide a convenience
>method for it.  If you're going to go this route, why stop with
>getXmlRepresentation?  Why not add a getIniFileRepresentation,
>getJsonRepresentation, getBinaryRepresentation,
>getXmlRepresentationInSpanish, etc?  That's an awfully slippery slope.
>
  So you extract that behavior to a separate set of objects - much the
same way as you use a DAO to persist your object - and you bring in some
kind of dependency injection to manage the relationship between your
business objects and their associated "helper" or implementation objects
- you have one method, and you either get an object of the correct type,
or the object delegates to an object of the correct type - this is what
i meant by using the facade pattern in my last mail. As for having to
"...predict everything that anyone will ever want to do with my
object..." - you don't, you just need to decide what you will allow
anyone to do with your object and then provide a public method to do
that. It's called "design", and it's why we get paid the big bucks.
Blindly providing getter and setter methods for every field is a
cop-out: basically allowing you to treat an object as little more than a
crypto-record:

<tr>
        <td>#Product.getName()#</td>
        <td><cfif Product.isPromo()>Special!
</cfif>#Dollarformat(Product.getPrice())#</td>
</tr>

i'm sorry, but that the exact same code you would have written with a
query - the fact that you sprinkle on a few parenthesis and use
sexyCamelCasing to name your "columns" doesn't magically make it OO.


>We can go around in circles about this all day, but the fact 
>is that the "ActOnThyself" pattern described in that article 
>is a far more niche pattern than the article would lead users 
>principles that it violates, as well as the fact that there 
>to believe.  The number of other are many other, and in my 
>dealing with the same issues limit this specific approach to 
>estimation *clearer/broader/more common/better * patterns 
>for solving a very tiny set of problems really makes it 
>trivial in all but the most specific situations.

  The article is *not* about some kind of "ActOnThyself" pattern  - it's
about the "tell, don't ask" pattern of object usage, and using that
pattern to decrease coupling. When you implement getters and setters for
your private instance fields, you are exposing the values stored in
these fields to use and manipulation OUTSIDE the objects in which they
live. Imagine you have an address object made up of a number of fields -
street, state, country, etc. If you go down the getter/setter road, you
are basically inviting code outside your address object to know too much
about what constitutes an address - and this "expertise" constitutes
tight coupling. Whether there is a private string field called "street"
or whether the string return value of getStreet() is computed at runtime
is irrelevant - why do i need to know that an address is composed of a
street in the first place? I have no idea whatsoever how an internal
combustion engine works or what parts it is composed of: i just know
that you push _this_ pedal to make it go and _this_ pedal to make it
stop. Back to our address, let's now imagine you want to add a new field
- zip code - think of all the places you'd have to modify to make that
work. Worse than that, think of trying to find all those places! If you
used a "tell, don't ask" strategy, then all the change would be either
confined to the object itself, or to known dependencies of the object
(its DAO, renderer, etc) hopefully defined in some sort of dependency
injection system. Better yet, since you are using delegation, *no other
code* has to change, because address.render() and address.save() can be
changed in a way that is transparent to the calling code. If you add a
field to address and wind up having to change the order display view,
that should set off some warning bells in your mind.

/t


----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email to 
cfcdev@cfczone.org with the words 'unsubscribe cfcdev' as the subject of the 
email.

CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting 
(www.cfxhosting.com).

An archive of the CFCDev list is available at 
www.mail-archive.com/cfcdev@cfczone.org


Reply via email to