<?xml version='1.0' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
               "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!ENTITY % myvars SYSTEM "../variables.ent">
%myvars;
]>
<sect1 id="style-guide" xreflabel="OpenACS Style Guide">
  <title>OpenACS Style Guide</title>

  <para>
    By Jeff Davis
  </para>

  <sect2 id="style-guide-motivation" xreflabel="Style Guide Motivation">
    <title>Motivation</title>
    <para>
      Why have coding standards for OpenACS?  And if the code works why change it to
      adhere to some arbitrary rules?
    </para>
    <para>
      Well, first lets consider the OpenACS code base (all this as of
      December 2003 and including dotLRN).  There are about 390,000
      lines of tcl code, about 460,000 lines of sql (in datamodel
      scripts and .xql files), about 80,000 lines of markup in .adp
      files, and about 100,000 lines of documentation.  All told, just
      about a million lines of "stuff".  In terms of logical units
      there are about 160 packages, 800 tables, 2,000 stored
      procedures, about 2,000 functional pages, and about 3,200 tcl
      procedures.
    </para>
    <para>
      When confronted by this much complexity it's important to be
      able to make sense of it without having to wade through it all.
      Things should be coherent, things should be named predictably
      and behave like you would expect, and your guess about what
      something is called or where it is should be right more often
      than not because the code follows the rules.
    </para>
    <para>
      Unfortunately, like any large software project written 
      over a long period by a lot of different people, OpenACS 
      sometimes lacks this basic guessability and in the interest 
      of bringing it into line we have advanced these guidelines.
    </para>
  </sect2>

  <sect2 id="style-commandments" xreflabel="Style Commandments">
    <title>Commandments</title>
    
    <para>
      Here is a short list of the basic rules code contributed to 
      OpenACS should follow...
    </para>
    <orderedlist>

      <listitem>
        <formalpara>
          <title>Follow the file naming and the package structure rules</title>
          <para>
            Some of the file naming rules are requirements for things
            to function correctly (for example data model creation
            scripts and tcl library files must be named properly to be
            used), while some are suggestions (the
            <emphasis>object-verb</emphasis> naming convention) which
            if ignored won't break anything, but if you follow the
            rules people will be able to understand your package much
            more easily.
          </para>
        </formalpara>
      </listitem>

      <listitem>
        <formalpara>
          <title>Be literate in your programming</title>
          <para>
            Use ad_proc, ad_library, and ad_page_contract to provide
            documentation for your code, use comments on your
            datamodel, explain what things mean and how they should
            work.
          </para>
        </formalpara>
      </listitem>


      <listitem>
        <formalpara>
          <title>Test</title>
          <para>
            Write test cases for your API and data model; test
            negative cases as well as positive; document your tests.
            Provide tests for bugs which are not yet fixed. Test,
            Test, Test.
          </para>
        </formalpara>
      </listitem>


      <listitem>
        <formalpara>
          <title>Use namespaces</title>
          <para>
            For new packages choose a namespace and place all procedures in it
            and in oracle create packages.
          </para>
        </formalpara>
      </listitem>

      <listitem>
        <formalpara>
          <title>Follow the constraint naming and the PL/SQL and PL/pgSQL rules</title>
          <para>
            Naming constraints is important for upgradability and for consistency.  Also, 
            named constraints can be immensely helpful in developing good error handling.
            Following the PL/SQL and PL/pgSQL rules ensure that the procedures created 
            can be handled similarly across both Oracle and PostgreSQL databases.
          </para>
        </formalpara>
      </listitem>


      <listitem>
        <formalpara>
          <title>Follow the code formatting guidelines</title>
          <para>
            The code base is very large and if things are formatted
            consistently it is easier to read.  Also, if it conforms
            to the standard it won't be reformatted (which can mask
            the change history and making tracking down bugs much
            harder).  Using spaces rather than tabs makes patches
            easier to read and manage and does not force other
            programmers to decipher what tab settings you had in place
            in your editor.
          </para>
        </formalpara>
      </listitem>


      <listitem>
        <formalpara>
          <title>Use the standard APIs</title>
          <para>
            Don't reinvent the wheel.  Prefer extending an existing
            core API to creating your own.  If something in the core
            does not meet your particular needs it probably won't meet
            others as well and fleshing out the core API's makes the
            toolkit more useful for everyone and more easily extended.
          </para>
        </formalpara>
      </listitem>

      <listitem>
        <formalpara>
          <title>Make sure your datamodel create/drop scripts work</title>
          <para>
            Break the table creation out from the package/stored
            procedure creation and use <computeroutput>create or
            replace</computeroutput> where possible so that scripts
            can be sourced more than once.  Make sure your drop script
            works if data has been inserted (and permissioned and
            notifications have been attached etc).
          </para>
        </formalpara>
      </listitem>


      <listitem>
        <formalpara>
          <title>Practice CVS/Bug Tracker Hygiene</title>
          <para>
            Commit your work. commit with sensible messages and include
            patch and bug numbers in your commit messages.
          </para>
        </formalpara>
        <para>
          Create bug tracker tickets for things you are going to work
          on yourself (just in case you don't get to it and to act as
          a pointer for others who might encounter the same problem).
        </para>
      </listitem>



      <listitem>
        <formalpara>
          <title>Solicit code reviews</title>
          <para>
            Ask others to look over your code and provide feedback and do 
            the same for others.  
          </para>
        </formalpara>
      </listitem>

    </orderedlist>
  </sect2>

  
  <sect2 id="style-guide-rev-history">
    <title>Revision History</title>

    <informaltable>
      <tgroup cols="4">
	<thead>
	  <row>
	    <entry>Document Revision #</entry>
	    <entry>Action Taken, Notes</entry>
	    <entry>When?</entry>
	    <entry>By Whom?</entry>
	  </row>
	</thead>
	<tbody>

	  <row>
	    <entry>0.1</entry>
	    <entry>Creation</entry>
	    <entry>12/2003</entry>
	    <entry>Jeff Davis</entry>
	  </row>

	</tbody>
      </tgroup>
    </informaltable>
    <para><phrase role="cvstag">($Id: style-guide.xml,v 1.3 2006/07/17 05:38:37 torbenb Exp $)</phrase></para>
  </sect2>

</sect1>
