From 13b1663c816d5a14af6c4fbf4ea9dd82facc1fa4 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Fri, 3 Aug 2018 16:10:12 -0600 Subject: [PATCH] Fix formatting of our coding conventions. This file used to be a stand-alone HTML file but is now run through doxygen. We need to use different markup for that. --- doc/doxygen/headers/coding_conventions.h | 88 +++++++++--------------- 1 file changed, 32 insertions(+), 56 deletions(-) diff --git a/doc/doxygen/headers/coding_conventions.h b/doc/doxygen/headers/coding_conventions.h index aaeb05eba5..5576ee00cb 100644 --- a/doc/doxygen/headers/coding_conventions.h +++ b/doc/doxygen/headers/coding_conventions.h @@ -34,26 +34,22 @@ code is written, without having to look up the exact definition of something.

deal.II uses clang-format 6.0 to normalize indentation. A style file is provided at - -

+@code
   ${SOURCE_DIR}/.clang-format
-
- +@endcode

Before a commit, you should run - -

-  clang-format -i <file>
-
- +@code + clang-format -i +@endcode on each of your files. This will make sure indentation is conforming to the -style guidelines outlined in this page. Alternatively, you can run - -
+style guidelines outlined in this page.
+
+This is cumbersome. Consequently, and more easily, you can just run
+@code
   make indent
-
-
-in whatever directory you set up the library to be compiled in to indent all +@endcode +in whatever directory you set up the library to be compiled in, to indent all source files that have been changed recently. If you want to make sure that the indenting is correct for all your commits, you might want to set up a pre-commit hook. One way to do so, is to copy @@ -100,7 +96,7 @@ executable.
  • %Function and variable names may not consist of only one or two letters, unless the variable is a pure counting index.
  • -
  • Type aliases (using-declarations) are preferred to +
  • Type aliases (using-declarations) are preferred to typedef-declarations.
  • Use the geometry information in GeometryInfo to get the @@ -141,8 +137,7 @@ executable. non-member functions that are not part of the public interface and are only meant to be called in the current source file. Such free functions should be put in an internal namespace structured in the following way: - -
    +  @code
       namespace internal
       {
         namespace ClassNameImplementation
    @@ -150,8 +145,7 @@ executable.
           // free functions go here
         }
       }
    -  
    -
    + @endcode where ClassName is the name of the calling class.
  • Classes and types generally are named using uppercase letters to denote @@ -250,8 +244,7 @@ we list here:
  • Assert preconditions on parameters: People call functions with wrong or nonsensical parameters, all the time. As the prototypical example, consider a trivial implementation of vector addition: - -
    +  @code
         Vector &
         operator += (Vector       &lhs,
                      const Vector &rhs)
    @@ -260,8 +253,7 @@ we list here:
             lhs(i) += rhs(i);
           return lhs;
         }
    -  
    -
    + @endcode While correct, this function will get into trouble if the two vectors do not have the same size. You think it is silly to call this function with vectors of different size? Yes, of course it is. But it happens @@ -274,8 +266,7 @@ we list here: but you'll probably get random errors at a later time. It would be much easier if the program just stopped here right away. The following implementation will do exactly this: - -
    +  @code
         Vector &
         operator += (Vector       &lhs,
                      const Vector &rhs)
    @@ -286,8 +277,7 @@ we list here:
             lhs(i) += rhs(i);
           return lhs;
         }
    -  
    -
    + @endcode The Assert macro ensures that the condition is true at run time, and otherwise prints a string containing information encoded by the second argument and aborts the program. This way, @@ -321,8 +311,7 @@ we list here: return values to be. For example, a function that computes the norm of a vector would expect the norm to be positive. You can write this as follows: - -
    +  @code
         double norm (const Vector &v)
         {
           double s = 0;
    @@ -332,8 +321,7 @@ we list here:
           Assert (s >= 0, ExcInternalError());
           return std::sqrt(s);
         }
    -  
    -
    + @endcode This function is too simple to really justify this assertion, but imagine the computation to be lengthier and you can see how the assertion helps you ensure (or hedge) yourself against mistakes. Note that one @@ -351,8 +339,7 @@ we list here: of what is going on matches what is indeed true. For example, assume you are writing a function that ensures that mesh sizes do not change too much locally. You may end up with a code of the following kind: - -
    +  @code
         for (const auto &cell = triangulation.active_cell_iterators())
           for (unsigned int face=0; ...)
             {
    @@ -364,8 +351,7 @@ we list here:
                     // be at the boundary if we got here
                 }
             }
    -  
    -
    + @endcode The conditions that got us into the else-branch may be complicated, and while it may be true that we believed that the only possibility we got here is that the neighbor is at the boundary, @@ -382,8 +368,7 @@ we list here: Traditional C required that variables are declared at the beginning of the function even if they are only used further below. This leads to code like this that we may imagine in a 1d code: - -
    +  @code
         template @
         void foo ()
         {
    @@ -396,8 +381,7 @@ we list here:
             }
           ...
         }
    -  
    -
    + @endcode The problem is that if the code between the declaration and initialization is long and complicated, you can't look up on one page what the type of a variable is and what it's value may be. In fact, it may not even be @@ -405,8 +389,7 @@ we list here: is accidentally left uninitialized.

    A better way to do this would be as follows: - -

    +  @code
         template @
         void foo ()
         {
    @@ -418,8 +401,7 @@ we list here:
             }
           ...
         }
    -  
    - + @endcode This makes it much clearer what the type of the variable is and that it is in fact only ever used when initialized. Furthermore, if someone wants to read the code to see what the variable is in fact @@ -442,8 +424,7 @@ we list here: that in most cases we will never change the variable so initialized any more. In other words, if this is the case, we may as well write things as follows: - -
    +  @code
         template @
         void foo ()
         {
    @@ -456,16 +437,13 @@ we list here:
             }
           ...
         }
    -  
    -
    + @endcode By marking the variable as constant we make sure that we don't accidentally change it. For example, the compiler could catch code like this: - -
    +  @code
             if (cell_center[0] = 0)
               ...
    -  
    -
    + @endcode This was most likely meant to be a == rather than an assignment. By marking the variable as const, the compiler would have told us about this bug. Maybe equally importantly, human readers of the @@ -479,8 +457,7 @@ we list here: of changing a variable (which is typically the case for input arguments), then mark it as constant. For example, the following function should take its argument as a constant value: - -
    +  @code
          template @
          typename Triangulation::cell_iterator
          CellAccessor::child (const unsigned int child_no)
    @@ -488,8 +465,7 @@ we list here:
            ...
            return something;
          }
    -  
    -
    + @endcode Here, the user calls cell-@>child(3), for example. There really is no reason why the function would ever want to change the value of the child_no argument — so mark it as constant: -- 2.39.5