Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re: Code Maintainability

by moritz (Cardinal)
on Dec 04, 2008 at 08:38 UTC ( #727904=note: print w/replies, xml ) Need Help??

in reply to Code Maintainability

I found your example of the constructor quite intriguing. Let me re-write that as a concrete example of generating a geometric shape:
my $circle = Circle->new(4.5, 2.3, 2.2, 1)

Do you know which parameter does what? No, of course not, you'd have to memorize the order of parameters, which nobody can or want for larger libraries.

Consider this in contrast:

my $circle = Circle->new(); $circle->set_radius(4.5); $circle->set_origin(2.3, 2.2); $circle->set_visibility(1);

Although the second version is bloated, it's much more readable. So in terms of maintainability, it wins. IMHO. I don't like it, but it's easier to understand, and at least in terms of readability it also scales to more arguments.

But wait - can't we do better? The repeated part $circle->set_ is ugly, and repetition is the enemy of good programming. Consider this instead:

my $circle = Circle->new( radius => 4.5, origin => [2.3, 2.2], visibility => 1, );

That's not shorter than the second example, but much less bloated, because of less repetition. But it's still as readable, and it scales well (ie even if you have eight or ten arguments to new() you can see what it does).

(If you are a Perl 6 fan boy like me, you'll be pleased to learn that Perl 6 provides such constructors with named parameters by default. Of course they can be overwritten).

Replies are listed 'Best First'.
Re^2: Code Maintainability
by mpeever (Friar) on Dec 04, 2008 at 16:52 UTC

    Consider this instead:
    my $circle = Circle->new( radius => 4.5, origin => [2.3, 2.2], visibility => 1, );
    I agree that named parameters are a huge win. That's a bit of Lisp and PL/SQSL I miss frequently in other languages.

    And frankly, without named parameters, it seems to me the convenience constructor debate really becomes a choice between the lesser of two evils. On the one hand we can be verbose, on the other we can be cryptic. I personally prefer cryptic to verbose: I expect a maintainer to look up parameters as he or she needs.

    But I return to my thesis: maintainability is a red herring. If we choose which idioms to use based on aesthetic value, we eliminate the problem. We both agree that a constructor taking a series of numbers is ugly. But I would argue that :

    my $capital = Capital -> new ("Canada", "Ottawa");
    Is obvious and very maintainable, even though it's conceptually the same pattern.

    My conclusion is that a sense of code aesthetics allows us to choose the best (or least evil) option on a case-by-case basis.

      Actually, I think it's more than just cryptic vs verbose. One of those examples has a serious logical flaw, and the other doesn't.

      my $circle = Circle->new(); # What is $circle now?! $circle->set_radius(4.5); # or now? $circle->set_origin(2.3, 2.2); $circle->set_visibility(1);

      See those comment I added? When you first create a circle object without any parameters, what is it, logically speaking? It has no radius and no origin, so it's more like a theoretical circle, but not representative of any real-world circle.

      After we set a radius, it starts to make sense, though maybe in our particular app circles always need an origin too.

      This dovetails with one of my newer mantras, which is that mutable state is evil. In the "pass everything to the constructor" version, we might be able to avoid (or at least limit) our mutators. If we're lucky, there's no need to change the radius of a circle, we can just make new ones with different radii. Avoiding mutable state greatly simplifies code. It makes APIs smaller, and makes reasoning about an application much simpler.

      Java, with it's regular pattern of "construct, set, and call", makes mutable state a given, and that's a terrible thing to do.

Re^2: Code Maintainability
by jeffa (Bishop) on Dec 04, 2008 at 17:19 UTC

    I believe your second example (which is always the way i call methods and subs now) is something that is almost exclusive* to Perl because of the concept of lists. PHP can't even do this "out of the box" like Perl can, observe:

    my $circle = Circle->new( array( radius => 4.5, origin => array( 2.3, 2.2 ), visibility => 1 ) );
    That's right ... PHP methods do not accept a list of arguments -- you have to make your array and pass it to your method. Now, you can use named args in PHP but they are still positional, meaning that you can't pass the args in an arbitrary order. In Java you would need to first instantiate a new Hash object, fill in its values and then pass that to your object's constructor. Yuck!

    All of this just reinforces my belief that 9 out of 10 Perl haters only hate Perl because they just don't get it. I myself am no fan of Perl 6, but it is good to hear that named parameters are now default.

    *I haven't bothered to read up on it, but i'll wager $50 that Ruby and Python can handle this.

    UPDATE: Duh! Lisp! Thanks for setting me straight Porculus. :)


    (the triplet paradiddle with high-hat)

      It's far from exclusive to Perl. You're right that Python can handle it; I don't know about Ruby, but there are plenty of other languages that do, the granddaddy of them all being Lisp.

      It doesn't require that things be based on lists of arguments, of course, though it helps (that's the way Lisp does it!), and it doesn't even require a dynamic language. For example, the completely static language O'Caml provides named arguments as a syntactic feature, with compile-time checking etc.

        For example, the completely static language O'Caml provides named arguments as a syntactic feature, with compile-time checking etc.
        Visual Basic too. /me hides

        holli, /regexed monk/
        Ada, PL/SQL, PowerShell, Modula 3, and Fortran 90 allow named parameters in arbitrary order, too. I'm sure there are more out there.
Re^2: Code Maintainability
by James Board (Beadle) on Dec 06, 2008 at 03:09 UTC
    I agree. You will probably spend twice as much time debugging, and later maintaining, your code then you will writing it (stolen from Perl Best Practices, or some book like that). So, it makes much more sense to optimize your code for later readability and ease of understanding (two or three months later when you don't have the whole thing in memory) then it does to optimize it for the initial ease of writing.

    Of course, one line is always quicker to read then five, so if you're sure you'll be able to quickly understand that one line instantly, at a glance, months later, then that one line will be the way to go.

    And that's the tradeoff, which will always evaluate differently for beginning, mid-level, and advanced Perl programmers.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://727904]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2020-07-05 14:30 GMT
Find Nodes?
    Voting Booth?

    No recent polls found