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

Re: A guide to coding Perl

by PetaMem (Priest)
on Dec 11, 2002 at 11:05 UTC ( #219058=note: print w/ replies, xml ) Need Help??


in reply to A guide to coding Perl

Hi,

I like it. It's informal, but that's ok because it's made for a one man show. Plus it has some things I never thought of that are just smart. Big ++ from me. Oh. And here's something from our PPCGs (PetaMem Perl COding Guidelines): These are made to be aplicable for a group of programmers, with bits from other styleguides shamelessly stolen and even containing some totalitary guides like "you have to program with that editor". But I think this totalitarism is needed if you need to keep a Perl development team in sync.

  1. Why PPCG? Why English?

    First off, be assured, that other programmers *will* have to read your code. This can be in one or in two years, or in a week. Be also assured, that YOU will have to read your own code in a year or so. The other programmers reading your code may not speak czech, german, hindi or esperanto, but they certainly will speak and understand english. That's why all development has to happen in this language.

    • english documentation
    • english remarks in the program
    • english variable, package, symbol, subroutine ... names

  2. Choose the right editor - it can help your career!

    Basically you may choose whatever editor you like. If you don't choose emacs - however - you have to make pretty sure, that your source code is not screwed up in emacs. Why? Because the pointy haired big boss (PHBB) is using emacs and wants to use emacs and he will review all of your code in this editor. And because you'll see, that there are more requirements to a PetaMem sourcecode, that only few editors are able to meet.

    If you to a later point want to be promoted to some "inferior big boss" position and review the code of some PetaMem programmers, you must do this in emacs. Why? Because even as an "inferior big boss" it can happen to you, that the real PHBB will re-review this code. If he should find any mistakes in a sourcode aproved by you, you will be very fast transformed from an "inferior big boss" to a dishwasher. So emacs can help your career - it cannot guarantee it however.

    Make use of folding at the subsourine/method level. '{{{' is the start of a fold '}}}' is the end of it. The folding.el module for emacs does a good job at this. It should look like that:

    # {{{ main_init main initialization routine # sub main_init { # # The priority of configurations is: # 1. command line parameters # 2. .elricrc file # 3. defaults/autodetection # At every beginning of a block - if you have to declare my variable +s... my $cpu = ''; my $get_opt = ''; if(-e '.elricrc') { $config = ConfigReader::Simple->new(&globalconf('rscfile')); $config->parse(); $cpu = $config->get('cpu') || &num_cpus; } $get_opt = GetOptions('cpu=i', \$cpu, 'c=i', \$cpu, 'help', \&print_usage_cmdline, 'h', \&print_usage_cmdline, 'v', \&print_version); &print_welcome; &globalconf('cpu',$cpu); } # }}} Give emacs hints what this source is all about: # For Emacs: -*- mode:cperl; mode:folding -*- Yes, use cperl-mode

    Don't use nested folds. There are at least two reasons:

    1. Nested folds are realized using different line ending, so this source cannot be compiled correctly.
    2. You've done a mistake in your problem specification and/or don't write clean and efficient code.

  3. The absolute basic hints

    • Know what the code is supposed to do BEFORE you start
    • Don't be too clever. Be elegant when coding and yes - cleverness is helpfull, but don't be TOO clever making it hard for someone reviewing your code a year later trying to find out what idea you had that best day in your life far ago.
      "You may think of a very clever way to code something this week. Unfortunately you may not be as clever next week and you might not be able to figure out what you did."
    • If you want to be especially clever (or need to, because the problem is hard) use apropriate documentation. Apropriate documentation is, what all of the rest of the development team understand (including the PHBB).
    • don't mix platform dependent code with platform independent one. Test your code under various platforms.
    • Maintainable code should be your holy grail, above and beyond any other consideration (except for correctness). It should be more important than optimization (save for when business needs demand it).

  4. PetaMem Specifics

    You will use CVS source code and versioning system. Get used to it and USE it. Don't see the additional information requirements it puts on you as balast. You will miss that information to a later point. (Or regret not filling out after a talk with the PHBB) Every File of your Perl Sourcecode must contain the following header <xx> are placeholders:

    # Started &lt;date&gt; by &lt;name&gt; # # $Author$ # $Date$ # $Id$ # $Revision$ # # [Modified &lt;date&gt; by &lt;name&gt;]* # &lt;name of the file&gt; &lt;version_of_the_source&gt; # Sanity checks: VARS|PROF|CERT # # PPCG: &lt;version of the PPCG you are coding after&gt; As for the sanity checks: VARS: Checked if there are any unnecessary variables (unused, used only once) and removed them PROF: Code has been examined and optimized by the help of the Profiler CERT: Certify, that this file has been validated against the stated PPCG - To work out the design priorities at PetaMem consider the following priorities for your code: Prio 1 CORRECT does what you intended what you intended was specified Prio 2 MAINTAINABLE well structured/modularized good documented easy to understand Prio 3 REUSABLE generic Prio 4 EFFICIENT fast ressource friendly small memory footstep etc.

    • Efficient being last priority doesn't mean, that you can or should choose the wrong algorithm O(n) instead of O(log n), or - to speak mor generally - with a runtime/memory complexity some level above the optimum solution. It just means, that you don't need to worry about reimplementing in C immediatedly. If you encounter a memory/cpu tradeoff situation, going for more memory instead of hoping for a faster CPU is the way. (most of the time and even then it depends)
    • Before you "finish" your work on a module or logical piece of code of yours, use Benchmark and the Profiler. See if there are any bottlenecks and eliminate them. Then your code is nearly "finished". So far for efficiency.
    • Then test it on various platforms and run it through the bytecode compiler. If it won't work on a platform, find out why and try to fix it. If fixing doesn't work (without major work), document it. Same applies to bytecompiling the code. THEN and only after youve performed all these steps. Your code can be seen as "finished" - ready for the maintainance mode.

  5. Use Comments

    If your program is not worth documenting, it probably isn't worth running. The time you save by writing clean code and commenting it carefully may be your own. Your comments are as important as your code. The compiler won't see them, but pople will. Be precise, don't be lenghty. Making speling errors in comments is bad. Have you forgotten? Comments are important and deserve at least a proofreading. You will see examples of comments later in the examples section.

    You should use your comments to be easy used by others. It's hard to read and underestand program code if you must be very carefull to don't skip some fundamental construction hidden between comment lines.

    It is better to use block of comments describing some action followed by block of code with described functionality instead to comment each line of code. If you need to comment each line place comments at the end of these lines.

    Wide acceptable are comment schemes like

    comment comment comment comment comment comment comment
    comment comment comment comment comment comment comment
    comment comment comment comment comment comment comment
    code code code code code code code code code code code
    code code code code code code code code code code code
    code code code code code code code code code code code
    code code code code code code code code code code code
    code code code code code code code code code code code
    
    or
    code code code code              comment comment comment
    code code code code              comment comment comment
    code code code code              comment comment comment
    code code code code              comment comment comment
    code code code code              comment comment comment
    code code code code              comment comment comment
    
    But not
    comment comment comment comment comment comment comment
    code code code code code code code code code code code
    comment comment comment comment comment comment comment
    code code code code code code code code code code code
    comment comment comment comment comment comment comment
    code code code code code code code code code code code
    
  6. Robust Code
    1. use -w, don't use warnings instead
    2. use strict
    3. use Carp
    4. be robust. Write robust code. That is - your code shouldn't break. When your code is robust enough, you will realize, that it is the environment that will break. Don't assume everything will go ok. Test the return values of the system calls and let subroutines have intelligent return values that allow you to be robust. (i.e. end gracefully on fatal errors or - even better - be that high-level fault tolerant that allows you to continue alternatively. Remember: You're working for a company that creates AI-entities. You don't need to restart your brain when encountering an error. The AI shouldn't either. The AI may go down if the machine it is running on explodes. And only then and only if the machine explodes completedly.
    5. I said be robust don't be paranoid. Testing the return value of print is paranoid. (Most of the time)
    6. Concrete examples for robustness:
      • User-Level: Handle wrong inputs or completedly missing inputs gracefully. In fact, expect them to go wrong.
      • System-Level: Expect that system calls may go wrong. Don't die because of this
      • Program-Level: It shouldn't happen, but as we can create code dynamically @ runtime... Handle missing or wrong parameters gracefully.
      • Hardware-Level. The machine you're running on is or may get buggy. Have sanity checks. Die gracefully and informative if you find your context broken.
  7. General Perl Habits @ PetaMem

    • All PetaMem Perl developers are members of perlmonks.org, some are at the Prague Perlmonks.

  8. Using Alien Perl Modules

    • Use of alien modules (from CPAN) is strongly preffered over the use of an own reimplementation of some task. Even if the module may seem an overkill. However: The policy for using modules is, that first the "best" module for a given task has to be choosen. Choosing is done by a gremium of at least 2 programmers. These are commited to do research at various community places like Perl-Newsgroups or Websites to form and support their decision. After they've chosen, they have to CARVE their decision in a document at W3, stating which module was chosen over what others, when and why.
    • Now be very VERY careful what you chose, because: If time shows, that another module is better (extended/faster functionality) and should be used instead of the old one, a gremium of at least 2 programmers including the PHBB has to make the decision to replace the old module against the new one. IF the decision is made, ALL use of the old module in existing sourcecode has to be replaced with the new one. Therefore it may well be, that replacing a modul won't happen even if it is technically superior. That's a bad thing. PetaMem programs should be that well written (functional encapsulation) and documented, that a replacement could happen.
    • If a module gets replaced, this decision has to be CARVED in W3. The information about why we used the old module becomes part of this report.
    • We're a small company (for now). But we're using a powerfull language and we're moving in a powerfull community. These two pillars are the giants on whose shoulders we stand. Don't program it if it already exists. If you do, you're asking for trouble.

  9. Various suggestions

    Interpolation, concatenation and list context
    Using interpolation is in many cases a waste of ressources. Interpolation is absolutedly equivalent (in terms of speed) to concatenation and this is - when printing - much slower than using list context. This is because print expects a list context.

    • "$blah1 $blah2"  (INTERPOLATION)
    • $blah.' '.$blah2 (CONCATENATION)
    • $blah,' ',$blah2 (LIST CONTEXT)

    If you just need to construct a string which you need in scalar context, you must concatenate. And therefore it is sometimes much clearer and more readable if you use interpolation.

    You may prefer interpolation for readability AND(!) if the operation doesn't require maximum speed. In every other case use list context.

    Code length

    If your subroutine is longer than 70 lines of code, you can be sure, that you're doing something wrong. If it is more than 100 lines you most probably have done a major mistake in the design of your code and it needs to be reviewed by someone other.

  10. Overall module structure

    Make your folded module look like this:

    # CREATE methods # {{{ new constructor... # {{{ read read and parse lexicon from file... # {{{ restore fast restore of dumped lexicon... # QUERY methods # {{{ isin is the $key in this lexicon... # {{{ info information about the contents of this lexico +n object... # MODIFY methods # {{{ add_entry add entry to lexicon... # {{{ add_entries add entries to lexicon... # {{{ add_meaning add meaning IF DISJOINT else DISCARD or REPLA +CE... # {{{ del_entries delete entries from lexicon... # {{{ merge merge some other lexicon to this one... # {{{ consolidate consolidate this lexicon... # {{{ dump dump lexicon for fast recovery... # DERIVE methods # {{{ expand expand one entry...
  11. To be continued...

signed the PHBB & Co.

Bye
 PetaMem


Comment on Re: A guide to coding Perl
Select or Download Code

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2014-09-22 00:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (176 votes), past polls