in reply to Re^3: Any gotchas with CGI and Mouse running together?
in thread Any gotchas with CGI and Mouse running together?

Thanks for the follow-up and no problem with rephrasing the question.

Up until you posted this, I hadn't seen any discussion regarding Moo being anti-modular.

I don't know if the concern here is that Moo readily implements a poor modular design, or that Moo generates poor code from a good design.

I've designed my interfaces and started to code the framework in Moo. I see no lack of modularity at all at this stage. I'd be interested in any heads-up regarding problems that (perhaps you think) will present themselves later on.

-- Ken

  • Comment on Re^4: Any gotchas with CGI and Mouse running together?

Replies are listed 'Best First'.
Re^5: Any gotchas with CGI and Mouse running together?
by Arunbear (Prior) on Mar 06, 2015 at 10:50 UTC
    There has been previous discussion of Moose being anti-modular (the Anonymous monk has given links to some of those), and those arguments apply to Moo as well, even more so.

    The concern here is that using Moo leads to code which is un-modular. A simple example showing how easy it is to go off the modular path is in this subthread, which was looking at how to implement a bounded queue.

    Logically, the operations such a queue should support are "new" (construction), "push" (adding an item) and "pop" (removing an item). In a hand crafted solution this is exactly what you get. But in a Moo solution you also get an operation called "items" that returns the underlying array ref. This defeats encapsulation, so is un-modular (it would be like putting a button on an ATM that allowed regular users to dump out all the cash). An example showing this version of the queue is not bounded after all.

    An interface with, say 20 methods is harder to change/support than one with 5 methods, yet with Moo you typically end up with fat leaky interfaces, because all the attributes are part of the interface. With Moose you can avoid this by declaring an attribute as "bare", but Moo doesn't support this so the nearest approximation is to use a convention like $obj->_get_foo() (but neither of these practices seem common judging by what we see on CPAN).

    The point of modularity is to make change easier by hiding implementation details behind an interface. Yet with Moo(se), by default those implementation details are exposed via accessors and the constructor (init_arg's). So to get modularity you have to avoid the defaults, which is tedious and hence very few people seem to do so.

      ++ Many thanks for this information (and my apologies for the late response - I've been caught up with other things over the last week).

      You've made valid points regarding "fat leaky interfaces". I'll keep this in mind as I am coding.

      -- Ken

      So to get more modular, perhaps "namespace::onlykeep" or Moo::OnlyNew?

      { package Foo; use Moo; has(('it', 'is', 'ro')); has(('bit', 'is', 'rw')); sub fit { warn $_[0]->bit, $_[0]->it; } use namespace::onlykeep qw/ fit new /; 1; } use Data::Dump qw/ dd /; my $f = 'Foo'->new('it', 'was', 'bit', 'ten'); dd($f); $f->fit; ## should warn dd($f->it, $f->bit); ## should die

      Someone think of something please :)