in reply to Re: (Re:) $class = ref $class || $class
in thread Constructor/Factory Orthodoxy

In your argument there is a lot of assumed knowledge about the code. I hope you have great recall or don't need to maintain your code in a distant future.

In the below code $response->finish is not working correctly. It seems someone forgot to add code to register some action with the legacy system to the called finish method. Some client has expanded his use of the info generated and this is suddenly a noticed misfeature. As the newly hired Perl expert your assigned task is to fix the problem.

# Mark the calling request object as answered, use the # ID param to create and return an response packet object. # Let the old system know this is done. sub _respond { my ($self, $request, $id, $response ) = @_; my $response = $request->new; ### Hey!! $request->count( $request->count + 1 ); if ( $response->approved) { $response->requestor( $id); $response->finish( SUCCESS ); $request->answered( $id) Request_handler->reap( $request->id()); return $response; } $response->finish( FAIL); return; }
There are 27 variations of the type Packet floating around the system. _respond is called from 19 different places all but 2 of which get $request or its forerunner passed in.

My point: Do your posited circumstances exist here?

The author who wrote the code knew. He knew that $_[1] would always be a Packet_Foreign here. He didn't care about truth or clarity so the find part of a find and fix problem now requires much more effort.

I am not a great typist so I like to avoid unnecessary typing but sacrificing information for the sake of fewer keystrokes is foolish.

Replies are listed 'Best First'.
Re: (Re:)+ $class = ref $class || $class
by herveus (Prior) on Mar 03, 2003 at 12:39 UTC
    Howdy!

    I can't tell if my posited circumstance is in place.

    Whether I say $request->new or ref($request)->new has no effect on the assumption that the ref($request) is of the appropriate class (either directly or by inheritance). If it is important to verify the particular package that a ref is blessed into to ensure that the ->new part goes to the right place, then you need to check that explicitly. I don't see where that bears on the particular dispute at hand.

    The sample code presented would lead me to the presumption that the range of values ref($request) could take would all have the expected methods available to it. The code would die if that assumption were invalid. If I were faced with that range of classes for $request, I would have to dredge through the various packages to discern what variations in behavior were occurring to figure out just where to patch finish().

    I did note that I assumed that the packages were documented to permit users to know what methods were provided where. I'm still not seeing the objection.

    yours,
    Michael

      If I were faced with that range of classes for $request, I would have to dredge through the various packages to discern what variations in behavior were occurring to figure out just where to patch finish().

      Exactly! But you would not have to dredge if the author had written Packet_Foreign->new. This is the root of the objection.

      (ref $obj)->new
      The code tells that you need to determine the type of $obj to figure out how the call to new is resolved.

      Obj->new
      The code tells you where to start to resolve the call to new. This can be of great benefit to the reader in some situations.

      $obj->new
      The code obscures the author's intent. Could he have written Obj->new but didn't just because of mindless imitation? Could he have written (ref $obj)->new but didn't just because of mindless imitation?

      I give you rir's observation: When the code is bad, the documentation is worse. So I find your statements to rely on the documentation unconvincing. If truth and beauty don't exist in the code, I won't count on finding them in the documentation.

      I am sorry that I unable to make my point to you. Last fall when I first read merlin's criticism of this idiom as Cargo Cultism, I was resistent. My first thoughts: it is no big deal; it's just a little convenience; it is in the Camel; it has never bothered me; and merlyn is being exceedingly fussy.

      But since I really had adopted the usage without critical thought. And since I had, still have, no good argument against high standards, especially where it resolves to an idiom, i.e. think once -- type many. I did consider and quickly found fault with the idiom. My reason to deprecate the idiom is different from merlyn's and, I think, a much stronger one.

      I won't write $class = ref $class || $class because it supports the thoughtless use of $obj->new which can be obscure.

      There are other views: tilly's posts A Cat's eye view of OO and Re (tilly) 2: Paradigm Shift - Dual Use Constructors and their associated threads. Also Re: (Ovid - minor code nits) Re: Adding autoloaded methods to symbol table with using strict refs.

      Update: True confession time: When first I adopted the dual method trick its cuteness appealed to me. So I used it unnecessarily.
      Fixed minor typos.

        Howdy!

        ...but writing Packet_Foreign->new means that I have a priori knowledge that I always need a Packet_Foreign thingy. That is not the situation in the scenario at hand.

        In the scenario under consideration, one is handed an object and needs another of the same class. Either one takes ref($obj) before calling new or one does it *in* new. The scenario does not admit a choice. One *could* pass the value to new as an argument, but that is just another variation (that may be productive) that I'm going to gloss over for now.

        The code obscures the author's intent. Could he have written Obj->new but didn't just because of mindless imitation? Could he have written (ref $obj)->new but didn't just because of mindless imitation?

        I give you rir's observation: When the code is bad, the documentation is worse. So I find your statements to rely on the documentation unconvincing. If truth and beauty don't exist in the code, I won't count on finding them in the documentation.

        It is not reasonable to attribute use of the offending idiom to "mindless imitation". That steers the discourse toward a discussion of the discussor and away from the subject. The followup observation continues that unpleasant course.

        I do not blindly accept that the idiom is, per se, a Bad Thing(tm). I do accept that it has the potential to create confusion. I do claim that proper documentation and the use of it by the programmer should mitigate that confusion. It is not that you are "unable to make your point to [me]"; it is that I do not blindly accept it as the One Truth.

        More generally, what do you expect to happen if you call a class method as an object method? As developer of the module? As user of the module?

        I see this whole issue as having a number of shades of gray, not just black and white.

        yours,
        Michael