in reply to Re: Parallel structures are NOT maintainable
in thread using references as keys in a hash.

A few comments:
  1. I'm merely pointing out that no data structure can prevent the scenerio you describe.

    No, but it can mitigate it. I am saying that, all things being equal, nested data structures contain more information intrinsic to their structure that parallel ones do.

  2. Will the programmer know to look in $$object{ISBN} for the piece of data he needs to fulfill the change request?

    Yes, he/she will. Why? Because they can go look at the definition for $object and see that there is an ISBN member. (You do have object definitions, right?) Failing that, Data::Dumper is one of the maintenance programmer's best friends. But, Data::Dumper doesn't know about that parallel data structure, does it? If it doesn't, it takes more time for me to find the right solution.

    (Nit: Use $object->{ISBN} instead ... $$object{ISBN} can lead to subtle bugs. Another maintenance headache, not a style issue.)

  3. The program will get the same result either way.

    This is a horrible statement, especially in this argument. Not only is it a tautology, but I don't care what hoops the computer has to go through to understand what I want it to do. COMPUTER RESOURCES ARE (NEARLY ALWAYS) CHEAPER THAN HUMAN RESOURCES.

Let me put that last point another way. My programming services cost more per week than a top-of-the-line linux server. People like merlyn and others cost at least twice that. Is it worth it to you for me to spend 40 hours figuring out how to save a meg of RAM?

It is worth a lot of money to write code that encapsulates as much information as possible in as many ways as possible that will be guaranteed to change as the code changes. Parallel data structures are a matter of style, yes. They are a poor choice of style because they will cost more money in maintenance than nested structures.

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

  • Comment on Re2: Parallel structures are NOT maintainable

Replies are listed 'Best First'.
That Nit (was Re: Parallel structures are NOT maintainable)
by jonadab (Parson) on Feb 25, 2003 at 16:20 UTC
    Nit: Use $object->{ISBN} instead ... $$object{ISBN} can lead to subtle bugs.

    I meant to ask before, and forgot: can you elaborate on this? Assuming for the moment that $object is a real reference here, not a "symbolic reference" string (we'll pretend for the moment that I was using strict; if the program were complex enough to span more than about half a dozen subroutines I would be), what subtle bugs would (or could) my syntax lead to? At first I thought you meant that someone might write $object{foo} by mistake instead of $$object{foo}, but then I realised warnings or strict either one would catch that, so you must be talking about something more subtle... but what?


    sub H{$_=shift;while($_){$c=0;while(s/^2//){$c++;}s/^4//;$ v.=(' ','|','_',"\n",'\\','/')[$c]}$v}sub A{$_=shift;while ($_){$d=hex chop;for(1..4){$pl.=($d%2)?4:2;$d>>=1}}$pl}$H= "16f6da116f6db14b4b0906c4f324";print H(A($H)) # -- jonadab
      There are a few reasons.
      1. You're talking about objects. Objects have methods. You cannot use the indirect dereference with methods. So, now you have one syntax for getting values from the object and another to call methods. Much better is to have one syntax for both. (This is why Perl4 uses that indirect dereference and Perl5 uses the arrow. But, Perl5 is backwards compatible ...)
      2. $$object is the syntax for soft references. That is the only way to do soft references. So, whenever I (your doughty maintenance programmer) see that syntax, I start thinking about why you want to have a soft reference there. But, you don't have a soft reference there. You're using cargo-cult programming learned from someone who never made the jump from Perl4 to Perl5. This is confusing. You could have made it clear that there is no soft reference.

        (Soft references are not always bad ... but you shouldn't use them until you know why they are always bad.)

      So, it's not a matter of things will necessarily break. In fact, I work on a 250K line system where that syntax is used everywhere. (Lots of legacy code. *shudders*) However, I wouldn't trust it. It's safer to do things the cleaner way.

      Update: Fixed mistaken notion re: symbolic references. (Thanks, tye!)

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        $$object is the syntax for soft references. That is the only way to do soft references.

        No, that is just dereference syntax and it and $object-> both do exactly the same thing whether $object contains a hard reference or just a variable name ("soft reference").

                        - tye
        You're talking about objects. Objects have methods. You cannot use the indirect dereference with methods. So, now you have one syntax for getting values from the object and another to call methods.

        This makes good sense. I think I know why I missed it up to this point: none of the objects I've written in Perl as yet has needed any routine properties. In the language where I have written objects complex enough to need them, references are handled somewhat differently. (Depending on how you view it, either there's no such thing as a reference, or else references are the only way to refer to any data type besides integers.) So the direct syntax, foo.bar or foo.bar() works for both. (In fact, foo.bar() will DTRT if the bar property is a reference to a string instead of a reference to a routine. This is useful because in Inform routines and strings are in many cases interchangeable from the caller's perspective; the difference is an implementation detail of the object.) But I can see that if ${$foo{bar}}() won't do the right thing in Perl, then for consistency I should use the other syntax. [Jonadab idly wonders for a moment about &{$foo{bar}}() but then thinks better of it.]

        So, whenever I see that syntax, I start thinking about why you want to have a soft reference there.

        But surely if I were using strict, you could easily dismiss that thought.

        You're using cargo-cult programming learned from someone who never made the jump from Perl4 to Perl5.

        I'm not certain where I picked it up, but if I had to guess my first guess would be the Camel; most of the Perl I know I learned from that book (2nd ed). But the reason I liked it is because it makes sense: it looks like a dereference. Conceptually, it's a natural extension of Perl's other syntax. The arrow syntax I've never liked; it comes from languages with really lousy OO models, such as C++. Perl is the only language I ever liked that allows it. The syntax I want is the foo.bar syntax...

        sub moveto { my ($p, @ch) = @_; foreach $c (@ch) { $c.parent = $p; push @p.children, $c; $c.siblings = (listsubtract(\@ch, [$c]); } }

        I guess I'll have to wait for Perl 6 for that.

        (Soft references are not always bad ... but you shouldn't use them until you know why they are always bad.)

        I'm careful about soft references. I don't use them with wild abandon. I have been known to do something like the following (where $r comes from a DBI fetchrow query) ...

        foreach $f ('foo', 'bar', 'baz', 'wibble', 'tlee') { $$f = $r->{$f}; }

        But that's very localised and controlled; $f is not set in some far-off location, calculated by a subroutine from another module, entered by a remote user on the web, extracted from a file by a regex, or autovivified by the assignment. (In that case, it would be $input{$f} instead of $$f -- I'm not entirely without a modicum of sense.)


        sub H{$_=shift;while($_){$c=0;while(s/^2//){$c++;}s/^4//;$ v.=(' ','|','_',"\n",'\\','/')[$c]}$v}sub A{$_=shift;while ($_){$d=hex chop;for(1..4){$pl.=($d%2)?4:2;$d>>=1}}$pl}$H= "16f6da116f6db14b4b0906c4f324";print H(A($H)) # -- jonadab
        Uhm, strict will catch any and all attempts to use symbolic references - regardless of whichever syntax you use.

        Makeshifts last the longest.

Re: Parallel structures are NOT maintainable
by Abigail-II (Bishop) on Feb 25, 2003 at 15:44 UTC
    Is it worth it to you for me to spend 40 hours figuring out how to save a meg of RAM?

    Maybe, maybe not. A meg of RAM may not seem much, but things tend to add up. If it's a long running process, a meg of RAM every now and then does add up. And suddenly, you reach the memory limit your OS allows for a process, requiring a restart of the process every two to three days. You might say, so what? But some business models just don't accept that.

    Abigail

Re: Parallel structures are NOT maintainable
by jonadab (Parson) on Feb 25, 2003 at 05:42 UTC
    Let me put that last point another way. My programming services cost more per week than a top-of-the-line linux server. People like merlyn and others cost at least twice that. Is it worth it to you for me to spend 40 hours figuring out how to save a meg of RAM?

    Huh? Where did that come from? Fourty hours to find and fix a single small issue? If I spent an entire five-hour shift fixing some little thing like that, I'd feel like I didn't get anything done that day. In a thirty-hour work week, I could rewrite the application from scratch and have time left over to unstick printers, bug the APCC tech support people about our ongoing PowerChute issue, teach an Introduction to the Internet class to a group of senior citizens, reboot my coworkers' Windows systems for them as necessary ("I restarted it. It should be better now."), run a couple of custom reports for my boss (and write one-off Perl scripts to turn them into meaningful data), and redo the stylesheets for the cgi scripts in question just because I felt like it.

    Either we're talking about programs so different in size that it's not remotely meaningful to talk about them in the same conversation (as I suspected when I read your previous message upthread), or else one of is seriously mispaid (since I don't make anything like the kind of wage you are talking about).

    I said that for complex situations the nested structures are better, but it seems to me that deeply complex programs are the only kind you are willing to concede might ever exist. Take a deep breath; some of us do simple stuff sometimes.


    sub H{$_=shift;while($_){$c=0;while(s/^2//){$c++;}s/^4//;$ v.=(' ','|','_',"\n",'\\','/')[$c]}$v}sub A{$_=shift;while ($_){$d=hex chop;for(1..4){$pl.=($d%2)?4:2;$d>>=1}}$pl}$H= "16f6da116f6db14b4b0906c4f324";print H(A($H)) # -- jonadab
      Actually, it's both - I do work primarily on large and very-large systems. And, I am seriously overpaid by my current employer. :-)

      And it came from the fact that I have been told to "save a Meg of RAM, not matter what it took". *shrugs* Reminded me of the Dilbert cartoon where the little bald guy says "I'm going to write me a minivan this week!"

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        And it came from the fact that I have been told to "save a Meg of RAM, not matter what it took".

        Ah. Saving a meg of RAM is not a good reason to use parallel hashes for a complex problem, I can agree on that point. In fact, I've been known to save myself time by throwing an enormous partially-redundant hash at a problem thus consuming around a hundred megs of RAM where it would have been possible to use less than half that. Of course, that script only has to run once a year, so it isn't worth optimising -- which I think is really what this discussion came to be about: knowing when something is worth doing and when it isn't.

        And don't let word get back to your employer that you are overpaid :-)


        sub H{$_=shift;while($_){$c=0;while(s/^2//){$c++;}s/^4//;$ v.=(' ','|','_',"\n",'\\','/')[$c]}$v}sub A{$_=shift;while ($_){$d=hex chop;for(1..4){$pl.=($d%2)?4:2;$d>>=1}}$pl}$H= "16f6da116f6db14b4b0906c4f324";print H(A($H)) # -- jonadab