Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: Re: Would you use 'goto' here?

by perrin (Chancellor)
on Dec 06, 2001 at 11:53 UTC ( #129866=note: print w/replies, xml ) Need Help??

in reply to Re: Would you use 'goto' here?
in thread Would you use 'goto' here?

As for the criticism that a later programmer might not understand the code: limiting yourself to widely-known and well-used syntax is the antithesis of Perl programming and I want no part of it.

But using obscure syntax when obvious and well-known syntax (a subroutine call) exists is the antithesis of maintainable code. There are so many ways to do things in Perl that you have to choose what you want to optimize for. Ovid says he wants to optimize for clarity and maintainability. That sometimes means doing things in a simpler way and avoiding cool but obscure (though documented) tricks like this.

Replies are listed 'Best First'.
My code and your stupidity don't mix!
by dragonchild (Archbishop) on Dec 06, 2001 at 18:53 UTC
    No. No. NO. NO. NO!

    A language has a certain syntax. Knowing that syntax is the responsability of the person who says "I know language XXX". It is not my responsability to make sure that I dumb down my code for your inability or unwillingness to keep your end of the bargain!

    I'm currently in a shop where use of $_, map, and grep is nominally discouraged. Why? Because others might not understand the code later down the line. (Yet, this place uses the most complex regexes I've ever seen, making me go to my book over and over.)

    If I was in C, would you discourage bit-masking? What about pointer arithmetic? Yes, they can cause problems, but they're a feature, not an 'oops'!

    Let me take another tack. Let's say you told me "I can read English". So, I write you a letter in English. No problems, right? Well, you start complaining about my use of the words with more than 6 letters. They're too difficult. You've never seen them. You don't like them. (And, yes, I've received this complaint before!) Should I not use a standard part of the language you have said you speak solely because you don't want to make good your assertion?!?

    I didn't think so.

    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.

      Since I'm willing to bet your paycheck that I have a few more years in the software industry that you, allow me to point something out:

      A software shop does not want to have to hire the top 5% of the skill pool just to do code base maintainence when you leave. You also don't probably don't want to spend the rest of your work career at that company maintaining a project you wrote 5 years ago.

      To this end, it's well and fine to use out-of-idiom methods when absolutely necessary, but not just because you can, or because they're cute. An *experienced* programmer recognizes when to write for efficiency (and saving .0001 CPU seconds off a job that runs once a week hardly qualifies), and when to write for maintainability.

      Some languages support the ability to write obfusicated code more than others. Perl outshines C in this respect, since Perl is a richer and more complex language. If the next guy that comes along to make some changes to your code has to track you down across the country to ask about how something what was done, that doesn't necessarily make him stupid. It may make him less skilled, but it's also a reflection on your inability to write for maintainability.

      Try getting involved in code reviews. If you have 5 people on the team, odds are they will not all have the same skill levels. If 2 or more agree that your code is obtuse, perhaps you should consider your style.

      The inability to write for maintainability costs a company money. You may have saved 10 minutes thinking about how to do it, but if it took 3 days for someone else to figure out it's supposed to work, you've burdened the company with your 'coolness'.

      Let me take another tack. Let's say you told me "I can read English". So, I write you a letter in English. No problems, right? Well, you start complaining about my use of the words with more than 6 letters. They're too difficult. You've never seen them. You don't like them. (And, yes, I've received this complaint before!) Should I not use a standard part of the language you have said you speak solely because you don't want to make good your assertion?!?

      This is a bad assertion, by the way. There are plenty of phrases I can write that will send you to a dictionary to figure out what I mean. Unless your goal is to complicate communication, there's no point in using obscure words. If you're trying to be understood, you don't use words that only see print when a new dictionary is released.

      A whole armamentarium of devices to create an illusion of real life -- Kenneth Rexroth


      e-mail jcwren

        While I would cheerfully bet your paycheck that you have been in software longer than I have, I think there is a bit of a 2-way street between keeping to what other people know, and teaching them more about the tool.

        If you do code reviews and 40% of developers find your code obscure, then possibly you do need to work on making your code clearer. OTOH possibly you need to work on educating them so that they understand your code, and work more effectively themselves. I think it is good for a company to decide that its standards for new employees include a learning curve, and that learning curve shall include mastering a set of features which may or may not be in wide use elsewhere.

        I think that is particularly true with a language like Perl where most people who claim on their resume to know it actually know it very poorly.

        Note that I am not saying that all problems are to be solved by teaching your fellow co-workers. There is a balance to be reached between using features that make you personally more productive, and keeping to what is generally known.

        I have, in no way, said that obfuscated code is a good idea. I have also not said that using undocumented features of Perl is a good thing to do. I'm talking about lesser-known features, like goto &foo, that are documented and correct to use in certain situations.

        Here's an example - would you say that using the Schwartzian Transform or Orcish Manauver is "obtuse"? Yet, one uses map liberally and the other uses ||=, which is a lesser-known feature. (It receives less than one page in the 3rd ed. Camel book.) If I were to take the Orcish Manauver to a code review in most Perl shops, 2/5 would definitely vote it's obfuscated! Yet, I hope you're not advocating that the Orcish Manauver is unmaintainable.

        Yes, you have a number of years more in the industry. However, nearly all my years have been rewriting badly written code and being forced to make it more maintainable in order to do anything with it. My "coolness" may cost the company three days, but someone else's "stupidity" just cost the company my last month's of work.

        I'd much rather someone use lesser-known features, but wrote good code, than someone use the easier 50% and write it badly.

        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.

      Let me point to the discussion at Operator Precedence and specifically my comments therein. I'm all for using the best tool for the job, but if you are writing code that others are going to see, you need to try to keep it as reasonably understandable as possible. What's 'reasonably'? Well, that definition's going to vary, particularly with perl.

      In the Big 3 languages, C, C++, and Java, these are typically taught to CS students, and there's a few key textbooks that are used for this; in addition, these languages don't offer the richness that Perl or other scripting languages have in terms of builtin functions, syntax, etc. Thus, if I was in a shop that used the Big 3, I'd know where to expect the 'reasonably understood' level to be at. As an example, I'd expect someone to understand a massively deep inheritence structure in C++; however, I would expect that someone might have trouble with C++ templates, and would effort myself to write more comments in that area.

      Perl, since it doesn't have a standard teaching path, is much different. (While we believe that at least one school does teach it, based on the massive duplication of the finite automata question, this is only one of thousands). Based on what I read on NGs, here, and elsewhere, the most common learning path of perl is what is in 'Learning Perl', and possibly what is out of 'Programming Perl'. I don't have the former book in front of me, but I don't recall a lot of advanced topics coming up in it, things like map and grep, for example; instead, my reading of the book was more focused on doing direct input and output from a script (actually using perl as the expanded acronym implies). Thus, if we assume a perl shop has, at *best* that common knowledge from 'Learning Perl', then we are drastically restricting what we can do with the language, unfortunately. This may be one reason why dc's shop highly discourages these idioms.

      Now, if I were in charge of such a shop, would I stop at that point? Probably not; sure, I know those coming in would be at a disadvantage, but that's why you train employees. Teach them the advanced features of perl (IF NEEDED!!) by either an in-house trainer, or someone from outside. Get them immersed in existing code that may use the advanced features. This way, you don't have your hands tied by limiting yourself to a subset of features.

      Of course, I would still discourage the use of advanced features that are not intuitively obvious. Map and grep , for example, are very simple to understand once you know they are there and seen them in use a few times. But Ovid's non-standard goto example, or using some of the code that pops up from Golf solutions, would be questionable because of it's readibility. If someone did determine that they just had to use an advanced feature to get the job done right, I wouldn't discourage it, but I would strongly encourage excessive commenting of the code around it. For example, in Ovid's case, if a comment such as 'In this form of goto (to a sub reference), the calling stack immediately switches to that code' preceded the questionable line, then I'd be more comfortable with that code (though as others have pointed out, the programming logic can be replaced by other code bits that are much more readable).

      So to get back to the point at hand, I would never encourage dumbing down code to a very basic level; I'd determine where a reasonable level would be, and try to take all advantages of that level. However, commentings would be very important here, and I would strive to make my programs as readable as possible without the comments in the first place. The right combination of readable code and commenting will make even the most complex pieces of perl code understandable by all levels of programmers.

      Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

      I'm currently in a shop where use of $_, map, and grep is nominally discouraged. Why? Because others might not understand the code later down the line.

      Those are often-abused features of Perl. I've seen crazy things done with map when much simpler stuff would have worked. I would definitely encourage people to think twice before choosing them, but I wouldn't ban them. Sometimes they are the best thing to use.

      A lot of this comes down to knowing what the shared level of knowledge you can expect from your team is. When I worked at eToys, we wanted to use mod_perl and OO code extensively for a new version of our system. To that end, I taught a brief class on mod_perl fundamentals, and we hired merlyn and TheDamian to help our team with OO and some of the tricky but useful Perl idioms. We gave everyone a copy of the Effective Perl and OO Perl books. That gave us a higher baseline than most Perl development groups, and freed us to use some trickier stuff.

      Even so, any time I used something a bit unusual like a hash slice, I would document it carefully. Sure, you can look it up, but you have to spot it in the first place and you have to have some idea of what you're looking up to know where to find it.

      Your English analogy is actually pretty good because I think it makes my point. When writing English for fun or for an audience of serious readers, you can use some wild and obtuse stuff. People have often "hacked" English for artistic purposes and created great things. However, if you were writing for a newspaper you would be expected to use a subset of English that supports the business goal of the newspaper, i.e. being clear and easy to understand for the average reader. Newspapers have extensive style guides on how you should use English in their papers. Perl shops tend to be less prescriptive about it and assume that you will exercise some common sense. Since most places have bug fixes and enhancements as major goals for their projects, writing code that the available pool of programmers can maintain is an implicit rule.

      Here's my take on this:

      I'm currently filling the role of quasi-lead for a Perl-powered web application. Due to the nature of our customers this web application is frequently in heavy development and we often find ourselves developing faster than we would like.

      It is my _preference_ that our team be explicit and as clear as possible about the way they are accomplishing tasks. This practice extends beyond the way we solve problems in our Perl-codebase. I typically encourage the guys to solve as they see fit but I am constantly reminding them to "keep it simple."

      $_, map and grep are among some of the cool features of Perl. They have their place and are often useful in reducing the number of lines of code required to complete a particular task (among other things). The problem with them is that they are _not_, in my experience, easy to understand. There are often much more simple ways of expressing concepts and those that are clearer are less likely to cause confusion.

      And productivity, in my current job (and frankly, in most of my previous jobs), is closely linked with effective communication. When I code I am more concerned with readability from the perspective of others than I am about how quickly I can express myself or how Perlish I can be. I have managed to learn that viewing a problem from the perspective of another person can often grant me a better understanding of the problem domain and solution.



        Which one would you prefer to read in your documentation?
        • the ways that I can let you know what I am thinking that will help you know what I am thinking better
        • effective communication

        The first phrase doesn't use a word over 8 letters, and only three words are six letters or more. Every word is one that a second-grader would know what it means. It's also 22 words long.

        The second phrase, however, is only two words long - 9 letters and 13 letters respectively. Both are words that I wouldn't expect a child in fourth grade to know. Oh, and the second phrase still contains a more precise meaning than the first phrase.

        That's what map and grep and $_ do for you. Succinct communication is often more effective communication.

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Fear of Large Languages (was: "Would you use goto")
by clintp (Curate) on Dec 06, 2001 at 19:11 UTC
    I couldn't possibly disagree more.

    Just so everyone understands that you're not just afraid of goto, let's take a look at a few pieces of syntax:

    • while(<FH>) assignment to $_
    • { local $/; $a=<SLURP>; }
    • sub cntr { my $r=0; return sub { $r++ }; }
    • $a="aaaa"; $a++
    • map {...} sort {...} map {... }
    • grep { s/foo/bar/ } @arr
    • *copy=\$original;
    Are these pieces of code obscure (though documented) tricks? Arguably, to someone new to Perl they're all tricks. Most of these can't be attempted (in their current form) in C, Shell, Java, Pascal, REXX, FORTRAN, or Basic without throwing a lot more code at the problem. So a programmer with 25 years of fairly broad experience could claim that these are all witchcraft of the worst sort and insist you avoid them. (All of these have an alternate "workaround" in Perl that could be used for "clarity.")

    But, in fact, they're all fairly idiomatic and common Perl. One programmer's "trick" is another programmer's tool. When does a "trick" become an idiom?

    I'd use any of them in a heartbeat if it was the appropriate tool for the job. I would hope you would too. Coding for clarity is one thing, wearing shackles is quite another. If the syntax is there, documented, and not deprecated -- use it.

    Those that fear and are unable to deal with large languages should stick to C.

      I figured it would be a controversial comment, but since this is one of the most fundamental issues when using Perl I wanted to bring it up and see what others think.

      To me the most interesting thing you say here is this: But, in fact, they're all fairly idiomatic and common Perl.

      That is the key difference. Common idioms that are widely recommended in books, on mailing lists, and sites like this one, are fair game in my opinion. If someone doesn't know how to slurp a file, he should learn. On the other hand, goto is not common or recommended (though not deprecated in this form). The comment from tilly that inspired this thread basically said that he could imagine a situation where he might want to use goto, but it had never happened and he didn't think it ever would.

      Remember, the only advantage that goto has in this situation is that it replaces the current sub in the call stack so that you can't tell it wasn't called directly in the first place. I consider this a disadvantage in most circumstances since it will make things more confusing to debug.

        Um, that wasn't what I basically said.

        The quote you are paraphrasing from goes:

        I have not personally ever felt the desire to (other than in deliberate experimentation) use a goto in Perl for anything other than subverting the stack. However I remain aware that I could, and I would do it without hesitation if I thought the situation warranted it. I also doubt I will ever encounter such a situation, but I think I could likely spot it if I did...
        Which means that I have used goto. In production code. For exactly what Ovid is doing, namely subverting the stack. While I wouldn't use a goto for that here, it is sometimes the right thing to do. An example is in an import method. Take a look at, for instance, Versioned modules. Why do I need to do it there? Quite simply because I need to remove myself from the call-stack so that an import method which knows nothing of me will export anything it exports to the correct package.

      Just as a note,

      It seems to me that the grep example shouldn't be used anyway, because you're modifying $_ en passent. This can lead to all kinds of problems, not the least of which is a lower level programmer misunderstanding why this is bad.

      Doing that in two lines seems to be a bit better, if more verbose:

      s/foo/bar foreach @arr; return grep { /bar/ } @arr;

      update: excuse my slow thinking

      i first thought that clintp was demonstrating canonical use of grep, which is documented, but difficult to understand at first (akin to canonical use of map). i feel sheepish. It now behooves me to think that he was in fact directing his snippet at what i was trying to point out: a subtle feature that is documented and so able to be understood (and used in production code).

      i feel there is still a point to be made however. While most of his other code snippets could be discovered plainly from documentation, this example is a bit more insidious. The student learning grep will probably not "get" what is being said in the documentation about this feature (i know i didn't the first few times through it). More to the point, while clintp's example is fine, a learning student would probably not notice the pitfall, since it doesn't directly follow; thinking they will is, sadly, overestimating their intelligence. Then later they could easily try altering $_ and get bizarre results.

      In the end, it seems better to avoid this usage in code for maintainability, whereas the other examples seem perfectly valid. Maybe it's just me...

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (3)
As of 2021-07-28 20:26 GMT
Find Nodes?
    Voting Booth?

    No recent polls found