in reply to Re^5: Re-blessing || Re-constructing objects
in thread Re-blessing || Re-constructing objects

Have the user object contain an authorization object. Then, when the userobj wants to know if it's allowed to do certain things, it asks the authobj. The authobj replies with a boolean yes-or-no.

But then you have an ugly set of

sub method1 { ... if ($self->authenticated) { ... } else { ... } ... } sub method2 { ... if ($self->authenticated) { ... } else { ... } ... } sub method3 { ... if ($self->authenticated) { ... } else { ... } ... }
instead of a nice set of
package User::Anonymous; sub method1 { ... } sub method2 { ... } sub method3 { ... } package User::Authenticated; sub method1 { ... } sub method2 { ... } sub method3 { ... }

I think checking inside the methods is (security) error prone, and a lot more work, resulting in uglier code that is harder to maintain. Besides that, it's less efficient because of the extra check (which if you abstract properly, is a method call). I prefer doing something that isn't entirely pure in the sense of "how OO was officially meant" (if such a thing even exists) to something that is pure, but causes me and the future maintenance guy extra work. And OO purity is a performance killer in many ways, which is a problem if you happen to work for one of those shops that still care about that.

So you can't easily subclass anymore. Fine with me, because you can still wrap. If I properly designed my User, I'd let you add arbitrary states like Anonymous and Authenticated, and you could change things through that interface. Personally, I don't think inheritance is holy enough to have as a primary design objective. Composition is more useful IMO, and reblessing to change state (combined with inheriting (or mixing in) from a state independent class) is a primitive way of doing that.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Replies are listed 'Best First'.
Re^7: Re-blessing || Re-constructing objects
by dragonchild (Archbishop) on Apr 18, 2006 at 12:03 UTC
    Yes. However, I tend to put my authentication code in my cgiapp_prerun and, very rarely, refer to it in other places. This reduces work quite dramatically.

    I am advocating a composition solution in favor of an inheritance solution. Are we just in violent agreement here?

    As for not subclassing as easily, it's the reblessing solution that's harder to subclass. Not only am I restricted to a given implemention, but I have to support every single key used by every version of those other implementations. What a nightmare!


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      Yes. However, I tend to put my authentication code in my cgiapp_prerun and, very rarely, refer to it in other places. This reduces work quite dramatically.

      In the case of only authentication, that's a perfect solution. However, sometimes the authentication leads to authorization, and you have a system of user rights scattered all over the place. Instead of having many conditionals, I typically prefer to put all functionality in methods, and indicate rights by (re)blessing into the right package.

      it's the reblessing solution that's harder to subclass.

      That is what I referred to.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        Well, if your runmode dispatches based on a certain level of authorization, then it should be asking the user "Do you have this authorization?". This is self-documenting and resilient in the face of change. I don't see how reblessing is a better solution.

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?