Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
laziness, impatience, and hubris
 
PerlMonks  

Re^5: VarStructor 1.0

by tkil (Monk)
on May 11, 2004 at 01:14 UTC ( [id://352314]=note: print w/replies, xml ) Need Help??

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.


in reply to Re: Re^3: VarStructor 1.0
in thread VarStructor 1.0

I still haven't finished reviewing everything, but I wanted to thank you for reviewing my code in such depth.

You're welcome. Even with code where I disagree with both the style and the purpose (nicely done! :), I can still enjoy trying to figure out what is going on.

One way that I record my understanding, however, is to rewrite the code in my own style, with my own cues in variable naming, indentation, and control structures. This is probably not the most effective way of doing it (and, without good test cases, often a spectacularly bad way of doing it), but it works for me.

I used to format my comments to a certain width, but that makes them more difficult to edit and artificially increases the line count, so I only format certain comment blocks that way, such as ones most likely of interest to others.

My preference is for comments that are split onto lines of reasonable length. The editor I use most often (FSF or X Emacs) has a built-in function for wrapping text across lines like this (they call it "filling"); in vi, the standard technique is to hand off the filling responsibilities to a command like fmt.

The point here is that proper editor support can make it easier to develop code that is then easier to read as well as being nearly painless to develop and modify. Code is read far more often than it is editted, so taking a slight bit of extra pain is probably called for. (Also, you can defer reformatting those comments until you issue a point release, which would further reduce your maintenance burden.)

I won't be using all those x modifiers and extra spaces, I'll change the indentation, etc.

Well, the use of /x is generally a good idea for regexes of any complexity at all — and some of yours are doozies. The only down side to the /x modifier is that whitespace has to be specified explicitly.

You mentioned this above, and it's implicit in the pervious point as well: yes, many of these suggestions will increase the line count. So? This is not a competition for the shortest solution. There are many metrics for what makes good code: terseness is rarely one of the top reasons. Your background in assembler and BASIC might be working against you here... but in perl, any inefficiency due to space is proportional to the number of opcodes that are found by the perl parser when it first encounters your code. Whitespace is literally irrelevant (except for seperating tokens.)

There is the issue of code density, where it can be beneficial to keep as much "action" as possible on one screen. Two reasons that keep me from worrying much about this: first, perl is an incredibly dense langauge, and can do amazing things with very little code; and second, a "screen" today is typically a long terminal or editor window on a graphical system, offering 40 to 60 or more lines visible at once.

You added variables, such as $out_vars and changed lots of other stuff without clearly indicating where the changes were made.

Apologies! Some of these omissions were influenced by the fact that I kept it under version control, and I can always go back and say "Hm, what did I change when I added this variable?".

Another reason that these variables are not very well commented is because I was still figuring out what they were for. I did quite a few purely-textual replacments: just search for where a particular value is used, and use a new variable name (a lexical variable introduced with the my keyword) instead of a global value (because, without knowing all of the rest of the program, I have no idea where those global values are manipulated or accessed).

So they are different variable names, and I can see how you'd have to re-learn a routine after that replacement. The advantage is one that you have not been particularly receptive to: the use of my variables. While they add to the initial dose of code that has to be digested when you read it at first — but that is offset the the knowledge that, outside this one screen of text, nothing can modify that variable. Once fully understood, this freedom is liberating to the point of being intoxicating.

(This resonates with the reason that I — and, it seems, the majority of the Perl monks — find your module to be distasteful to the point of being dangerous. See the end of this response for more on that, though.)

I like my parameter handling. It makes it easier on the programmer because he could add just the parameters he wants without extra commas.

One of the most fascinating tensions in Perl is that between consistency and "do what I mean". Perl tries very hard to fulfill the later, often at a cost to the former. Which is fun and pleasant and (as the vibrant community can attest), generally it works. But it is not for nothing that this inconsistency has been described as Perl's greatest strength and its greatest weakness.

On the far side of the scale are languages like Lisp, where the syntax is kept regular to the point of forcing the programmer to write convoluted things to satisfy the simplistic parser. There is a hidden benefit to this approach, though: if the language itself is simple and regular, then it is easier to write code which writes code itself: meta-code. This sounds arcane at first, but it is an amazingly powerful technique in certain circumstances.

... though I see you replaced my sub detection routine with your own. I guess I'll take a look at it and maybe use it.

Hm. I'm hesitant to even call it its own subroutine; the point is that there are a couple of different ways of declaring subroutines (with and without prototypes; as anonymous code references). This doesn't begin to touch on the use of require or use to bring in functions that are implemented somewhere other than in the main file.

I'm not afraid of saying "if you don't do it this way, my utility won't work," in some cases. It makes label and sub detection easier, and my rules aren't so unreasonable. The ability to omit and include those blocks when clearing or listing variables isn't offered in any other product as far as I know, so limitations aren't so bad, ...

Look at it another way: are our coding guidelines any more restrictive than this? If someone has to modify their code to take advantage of your utility, or if they have to modify their code to take advantage of the "best practices" and common style of most perl programmers?

You've come close to making the fears I expressed here come true: "One of the reasons I'd be reluctant to release a subroutine of my script as a Perl module is that it would probably be pounced upon and improved beyond recognition and beyond my ability to work with it any longer, and I wouldn't want to lose my first baby."

Interesting analogy. Would you let others help you instruct your baby, or is the fact that you and you alone raised it more important than getting the best possible education, medical care, and experiences for the baby?

The easiest way to avoid any issues with this would be to preface any post with exactly what you expect us to do with it. If you look around our site, you'll notice that posted code is often critiqued (both in the large and in the small), modules to replace or augment it are suggested, etc. If this is not what you want, say so!

I think that you genuinely were trying to be helpful: you have a tool that helps you get your job done, and you wanted to share it. And most of us appreciate your generosity.

At the same time, we feel that there are better ways of solving the same problems: ways that are more scalable, have better support in the language, often more effecient, and simply a much more common idiom (which means that you can get support anywhere).

If someone were to come to us with a script suffering from problems that could be helped by this module (namely, a way to grab a quick snapshot of global state, or potentially to reset global variables at a fair distance), we would instead suggest that they fix the code to use the tools the language offers directly for local control, information hiding, and disposing of variables that are no longer needed.

The fact that your module exhibits exactly those problems that it tries to fix / support is what has made many of the exchanges here so painful. As just one example, you might know that you're not using a variable anywhere else, so you feel comfortable leaving it globally accessable; we don't know your codebase, and since you weren't explicitly marking it locally controlled (with my or local), we had to assume that there might be other users, and therefore any change to it would be fragile.

Anyway. I wish you luck with this code, and hope that you don't have to use it too often. :)

Replies are listed 'Best First'.
Re: Re^5: VarStructor 1.0
by Wassercrats (Initiate) on May 11, 2004 at 02:17 UTC
    Even with code where I disagree with both the style and the purpose (nicely done! :), I can still enjoy trying to figure out what is going on.

    I keep forgetting to look into whether alternative methods of listing variables list the values as well, but I do know that when I used Xref at the command line, it gave me a laundry list of stuff that I didn't care about. There's no post-processing necessary for VarStructor to give you the user defined variables and values, and it's faster, easier to use, and more flexible than Xref.

    I don't know how anyone could say that the addition of a reset feature that's more flexible and safer than Perl's not-yet-deprecated reset function is a bad addition, but you can't deny that listing variables and their values is useful.

    The fact that your module exhibits exactly those problems that it tries to fix / support is what has made many of the exchanges here so painful.

    My subroutine doesn't try to fix anything. It succeeds in being a tool to be used the way any module or Perl function is used. I'm using it because it's the best way to do what I have to do, and I won't settle for second-best just because others prefer it.

      I keep forgetting to look into whether alternative methods of listing variables

      And you continue to ignore the fact that we are advocating a programming style where you never have to do massive lists of variables, because all the active variables are local to the current subroutine. Any longer-lived values live in a very very few globals, or in objects that can operate on their own contents.

      I don't know how anyone could say that the addition of a reset feature that's more flexible and safer than Perl's not-yet-deprecated reset function is a bad addition,

      We're not saying that such an addition would be bad. We're saying that such an addition has already been made, and its name is my. Variables so declared are "reset" at the end of the block, with no additional code needed! Magic!

      We see you driving around an old jalopy that's leaking oil and basically being a mainenance nightmare. Doesn't matter whether you wrote it, or if you just inherited it. We are suggesting that you fix the car; you keep on wanting to build a bigger and better tow truck.

      As before, I wish you luck. Especially because, with this programming style and development mindset, you are going to need it.

        I counted 15 globals just at the top of cgi.pl, where it says "# >>>>> Here are some globals that you might want to adjust <<<<<<" which makes sense because you would want all the user-configurable stuff together, at the top of the script, no matter what subroutine they get used in. Whoever wrote CGI.pm surely knew how my variables work because he used them, but he didn't think it was practical to make the user defined variables local. Everyone's programming habits are different, and there are some much longer programs than cgi.pm, even though it's one of the longest modules. I don't think it would be too difficult to find a script with much more than 15 globals.

        Everyone seems to be picking on the cosmetic things or the things they wouldn't need. Remember, along with the values, you get the variable names, which someone decided is useful since they're provided by Xref.

        It's impossible for anyone to say that a script is a maintenance nightmare just because it uses all globals, no warnings and no strict. My script requires fewer hops to different subroutines, which could make it an easier read. Thinking up unique variable names is easy, and searching the script just in case is easy too. Well written comments within the script and on top are a big help. I have well defined "blocks" of code, but I don't have to bother passing local variables around. They're always exactly where I want them. I don't have the problems described here either.

        Not only is my 3400 line script not a maintenance nightmare, but it has fewer bugs and works better than many production scripts I've seen, including its future competition.

        EDIT... Forgot to mention another benefit of VarStructor. It could help you be sure that your variables are "my" variables. If it shows a value, you know you forgot "my."

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://352314]
help
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.