bakunin has asked for the wisdom of the Perl Monks concerning the following question:

Hello friends!

I'm working on several Perl modules that make life much easier with Ming-Perl. Ming creates SWF, and can do so dynamically via CGI. It's awesome!
Now, I love OO, and not suprisingly I use it extensively with my project. But to tell you the truth the length of this syntax really bugs me when it comes to GUI design: (in which you hand code it many times)

$b = Foo::Button->new(@args);

Why not use ,

$b = newButton(@args);

Also considering the overall module network's design (on inheritance for example), I came up with this:
package Foo::Button; use strict; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw (newButton); ## short hand method that feeds some initial data to ## the constructor new() sub newButton { __PACKAGE__->new( {Up=>shift} ); } ## Class call only sub new { my $class = shift; my $self = {}; bless $self,$class; $self->{shape} = shift; ## fill up some other fields, then return $self; } 1; ## in file test.pl package main; use Foo::Button; my $b = newButton(@args);

Usually I use methods like "newButton" as short hand constructors in which the blessing is left to the perfectly healty new() constructor. (Let's also suppose that the exported class method does the blessing. )
Now, do you think this is a wrong approach? Can it be improved? Any better ways?
Any feedback is appreciated!

Ogla

Replies are listed 'Best First'.
•Re: Foo::Button->new vs. newButton()
by merlyn (Sage) on Jan 16, 2004 at 19:10 UTC
    One of the cool thing about objects is how it keeps the namespaces all clean.

    What if you wanted to use two different classes, both of which wanted to call their constructor newButton? Bad news. By using a method in that namespace, it's easier.

    Also, what if you wanted to subclass that class, and add extra behavior during the object instantiation? With named constructors, it's harder.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: Foo::Button->new vs. newButton()
by stvn (Monsignor) on Jan 16, 2004 at 19:28 UTC

    I not a fan of the idea of exporting procedural-style class constructors from modules, since it kind of hides the OO, and a symbol like "newButton" could be handy to users of your library elsewhere. IMHO exporting symbols can get real messy, real fast.

    There is always the not-so-great indirect object syntax:

    $b = new Foo::Button @args
    but that can sometimes be more trouble than its worth.

    What about the syntax length bothers you? Are your modules nested deeply? (ex: Olga::Ming::Widgets::Button) If so, you could create your own class loader for your framework. I have done this with the object framework I have been working on and it works quite well. Here is the syntax :

    use iI::Framework qw( Web.Request Web.ModPerl.DispatchHandler );
    Then the iI::Framework module's import method simply changes all the "."s to "/"s and requires each module. After that the modules can then be refered to as "Request" and "DispatchHandler" instead of "iI::Web::Request" and "iI::Web::ModPerl::DispatchHandler". Its a little weird (maybe not terribly perl-ish), but it keeps my module name length down and still allows me to organize the almost 100 different classes I have into a neat tidy folder heirarchy.

    -stvn
      No, no the class names are not long at all. But thanks for the input. Well, it hides OO to some point. And I should of course put the symbol exported in EXPORT_OK.

      As for the length, well... this is a static method. And no inheritance is needed beyond Foo::Button along the library. So why write Foo::Button->new and many others (for Text,Menu,FadeMenu,MovieClip,... ) where I can just get away with newFoo()
      It was just a thought. :))
      Thanks.

        Just because you dont inherit it, doesn't mean someone else wont want to.

        -stvn
Re: Foo::Button->new vs. newButton()
by hardburn (Abbot) on Jan 16, 2004 at 19:13 UTC

    Nothing particularly wrong with exporting a constructor to get that syntax, although I'd put it in @EXPORT_OK instead. newButton should pass the entire @_ variable to new.

    Perhaps the biggest problem is that subclasses won't be able to be called with newButton. That being the case, newButton might as well call new as new(__PACKAGE__, @_) to improve performance.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: Foo::Button->new vs. newButton()
by adrianh (Chancellor) on Jan 16, 2004 at 21:48 UTC

    I'm with merlyn and think that the downside of exporting stuff into the namespace outweigh the advantages of saving typing a few characters.

    Any better ways?

    If all the extra typing is really causing you problems you might consider shortening the class name by using a constant:

    use Btn => 'Foo::Button'; ... $b = Btn->new(@args);

    or variable

    my $Btn => 'Foo::Button'; ... %b => $Btn->new(@args);
Re: Foo::Button->new vs. newButton()
by gmpassos (Priest) on Jan 16, 2004 at 23:19 UTC
    I disagree with that idea. The user should know well what type of object it's creating. If you want to make a creator wrapper, to make the code easier, is better to create something like that:

    my $oo = wrapper::package() ; ## that can be something like that: my $oo = new::Button() ; my $oo = new::Label() ; ...
    Soo, you won't polute namespaces, and can make an automation of the package names that new:: will handle, since you don't need to implement any of the methods (Button, Label), you just use AUTOLOAD. Also you can make new:: load automatically the modules, soo you don't need to make use Button, before create it.

    But I still preffer the normal way! ;-P

    Well, I have just released Class::HPLOO for a easier way to declare classes and PerlModules. Maybe this can be useful for you.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

Re: Foo::Button->new vs. newButton()
by CountZero (Bishop) on Jan 16, 2004 at 22:38 UTC
    If you don't like the extra typing, why don't you use the "search and replace" functions of your editor? Just type instead of "Foo::Button" "XX" and then search and replace "XX" by "Foo::Button". Or use a pre-processor or a massive list of "s//" constructs in a script, so you can be even more flexible ("F::B" to "Foo::Button"; "F::M" to "Foo::Menu"; ...). Your creativity is the limit!

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Foo::Button->new vs. newButton()
by mvc (Scribe) on Jan 17, 2004 at 17:11 UTC

    Take a look at how Rui does it. You create a widget through its parent:

    $label = $panel->Label(value => 'foo'); # is alias exi +sts $label = $panel->Rui__Widget__Label(value => 'bar'); # if not

    It allows you to add aliases per project, solves the problem of the user having to set a parent on the child widget, allows you to change the real classes used for widgets in one place, and works with inheritance.

    You want to look at Widget::Panel and Widget::Factory.