summaryrefslogtreecommitdiff
path: root/ACE/docs/ACE-guidelines.html
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/docs/ACE-guidelines.html')
-rw-r--r--ACE/docs/ACE-guidelines.html1394
1 files changed, 1394 insertions, 0 deletions
diff --git a/ACE/docs/ACE-guidelines.html b/ACE/docs/ACE-guidelines.html
new file mode 100644
index 00000000000..2d85c775506
--- /dev/null
+++ b/ACE/docs/ACE-guidelines.html
@@ -0,0 +1,1394 @@
+<!-- $Id$ -->
+
+<html>
+ <head>
+ <title>ACE Software Development Guidelines</title>
+ <link rev=made href="mailto:ace-users@cs.wustl.edu">
+ </head>
+
+<body text = "#000000"
+link="#000fff"
+vlink="#ff0f0f"
+bgcolor="#ffffff">
+
+<hr>
+<h3>ACE Software Development Guidelines</h3>
+
+<ul>
+ <li><strong>General</strong><p>
+ <ul>
+ <li>Every text file must end with a newline.<p>
+
+ <li>Use spaces instead of tabs, except in Makefiles. Emacs users
+ can add this to their <strong>.emacs</strong>:
+
+ <pre>(setq-default indent-tabs-mode nil)</pre></p>
+
+ Microsoft Visual C++ users should do the following:
+
+ <pre>
+ Choose: Tools -- Options -- Tabs
+ Then Set: "Tab size" to 8 and "Indent size" to 2, and
+ indent using spaces.
+ </pre><p>
+
+ <li>Do not end text lines with spaces. Emacs users can add this to
+ their <strong>.emacs</strong>:
+
+ <pre>(setq-default nuke-trailing-whitespace-p t)</pre>
+
+ Newer versions of emacs will require the following instead:
+
+ <pre>(add-hook 'before-save-hook 'delete-trailing-whitespace)</pre>
+
+ <strong>Note for Microsoft Visual Studio .NET Users:</strong>
+ <p>There is a macro project <code>(ace_guidelines.vsmacros)</code>
+ located in <code>$ACE_ROOT/docs</code> that replaces tabs with spaces
+ and removes trailing spaces each time you save a file.</p>
+
+ <li>Try to limit the length of source code lines to less than 80
+ characters. Users with 14 inch monitors appreciate it when
+ reading code. And, it avoids mangling problems with email
+ and net news.<p>
+
+ <li>Try to avoid creating files with excessively long names (45 characters).
+ Moreover, ensure that the names of generated files e.g. <code>MakeProjectCreator</code>,
+ <code>tao_idl</code> do not also go beyond that limit. Some operating
+ systems cannot handle very long file names correctly.<p>
+
+ <li>If you add a comment to code that is directed to, or
+ requires the attention of, a particular individual:
+ <strong>SEND EMAIL TO THAT INDIVIDUAL!</strong>.<p>
+
+ <li>Every program should have a "usage" message. It should be
+ printed out if erroneous command line arguments, or a
+ <strong><code>-?</code></strong> command line argument, are
+ provided to the program.<p>
+
+ <li>An ACE-using program's entry point should use the portable form:
+ <pre>
+ int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+ </pre>
+ This form is portable to all ACE platforms whether using narrow
+ or wide characters. The other two common forms:
+ <pre>
+ int main (int argc, char *argv[])
+ int wmain (int argc, wchar_t *argv[])
+ </pre>
+ as well as any other main entrypoint form should only be used
+ when there is some overarching reason to not use the portable form.
+ One example would be a Windows GUI program that requires WinMain.
+ <p>See <a href="wchar.txt"><code>$ACE_ROOT/docs/wchar.txt</code></a>
+ for more information on ACE support on <code>wchar</code>.<p>
+
+ <li>The program entry point function, in any form mentioned above, must
+ always be declared with arguments, <em>e.g.</em>,
+ <pre>
+ int
+ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+ {
+ [...]
+
+ return 0;
+ }
+ </pre><p>
+
+ If you don't use the <code>argc</code> and/or <code>argv</code>
+ arguments, don't declare them, <em>e.g.</em>,
+ <pre>
+ int
+ ACE_TMAIN (int, ACE_TCHAR *[])
+ {
+ [...]
+
+ return 0;
+ }
+ </pre><p>
+
+ Please declare the second argument as <code>ACE_TCHAR *[]</code>
+ instead of <code>ACE_TCHAR **</code> or <code>char *[]</CODE>.
+ Ancient versions of MSC++
+ complained about <code>ACE_TCHAR **</code> and <code>char
+ *[]</CODE> is not Unicode-compliant.<p>
+
+ <code>main</code> must also return 0 on successful
+ termination, and non-zero otherwise.<p>
+
+ <li>Avoid use of floating point types (<code>float</code> and
+ <code>double</code>) and operations
+ unless absolutely necessary. Not all ACE platforms support them.
+ Therefore, wherever they are used, <code>ACE_LACKS_FLOATING_POINT</code>
+ conditional code must be also be used.<p>
+
+ <li>Avoid including the string "<code>Error</code>" in a source
+ code filename. GNU Make's error messages start with
+ "<code>Error</code>". So, it's much easier to search for
+ errors if filenames don't contain "<code>Error</code>".<p>
+
+
+ <li>Narrow interfaces are better than wide interfaces. If there
+ isn't a need for an interface, leave it out. This eases maintenance,
+ minimizes footprint, and reduces the likelihood of interference
+ when other interfaces need to be added later. (See the
+ <a href="#ACE_Time_Value example">ACE_Time_Value</a> example
+ .<p>
+
+ <li> Never use <CODE>assert()</CODE> macros or related constructs
+ (such as abort()) calls in core ACE, TAO, and CIAO
+ library/framework code. These macros are a major problem for
+ production software that uses this code since the
+ error-handling strategy (i.e., abort the process) is
+ excessive. Instead, extract out the expressions from
+ assert() macros and use them as
+ precondition/postconditions/invariants in the
+ software and return any violations of these
+ conditions/invariants via exceptions or error return values.
+ It's fine to use <CODE>assert()</CODE> macros et al. in test
+ programs, but make sure these tests never find their way into
+ the core ACE, TAO, and CIAO library/framework code base. <P>
+
+ </ul>
+
+ <li><strong>Coding Style</strong><p>
+ <ul>
+ <LI> When writing ACE, TAO, and CIAO class and method names make sure to use underscores ('_') to separate the parts of a name rather than intercaps. For example, use
+
+ <pre>
+ class ACE_Monitor_Control
+ {
+ public:
+ int read_monitor (void);
+ // ...
+ };
+ </PRE>
+
+rather than
+
+ <pre>
+ class ACEMonitorControl
+ {
+ public:
+ int readMonitor (void);
+ // ...
+ };
+ </PRE>
+
+ </UL>
+
+ <li><strong>Code Documentation</strong><p>
+ <ul>
+ <li>Use comments and whitespace (:-) liberally. Comments
+ should consist of complete sentences, <em>i.e.</em>, start
+ with a capital letter and end with a period.<p>
+
+ <li>Insert a svn keyword string at the top of every source file,
+ Makefile, config file, <em>etc</em>. For C++ files, it is:
+ <pre>
+ // $<!-- -->Id$
+ </pre>
+ It is not necessary to fill in the fields of the keyword string,
+ or modify them when you edit a file that already has one. SVN
+ does that automatically when you checkout or update the file.<p>
+
+ To insert that string at the top of a file:
+ <pre>
+ perl -pi -e \
+ 'if (! $o) {printf "// \$<!-- -->Id\$\n\n";}; $o = 1;' <em>file</em>
+ </pre><p>
+
+ <li>Be sure to follow the guidelines and restrictions for use of the
+ documentation tools for ACE
+ header files, which must follow the
+ <a href="http://www.doxygen.org/">Doxygen</a>
+ format requirements.
+ The complete documentation for Doxygen is available in the
+ <a href="http://www.stack.nl/~dimitri/doxygen/download.html#latestman">
+ Doxygen manual</a>.
+ For an example header file using Doxygen-style comments,
+ please refer to <a href="../ace/ACE.h">ACE.h</a>.<p>
+
+ <li>The header file comment should at least contain the following
+ entries:
+ <pre>
+ /**
+ * @file Foo.h
+ * @author Authors Name &lt;author@email.org&gt;
+ *
+ * A few words describing the file.
+ */
+ </pre></p>
+
+ <li>A class should be commented this way:
+ <pre>
+ /**
+ * @class Foo_Impl
+ * @brief A brief description of the class
+ *
+ * A more detailed description.
+ */
+ </pre></p>
+
+ <li>The preferred way to document methods is:
+ <pre>
+ /// This function foos the bars
+ /// another line of documentation if necessary
+ /// @param bar The bar you want to foo
+ void foo (int bar);
+ </pre></p>
+
+ <li>All binary options for ACE and TAO should be specified in
+ terms of the integral values 0 and 1, rather than "true" and
+ "false" or "yes" and "no". All TAO options should be
+ documented in the <A HREF="../TAO/docs/Options.html">online
+ TAO options document</A>. <P>.
+
+ </ul>
+
+ <li><strong>Preprocessor</strong><p>
+ <ul>
+ <li>Never #include standard headers directly, except in a few
+ specific ACE files, <em>e.g.</em>, OS.h and stdcpp.h. Let
+ those files #include the correct headers. If you do not do
+ this, your code will not compile with the Standard C++ Library.<p>
+
+ <li>Always use <strong><code>#if defined (MACRONAME)</code></strong>
+ to test if a macro is defined, rather than the simpler
+ <strong><code>#if MACRONAME</code></strong>. Doxygen requires this.
+ The one exception to this the macros used to prevent multiple
+ inclusion of header files, as shown below.
+
+ <li>Always follow a preprocessor <strong><code>#endif</code></strong>
+ with a <strong><code>/* */</code></strong> C-style comment. Using
+ C-style comments with preprocessor code is required for some old
+ compilers. It should correspond to the condition in the matching
+ <strong><code>#if</code></strong> directive. For example,
+ <pre>
+ #if defined (ACE_HAS_THREADS)
+ # if defined (ACE_HAS_STHREADS)
+ # include /**/ &lt;synch.h&gt;
+ # include /**/ &lt;thread.h&gt;
+ # define ACE_SCOPE_PROCESS P_PID
+ # define ACE_SCOPE_LWP P_LWPID
+ # define ACE_SCOPE_THREAD (ACE_SCOPE_LWP + 1)
+ # else
+ # define ACE_SCOPE_PROCESS 0
+ # define ACE_SCOPE_LWP 1
+ # define ACE_SCOPE_THREAD 2
+ # endif /* ACE_HAS_STHREADS */
+ #endif /* ACE_HAS_THREADS */
+ </pre><p>
+
+ <li>Be sure to put spaces around comment delimiters, e.g.,
+ <strong><code>char * /* foo */</code></strong> instead of
+ <strong><code>char */*foo*/</code></strong>. MS VC++
+ complains otherwise.<p>
+
+ <li>Always insert a <strong><code>/**/</code></strong> between an
+ <strong><code>#include</code></strong> and
+ <strong><code>filename</code></strong>, for system headers and
+ <strong><code>ace/pre.h</code></strong> and
+ <strong><code>ace/post.h</code></strong> as
+ shown in the above example. This avoids dependency problems
+ with Visual C++ and prevents Doxygen from including the
+ headers in the file reference trees. <p>
+
+ <li>Be very careful with names of macros, <code>enum</code> values, and variables
+ It's always best to prefix them with something like <code>ACE_</code>
+ or <code>TAO_</code>. There are too many system headers out
+ there that <code>#define</code> <code>OK</code>, <code>SUCCESS</code>,
+ <code>ERROR</code>, <code>index</code>, <code>s_type</code>,
+ and so on.<p>
+
+ <li>When using macros in an arithmetic expression, be sure to test
+ that the macro is defined, using <code>defined(<em>macro</em>)</code> before specifying
+ the expression. For example:
+<pre>
+#if __FreeBSD__ &lt; 3
+</pre>
+
+will evaluate true on any platform where <code>__FreeBSD__</code> is
+not defined. The correct way to write that guard is:
+<pre>
+#if defined (__FreeBSD__) && __FreeBSD__ &lt; 3
+</pre>
+
+If using g++, problems like this can be flagged as a warning by using the "<code>-Wundef</code>" command line option.
+
+ <li>Try to centralize <code>#ifdef</code>s with <code>typedef</code>s
+ and <code>#define</code>s. For example, use this:
+ <pre>
+ #if defined(ACE_PSOS)
+ typedef long ACE_NETIF_TYPE;
+ # define ACE_DEFAULT_NETIF 0
+ #else /* ! ACE_PSOS */
+ typedef const TCHAR* ACE_NETIF_TYPE;
+ # define ACE_DEFAULT_NETIF ASYS_TEXT("le0")
+ #endif /* ! ACE_PSOS */
+ </pre><p>
+
+ instead of:
+
+ <pre><p>
+ #if defined (ACE_PSOS)
+ // pSOS supports numbers, not names for network interfaces
+ long net_if,
+ #else /* ! ACE_PSOS */
+ const TCHAR *net_if,
+ #endif /* ! ACE_PSOS */
+ </pre><p>
+
+ <li>Protect header files against multiple inclusion with this
+ construct:
+ <pre>
+ #ifndef FOO_H
+ #define FOO_H
+
+ [contents of header file]
+
+ #endif /* FOO_H */
+ </pre><p>
+
+ This exact construct (note the <code>#ifndef</code>)
+ is optimized by many compilers such they only open the
+ file once per compilation unit. Thanks to Eric C. Newton
+ &lt;ecn@smart.net&gt; for pointing that out.<p>
+
+ If the header <code>#include</code>s an ACE library header,
+ then it's a good idea to include the <code>#pragma once</code>
+ directive:
+ <pre>
+ #ifndef FOO_H
+ #define FOO_H
+
+ #include "ace/ACE.h"
+ #if !defined (ACE_LACKS_PRAGMA_ONCE)
+ # pragma once
+ #endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ [contents of header file]
+
+ #endif /* FOO_H */
+ </pre><p>
+
+ <code>#pragma once</code> must be protected, because some
+ compilers complain about it. The protection depends on
+ <code>ACE_LACKS_PRAGMA_ONCE</code>, which is defined in
+ some ACE config headers. Therefore, the protected
+ <code>#pragma once</code> construct should only be used after
+ an <code>#include</code> of an ACE library header. Note that
+ many compilers enable the optimization if the <code>#ifndef</code>
+ protection construct is used, so for them, <code>#pragma once</code>
+ is superfluous.<p>
+
+ <strong>No</strong> code can appear after the final
+ <code>#endif</code> for the optimization to be effective and
+ correct.<p>
+
+ <li><p>Files that contain parametric classes should follow this style:
+ <pre>
+ #ifndef FOO_T_H
+ #define FOO_T_H
+
+ #include "ace/ACE.h"
+ #if !defined (ACE_LACKS_PRAGMA_ONCE)
+ # pragma once
+ #endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ // Put your template declarations here...
+
+ #if defined (__ACE_INLINE__)
+ #include "Foo_T.inl"
+ #endif /* __ACE_INLINE__ */
+
+ #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+ #include "Foo_T.cpp"
+ #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+ #pragma implementation "Foo_T.cpp"
+ #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+ #endif /* FOO_T_H */
+</pre></p>
+ <p>
+ Notice that some compilers need to see the code of the template,
+ hence the <code>.cpp</code> file must be included from the
+ header file.
+ </p>
+ <p>
+ To avoid multiple inclusions of the <code>.cpp</code> file it
+ should also be protected as in:
+ <pre>
+ #ifndef FOO_T_CPP
+ #define FOO_T_CPP
+
+ #include "Foo_T.h"
+ #if !defined (ACE_LACKS_PRAGMA_ONCE)
+ # pragma once
+ #endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ #if !defined (__ACE_INLINE__)
+ #include "ace/Foo_T.inl"
+ #endif /* __ACE_INLINE__ */
+
+ // put your template code here
+
+ #endif /* FOO_T_H */
+</pre></p>
+ <p>Finally, you may want to include the template header file from a
+ non-template header file (check
+ <code>$ACE_ROOT/ace/Synch.h</code>); in such a case the template
+ header should be included <strong>after</strong> the inline
+ function definitions, as in:</p>
+ <p><pre>
+ #ifndef FOO_H
+ #define FOO_H
+
+ #include "ace/ACE.h"
+ #if !defined (ACE_LACKS_PRAGMA_ONCE)
+ # pragma once
+ #endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ // Put your non-template declarations here...
+
+ #if defined (__ACE_INLINE__)
+ #include "Foo.inl"
+ #endif /* __ACE_INLINE__ */
+
+ #include "Foo_T.h"
+
+ #endif /* FOO_H */
+</pre></p></li>
+
+ <li>Avoid <code>#include &lt;math.h&gt;</code> if at all possible.
+ The <code>/usr/include/math.h</code> on SunOS 5.5.1 through 5.7
+ defines a struct name <strong>exception</strong>, which complicates
+ use of exceptions.<p>
+
+ <li>On a <code>.cpp</code> file always include the corresponding
+ header file <em>first</em>, like this:<p>
+<pre>
+ // This is Foo.cpp
+
+ #include "Foo.h"
+ #include "tao/Bar.h"
+ #include "ace/Baz.h"
+
+ // Here comes the Foo.cpp code....
+</pre><p>
+
+ In this way we are sure that the header file is self-contained
+ and can be safely included from some place else.
+
+ <li>In the TAO library <strong>never</strong> include
+ <code>&lt;corba.h&gt</code>, this file should only be included
+ by the user and introduces cyclic dependencies in the library
+ that we must avoid.<p>
+
+ <li>Never include a header file when a forward reference will do,
+ remember that templates can be forward referenced too.
+ Consult your favorite C++ book to find out when you must include
+ the full class definition.<p>
+ </ul>
+
+ <li><strong>C++ Syntax and Constructs</strong><p>
+ <ul>
+ <li><strong><code>for</code></strong> loops should look like:
+ <pre>
+ for (unsigned int i = 0; i &lt; count; ++i)
+ ++total;
+ </pre>
+
+ Similarly, <strong><code>if</code></strong> statements should have
+ a space after the "<strong>if</strong>", and no spaces just after
+ the opening parenthesis and just before the closing parenthesis.<p>
+
+ If there's just one statement in the loop or if statement
+ there's no need to use additional braces.
+
+ <li>If a loop index is used after the body of the loop, it
+ <strong>must</strong> be declared before the loop. For example,
+
+ <pre>
+ size_t i = 0;
+ for (size_t j = 0; file_name [j] != '\0'; ++i, ++j)
+ {
+ if (file_name [j] == '\\' && file_name [j + 1] == '\\')
+ ++j;
+
+ file_name [i] = file_name [j];
+ }
+
+ // Terminate this string.
+ file_name [i] = '\0';
+ </pre><p>
+
+ <li>Prefix operators are generally more efficient than postfix
+ operators. Therefore, they are preferred over their postfix
+ counterparts where the expression value is not used.<p>
+
+ Therefore, use this idiom for iterators, with prefix operator
+ on the loop index:
+ <pre>
+ ACE_Ordered_MultiSet&lt;int&gt; set;
+ ACE_Ordered_MultiSet_Iterator&lt;int&gt; iter(set);
+
+ for (i = -10; i &lt; 10; ++i)
+ set.insert (2 * i + 1);
+
+ </pre>
+ rather than the postfix operator:
+ <pre>
+ for (i = -10; i &lt; 10; i++)
+ set.insert (2 * i + 1);
+ </pre><p>
+
+ <li>Prefer using <strong> <code> if (...) else .... </code> </strong>
+ instead of <strong> <code> ?: </code> </strong> operator. It is a lot
+ less error prone, and will help you avoid bugs caused due to the
+ precedence of <strong> <code> ?: </code> </strong>, compared with other
+ operators in an expression.
+
+ <li>When a class provides <code>operator==</code>, it must also provide
+ <code>operator!=</code>. Also, both these operators must be
+ <code>const</code> and return <code>bool</code>.
+
+ <li>Avoid unnecessary parenthesis. We're not writing Lisp :-)<p>
+
+ <li>Put inline member functions in a <strong><code>.inl</code></strong>
+ file. That file is conditionally included by both the
+ <strong><code>.h</code></strong> file, for example:<p>
+
+ <pre>
+ class ACE_Export ACE_High_Res_Timer
+ {
+ [...]
+ };
+
+ #if defined (__ACE_INLINE__)
+ #include "ace/High_Res_Timer.inl"
+ #endif /* __ACE_INLINE__ */
+ </pre><p>
+
+ and <strong><code>.cpp</code></strong> file:<p>
+
+ <pre>
+ #define ACE_BUILD_DLL
+ #include "ace/High_Res_Timer.h"
+
+ #if !defined (__ACE_INLINE__)
+ #include "ace/High_Res_Timer.inl"
+ #endif /* __ACE_INLINE__ */
+
+ ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer)
+ </pre><p>
+
+ <strong>NOTE:</strong> It is very important to ensure than an
+ inline function will not be used before its definition is seen.
+ Therefore, the inline functions in the .inl file should be arranged
+ properly. Some compilers, such as <code>g++</code> with the
+ <code>-Wall</code> option, will issue warnings for violations.<p>
+
+ <li>Some inlining heuristics:<p>
+ <ul>
+ <li>One liners should almost always be inline, as in:
+<pre>
+ACE_INLINE
+Foo::bar ()
+{
+ this-&gt;baz ();
+}
+</pre><p>
+
+ <li>The notable exception is virtual functions, which should
+ generally not be inlined.<p>
+
+ <li>Big (more than 10 lines) and complex function (more than one if ()
+ statement, or a switch, or a loop) should not be inlined.<p>
+
+ <li>Medium sized stuff depends on how performance critical it is.
+ If you know that it's in the critical path, then make it
+ inline. When in doubt, profile the code.<p>
+ </ul>
+
+ <li><code>ACE_Export</code> must be inserted between the
+ <code>class</code> keyword and class name for all classes that
+ are exported from libraries, as shown in the example above.
+ <strong>However</strong>, do <strong>not</strong> use
+ <code>ACE_Export</code> for template classes or classes that
+ are not used out of the ACE library, for example.!<p>
+
+ <li>Mutators and accessors should be of this form:<p>
+
+ <pre>
+ /// Sets @c object_addr_ cache from @c host and @c port.
+ void object_addr (const ACE_INET_Addr &);
+
+ /// Returns the ACE_INET_Addr for this profile.
+ const ACE_INET_Addr &object_addr const (void);
+ </pre><p>
+
+ instead of the "set_" and "get_" form.<p>
+
+ <li>Never use <strong><code>delete</code></strong> to deallocate
+ memory that was allocated with <strong><code>malloc</code></strong>.
+ Similarly, never associate <strong><code>free</code></strong> with
+ <strong><code>new</code></strong>.
+ <strong><code>ACE_NEW</code></strong> or
+ <strong><code>ACE_NEW_RETURN</code></strong> should be used to
+ allocate memory, and <strong><code>delete</code></strong> should
+ be used to deallocate it. And be careful to use the correct form,
+ <strong><code>delete</code></strong> or
+ <strong><code>delete []</code></strong> to correspond to the
+ allocation.<p>
+
+ <li>Don't check for a pointer being 0 before deleting it. It's
+ always safe to delete a 0 pointer. If the pointer is visible
+ outside the local scope, it's often a good idea to 0 it
+ _after_ deleting it. Note, the same argument applies to
+ free().<p>
+
+ <li>Always use <strong><code>ACE_NEW</code></strong> or
+ <strong><code>ACE_NEW_RETURN</code></strong> to allocate memory,
+ because they check for successful allocation and set errno
+ appropriately if it fails.<p>
+
+ <li>Never compare or assign a pointer value with <strong>NULL</strong>;
+ use <strong>0</strong> instead. The language allows any pointer to
+ be compared or assigned with <strong>0</strong>. The definition
+ of <strong>NULL</strong> is implementation dependent, so it is
+ difficult to use portably without casting.<p>
+
+ <li>Never cast a pointer to or from an <strong><code>int</code></strong>
+ or a <strong><code>long</code></strong>. On all currently supported
+ ACE platforms, it is safe to cast a pointer to or from
+ <strong><code>intptr_t</code></strong> or
+ <strong><code>uintptr_t</code></strong> (include ace/Basic_Types.h).<p>
+
+ <li>Be very careful when selecting an integer type that must be a
+ certain size, <em>e.g.</em>, 4 bytes. <strong>long</strong> is
+ not 4 bytes on all platforms; it is 8 bytes on many 64-bit
+ machines. ACE_UINT32 is always 4 bytes, and ACE_UINT64 is
+ always 8 bytes.<p>
+
+ <li>If a class has any virtual functions, and its destructor is
+ declared explicitly in the class, then the destructor should
+ <strong>always</strong> be virtual as well. And to support
+ compiler activities such as generation of virtual tables and,
+ in some cases, template instantiation, the virtual destructor
+ should <strong>not be inline</strong>. (Actually, any non-pure
+ virtual function could be made non-inline for this purpose. But,
+ for convenience, if its performance is not critical, it is usually
+ easiest just to make the virtual destructor non-inline.)<p>
+
+
+ <li><a name="ACE_Time_Value example">Avoid default arguments</a>
+ unless there's a good reason. For an example of how they got
+ us into a jam is:
+ <pre>
+ ACE_Time_Value (long sec, long usec = 0);
+ </pre>
+
+ So, <code>ACE_Time_Value (2.5)</code> has the unfortunate
+ effect of coercing the 2.5 to a long with value 2. That's
+ probably not what the programmer intended, and many compilers
+ don't warn about it.<p>
+
+ A nice fix would be to add an <code>ACE_Time_Value (double)</code>
+ constructor. But, that would cause ambiguous overloading
+ due to the default value for the second argument of
+ <code>ACE_Time_Value (long sec, long usec = 0)</code>.
+ We're stuck with <code>ACE_Time_Value</code>, but now we
+ know that it's easy to avoid.<p>
+
+ <li>Constructor initializers must appear in the same order as
+ the data members are declared in the class header. This avoids
+ subtle errors, because initialization takes place in the order
+ of member declaration.<p>
+
+ <li>Initialization is usually cleaner than assignment, especially
+ in a conditional. So, instead of writing code like this:
+
+ <pre>
+ ssize_t n_bytes;
+
+ // Send multicast of one byte, enough to wake up server.
+ if ((n_bytes = multicast.send ((char *) &reply_port,
+ sizeof reply_port)) == -1)
+ </pre>
+
+ Write it like this:
+
+ <pre>
+ ssize_t n_bytes = multicast.send ((char *) &reply_port,
+ sizeof reply_port)
+
+ // Send multicast of one byte, enough to wake up server.
+ if (n_bytes == -1)
+ </pre><p>
+
+ But, beware if the initialization is of a static variable.
+ A static variable is only initialized the first time its
+ declaration is seen. Of course, we should avoid using
+ static (and non-constant) variables at all.<p>
+
+ <li>It is usually clearer to write conditionals that have
+ both branches without a negated condition. For example,<p>
+
+ <pre>
+ if (test)
+ {
+ // true branch
+ }
+ else
+ {
+ // false branch
+ }
+ </pre><p>
+
+ is preferred over:<p>
+
+ <pre>
+ if (! test)
+ {
+ // false test branch
+ }
+ else
+ {
+ // true test branch
+ }
+ </pre><p>
+
+ <li>If a cast is necessary, avoid use of C-style "sledgehammer"
+ casts. Use standard C++ casts
+ (e.g. <code>static_cast&lt;int&gt; (foo)</code>) instead.<p>
+
+ <li>In general, if instances of a class should not be copied,
+ then a private copy constructor and assignment operator should
+ be declared for the class, but not implemented. For example:
+
+ <pre>
+ // Disallow copying by not implementing the following . . .
+ ACE_Object_Manager (const ACE_Object_Manager &);
+ ACE_Object_Manager &operator= (const ACE_Object_Manager &);
+ </pre><p>
+
+ If the class is a template class, then the
+ <code>ACE_UNIMPLEMENTED_FUNC</code> macro should be used:
+
+ <pre>
+ // = Disallow copying...
+ ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS&lt;TYPE&gt; &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS&lt;TYPE&gt; &))
+ </pre><p>
+
+ <code>ACE_UNIMPLEMENTED_FUNC</code> can be used with non-template
+ classes as well. Though for consistency and maximum safety, it
+ should be avoided for non-template classes.<p>
+
+ <li>Never use <code>BOOL</code>, or similar types.
+ (<code>ACE_CDR::Boolean</code> and
+ <code>CORBA::Boolean</code> are acceptable). Use the
+ standard C++ <code>bool</code> for boolean variables, instead.<p>
+
+ <li>Functions should always return -1 to indicate failure, and
+ 0 or greater to indicate success.<p>
+
+ <li>Separate the code of your templates from the code for
+ non-parametric classes: some compilers get confused when
+ template and non-template code is mixed in the same file.<p>
+
+ <li>It's a good idea to specify the include path (with <code>-I</code>)
+ to include any directory which contains files with template
+ definitions. The Compaq Tru64 cxx <code>-ptv</code> compiler option
+ may help diagnose missing template instantiation problems.<p>
+
+ <li>When referring to member variables and functions, use
+ <code>this-&gt;</code><em>member</em>. This makes it clear to the
+ reader that a class member is being used. It also makes it crystal
+ clear to the compiler which variable/function you mean in cases
+ where it might make a difference. <p>
+
+ <li>Don't use template template arguments, this C++ construct is not
+ supported by the HP aCC 3.70 compiler at this moment. For example the
+ following template decleration is one that just doesn't work.
+ <pre>
+ template&lt;typename S_var, size_t BOUND, template &lt;typename&gt; class Insert_Policy&gt; class A {};
+ </pre>
+ </ul>
+ <li><strong>I/O</strong><p>
+ <ul>
+ <li>Use <strong><code>ACE_DEBUG</code></strong> for printouts,
+ and <strong><code>ACE_OS::fprintf ()</code></strong> for
+ file I/O. Avoid using iostreams because of implementation
+ differences across platforms.<p>
+ <li>After attempting to open an existing file, always check for success.
+ Take appropriate action if the open failed.<p>
+ <li>Notice that <strong><code>ACE_DEBUG</code></strong> and
+ <strong><code>ACE_ERROR</code></strong> don't support
+ <code>%ld</code> of any other multicharacter format.<p>
+ </ul>
+
+ <li><strong>WCHAR conformity</strong><p>
+
+ <ul>
+ <li>For ACE, use <code>ACE_TCHAR</code> instead of char for strings and <code>ACE_TEXT()</code>
+ around string literals. Exceptions are <code>char</code>
+ arrays used for data and strings that need to remain as 1
+ byte characters.
+
+ <li>If you have a char string that needs to be converted to <code>ACE_TCHAR</code>,
+ use the <code>ACE_TEXT_CHAR_TO_TCHAR()</code> macro. If you have a <code>ACE_TCHAR</code>
+ string that needs to be converted to a <code>char</code> string, use the
+ <code>ACE_TEXT_ALWAYS_CHAR()</code> macro
+
+ <li>Do not use the Win32 <code>TCHAR</code> macros. The wide character-ness of ACE
+ is separate from UNICODE and _UNICODE.
+
+ <li>For TAO, don't use <code>ACE_TCHAR</code> or <code>ACE_TEXT</code>. The CORBA specification
+ defines APIs as using char. So most of the time there is no need
+ to use wide characters.
+ </ul><P>
+
+ <li><strong>Exceptions</strong><p>
+
+ <ul>
+ <li>There are many ways of throwing and catching exceptions. The
+ code below gives several examples. Note that each method has
+ different semantics and costs. Whenever possible, use the
+ first approach.<p>
+
+ <pre>
+ #include "iostream.h"
+
+ class exe_foo
+ {
+ public:
+ exe_foo (int data) : data_ (data)
+ { cerr &lt;&lt; "constructor of exception called" &lt;&lt; endl; }
+ ~exe_foo ()
+ { cerr &lt;&lt; "destructor of exception called" &lt;&lt; endl; }
+ exe_foo (const exe_foo& foo) : data_ (foo.data_)
+ { cerr &lt;&lt; "copy constructor of exception called"
+ &lt;&lt; endl; }
+ int data_;
+ };
+
+
+ void
+ good (int a)
+ {
+ throw exe_foo (a);
+ };
+
+ void
+ bad (int a)
+ {
+ exe_foo foo (a);
+ throw foo;
+ };
+
+ int main ()
+ {
+ cout &lt;&lt; endl &lt;&lt; "First exception" &lt;&lt; endl
+ &lt;&lt; endl;
+ try
+ {
+ good (0);
+ }
+ catch (exe_foo &foo)
+ {
+ cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
+ &lt;&lt; endl;
+ }
+
+ cout &lt;&lt; endl &lt;&lt; "Second exception" &lt;&lt; endl
+ &lt;&lt; endl;
+ try
+ {
+ good (0);
+ }
+ catch (exe_foo foo)
+ {
+ cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
+ &lt;&lt; endl;
+ }
+
+ cout &lt;&lt; endl &lt;&lt; "Third exception" &lt;&lt; endl
+ &lt;&lt; endl;
+ try
+ {
+ bad (1);
+ }
+ catch (exe_foo &foo)
+ {
+ cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
+ &lt;&lt; endl;
+ }
+
+ cout &lt;&lt; endl &lt;&lt; "Fourth exception" &lt;&lt; endl
+ &lt;&lt; endl;
+ try
+ {
+ bad (1);
+ }
+ catch (exe_foo foo)
+ {
+ cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
+ &lt;&lt; endl;
+ }
+
+ return 0;
+ }
+ </pre>
+
+ Output is: <p>
+
+ <pre>
+ First exception
+
+ constructor of exception called
+ exception caught: 0
+ destructor of exception called
+
+ Second exception
+
+ constructor of exception called
+ copy constructor of exception called
+ exception caught: 0
+ destructor of exception called
+ destructor of exception called
+
+ Third exception
+
+ constructor of exception called
+ copy constructor of exception called
+ destructor of exception called
+ exception caught: 1
+ destructor of exception called
+
+ Fourth exception
+
+ constructor of exception called
+ copy constructor of exception called
+ destructor of exception called
+ copy constructor of exception called
+ exception caught: 1
+ destructor of exception called
+ destructor of exception called
+
+ </pre>
+
+ </ul><p>
+
+ <li><strong>Compilation</strong><p>
+ <ul>
+ <li>Whenever you add a new test or example to ACE or TAO, make
+ sure that you modify the MPC file in the parent directory.
+ This will make sure that your code gets compiled on a
+ regular basis.<p>
+ </ul><p>
+</ul>
+
+<hr>
+<h3><a href="http://www.cs.wustl.edu/~schmidt/ACE-overview.html">ACE</a>
+ Shared Libary Guidelines</h3>
+ <ul>
+ <li>
+ <p>
+ Create a separate export macro for each dynamic library. A
+ header file containing the export macro and additional
+ support macros should be generated by using the <a
+ href="../bin/generate_export_file.pl">ACE_wrappers/bin/generate_export_file.pl</a> Perl script.
+ </p>
+ </li>
+ <li>
+ <p>
+ Make sure that your classes, structures and free functions
+ are annotated with this export macro. The only exceptions
+ are pure template classes, structures and free functions.
+ </p>
+ <p>
+ Only classes (and structures, free functions, etc) that are
+ part of the library public interface must be exported
+ (e.g. declared with an export macro). Those that are only
+ meant to be used internally need not be exported,
+ particularly for g++ <code>&gt;=</code>4.0 since doing so
+ defeats some neat optimizations. Here's a common case in
+ where an export macro is generally used unnecessarily:
+ </p>
+ <blockquote>
+ <pre>
+class FooExport Foo
+{
+public:
+ virtual void kung_fu () = 0;
+};
+
+class FooExport Bar : public Foo
+{
+public:
+ virtual void kung_fu () { ... }
+};
+
+class FooExport FooFactory
+{
+public:
+ Foo * make_foo ()
+ {
+ // Assume that this implementation is hidden from
+ // the application and is consequently out of line.
+ return new Bar();
+ }
+};
+ </pre>
+ </blockquote>
+ <p>
+ Here the application is only meant to invoke operations
+ through a pointer or reference to the abstract base class
+ "<code>Foo</code>" created by the "<code>FooFactory</code>",
+ not the "<code>Bar</code>" subclass. In this case,
+ exporting "<code>Bar</code>" is unnecessary. If your
+ concrete class is meant to be used outside of the shared
+ library (e.g. as a template parameter, within a
+ <code>dynamic_cast&lt;&gt;</code>, etc) you must then export
+ it. Otherwise, avoid doing so if you can.
+ </p>
+ </li>
+ <li>
+ <p>
+ Make sure that you specify that you are creating a dynamic
+ library in your <a href="../MPC/README">MPC</a> file by adding
+ a <code>sharedname</code> tag.
+ </p>
+ </li>
+ <li>
+ <p>
+ Make sure that you add the <code>FOO_BUILD_DLL</code>
+ preprocessor symbol to the <code>dynamicflags</code> of the
+ MPC project that is used to build a library. Note that the
+ export files are setup such that when this macro is defined,
+ the symbols are exported, otherwise they are imported. The
+ default behaviour is to set up for import so that clients of
+ your library don't need to worry about arcane build flags
+ like <code>FOO_BUILD_DLL</code> in their build setup. This
+ ties back to the first item.
+ </p>
+ </li>
+ <li>
+ <p>
+ When you specify the order of libraries to link to, make
+ sure that the dependent libraries come after the libraries
+ which depend on them, i.e., your link line should always
+ contain <code>-lDependsOnFoo -lFoo</code>. Note that this
+ is not a requirement on GNU/Linux but linkers on other
+ platforms are not as forgiving.
+ </p>
+ </li>
+ <li>
+ <p>
+ Use the <code>ACE_SINGLETON_DECLARE</code> macro to declare
+ a class as a singleton. Declare exported (i.e. default
+ visibility) singleton templates prior to typedefs that
+ reference them. This prevents g++ 4.0 from silently making
+ their visibility hidden (see <a
+ href="http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=2260">Bug 2260</a> for details).
+ </p>
+ </li>
+ <li>
+ <p>
+ Avoid inlining virtual functions in classes that must be
+ exported since doing so can cause RTTI related problems
+ (e.g. <code>dynamic_cast&lt;&gt; failures</code>) when using
+ g++ &gt;= 4.0 due to our use of that compiler's "visibility
+ attribute" support that is tied in to the export macros.
+ This includes virtual destructors automatically created by
+ the compiler when you don't declare one. Make sure you
+ define a no-op out-of-line virtual destructor if your base
+ class has a virtual destructor since you may otherwise run
+ into the mentioned RTTI problems.
+ </p>
+ </li>
+ </ul>
+
+
+<hr>
+<h3><a href="http://www.cs.wustl.edu/~schmidt/ACE-overview.html">ACE</a>
+ Usage Guidelines</h3>
+<ul>
+ <li>Always use the <strong><code>ACE_OS</code></strong>
+ namespace functions instead of bare OS system calls.<p>
+
+ <li>As a general rule, the only functions that should go into the
+ <strong><code>ACE_OS</code></strong> namespace are ones that
+ have direct equivalents on some OS platform. Functions that
+ are extensions should go in the
+ <strong><code>ACE</code></strong> namespace.<p>
+
+ <li>Use the <strong><code>ACE_SYNCH_MUTEX</code></strong> macro,
+ instead of using one of the specific mutexes, such as
+ <strong><code>ACE_Thread_Mutex</code></strong>. This provides
+ portability between threaded and non-threaded platforms.<p>
+
+ <li>Avoid creating a static instance of user-defined (class) type.
+ Instead, either create it as an
+ <strong><code>ACE_Singleton</code></strong>,
+ <strong><code>ACE_TSS_Singleton</code></strong>, or as an
+ <strong><code>ACE_Cleanup</code></strong> object. See the
+ <strong>ACE</strong>
+ <a href="../ace/Singleton.h"><code>Singleton.h</code></a>,
+ <a href="../ace/Object_Manager.h"><code>Object_Manager.h</code></a>, and
+ <a href="../ace/Managed_Object.h"><code>Managed_Object.h</code></a>
+ header files for more information.<p>
+
+ Static instances of built-in types, such as
+ <strong><code>int</code></strong> or any pointer type, are fine.<p>
+
+ Construction of static instance of a user-defined type should
+ <em>never</em> spawn threads. Because order of construction of
+ statics across files is not defined by the language, it is usually
+ assumed that only one thread exists during static construction.
+ This allows statics suchs as locks to be safely created. We do not
+ want to violate this assumption.<p>
+
+ <li>Do not use C++ exception handling directly. Some platforms do
+ not support it. And, it can impose an execution speed penalty.
+ Instead use the TAO/ACE try/catch macros.<p>
+
+ <li>Because ACE does not use exception handling, dealing with
+ failures requires a bit of care. This is especially true
+ in constructors. Consider the following approach:
+
+ <pre>
+ ACE_NEW_RETURN (this-&gt;name_space_, LOCAL_NAME_SPACE, -1);
+
+ if (ACE_LOG_MSG-&gt;op_status () != 0)
+ ....
+ </pre>
+
+ This snip of code is from
+ <a href="../ace/Naming_Context.cpp"><code>ACE_Naming_Context</code></a>.
+ All failed constructors in ACE (should) call ACE_ERROR. This sets
+ the thread-specific <strong>op_status</strong>, which can be checked
+ by the caller. This mechanism allows the caller to check for a failed
+ constructor without the requiring the constructor to throw
+ exceptions.<p>
+
+ <LI>Another consequence of ACE's avoidance of exception handling is
+ that you should use <CODE>open()</CODE> methods on classes that
+ perform initializations that can fail. This is because <CODE>open()</CODE>
+ returns an error code that's easily checked by the caller,
+ rather than relying on constructor and thread-specific status
+ values. <P>
+
+ <li>Avoid using the C++ Standard Template Library (STL) in our
+ applications. Some platforms do not support it yet. It is
+ safe to use the STL generic algoritms. The following have been
+ used already and don't seem to cause any portability issues:
+ <pre>
+ std::swap
+ std::for_each
+ std::fill
+ std::generate
+ std::transform
+ std::copy
+ </pre><p>
+
+ <li>Be <em>very</em> careful with <code>ACE_ASSERT</code>. It
+ must only be used to check values; it may never be used to
+ wrap a function call, or contain any other side effect. That's
+ because the statement will disappear when ACE_NDEBUG is enabled.
+ For example, this code is BAD:
+ <pre>
+ ACE_ASSERT (this-&gt;next (retv) != 0); // BAD CODE!
+ </pre>
+
+ Instead, the above should be coded this way:
+
+ <pre>
+ int const result = this-&gt;next (retv);
+ ACE_ASSERT (result != 0);
+ ACE_UNUSED_ARG (result);
+ </pre><p>
+
+ <li>Never put side effects in <code>ACE_DEBUG</code> code:
+ <pre>
+ ACE_DEBUG ((LM_DEBUG,
+ "handling signal: %d iterations left\n",
+ --this-&gt;iterations_)); // BAD CODE!
+ </pre>
+
+ Note that this won't work correctly if <code>ACE_NDEBUG</code> is
+ defined, for the same reason that having side-effects in
+ <code>ACE_ASSERT</code>s won't work either, <em>i.e.</em>, because
+ the code is removed.<p>
+
+ <li>Be <strong>very</strong> careful with the code that you put
+ in a signal handler. On Solaris, the man pages document systems
+ calls as being Async-Signal-Safe if they can be called from signal
+ handlers. In general, it's best to just set a flag in a signal
+ handler and take appropriate action elsewhere. It's also best
+ to avoid using signals, especially asynchronous signals.<p>
+
+ <li>Immediately after opening a temporary file, unlink it. For
+ example:
+ <pre><code>
+ ACE_HANDLE h = open the file (filename);
+
+ ACE_OS::unlink (filename);
+ </code></pre><p>
+
+ This avoids leaving the temporary file even if the program crashes.<p>
+
+ <li>Be sure to specify the <code>THR_BOUND</code> thread creation
+ flag for time-critical threads. This ensures that the thread competes
+ for resources globally on Solaris. It is harmless on other platforms.<p>
+</ul>
+
+
+<hr>
+<h3><a href="http://www.cs.wustl.edu/~schmidt/ACE-overview.html">Other
+ ACE</a> and
+ <a href="http://www.cs.wustl.edu/~schmidt/TAO-overview.html">TAO</a>
+ Guidelines</h3>
+<ul>
+ <li>When enhancing, updating, or fixing ACE or TAO, always:
+ <ol>
+ <li>Test your change on at least Windows and Linux before commiting.
+ After commiting watch the scoreboard to catch errors your change
+ may be related to on other platforms.
+ <li>Add an entry to the appropriate ChangeLog. TAO and some
+ ACE subdirectories, such as <a href="../ASNMP">ASNMP</a>,
+ <a href="../apps/JAWS">JAWS</a>, and
+ <a href="../apps/gperf">gperf,</a> have their
+ own ChangeLogs. If you don't use one of those, use the
+ <a href="../ChangeLog">ChangeLog</a> in the top-level
+ <a href="..">ACE_wrappers</a> directory. A ChangeLog entry should
+ have the form:
+ <pre>&lt;tab&gt; * dir/file.ext [(methods)]: description...</pre>
+ If you have a number of files, the names should be on separate lines.
+ In this case, it's also ok to start the description on a new line
+ indented to "dir."
+ <li>Commit your change using a message of this form:<p>
+<code>
+ChangeLogTag: Thu Jul 22 09:55:10 UTC 1999 David L. Levine
+ &lt;levine@cs.wustl.edu&gt;
+</code>
+ <li>If the change is in response to a request by someone else:
+ <ol>
+ <li>Make sure that person is acknowledged in
+ <a href="../THANKS">ACE_wrappers/THANKS</a>, and<p>
+ <li>Respond to that person.<p>
+ </ol>
+ </ol>
+
+ <li><strong>Never</strong> add copyrighted, confidential, or otherwise
+ restricted code to the ACE or TAO distributions without reviewing
+ the situation with DOC management (i.e. Doug Schmidt). You will also
+ most likely need to get written permission from the owner. The
+ particular language and form needed will be relayed to you after
+ discussing it with DOC management.<p>
+</ul>
+
+
+<hr>
+<h3>SVN Usage Guidelines</h3>
+<ul>
+ <li>Always make sure that a change builds and executes correctly
+ on at least one platform before checking it into the SVN repository.
+ All changes <strong>must</strong> be tested with g++ before commiting.
+ That means you may need to test on at least two platforms.<p>
+</ul>
+
+
+<hr>
+<h3>Script Guidelines</h3>
+<ul>
+ <li>In general, it's best to write scripts in Perl. It's
+ OK to use Bourne shell. Never, never, never use csh, ksh,
+ bash, or any other kind of shell.<p>
+
+ <li>Follow the Perl style guide guide as closely as
+ possible. <code>man perlstyle</code> to view it.
+
+ <li>Don't specify a hard-coded path to Perl itself. Use
+ the following code at the top of the script to pick up
+ perl from the users <code>PATH</code>:<br>
+ <pre>
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+ </pre><p>
+
+ <li>Never, never, never start the first line of a script
+ with "<code>#</code>", unless the first line is "<code>#! /bin/sh</code>".
+ With just "<code>#</code>", t/csh users will spawn a new shell.
+ That will cause their <code>.[t]cshrc</code> to be
+ processed, possibly clobbering a necessary part of
+ their environment.<p>
+
+ <li>If your Perl script relies on features only available
+ in newer versions of Perl, include the a statement similar
+ to the following:<br>
+ <pre>
+ require 5.003;
+ </pre>
+
+ <li>Don't depend on <strong><code>.</code></strong> being
+ in the user's path. If the script spawns another executable
+ that is supposed to be in the current directory, be sure the
+ prefix its filename with <strong><code>.</code></strong>.<p>
+</ul>
+
+
+<hr>
+<h3>Software Engineering Guidelines</h3>
+<ul>
+ <li><strong>Advise</strong>: Keep other developers informed of problems
+ and progress.<p>
+
+ <li><strong>Authorize</strong>: We have contractual obligations to not
+ unilaterally change interfaces. If you need to change or remove an
+ interface, get an OK.<p>
+
+ <li><strong>Minimize</strong> risk: Test all changes. Solicit review of
+ changes.<p>
+
+ <li><strong>Revise</strong> only when necessary: Every change has risk,
+ so avoid making any change unless there is a good reason for it.<p>
+
+ <li><strong>Normalize</strong>: Factor out commonality. For example,
+ maintain a data value in only one place.<p>
+
+ <li><strong>Synthesize</strong>: Build stubs and scaffolding early to
+ simulate the complete system. Maintain a checked-in version of the
+ system that cleanly builds and tests at all times.<p>
+
+ <li><strong>Be available</strong>: Breaking compilation in one
+ platform or another should be avoided (see above),
+ but it is bound to happen when so many platforms are in use.
+ Be available after making a change,
+ if you won't be available for at least 48 hours after the change
+ is made then don't make it!<p>
+</ul>
+
+
+
+<hr>
+<h3><a href="http://www.cs.wustl.edu/~schmidt/rules.html">ACE
+ Design Rules</a></h3>
+
+
+<hr><p>
+ <font size=-1>
+<!-- hhmts start -->
+Last modified: Wed Nov 23 11:00:44 CST 2005
+<!-- hhmts end -->
+ </font><p>
+
+
+
+Back to <A HREF="index.html">ACE Documentation Home</A>.
+
+</body>
+</html>