Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Re^4: Moose: I want builder method to run every time I call an attribute (ugh)

by boftx (Deacon)
on Sep 27, 2013 at 04:47 UTC ( #1055928=note: print w/replies, xml ) Need Help??

in reply to Re^3: Moose: I want builder method to run every time I call an attribute (ugh)
in thread Moose: I want builder method to run every time I call an attribute

tye, in all seriousness, would you expand on that (rather broad) statement? I realize this could touch off a "tastes better/less filling" discussion with regard as to what proper OO design is, but I would like to know the basis for your statement. especially since chromatic has a much better claim to knowing what he is talking about than I do in this community. :)

On time, cheap, compliant with final specs. Pick two.
  • Comment on Re^4: Moose: I want builder method to run every time I call an attribute (ugh)

Replies are listed 'Best First'.
Re^5: Moose: I want builder method to run every time I call an attribute (rehash)
by tye (Sage) on Sep 27, 2013 at 06:04 UTC

    chromatic's suggestion was the example of good OO design.

    I've talked about this to significant lengths. But I'll let those interested do the searching (it isn't hard) if they want more than the below rehash.

    The original question was an example of how Moose's emphasis on object attributes (with the emphasis on method generation, constructor generation, emphasis away from non-accessor use of attributes from within methods, etc.) just further encourages a problematic focus on class design as "select what attributes you want to store in your objects and which of those you want to have accessors for vs. which you just want transparently exposed via constructor arguments".

    IME, good OO design comes from first deciding on the methods you want your class to provide and only after that deciding on the attributes that you want to use in order to implement those methods and keeping the attributes as internal aspects of the design that are not directly exposed in the interface. But it took years for me to recognize the pattern of class designs eventually going further and further wrong and distilling out that this was an important common element of many of these problematic designs.

    Objects as "bags of attributes" encourages designs that end up leaking/forcing object behavior into the code that uses the objects like this trivial example:

    $obj->log() if $obj->should_log();

    The original question shows a person so focused on "what accessors to what attributes should I design into my class?" that they didn't even recognize when they had a simple use-case for a simple, vanilla method (the very thing that should be the focus of the design). So they had to conceive of that as "an accessor but that invokes a builder".

    Of course, people often deride "blame the tool". It isn't like Moose forces you to design classes badly. But I couldn't resist when I saw somebody who didn't even recognize the need for "just a method".

    The second bad example is using "around" code. Not wanting to misquote, I found a prior summary I wrote that I think sums it up nicely so I'll just repeat it, slightly modified:

    So you end up defining a "data type" for that attribute and/or you declare a 'before' or 'after' wrapper around the method.

    This leads to: "Your logic for a single class will be split apart into tons of tiny pieces where the order and interactions will become almost impossible to see, predict, adjust, and debug. But your code will look pretty. Just don't try to understand it on any sort of deep level (such as when you need to fix something)."

    To which stvn, Moose's creator, noted: "Nothing about Moose forces you into doing something as idiotic as you describe."

    I prefer to not write idiotic code. I prefer to not come close to writing idiotic code. So I won't be using even one "around" method. The idea of an "around method" just doesn't even make sense in my classes. You can see the code. If you need to add code, you add it where it needs to go and the flow is obvious. And if you later realize that the order of things matters and is wrong, then you fix that by moving lines of code up or down within a subroutine.

    - tye        

      This is golden.

      My first thought when I saw the question was, "Has Moose made use forget how to write a method? It generally starts with some variation on, 'sub methodname { my $self = shift; ... }'."

      A famous aphorism of David Wheeler goes: "All problems in computer science can be solved by another level of indirection"; this is often deliberately mis-quoted with "abstraction layer" substituted for "level of indirection". Kevlin Henney's corollary to this is, "...except for the problem of too many layers of indirection."

      Humorous Internet memorandum RFC 1925 insists that:

      • (6) It is easier to move a problem around (for example, by moving the problem to a different part of the overall network architecture) than it is to solve it.
      • (6a) (corollary). It is always possible to add another level of indirection.


      All these layers of abstraction can become a shell game. Eventually someone's got to actually write some code. Spaghetti code can be written without ever using goto. ;)


        Spaghetti code can be written without ever using goto.

        See also OO-tagliatelle :)

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      Thanks everyone. I guess I got a little carried away with Moose's fancy features. ;-) Making it a method makes perfect sense. It seems to me the deciding factor on when to make something an attribute with a builder vs a method is, if the value will remain static throughout the life of the object, and you access it a lot, then attribute is more efficient. Else method.
Re^5: Moose: I want builder method to run every time I call an attribute (tyeoopood)
by Anonymous Monk on Sep 27, 2013 at 07:42 UTC

    I have these bookmarked/tagged with oop and tye and in proximity to each other
    How Large Does Your Project Have To Be to Justify Using Moose?,
    Re^2: Two simple code style advice questions (tye)
    module w/ object-oriented and functional interfaces: best practices?
    Advice please on variable naming style in modules
    Re: Object Oriented Orientation
    encapsulation violation Re: Programming patterns Programming patterns
    Moose class design for game

    And tye in the cb around the same time( 2011-06-18 06:23:39 UTC )

    the Moose will bite you in the end
    The classic steps of bad OO design are done in the following order: 1) Figure out which classes inherit from which other classes, 2) Figure out the attributes of each class, 3) Starting writing methods.
    ugh. data-type-based validation. If you want C++, you know where to find it. That's another thing Moose promotes that I find problematic.
    So, Moose pretty much forces you to only use attributes via accessors (that it generates). This forces your attributes into public view and leads to classes with lots of accessors. Bad design.
    Never inheritance! Though, you'll want simple delegation sometimes and there isn't a great solution for that yet (I'm working on it)
    It leads to fragile and overly complex design for a ton of reasons.
    The argument 'for' is that it can then be easy to muck with things in several rather unstructured ways. Rather like the argument for 'goto'. You don't have to bother to make the design structure clear. Just slap things however.
    No, I think OO is great. Inheritance sucks big time.
    Roles improve inheritance in some fairly superficial ways but don't fix the bad design aspects much if at all.
    And my disagreement with Moose's take on OO is not anything about 'anal'. It puts way too much stress on accessors, encourages validation only via data types. It adds the worst aspects of C++ and doesn't implement many good, required parts
    I don't mind having a good structure for doing OO. Moose got a lot of things right about that. But the negative still outweighs the good, IMO.
    Every so often I have to go find some good old hackers and ask them if inheritance is good so they can laugh at me and remind me how stupid the old-timers realize it is. This knowledge is not only not shared by enough people, but ...

    I also bookmarked meaning to ask something about coupling controllers, but I don't remember

    I also remember that tye is writing a oop/ood book(let?) , can't wait for 50 shades of tyed oops

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1055928]
and a kettle whistles...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2018-05-27 04:23 GMT
Find Nodes?
    Voting Booth?