diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2008-03-04 13:56:48 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2008-03-04 13:56:48 +0000 |
commit | c4078c377d74290ebe4e66da0b4975da91732376 (patch) | |
tree | 1816ef391e42a07929304908ac0e21f4c2f6cb7b /ACE/docs/ACE-guidelines.html | |
parent | 700d1c1a6be348c6c70a2085e559baeb8f4a62ea (diff) | |
download | ATCD-c4078c377d74290ebe4e66da0b4975da91732376.tar.gz |
swap in externals for ACE and TAO
Diffstat (limited to 'ACE/docs/ACE-guidelines.html')
-rw-r--r-- | ACE/docs/ACE-guidelines.html | 1371 |
1 files changed, 0 insertions, 1371 deletions
diff --git a/ACE/docs/ACE-guidelines.html b/ACE/docs/ACE-guidelines.html deleted file mode 100644 index b224d2f841f..00000000000 --- a/ACE/docs/ACE-guidelines.html +++ /dev/null @@ -1,1371 +0,0 @@ -<!-- $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> - - <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>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 <author@email.org> - * - * 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 /**/ <synch.h> - # include /**/ <thread.h> - # 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__ < 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__ < 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 - <ecn@smart.net> 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 <math.h></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><corba.h></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 < count; ++i) - ++total; - </pre> - Though, I prefer to always wrap the body of the loop in braces, - to avoid surprises when other code or debugging statements are - added, and to maintain sanity when the body consists of a macro, - such as an <code>ACE_ASSERT</code> without a trailing semicolon: - <pre> - for (unsigned int i = 0; i < count; ++i) - { - ACE_ASSERT (++total < UINT_MAX;) - } - </pre><p> - - 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> - - <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<int> set; - ACE_Ordered_MultiSet_Iterator<int> iter(set); - - for (i = -10; i < 10; ++i) - set.insert (2 * i + 1); - - </pre> - rather than the postfix operator: - <pre> - for (i = -10; i < 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->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<int> (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<TYPE> &)) - ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &)) - </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-></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<typename S_var, size_t BOUND, template <typename> class Insert_Policy> 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 << "constructor of exception called" << endl; } - ~exe_foo () - { cerr << "destructor of exception called" << endl; } - exe_foo (const exe_foo& foo) : data_ (foo.data_) - { cerr << "copy constructor of exception called" - << endl; } - int data_; - }; - - - void - good (int a) - { - throw exe_foo (a); - }; - - void - bad (int a) - { - exe_foo foo (a); - throw foo; - }; - - int main () - { - cout << endl << "First exception" << endl - << endl; - try - { - good (0); - } - catch (exe_foo &foo) - { - cerr << "exception caught: " << foo.data_ - << endl; - } - - cout << endl << "Second exception" << endl - << endl; - try - { - good (0); - } - catch (exe_foo foo) - { - cerr << "exception caught: " << foo.data_ - << endl; - } - - cout << endl << "Third exception" << endl - << endl; - try - { - bad (1); - } - catch (exe_foo &foo) - { - cerr << "exception caught: " << foo.data_ - << endl; - } - - cout << endl << "Fourth exception" << endl - << endl; - try - { - bad (1); - } - catch (exe_foo foo) - { - cerr << "exception caught: " << foo.data_ - << 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>>=</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<></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://deuce.doc.wustl.edu/bugzilla/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<> failures</code>) when using - g++ >= 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->name_space_, LOCAL_NAME_SPACE, -1); - - if (ACE_LOG_MSG->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->next (retv) != 0); // BAD CODE! - </pre> - - Instead, the above should be coded this way: - - <pre> - int const result = this->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->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>An 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><tab> * 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 - <levine@cs.wustl.edu> -</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> |