Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Re: What is this can() and why is breaking it (un)acceptable?

by dragonchild (Archbishop)
on Apr 06, 2004 at 14:56 UTC ( #342948=note: print w/replies, xml ) Need Help??

in reply to What is this can() and why is breaking it (un)acceptable?
in thread Why breaking can() is acceptable

I'm assuming that Net::Server::POP3 inherits from some basic Net::Server module that provides basic server functionality. Even if it doesn't, let's say that it does.

Now, let's say that there is some other server base module, called Net2::Server. It provides a very similar (but not identical) interface, but radically different innards. It's useful for different types of servers.

Now, let's say that I am using five servers, each an object of a class that either inherits from Net::Server or Net2::Server. I don't know which inherits from which. But, I do know that there is one interface difference I need to be aware of - foo() vs. bar(). So, I can do the following:

my $method = $server->can('foo') || $server->can('bar'); $server->$method( @args );

And I guarantee that my code will work, regardless of which baseclass the server inherits from.

We are the carpenters and bricklayers of the Information Age.

Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Replies are listed 'Best First'.
Re: Re: What is this can() and why is breaking it (un)acceptable?
by tilly (Archbishop) on Apr 06, 2004 at 19:19 UTC
    And you've just illustrated where I think that can() can be problematical.

    Despite your claimed guarantee, you didn't guarantee that Net2::Server (or some subclass thereof) won't someday implement a method named foo() that does something radically different from bar(). And then your code will break.

    The problem is that it is as much an abuse of an API to assume that a particular method will never be implemented as it is to use an internal one which may change. Also related is that it is a mistake to assume that what you'd think that foo() should mean will be what someone else will think. This is true even for such obvious values of foo() as a constant named PI. Is that a number or a Unicode character? This related mistake is a meta-problem with can().

    Instead the right way for you to do that is to have some compatibility layer which guarantees that the interface that you want will be supported. That layer could be something as simple as a hash that says that method X is provided by package Y under name Z. Or you can actually implement a class which proxies the methods that you are interested in (incidentally giving you somewhere to put utility methods that one base class has and the other doesn't).

    Now you don't have to worry about the API of Net2::Server changing on you, and you don't need to call can().

      So, to summarize what it is I think you're getting at:

      can() doesn't really serve any useful purpose.

      1. It doesn't really provide usefulness as an interface validator (because interfaces change and because of AUTOLOAD)
      2. Its secondary function of providing a coderef doesn't help, because of AUTOLOAD and because of the questionable use of this

      So, why does it exist?

      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

        What I want to get at depends on your programming style. Let me first give some perspective.

        If you are good about having really clear function names, then in practice nobody is actually going to name a function something that will conflict with the name that you look for. In that case, if can() finds the method, it is a reasonable assumption that the method will, in fact, do what you expect it to. Furthermore if you are good about not using AUTOLOAD, or else using AUTOLOAD and overriding can() and being aware of where your override works, then it is reasonable to assume that can() does what it should do.

        In that case there are lots of interesting design patterns that use can() for reflection. Which is why enough people consider it useful that it got put in the core.

        If, however, either of the assumptions is wrong, then its utility drops rapidly. It is fine in cases where you check that it works, but it will be a fragile layer. (Depending on your perspective you can blame the fragility on can() itself, or on the practices that made can() fragile. It doesn't really matter - the fragility is there.)

        Furthermore there are other styles of programming in which you are very unlikely to want to reach for can() at all. Therefore an erosion of can() is going to not matter to you.

        If you're in the first camp, people who want to reach for can() whose own personal style is going to make it work out for you, then people who casually break can() are going to frustrate you. I would like you to understand the perspective of people who are going to break can(), and be aware of why it is unrealistic to expect them to generally improve and start working like you want them to work.

        If you're in the second camp, people who are likely to accidentally break can(), I want you to understand what the issue is, why it becomes an issue, and have enough perspective to more deliberately make the decision about whether or not YOU will choose to support can() in any particular scenario.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://342948]
[LanX]: never liked it, but a friend of my mother was a big "fan" of Mr T xD
[LanX]: (talking about minority chicks)
[LanX]: Hollywood is built on stereotypes which sell, this includes stereotypes about English, French, russians and ... Americans
[Your Mother]: I think to some degree, maybe a large one, the stereotypes are purely products OF Hollywood and not what would sell best.
[LanX]: well those products which sold best are replicated
[Your Mother]: They get almost everything wrong on every level. I think they create and restrict the market and fundamentally misunderstand audiences.
[Your Mother]: Consider how long, for example, superhero movies were kept at bay because they weren't commercially viable. They always were, just Hollywood couldn't see it or understand how to make one because there is no management talent in the town.
[LanX]: Erich von Strohheim built his career on beeing the most hated guy (The man you love to hate)
[Your Mother]: You see these amazing set, costumes, performances, etc, etc, etc all ruined by production and script decisions from the top down.
[LanX]: well ... the traget audiance is 15-25

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (13)
As of 2018-03-19 14:56 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (240 votes). Check out past polls.