Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^4: Law of Demeter and Class::DBI

by jplindstrom (Monsignor)
on Nov 19, 2004 at 22:09 UTC ( [id://409171]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Law of Demeter and Class::DBI
in thread Law of Demeter and Class::DBI

I agree that accessing the underlying hash is a bad idea, but that's not the point. Among other things, OO is about putting the logic near the data.

Let's say we want to indicate that a logger object should flush itself to disk when it's appropriate (it may take some time, so we can't do it right away). An example of not so good OO design:

#in a time sensitive loop $logger->isFlushPending(1); #later on if($logger->isFlushPending) { $logger->flush(); $logger->isFlushPending(0); }

It's bad OO design to use getters to read the state of an object and then use that information to make decisions about how to use the object. The logic controlling the object is now located outside of the object rather than inside it.

So you avoid the getters (asking the object what state it has) and instead tell the object what you want it to do and it can sort out how to do that itself.

#in a time sensitive loop $logger->setFlushPending(); #later on $logger->flushPending();

and the logic controlling whether to flush the log data to disk is now implemented in the flushPending() method. Inside the object, not outside.

See also: TellDontAsk

/J

Replies are listed 'Best First'.
Re^5: Law of Demeter and Class::DBI
by fergal (Chaplain) on Nov 20, 2004 at 00:51 UTC

    I largely agree* with the principle of Tell Don't Ask. It's basically saying that where possible you should not expose the field. This is fair enough but some objects require exposed fields. For example an Employee has a Salary field which you should be able to set and get. There's no way around that. The fact that it is a get/settable field is a fundamental part of the interface for an Employee.

    What I'm saying is that in the situation where you must expose a field then it should be exposed in a way that allows you to control and customise the sets and gets and in Perl and most other languages that means having getters and setters.

    The original post that I replied to said

    Good OO code does not NEED getters and setters

    The only way you can write OO code without getters and setters is to either have no fields or to have fields but access them directly. The first is impossible (applying Tell Don't Ask might give you less fields but can't eliminate them all) and the second is a bad idea as you said yourself.

    * I think the idea of putting the logic beside the data is ok up to a point but I'm really starting to wish for good multimethods in Perl. In the example you gave, it's possible that your log flushing method would be useful for many types of object (basically any object that implemented isFlushPending and flush). So attaching it to a particular class means that all these objects which would find it useful will have to inherit from this class. This brings in the perils of multiple inheritance (perilous in most languages anyway).

      Good point with the Salary field. That could be considered a part of the public interface of the Empoyee class. And querying the Salary or Name of an Employee in order to display them or something, that would be okay. But as soon as you start comparing the Salary with something else that was taken out from inside the object, you're losing cohesion.

      After I read about this the first time, I thought I'd try to follow the sentiment of the principle, and that has resulted in better designed OO code, without me doing much designing. It just falls out of the principle.

      The wiki page really states the principle so much more succinct than what I wrote above: "It is okay to use accessors to get the state of an object, as long as you don't use the result to make decisions outside the object."

      Something I've noticed is that sometimgs it's vague where a piece of logic belongs: which class should implement the method, taking a property from another object as a parameter.

      For example: "is the Employee's Salary above average in her Department?" Should that go in the Employee class, or the Department class? It depends on the rest of the design.

      /J

Re^5: Law of Demeter and Class::DBI
by diotalevi (Canon) on Nov 19, 2004 at 22:22 UTC
    I've wondered about this - when a behaviour you want hasn't been given to the object yet do you give that object the method that implements the behaviour or wrap it somehow? If you wrap it, how do you avoid having a zillion custom namespaces and having to have mental models of all those layers? I've recently taken to just directly giving these methods directly to the object but I wonder how you'd handle this.

      Have a look at, for example, nice it's a dialect of java with multimethods. This effectively allows you to add new methods to old classes form the outside (even ones you didn't write). Making more methods available works a lot better when you have multiple dispatch as that helps to avoid some (but not all) of the name clash issues.

      I think the reason this is not much more common is because it's just not possible to do in the "main" OO languages. For example, in (standard) Java, C++, Object Pascal a new method would have to be added to the virtual method table (vtable) for the class but this is a fixed structure created at compile time and you can't change it at runtime so you're stuck with whatever methods the original author thought of. It's purely an implementation issue.

      I think it's ironic that these "real" OO languages can't do this because their dispatch mechanism is tightly coupled to the representation they chose for vtables long ago. It's almost as if their designers hadn't heard of OO!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://409171]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-26 00:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found