eng-standards-filenaming.adp
Delivered as text/html
Related Files
[ hide source ] | [ make this the default ]
File Contents
<property name="context">{/doc/acs-core-docs/ {ACS Core Documentation}} {ACS File Naming and Formatting Standards}</property> <property name="doc(title)">ACS File Naming and Formatting Standards</property> <master> <style> div.sect2 > div.itemizedlist > ul.itemizedlist > li.listitem {margin-top: 16px;} div.sect3 > div.itemizedlist > ul.itemizedlist > li.listitem {margin-top: 6px;} </style> <include src="/packages/acs-core-docs/lib/navheader" leftLink="eng-standards-constraint-naming" leftLabel="Prev" title="Chapter 12. Engineering Standards" rightLink="eng-standards-plsql" rightLabel="Next"> <div class="sect1"> <div class="titlepage"><div><div><h2 class="title" style="clear: both"> <a name="eng-standards-filenaming" id="eng-standards-filenaming"></a>ACS File Naming and Formatting Standards</h2></div></div></div><div class="authorblurb"> <p>By Michael Yoon and Aurelius Prochazka</p> OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.</div><p>To ensure consistency (and its collateral benefit, maintainability), we define and adhere to standards in the following areas:</p><div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="eng-standards-filenaming-nomenclature" id="eng-standards-filenaming-nomenclature"></a>File Nomenclature</h3></div></div></div><p>Usually, we organize our files so that they mainly serve one of the following three purposes:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc;"> <li class="listitem"><p>displaying objects and their properties</p></li><li class="listitem"><p>manipulating or acting on objects in some way (by creating, editing, linking, etc)</p></li><li class="listitem"><p>housing procedures, packages, data models and other prerequisite code Essentially, we want our files named in a fashion that reflects their purpose.</p></li> </ul></div><p>Under the page root:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc;"> <li class="listitem"> <p>For naming files that enable a specific action on an object, use this format:</p><div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><code class="computeroutput">object-verb.extension</code></em></span></p></blockquote></div><p>For example, the page to erase a user's portrait from the database is <code class="computeroutput">/admin/users/portrait-erase.tcl</code>.</p> </li><li class="listitem"> <p>However, modules typically deal with only one primary type of object - e.g., the Bookmarks module deals mainly with bookmarks - and so action-type files in modules don't need to be specified by the object they act on. Example: the user pages for the Bookmarks module live in the <code class="computeroutput">/bookmarks/</code> directory, and so there is no need to name the bookmark editing page with a redundant url: <code class="computeroutput">/bookmarks/bookmark-edit.tcl</code>. Instead, we omit the object type, and use this convention:</p><div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><code class="computeroutput">verb.extension</code></em></span></p></blockquote></div><p>Thus, the page to edit a bookmark is <code class="computeroutput">/bookmarks/edit.tcl</code>.</p> </li><li class="listitem"> <p>For naming files that display the properties of a primary object - such as the bookmark object within the bookmark module - use this convention:</p><div class="blockquote"><blockquote class="blockquote"><p><code class="computeroutput">one.extension</code></p></blockquote></div><p>For example, the page to view one bookmark is <code class="computeroutput">/bookmarks/one.tcl</code>. Note that no verb is necessary for display-type files.</p> </li><li class="listitem"> <p>Otherwise, if the object to be displayed is not the primary feature of a module, simply omit the verb and use the object name:</p><div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><code class="computeroutput">object.extension</code></em></span></p></blockquote></div><p>For example, the page to view the properties of an ecommerce product is <code class="computeroutput">/ecommerce/product.tcl</code>.</p> </li><li class="listitem"> <p>For naming files in a page flow, use the convention:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle;"> <li class="listitem"><p> <span class="emphasis"><em><code class="computeroutput">foobar.extension</code></em></span> (Step 1)</p></li><li class="listitem"><p> <span class="emphasis"><em><code class="computeroutput">foobar-2.extension</code></em></span> (Step 2)</p></li><li class="listitem"><p>...</p></li><li class="listitem"><p> <span class="emphasis"><em><code class="computeroutput">foobar-N.extension</code></em></span> (Step N)</p></li> </ul></div><p>where <span class="emphasis"><em><code class="computeroutput">foobar</code></em></span> is determined by the above rules.</p><p>Typically, we use a three-step page flow when taking user information:</p><div class="orderedlist"><ol class="orderedlist" type="1"> <li class="listitem"><p>Present a form to the user</p></li><li class="listitem"><p>Present a confirmation page to the user</p></li><li class="listitem"><p>Perform the database transaction, then redirect</p></li> </ol></div> </li><li class="listitem"> <p>Put data model files in <code class="computeroutput">/www/doc/sql</code>, and name them for the modules towards which they are used:</p><div class="blockquote"><blockquote class="blockquote"><p> <span class="emphasis"><em><code class="computeroutput">module</code></em></span><code class="computeroutput">.sql</code> </p></blockquote></div> </li> </ul></div><p>In the Tcl library directory:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc;"> <li class="listitem"> <p>For files that contain module-specific procedures, use the convention:</p><div class="blockquote"><blockquote class="blockquote"><p> <span class="emphasis"><em><code class="computeroutput">module</code></em></span><code class="computeroutput">-procs.tcl</code> </p></blockquote></div> </li><li class="listitem"> <p>For files that contain procedures that are part of the core ACS, use the convention:</p><div class="blockquote"><blockquote class="blockquote"><p> <code class="computeroutput">ad-</code><span class="emphasis"><em>description</em></span><code class="computeroutput">-procs.tcl</code> </p></blockquote></div> </li> </ul></div> </div><div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="eng-standards-filenaming-urls" id="eng-standards-filenaming-urls"></a>URLs</h3></div></div></div><p>File names also appear <span class="emphasis"><em>within</em></span> pages, as linked URLs and form targets. When they do, always use <a class="ulink" href="rp-design" target="_top">abstract URLs</a> (e.g., <code class="computeroutput">user-delete</code> instead of <code class="computeroutput">user-delete.tcl</code>), because they enhance maintainability.</p><p>Similarly, when linking to the index page of a directory, do not explicitly name the index file (<code class="computeroutput">index.tcl</code>, <code class="computeroutput">index.adp</code>, <code class="computeroutput">index.html</code>, etc.). Instead, use just the directory name, for both relative links (<code class="computeroutput">subdir/</code>) and absolute links (<code class="computeroutput">/top-level-dir/</code>). If linking to the directory in which the page is located, use the empty string (<code class="computeroutput">""</code>), which browsers will resolve correctly.</p> </div><div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="eng-standards-filenaming-headers" id="eng-standards-filenaming-headers"></a>File Headers and Page Input</h3></div></div></div><p>Include the appropriate standard header in all scripts. The first line should be a comment specifying the file path relative to the ACS root directory. e.g.</p><div class="blockquote"><blockquote class="blockquote"><p><code class="computeroutput"># /www/index.tcl</code></p></blockquote></div><p>or</p><div class="blockquote"><blockquote class="blockquote"><p><code class="computeroutput"># /tcl/module-defs.tcl</code></p></blockquote></div><p>For static content files (html or adp), include a CVS identification tag as a comment at the top of the file, e.g.</p><pre class="programlisting"> <!-- file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp --> </pre><p>In addition, all static HTML files, documentation and other pages should have a visible CVS ID stamp, at least during development. These can be removed at release times. This should take the form of a line like this:</p><pre class="programlisting"> <p> Last Modified: file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp </p> </pre><p>This can be at the top or bottom of the file.</p><div>Using ad_page_contract</div><p>For non-library Tcl files (those not in the private Tcl directory), use <a class="link" href="tcl-doc" title="ad_page_contract"><code class="computeroutput">ad_page_contract</code></a> after the file path comment (this supersedes set_the_usual_form_variables and ad_return_complaint). Here is an example of using ad_page_contract, which serves both documentation and page input validation purposes:</p><pre class="programlisting"> # www/register/user-login-2.tcl ad_page_contract { Verify the user's password and issue the cookie. \@param user_id The user's id in users table. \@param password_from_from The password the user entered. \@param return_url What url to return to after successful login. \@param persistent_cookie_p Specifies whether a cookie should be set to keep the user logged in forever. \@author John Doe (jdoe\@example.com) \@cvs-id file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp } { user_id:integer,notnull password_from_form:notnull {return_url {[ad_pvt_home]}} {persistent_cookie_p f} } </pre><p>Salient features of <code class="computeroutput">ad_page_contract</code>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc;"> <li class="listitem"><p>A mandatory documentation string is the first argument. This has the standard form with javadoc-style \@author, \@cvs-id, etc, and should contain a short description of the received variables and any necessary explanations.</p></li><li class="listitem"><p>The second argument specifies the page inputs. The syntax for switches/flags (e.g. multiple-list, array, etc.) uses a colon (:) followed by any number of flags separated by commas (,), e.g. <code class="computeroutput">foo:integer,multiple,trim</code>. In particular, <code class="computeroutput">multiple</code> and <code class="computeroutput">array</code> are the flags that correspond to the old <code class="computeroutput">ad_page_variables</code> flags.</p></li><li class="listitem"><p>There are new flags: <code class="computeroutput">trim</code>, <code class="computeroutput">notnull</code> and <code class="computeroutput">optional</code>. They do what you'd expect; values will not be trimmed, unless you mark them for it; empty strings are valid input, unless you specify notnull; and a specified variable will be considered required, unless you declare it optional.</p></li><li class="listitem"><p> <code class="computeroutput">ad_page_contract</code> can do validation for you: the flags <code class="computeroutput">integer</code> and <code class="computeroutput">sql_identifier</code> will make sure that the values supplied are integers/sql_identifiers. The <code class="computeroutput">integer</code> flag will also trim leading zeros. Note that unless you specify <code class="computeroutput">notnull</code>, both will accept the empty string.</p></li><li class="listitem"><p>Note that <code class="computeroutput">ad_page_contract</code> does not generate QQvariables, which were automatically created by ad_page_variables and set_the_usual_form_variables. The use of bind variables makes such previous variable syntax obsolete.</p></li> </ul></div><div>Using ad_library</div><p>For shared Tcl library files, use <a class="link" href="tcl-doc" title="ad_library"><code class="computeroutput">ad_library</code></a> after the file path comment. Its only argument is a doc_string in the standard (javadoc-style) format, like <code class="computeroutput">ad_page_contract</code>. Don't forget to put the \@cvs-id in there. Here is an example of using ad_library:</p><pre class="programlisting"> # tcl/wp-defs.tcl ad_library { Provides helper routines for the Wimpy Point module. \@author John Doe (jdoe\@example.com) \@cvs-id file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp } </pre><div>Non-Tcl Files</div><p>For SQL and other non-Tcl source files, the following file header structure is recommended:</p><pre class="programlisting"> -- <span class="emphasis"><em>path relative to the ACS root directory</em></span> -- -- <span class="emphasis"><em>brief description of the file's purpose</em></span> -- -- <span class="emphasis"><em>author</em></span> -- <span class="emphasis"><em>created</em></span> -- -- <a class="ulink" href="http://www.loria.fr/~molli/cvs/doc/cvs_12.html#SEC93" target="_top">$‌Id$</a> </pre><p>Of course, replace "<code class="computeroutput">--</code>" with the comment delimiter appropriate for the language in which you are programming.</p> </div><div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="eng-standards-filenaming-pages" id="eng-standards-filenaming-pages"></a>Page Construction</h3></div></div></div><p>Construct the page as one Tcl variable (name it <code class="computeroutput">page_content</code>), and then send it back to the browser with one call to <code class="computeroutput">doc_return</code>, which will call db_release_unused_handles prior to executing ns_return, effectively combining the two operations.</p><p>For example:</p><pre class="programlisting"> set page_content "<span class="emphasis"><em>Page Title</em></span>] <h2><span class="emphasis"><em>Page Title</em></span></h2> <hr> <ul> " db_foreach get_row_info { select row_information from bar } { append page_content "<li><span class="emphasis"><em>row_information</em></span>\n" } append page_content "</ul> [ad_footer]" doc_return 200 text/html $page_content </pre><p>The old convention was to call <code class="computeroutput">util_return_headers</code> and then <code class="computeroutput">ns_write</code> for each distinct chunk of the page. This approach has the disadvantage of tying up a scarce and valuable resource (namely, a database handle) for an unpredictable amount of time while sending packets back to the browser, and so it should be avoided in most cases. (On the other hand, for a page that requires an expensive database query, it's better to call <code class="computeroutput">ad_return_top_of_page</code> first, so that the user is not left to stare at an empty page while the query is running.)</p><p>Local procedures (i.e., procedures defined and used only within one page) should be prefixed with "<span class="emphasis"><em><code class="computeroutput">module_</code></em></span>" and should be used rarely, only when they are exceedingly useful.</p> </div><div class="sect2"> <div class="titlepage"><div><div><h3 class="title"> <a name="eng-standards-filenaming-tcllib" id="eng-standards-filenaming-tcllib"></a>Tcl Library Files</h3></div></div></div><p>Further standards for Tcl library files are under discussion; we plan to include naming conventions for procs.</p><div class="cvstag">($‌Id: filenaming.xml,v 1.8.2.2 2021/09/02 16:56:02 gustafn Exp $)</div> </div> </div> <include src="/packages/acs-core-docs/lib/navfooter" leftLink="eng-standards-constraint-naming" leftLabel="Prev" leftTitle="Constraint naming standard" rightLink="eng-standards-plsql" rightLabel="Next" rightTitle="PL/SQL Standards" homeLink="index" homeLabel="Home" upLink="eng-standards" upLabel="Up">