in reply to Re^4: Assignable Subroutines
in thread Assignable Subroutines

This was a getter/setter example, good OO does not use such methods, as it is truly "object oriented". These sort of things are, IMHO, a design smell. An object DOES something, you don't manipulate it's properties directly (and that's what getters/setters do, just in a PC way). Can you give another non getter/setter example?

Replies are listed 'Best First'.
Re^6: Assignable Subroutines
by demerphq (Chancellor) on Jan 25, 2005 at 17:31 UTC

    This was a getter/setter example, good OO does not use such methods, as it is truly "object oriented".

    I must not understand your point. Almost every object ive ever used has properties. In fact this comment is so crazy to me I cant even think of what to say in response.

    An object DOES something, you don't manipulate it's properties directly (and that's what getters/setters do, just in a PC way).

    Well i dont know where you get this from, it doesnt match up with my experience at all (to say the least). An object is just an encapsulation of data and the methods that manipulate that data. Its like a record that is smart enough to know what subroutines can manipulate it. Property accessors just provide a convenient syntactic sugar for how to pass data into the object and a place to validate it when you have.

    Lets bring this back to one of the original uses of OO: representing graphical elements in a GUI. Now say we have a cursor object, how do we change its color without using a property accessor? IME it would normally be done by something like:

    $cursor->color(BLUE);

    And no, im not going to give you a non getter/setter example, as that is what this thread is all about.

    ---
    demerphq

      No, the AnonMonk is quite correct. Sure, all objects have properties. They are necessary for the object to keep track of its own state. The problem comes when you expose those properties to the outside world through trvial accessors/mutators.

      The most OO-pure way to do things would have all its methods have void return values. It only takes parameters and modifies its own state accordingly. (The most successful example of this is Unix shell pipelines).

      The next best is to return complex objects in response to some methods (and void for the rest). This is essentially how I implemented Gopher::Server. On each request, the Gopher::Server::ParseRequest->parse() method generates a Net::Gopher::Request object, which is fed into a Gopher::Server::RequestHandler object. The process() method generates a Gopher::Server::Response object, which has a print_to() method for sending back the response to the client.

      Note that there isn't a single trvial accessor/mutator involved in this process. One object is simply fed into the next until a response is built. Not even the Response object returns a primitive type--it prints its data back to the socket directly.

      One advantage of this architecture is that different RequestHandlers can be easily swapped out. The current one uses a simple filesystem layout, but I imagine handlers that get all information from a database, or from menu files (as is done in some other Gopher server implementations). This will become really important to fully take advantage of Gopher+.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

        I think demerphq isn't speaking so much about publicly-exposed mutators as accessing properties from within the class itself.

        A good example of this would be a method in a base class. It needs to increment the value of the foo property. Should it

        • $self->{foo}++;?

          No good - some child class may have restricted the foo property and you just went past the maximum value.

        • $self->foo( $self->foo + 1 );?

          Now we're respecting the children. But ...

        wouldn't it be nice to say $self->foo++;. You get the conciseness of the first option with the child-safety of the second. And, you don't even have to know how you're represented in memory. It. Just. Works.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Your app may not have needed publicly accessible mutators but what happens in another app when I want to set the Salary property of an Employee object? What is the alternative to a publicly accessible mutator?