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

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.

Replies are listed 'Best First'.
Re^8: Assignable Subroutines
by dragonchild (Archbishop) on Jan 25, 2005 at 21:46 UTC
    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.

      you just went past the maximum value
      You get the conciseness of the first option with the child-safety of the second.
      Child-safety caps give me hand cramps.
Re^8: Assignable Subroutines
by fergal (Chaplain) on Jan 25, 2005 at 22:38 UTC
    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?

      Why isn't your salary in the database? Why aren't you changing it there?

      If your object is simply an access layer above the database (Class::DBI or something along those lines), then the mutator is no longer trivial.

      "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.

        How do you change it there? What is the mechanism by which you are going in and fiddling those bits? Presumably, it's some sort of access layer. Presumably, the access layer is made up of objects. And, presumably, you need a mutator.

        Once you want a mutator, you want the syntactic sugar that goes with assignable subroutines.

        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.

        Maybe it is in the DB but I'm not changing it in the database because the part of my program that wants to mutate the Employee doesn't (and shouldn't) need to know about databases. Also, storing it in a DB does not always mean that the mutator handles updating in the DB. If persistence is handled by a framework outside the object then the mutator remains trivial and storage is handled outside of your classes.

        Basically it comes down to the fact that many objects have chunks of them that behave exactly like a record/struct in that they are nothing more than passive fields that get twiddled by outsiders. These plain old fields should still not be part of your public interface because if they need to be something more than just plain old fields in the future you're shafted (unless you're in a language that makes it possible for an object to intercept direct twiddling of it's fields and do fancy stuff - Python's properties for example).

        If you don't provide mutators, even for trivial fields, then you are just storing up pain for the future.