StyleGuide

From EPrints Documentation
Revision as of 17:32, 7 August 2009 by WikiSysop (talk | contribs) (Conditionals)
Jump to: navigation, search

EPrints has been under development for many years and has some fluff about the place. For new programmers this document is intended as a 'style guide' to at least keep the code and documentation consistent across new modules.

Programming Style

Naming

             TYPE           EXAMPLE

             module         StyleGuide
             subroutine     get_value
             global var     AUTH_OK
             local var      $field_name

Subroutines

             sub get_value
             {
                     my( $self, $arg1, $arg2 ) = @_;

                     return $r;
             }

Where possible, use "return" rather than an "if" block.

AVOID:

             sub get_value
             {
                     my( $self, $arg1 ) = @_;

                     my $r;
                     if( $arg1 )
                     {
                             $r = $arg1 * 2;
                     }
                     else
                     {
                             log( "some error" );
                     }
                     
                     return $r;
             }

Prefer this style instead, treating the problem like a basic exception to the normal running of the function:

             sub get_value
             {
                     my( $self, $arg1 ) = @_;

                     if( !defined $arg1 )
                     {
                            log( "some error" );
                            return;
                     }
     
                     return $arg1 * 2;
             }

Conditionals

             if( ref($a) eq "ARRAY" )
             {
                     print "Dang";
                     return 0;
             }

If the code inside the condition this is acceptable:

             return 0 if( ref($a) eq "ARRAY" );
             $a = 23 if( !defined $a );

However this is NEVER OK:

             if( !defined $a ) $a = 23;

Loops

             foreach my $field ( @fields )
             {
                     push @foo, $field->get_name();
             }

OR, when nested:

             FIELD: foreach my $field ( @fields )
             { 
                     VALUE: foreach my $value ( @{$field->{ "lsd" }} )
                     {
                             next VALUE if !defined $value; 
                             $values{ $value } = 1;
                     }
             }

Avoid $_ where possible.

Try and use "next" rather than if when inside loops.

Licensing

We would like everything under the same license.... the EPrints license:

 ######################################################################
 #
 #  This file is part of GNU EPrints 3.
 #  
 #  Copyright (c) 2000-2007 University of Southampton, UK. SO17 1BJ.
 #  
 #  EPrints 3 is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation; either version 2 of the License, or
 #  (at your option) any later version.
 #  
 #  EPrints 3 is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #  GNU General Public License for more details.
 #  
 #  You should have received a copy of the GNU General Public License
 #  along with EPrints 3; if not, write to the Free Software
 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 ######################################################################

Description

Below the license block the name, description and synopsis (a synopsis is an example of usage). Lastly the METHODS title begins the section for inline subroutine documentation.

	=head1 NAME

	EPrints::MyModule - A one line description of MyModule

	=head1 DESCRIPTION

	One or two paragraphs explaining the function of EPrints::MyModule.

	=head1 SYNOPSIS

		use EPrints::MyModule;

		my $obj = EPrints::MyModule->new( $opts );
		$obj->do_thing( $thingy );

	=head1 METHODS

	=over 4

	=cut

Methods

Public Methods

Each public subroutine should have POD documentation above it, with hashes to separate it from the method above. A large module should probably be split into different sections, e.g. "CONSTRUCTOR METHODS", "ACCESSOR METHODS", etc. Private methods can be documented using Perl comments.

	######################################################################

	=item $objname = EPrints::StyleGuide->my_sub( $arg1, [$opt_arg2], \%opts )

	A description of what my_sub does and arguments it takes ($opt_arg2 is
	shown as optional by using brackets).

	A description of $arg1 if needed, along with an example:

		EPrints::StyleGuide->my_sub( "eprintid" );

		EPrints::StyleGuide->my_sub(
			$arg1,
			undef,
			{
				opt1 => $var1, # What is var1
				opt2 => $var2, # What is var2
			}
		);

	Further elaboration on the effect of $var2.

	=cut

	######################################################################

	sub my_sub
	{
		...
	}

Private Methods

Automatically reformatting code

There is a wonderful utility called perltidy (find link)

This reformats perl for you (and does a syntax check at the same time... lovely.

Use:

 perltidy -gnu -csc -b JSON.pm
 -gnu reformats into the general 'gnu' style (as opposed to the "Larry Wall/Perl" style)
 -csc adds comments to the end of longish loops
 -b edits the file in place (so you may want to leave that off initially)