Difference between revisions of "StyleGuide"

From EPrints Documentation
Jump to: navigation, search
(Conditionals)
(Licensing)
Line 107: Line 107:
 
Try and use "next" rather than if when inside loops.
 
Try and use "next" rather than if when inside loops.
  
==Licensing==
 
  
We would like everything under the same license.... the EPrints license:
 
 
<pre>
 
######################################################################
 
#
 
#  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
 
#
 
######################################################################
 
</pre>
 
  
 
==Description==
 
==Description==

Revision as of 17:33, 7 August 2009

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.


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)