filenaming.xml

Delivered as text/xml

[ hide source ] | [ make this the default ]

File Contents

<?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="eng-standards-filenaming" xreflabel="ACS File Naming and Formatting Standards">
<title>ACS File Naming and Formatting Standards</title>

 
<authorblurb>
<para>By Michael Yoon and Aurelius Prochazka</para>
</authorblurb>

<para>
To ensure consistency (and its collateral benefit, maintainability),
we define and adhere to standards in the following areas:
</para>

<sect2 id="eng-standards-filenaming-nomenclature">
<title>File Nomenclature</title>

<para>
Usually, we organize our files so that they mainly serve one of the following three purposes:
</para>

<itemizedlist>
<listitem><para> displaying objects and their properties</para></listitem>
<listitem><para> manipulating or acting on objects in some way (by creating, editing, linking, etc)</para></listitem>
<listitem><para> housing procedures, packages, data models and other prerequisite code
Essentially, we want our files named in a fashion that reflects their purpose.</para></listitem>
</itemizedlist>

<para>

Under the page root:
</para>

<itemizedlist>

<listitem><para>For naming files that enable a specific action on an object, use this format:</para>

<blockquote>
<para>
<emphasis><computeroutput>object-verb.extension</computeroutput></emphasis>
</para>
</blockquote>

<para>
For example, the page to erase a user&#39;s portrait from the database is
<computeroutput>/admin/users/portrait-erase.tcl</computeroutput>.
</para>
</listitem>

<listitem><para>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&#39;t need to be specified by the object they act on.  Example: the user pages
for the Bookmarks module live in the <computeroutput>/bookmarks/</computeroutput>
directory, and so there is no need to name the bookmark editing page with a redundant url: <computeroutput>/bookmarks/bookmark-edit.tcl</computeroutput>. Instead, we omit the object type, and use this convention:
</para>
<blockquote>
<para>
<emphasis><computeroutput>verb.extension</computeroutput></emphasis>
</para>
</blockquote>

<para>
Thus, the page to edit a bookmark is <computeroutput>/bookmarks/edit.tcl</computeroutput>.
</para>
</listitem>

<listitem><para>For naming files that display the properties of a primary object - such as the bookmark object within the bookmark module -  use this convention:</para>

<blockquote>
<para>
<computeroutput>one.extension</computeroutput>
</para>
</blockquote>

<para>
For example, the page to view one bookmark is
<computeroutput>/bookmarks/one.tcl</computeroutput>.  Note that no verb is necessary for display-type files.
</para>
</listitem>

<listitem><para>Otherwise, if the object to be displayed is not the primary feature of a module,  simply omit the verb and use the object name:</para>

<blockquote>
<para>
<emphasis><computeroutput>object.extension</computeroutput></emphasis>
</para>
</blockquote>

<para>
For example, the page to view the properties of an
ecommerce product is
<computeroutput>/ecommerce/product.tcl</computeroutput>.
</para>
</listitem>


<listitem><para>For naming files in a page flow, use the convention:</para>



<itemizedlist>
<listitem><para><emphasis><computeroutput>foobar.extension</computeroutput></emphasis> (Step 1)</para></listitem>
<listitem><para><emphasis><computeroutput>foobar-2.extension</computeroutput></emphasis> (Step 2)</para></listitem>
<listitem><para>...</para></listitem>
<listitem><para><emphasis><computeroutput>foobar-N.extension</computeroutput></emphasis> (Step N)</para></listitem>
</itemizedlist>


<para>
where <emphasis><computeroutput>foobar</computeroutput></emphasis> is determined by the above
rules.
</para>

<para>
Typically, we use a three-step page flow when taking user information:
</para>


<orderedlist>

<listitem><para>Present a form to the user</para></listitem>

<listitem><para>Present a confirmation page to the user</para></listitem>

<listitem><para>Perform the database transaction, then redirect</para></listitem>

</orderedlist>

</listitem>

<listitem><para>Put data model files in <computeroutput>/www/doc/sql</computeroutput>, and name them
for the modules towards which they are used:
</para>

<blockquote>
<para>
<emphasis><computeroutput>module</computeroutput></emphasis><computeroutput>.sql</computeroutput>
</para>
</blockquote>
</listitem>
</itemizedlist>

<para>
In the Tcl library directory:
</para>

<itemizedlist>

<listitem><para>For files that contain module-specific procedures, use the
convention:</para>

<blockquote>
<para>
<emphasis><computeroutput>module</computeroutput></emphasis><computeroutput>-procs.tcl</computeroutput>
</para>
</blockquote>
</listitem>

<listitem><para>For files that contain procedures that are part of the core ACS,
use the convention:</para>

<blockquote>
<para>
<computeroutput>ad-</computeroutput><emphasis>description</emphasis><computeroutput>-procs.tcl</computeroutput>
</para>
</blockquote>
</listitem>
</itemizedlist>

</sect2>

<sect2 id="eng-standards-filenaming-urls">
<title>URLs</title>

<para>
File names also appear <emphasis>within</emphasis> pages, as linked URLs and
form targets. When they do, always use <ulink url="rp-design">abstract
URLs</ulink> (e.g., <computeroutput>user-delete</computeroutput> instead of
<computeroutput>user-delete.tcl</computeroutput>), because they enhance maintainability.
</para>

<para>
Similarly, when linking to the index page of a directory, do not
explicitly name the index file (<computeroutput>index.tcl</computeroutput>,
<computeroutput>index.adp</computeroutput>, <computeroutput>index.html</computeroutput>, etc.). Instead, use
just the directory name, for both relative links
(<computeroutput>subdir/</computeroutput>) and absolute links
(<computeroutput>/top-level-dir/</computeroutput>). If linking to the directory in which
the page is located, use the empty string (<computeroutput>""</computeroutput>), which
browsers will resolve correctly.
</para>

</sect2>

<sect2 id="eng-standards-filenaming-headers">
<title>File Headers and Page Input</title>

<para>
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.
</para>

<blockquote><para><computeroutput>
# /www/index.tcl
</computeroutput></para></blockquote>

<para>
or
</para>

<blockquote><para><computeroutput>
# /tcl/module-defs.tcl
</computeroutput></para></blockquote>

<para>
For static content files (html or adp), include a CVS identification tag as a
comment at the top of the file, e.g.  
</para>

<programlisting>
&lt;!-- file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp --&gt;
</programlisting>

<para>
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:
</para>

<programlisting>
&lt;p&gt;
Last Modified: file-standards.html,v 1.2 2000/09/19 07:22:45 ron Exp
&lt;/p&gt;
</programlisting>

<para>
This can be at the top or bottom of the file.
</para>


<para><phrase>Using ad_page_contract</phrase></para>

<para>
For non-library Tcl files (those not in the private Tcl directory),
use <link linkend="tcl-doc-ad-page-contract"><computeroutput>ad_page_contract</computeroutput></link>
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:
</para>
 

<programlisting>
# www/register/user-login-2.tcl

ad_page_contract {
    Verify the user&#39;s password and issue the cookie.
    
    @param user_id The user&#39;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}
}
</programlisting>



<para>
Salient features of <computeroutput>ad_page_contract</computeroutput>:
</para>

<itemizedlist>

<listitem><para>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. </para></listitem>

<listitem><para>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. <computeroutput>foo:integer,multiple,trim</computeroutput>. In particular, <computeroutput>multiple</computeroutput> and
<computeroutput>array</computeroutput> are the flags that correspond to the old
<computeroutput>ad_page_variables</computeroutput> flags.</para></listitem>

<listitem><para>There are new flags: <computeroutput>trim</computeroutput>, <computeroutput>notnull</computeroutput> and
<computeroutput>optional</computeroutput>. They do what you&#39;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.</para></listitem>

<listitem><para><computeroutput>ad_page_contract</computeroutput> can do validation for you: the flags <computeroutput>integer</computeroutput>
and <computeroutput>sql_identifier</computeroutput> will make sure that the values
supplied are integers/sql_identifiers. The <computeroutput>integer</computeroutput> flag
will also trim leading zeros. Note that unless you specify
<computeroutput>notnull</computeroutput>, both will accept the empty string.
</para></listitem>

<listitem><para>Note that <computeroutput>ad_page_contract</computeroutput> 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.
</para></listitem>

</itemizedlist>

<para><phrase>Using ad_library</phrase></para>

<para>
For shared Tcl library files, use <link linkend="tcl-doc-ad-library"><computeroutput>ad_library</computeroutput></link> after
the file path comment. Its only argument is a doc_string in the
standard (javadoc-style) format, like
<computeroutput>ad_page_contract</computeroutput>. Don&#39;t forget to put the @cvs-id in
there.  Here is an example of using ad_library:
</para>
 

<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
}
</programlisting>


<para><phrase>Non-Tcl Files</phrase></para>

<para>
For SQL and other non-Tcl source files, the following file header structure is recommended:
</para>
 

<programlisting>
-- <emphasis>path relative to the ACS root directory</emphasis>
--
-- <emphasis>brief description of the file&#39;s purpose</emphasis>
--
-- <emphasis>author</emphasis>
-- <emphasis>created</emphasis>
--
-- <ulink url="http://www.loria.fr/~molli/cvs/doc/cvs_12.html#SEC93">&#36;Id&#36;</ulink>
</programlisting>


<para>
Of course, replace "<computeroutput>--</computeroutput>" with the comment delimiter
appropriate for the language in which you are programming.
</para>

</sect2>

<sect2 id="eng-standards-filenaming-pages">
<title>Page Construction</title>

<para>
Construct the page as one Tcl variable (name it
<computeroutput>page_content</computeroutput>), and then send it back to the browser with
one call to <computeroutput>doc_return</computeroutput>, which will call
db_release_unused_handles prior to executing ns_return, effectively
combining the two operations.
</para>

<para>
For example:
</para>
 

<programlisting>
set page_content "<emphasis>Page Title</emphasis>]

&lt;h2&gt;<emphasis>Page Title</emphasis>&lt;/h2&gt;

&lt;hr&gt;

&lt;ul&gt;
"

db_foreach get_row_info {
    select row_information 
    from bar
} {
    append page_content "&lt;li&gt;<emphasis>row_information</emphasis>\n"
}

append page_content "&lt;/ul&gt;

[ad_footer]"

doc_return 200 text/html $page_content
</programlisting>



<para>
The old convention was to call <computeroutput>util_return_headers</computeroutput> and
then <computeroutput>ns_write</computeroutput> 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&#39;s better to call

<computeroutput>ad_return_top_of_page</computeroutput>

first, so that the user is not left to stare at an empty page while
the query is running.)
</para>

<para>
Local procedures (i.e., procedures defined and used only within one
page) should be prefixed with "<emphasis><computeroutput>module_</computeroutput></emphasis>" and
should be used rarely, only when they are exceedingly useful.
</para>

</sect2>

<sect2 id="eng-standards-filenaming-tcllib">
<title>Tcl Library Files</title>

<para>
Further standards for Tcl library files are under discussion; we plan to 
include naming conventions for procs.
</para>

<para><phrase role="cvstag">($Id: filenaming.xml,v 1.8.2.2 2021/09/02 16:56:02 gustafn Exp $)</phrase></para>

</sect2>

</sect1>