1.. ## Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and 2.. ## other Axom Project Developers. See the top-level LICENSE file for details. 3.. ## 4.. ## SPDX-License-Identifier: (BSD-3-Clause) 5 6.. _scopesec-label: 7 8===================================== 96 Scope 10===================================== 11 12--------------------------------------------------------- 13Use namespaces to avoid name collisions 14--------------------------------------------------------- 15 166.1 All Axom code **must** be included in the project namespace 17'axom'; e.g.,:: 18 19 namespace axom { 20 // . . . 21 } 22 23.. note::We will change the top-level namespace at some point to shorten it. 24 256.2 Each Axom component **must** define its own unique namespace within 26the "axom" namespace. All contents of each component **must** reside 27within that namespace. 28 29 30--------------------------------------------------------- 31Use namespaces to hide non-API code in header files 32--------------------------------------------------------- 33 346.3 Code that must be appear in header files (e.g., templates) that is not 35intended to be part of a public interface, such as helper classes/structs 36and methods, **should** be placed in an internal namespace. 37 38 Common names for such namespaces include 'internal' (for implementations 39 used only internally) and 'detailed' (for types, etc. used only 40 internally). Any reasonable choice is acceptable; however, the choice 41 **must** be the same within each Axom component. 42 43 Note that declaring helper classes/structs private within a class 44 definition is another good option. See :ref:`scopenestedclass-label` 45 for details. 46 47 48--------------------------------------------------------- 49Use 'unnamed' namespace for hiding code in source files 50--------------------------------------------------------- 51 526.4 Classes/structs and methods that are meant to be used only internally to a 53single source file **should** be placed in the 'unnamed' namespace to make 54them invisible outside the file. 55 56 This guarantees link-time name conflicts will not occur. For example:: 57 58 namespace { 59 void myInternalFunction(); 60 } 61 62 63--------------------------------------------------------- 64Apply the 'using directive' carefully 65--------------------------------------------------------- 66 676.5 The 'using directive' **must not** be used in any header file. 68 69 Applying this directive in a header file leverages a bad decision to 70 circumvent the namespace across every file that directly or indirectly 71 includes that header file. 72 73.. note:: This guideline implies that each type name appearing in a header 74 file **must be fully-qualified** (i.e., using the namespace 75 identifier and scope operator) if it resides in a different 76 namespace than the contents of the file. 77 786.6 The 'using directive' **may** be used in a source file to avoid using a 79fully-qualified type name at each declaration. Using directives **must** appear 80after all "#include" directives in a source file. 81 826.7 When only parts of a namespace are used in an implementation file, only 83those parts **should** be included with a using directive instead of the 84entire namespace contents. 85 86 For example, if you only need the standard library vector container form 87 the "std" namespace, it is preferable to use:: 88 89 using std::vector; 90 91 rather than:: 92 93 using namespace std; 94 95 96--------------------------------------------------------- 97Use access qualifiers to control class interfaces 98--------------------------------------------------------- 99 1006.8 Class members **must** be declared in the following order: 101 102 #. "public" 103 #. "protected" 104 #. "private" 105 106 That is, order members using these access qualifiers in terms of 107 "decreasing scope of visibility". 108 109.. note:: Declaring methods before data members is preferred because methods 110 are more commonly considered part of a class interface. Also, 111 separating methods and data into their own access qualified 112 sections usually helps make a class definition clearer. 113 1146.9 Class data members **should** be "private". The choice to use "public" 115or "protected" data members **must** be scrutinized by other team members. 116 117 Information hiding is an essential part of good software engineering 118 and private data is the best means for a class to preserve its 119 invariants. Specifically, a class should maintain control of how object 120 state can be modified to minimize side effects. In addition, restricting 121 direct access to class data enforces encapsulation and facilitates 122 design changes through refactoring. 123 124 125--------------------------------------------------------- 126Use 'friend' and 'static' rarely 127--------------------------------------------------------- 128 1296.10 "Friend" declarations **should** be used rarely. When used, they 130**must** appear within the body of a class definition before any class 131member declarations. This helps make the friend relationship obvious. 132 133 Note that placing "friend" declarations before the "public:" keyword 134 makes them private, which preserves encapsulation. 135 1366.11 Static class members (methods or data) **must** be used rarely. In 137every case, their usage **should** be carefully reviewed by the team. 138 139 When it is determined that a static member is needed, it **must** appear 140 first in the appropriate member section. Typically, static member 141 functions **should** be "public" and static data members **should** be 142 "private". 143 144 145.. _scopenestedclass-label: 146 147--------------------------------------------------------- 148Hide nested classes when possible 149--------------------------------------------------------- 150 1516.12 Nested classes **should** be private unless they are part of the 152enclosing class interface. 153 154 For example:: 155 156 class Outer 157 { 158 // ... 159 private: 160 class Inner 161 { 162 // ... 163 }; 164 }; 165 166 When only the enclosing class uses a nested class, making it private 167 does not pollute the enclosing scope needlessly. Furthermore, nested 168 classes may be forward declared within the enclosing class definition 169 and then defined in the implementation file of the enclosing class. 170 For example:: 171 172 class Outer 173 { 174 class Inner; // forward declaration 175 176 // use name 'Inner' in Outer class definition 177 }; 178 179 // In Outer.cpp implementation file... 180 class Outer::Inner 181 { 182 // Inner class definition 183 } 184 185 This makes it clear that the nested class is only needed in the 186 implementation and does not clutter the class definition. 187 188 189--------------------------------------------------------- 190Limit scope of local variables 191--------------------------------------------------------- 192 1936.13 Local variables **should** be declared in the narrowest scope possible 194and as close to first use as possible. 195 196 Minimizing variable scope makes source code easier to comprehend and 197 may have performance and other benefits. For example, declaring a loop 198 index inside a for-loop statement such as:: 199 200 for (int ii = 0; ...) { 201 202 is preferable to:: 203 204 int ii; 205 ... 206 for (ii = 0; ...) { 207 208 Beyond readability, this rule has benefits for thread safety, etc. 209 210.. note:: **Exception:** When a local variable is an object, its constructor 211 and destructor may be invoked every time a scope (such as a loop) 212 is entered and exited, respectively. 213 214 Thus, instead of this:: 215 216 for (int ii = 0; ii < 1000000; ++ii) { 217 Foo f; 218 f.doSomethingCool(ii); 219 } 220 221 it may be more efficient to do this:: 222 223 Foo f; 224 for (int ii = 0; ii < 1000000; ++ii) { 225 f.doSomethingCool(ii); 226 } 227 2286.14 A local reference to any item in the global namespace (which should be 229rare if needed at all) **should** use the scope operator ("::") to make 230the fact that it resides in the global namespace clear. 231 232 For example:: 233 234 int local_val = ::global_val; 235