Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

OO, Class::MethodMaker, and get_set

by sigma (Initiate)
on Apr 01, 2003 at 16:14 UTC ( [id://247274]=perlquestion: print w/replies, xml ) Need Help??

sigma has asked for the wisdom of the Perl Monks concerning the following question:

I've been starting in with Class::MethodMaker and have some questions about get_set for an object.

Let's say I have an class that takes a few inputs, can be instructed to perform various computations, and produces various outputs. To be concrete, say the class is "sum", which takes two arguments, "a" and "b", and sums them to produce "c". (The real object has more inputs, does a much more complicated and expensive computation, and caches its result, but this toy example is good enough to illustrate my question.)

Using Class::MethodMaker, I declare a new_hash_init for the constructor, and "a", "b", "c" as get_set attributes. After creating an instance (specifying "a" and "b"), I then tell the object to compute, which populates "c".

This approach feels wrong to me.... "c" should be read-only; the object should recalculate "c" whenever "a" or "b" is changed (so the internal state is consistent), etc.

If I were building the object by hand, I'd write set and get to ensure the object stays consistent. But MethodMaker offers only set_get as an accessor/mutator pair... To get the behavior I want, I'd need to override the methodmaker canned procedures, so much so it doesn't seem to make sense to use it.

  • Should I be using a different design?
  • Should I not be using Class::MethodMaker?
  • What is the best design for a situation like this? Don't most objects need to adjust their internal state when a set is used to change one of their attributes?
Thanks for any advice ---
sigma

Replies are listed 'Best First'.
Re: OO, Class::MethodMaker, and get_set
by BrowserUk (Patriarch) on Apr 01, 2003 at 18:09 UTC

    If C isn't settable, and is derived from A and B, it isn't an attribute, it's a result or returned value.

    If the parameters are many, and the calculation is expensive, then re-calculating the results each time an attribute is set, rather than waiting until the result is requested will mean that many expensive calculations will be done, only to be discarded if more than one attribute can change between results being needed.

    Better to allow Class::MethodMaker to define your setter and getters on the attributes and only perform the calculation when the result is requested via your hand-coded method for this purpose.

    If you need to cache the results for efficiency, retain an internal copy of the attributes used along with the calculated result and only recalculate if they have changed.


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: OO, Class::MethodMaker, and get_set
by dragonchild (Archbishop) on Apr 01, 2003 at 16:18 UTC
    I have never (and probably will never) use a canned OO representation. I haven't found the need, plus I have my own hand-rolled way of doing things that meets my needs without giving me a bunch of jive I don't want. *shrugs*

    If you feel that Class::MethodMaker isn't going to do what you need it to do, don't use it.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

semi-OT: Lisp code
by hding (Chaplain) on Apr 01, 2003 at 18:06 UTC

    I'd do it something like this in Lisp (not very tested):

    (defclass sum () ((a :accessor a :initarg :a :initform 0) (b :accessor b :initarg :b :initform 0) (c :reader c))) (defmethod compute ((self sum)) (setf (slot-value self 'c) (+ (a self) (b self)))) (defmethod initialize-instance :after ((self sum) &key &allow-other-ke +ys) (compute self)) (defmethod (setf a) :after (val (self sum)) (declare (ignore val)) (compute self)) (defmethod (setf b) :after (val (self sum)) (declare (ignore val)) (compute self))

    Content of marginal relevance to Perl: Maybe there's something out there that implements something akin to Lisp's :after methods in Perl that would do what you want. I don't know, though.

      Maybe there's something out there that implements something akin to Lisp's :after methods in Perl that would do what you want.
      Well, there is Hook::LexWrap. But if what I read elsewhere in this thread is true (that we assume the computation of 'C' is expensive and we'd like to cache it), then you'd just want to clear the 'C' cache when you change 'A' or 'B', and when you request 'C', just return the cached value if it exists, else compute, cache, and return it.

        This is true. I was just trying to implement something as close as possible to what the original poster asked for with respect to his toy problem, which was recomputation of c whenever a or b was set. Of course it's be easy to modify things to use a cache; e.g. set c to nil (or some other convenient marker) whenever a or b is set and put a :before method on the method c that computes and sets the slot c it if it is nil.

Re: OO, Class::MethodMaker, and get_set
by perrin (Chancellor) on Apr 01, 2003 at 17:48 UTC
    Why don't you just write method C by hand and make it do the computation and handle the caching? It seems to me that the actual computation and caching should all be hidden behind this public API.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-07-13 11:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.