Trying to figure out the source of a method in one of our Catalyst controllers. Our controller inherited from one of our controller base classes. That, in turn, inherited from the deprecated Catalyst::Base which, in turn, does nothing but inherit from Catalyst::Controller, which inherits from three different classes. Two of those inherit from two classes each, which in turn ...
Let's see if I can figure this out our inheritance heirarchy so I can tell where that method is coming from:
Our::Controller Our::ControllerBase Catalyst::Base (deprecated passthrough) Catalyst::Controller Catalyst::Component Class::Accessor::Fast Class::Accessor Class::Data::Inheritable Catalyst::AttrContainer Class::Accessor::Fast Class::Accessor Class::Data::Inheritable Class::Accessor::Fast Class::Accessor Catalyst::Controller::REST Catalyst::Controller Catalyst::Component Class::Accessor::Fast Class::Accessor Class::Data::Inheritable Catalyst::AttrContainer Class::Accessor::Fast Class::Accessor Class::Data::Inheritable Class::Accessor::Fast Class::Accessor
Got that?
On the off chance that you're a Multiple Inheritance fanboy, I don't think I'm going to say anything right now. I'm on the verge of profanity. MI is a tool of last resort (no, I'm not saying it's always the wrong answer). Today there are so many excellent alternatives that you really have no excuse for using MI other than "I don't like change".
? Of course, that doesn't help with finding its super-methods, and if it does funny classless things then you'd need to instantiate an object. (Pause for a moment to hate the fact that perl parsesperl -MOur::Controller -MSub::Identify=stash_name -le'print stash_name(Our::Controller->can("method"))'
as a call tostash_name Our::Controller->can(...)
... wretched indirect object syntax.)Our::Controller->stash_name
Re:Err...
Ovid on 2008-03-07T13:21:50
Actually, I use my Sub::Information as it groups the info I need about subs in one spot. That being said, I typically don't reach for it as a first resort. I see a method or sub and I have the code open in my editor and I look for it. I only use tricky code when I'm really stuck because manually looking for code gives me a greater understanding of the overall code base. That's when I saw our lovely diamond inheritance which itself has diamonds further down
:(
Which to be fair is very complex, but at least it's somewhat readable.* Inheritance *
+------------------------------------------------------------------------------- ------------------------------------+
| +------------------------------------------------------------------------------- ---+ |
| | [ Class::Accessor ] | |
| +> [ Class::Accessor::Fast ] <+ | |
+------ [ Catalyst::AttrContainer ] | | |
| | | v
[ Catalyst::Controller ] --> [ Catalyst::Component ] --> [ Class::Data::Inheritable ]
[ Catalyst::Base ] ^
[ MyApp::ControllerBase::Import ] |
[ MyApp::ControllerBase::Import::REST ] |
[<MyApp::Our::Controller >] --> [ Catalyst::Controller::REST ]
Re:NEXT
Ovid on 2008-03-07T18:11:42
Yes, they do, but not all of our code does. However, MI is still a bad and fragile thing. It frequently introduces inappropriate compositions because it's a seductively easy (read: bad lazy) way of sharing behavior.
Re:NEXT
perrin on 2008-03-07T19:54:59
I agree. I was wondering if NEXT would make it better or worse.Re:NEXT
Aristotle on 2008-03-11T09:33:42
The plan, it seems, is to eventually rewrite Catalyst with Moose. (Originally the plan was to use C3 instead of NEXT, but that work was never completely finished.)
Re:NEXT
groditi on 2008-03-19T03:06:04
Yes, that is correct. I am currently working on that project and we are making decent progress, which you may see as a branch of 5.8 on the repo. One of the goals of this project is to eliminate unnecessary instances of MI (C::A::F, C::D::I) in the Catalyst core, and replace most instances of MI with roles. C3 will work fine with Moose (according to people who know better than I do) and so we will be using C3 and a compatibility layer for NEXT to minimize instances of broken legacy code.