WebGUI
      Click here to register.
      
irc://irc.freenode.net#webgui

iPhoneGuy: WebGUI is a pile of crap.
rizen: If WebGUI is such a pile of crap, why do you use it?
iPhoneGuy: Because it's the best pile of crap out there.

If this is what people who hate us are saying, imagine what people who love us will say. Come join us on IRC.

Development Best Practices

One of WebGUI's greatest strengths is that it works on many operating systems and can connect to many external resources such as LDAP, Database, and web servers. If you're planning on writing plug-ins for or making core changed to WebGUI you should follow the coding guidelines presented here to ensure maximum compatibility. In addition, WebGUI has been built with performance in mind; we try to keep our code neat and elegant, so should you.

Perl Best Practices 

We, as a community have decided to adopt Perl Best Practices as our best practices for WebGUI. As far as we are concerned you might as well scratch "Perl" off the cover and replace it with "WebGUI". The following guidelines are areas where we have decided to override, or further clarify the rules set forth in the book.

See: PerlCritic

Reuse Code

Don't reinvent the wheel. Save yourself a lot of time and effort by using code that someone else has already written for you.

We've built a decent sized code-base within WebGUI. Much of the functionality needed by plug-ins has already been developed; such as URL rewriting, database access, date math, discussions, etc. Also, you may find that the functionality you are looking for has been written by someone else and stored at CPAN (www.cpan.org). The easiest way to find useful modules on CPAN is to use Search CPAN.

Staying Database Agnostic

If you're careful about how you construct your database statements, you'll be able to stay database agnostic. Here are a few hints:

  • All inserts should take this format: insert into table (column1,column2, column3) values (field1,field2,field3)
  • All updates should take this format: update table set field1='value', field2='value', field3='value' where field4='value'
  • Do not mix static fields with group by functions like this: select field1,count(*) from table group by field3
  • Be sure not to use functions that are database specific. For instance the date functions in most databases are database specific. Instead use a built in WebGUI library, or create your own external methods to handle those cases.
  • If you get row data using hashes or hash references, always tie your hash to Tie::CPHash. This keeps the hash case-insensitive. It's important because some databases return column names all uppercase, some are all lower-case, and some are mixed-case.
  • If you muck around with database tables for an upgrade script, especially asset, assetData, or wobject tables, you need to test back beyond the current upgrade to 6.8.10.


Best Practices

We've created these guidelines to keep the WebGUI code clean, self-documenting, and easy to read. If you follow the same guidelines your code will stay easily manageable.

Put a horizontal separator above each "sub" statement. Like this:

#-------------------------------------------------------------------
sub myMethod {

Keep your methods and subroutines in alphabetical order.

Always mark private methods with an underscore. Like this:

sub _privateMethod {

However, try never to make private methods, unless they absolutely need to be private. You never know what someone outside your module might need from your module, so consider making all your methods public unless they're subject to change or be removed in the near term. 

Always mark methods that are accessible to the web with www_. Like this:

sub www_myMethod {

Never abbreviate anything. This means that your subroutines, variables, table names, etc. should consistently have long meaningful names. This keeps the code readable.

Refrain from using the default variable ($_), especially in passing method parameters ($@). Instead, shift off all of the method parameters.

Use POD (Plain Old Documentation) to document all your methods. Type perldoc perlpod at the command line for more information.

Use OO Design (object-oriented) where it fits and procedural design where it fits. Contrary to popular belief one is not wholly better than the other, and there is a need for both; especially in Perl. For instance, objects are anywhere from 50% to 200% slower than procedural code at runtime (depending upon the situation and the benchmark used). However, objects typically lend themselves to more powerful and reusable functionality.

Never use  . or any other punctuation in your template variable names.  Underscore is okay.

Balance method granularity with code readability. You can always make something more granular later, but once it's granular,  going back means breaking the API.

After implementing new functionality always write/update any relevant documentation and/or help files. Doing this as you create your code will ensure that everything is always up to date.

Namespaces

For any plug-in you create, select a namespace that is not currently in use by any other plug-in. Make sure that your namespace is descriptive and useful. Use namespaces in package names, incrementers, tables, help, internationalization, etc. Here are some examples:

package WebGUI::Asset::Wobject::MyNewWobject;

create table MyNewWobject ();

create table MyNewWobject_colateralData ();

In any of your asset collateral tables, name the primary key something descriptive. If you need an incrementer for your key, use the table name combined with the column name as the incrementer name. Every incrementer should begin with the namespace to prevent overlap.
 

Code Formatting

As a community we have decided that our code will be formatted according to the suggestions in Perl Best Practices with the following exception:
 
Instead of 78 characters per line, we've chosen to go with 115 characters per line. The reason is that the lowest resolution any of the core developers is likely to use is 1024x768, and even on that you can view an editor with 120 characters. In addition, we don't often print out our code, so we don't have to worry about it fitting on a printer. 
 

Errata

Do not use "return;" as defined in PBP. Instead use "return undef;". This is because "return;" does different things in different contexts, which can cause problems that are unforseeable. 

Keywords: api plugin