Merged in cmake-ode-config (pull request #4)
[ode.git] / CSR.txt
blob7d4ca2e135cd7c5b2f5974e7cb978a28c39c516a
1 CODING STYLE REQUIREMENTS\r
2 \r
3 Copyright (c) 2011-2017 Oleh Derevenko\r
4 This article is provided to you under the terms of Artistic License 2.0\r
5 (http://www.opensource.org/licenses/artistic-license-2.0).\r
6 \r
7 (I) General Coding Requirements\r
8 =============================================================================\r
9 \r
10 1. Not more than one complex construction per function\r
11 ----------------------------------------------------------------------------\r
13 A function must not contain more than one* operator from the following set:\r
14 for, while, do..while, switch and constructions try..catch, try..finally. \r
15 Moreover, those operators/constructions must not appear inside of a \r
16 conditional operator.\r
18 * Loop inclusion is allowed if multi-dimensional array must be iterated and \r
19 all the elements are uniform and need to be processed linearly.\r
20 try..finally construction inclusion is allowed for several resource \r
21 allocations that need to be performed together.\r
24 2. Absence of jumps\r
25 ----------------------------------------------------------------------------\r
27 goto and continue operators must not be used.\r
30 3. Single exit point at the end of function\r
31 ----------------------------------------------------------------------------\r
33 A function must not have other exit points except for the end of its \r
34 definition. If a function returns a value, return operator must be the last\r
35 syntactical construction in the function.\r
38 4. Zero value means failure\r
39 ----------------------------------------------------------------------------\r
41 Function results must be chosen the way that binary zero value had a meaning\r
42 of failure. Similarly, types must be designed so that binary zero element \r
43 had the meaning of an invalid value (if invalid element concept is applicable\r
44 for the type).\r
47 5. Variables and parameters are initialized with zeroes\r
48 ----------------------------------------------------------------------------\r
50 Variables and class fields must be initialized with values of binary zero \r
51 presentation. Public enumerated types must be designed to have zero element \r
52 and that element is to be the default element. Function default parameters \r
53 must be chosen in the form to have binary zero value.\r
56 6. Variables are not reused\r
57 ----------------------------------------------------------------------------\r
59 Variables must not be reused for other purposes after they have already been\r
60 used for something. The only value that might be stored in a variable is that\r
61 described with its name.\r
64 7. Parameters passed by value are treated as constants\r
65 ----------------------------------------------------------------------------\r
67 Parameters that are passed by value must not be modified*. All of them must\r
68 be treated as if they have been implicitly declared with const modifier.\r
70 * An exception could be the case when a value loses its meaning (e.g. a \r
71 pointer to an object being deleted).\r
74 8. Result assignment is performed at the end of function\r
75 ----------------------------------------------------------------------------\r
77 Every function returning a result must have a variable to contain the result\r
78 of that function. It is to be declared (initialized if necessary) at the \r
79 beginning of the function* and the only access to it after that should be its\r
80 final value assignment. The assignment should be the last meaningful operator\r
81 in an execution branch**. Several assignments, one per each execution branch,\r
82 are allowed.\r
84 * It is allowed to declare result variable with assignment immediately before\r
85 return operator.\r
86 ** It is allowed to include technical constructions like logging or \r
87 performance measuring after result variable assignment.\r
90 9. Parameters by reference are not used in expressions\r
91 ----------------------------------------------------------------------------\r
93 Parameters of simple types passed by reference must be copied into local \r
94 variables at function entry and then be assigned their final values at \r
95 function exit.\r
96 Output parameters can be initialized at function entry and must be assigned\r
97 their final values immediately before the function result variable assignment.\r
100 (II) Class Design Requirements\r
101 =============================================================================\r
103 1. Classes work with their fields on their own\r
104 ----------------------------------------------------------------------------\r
106 A function or method must not call several methods of other class, some of\r
107 them being used to return and the others being used to assign the class fields.\r
108 Such a code must be implemented as a method of that other class.\r
111 2. No direct access to the fields\r
112 ----------------------------------------------------------------------------\r
114 All the work with class fields (including fields of own class) must be \r
115 performed with aid of dedicated methods (accessors) that return and assign \r
116 field values. Exceptions can be made for constructors/destructors and methods\r
117 dedicated for field initialization/finalization.\r
120 3. Private fields only\r
121 ----------------------------------------------------------------------------\r
123 All class fields must be private.\r
126 4. No code in constructors and destructors\r
127 ----------------------------------------------------------------------------\r
129 Class constructors must not have raw code other than doing trivial field \r
130 initialization. If creation of contained objects is necessary or other \r
131 operations need to be done they are to be performed via calls to the class \r
132 methods rather than placed directly in constructor. Initial zero-assignment\r
133 to a field is always required even if that field is later to be \r
134 unconditionally assigned in methods called from the constructor.\r
135 Similarly, a destructor must free contained objects with calls to the class \r
136 methods rather than containing that code inline.\r
139 5. No code in callbacks\r
140 ----------------------------------------------------------------------------\r
142 Event handlers, callback interface methods and static callback methods must \r
143 not have meaningful code within them. Their implementation should validate \r
144 input arguments, convert them to proper internal types if necessary, and call \r
145 one or more other methods of the class. These methods must not be declated in\r
146 public section.\r
149 6. No public virtual methods\r
150 ----------------------------------------------------------------------------\r
152 Methods declared as virtual must not be public. The public calls to such \r
153 methods must be wrapped with ordinary class methods.\r
156 7. No logical level violations\r
157 ----------------------------------------------------------------------------\r
159 Methods of lower logical levels must not call any methods of higher logical \r
160 levels of the class. In particular, methods declared as protected and private\r
161 must not call methods declared in public sections of own or ancestor classes.\r
162 Methods declared as public may only call protected and private methods.\r
163 Similarly classes of lower logical levels must not call public methods of \r
164 classes at higher logical levels. Such calls are only possible via dedicated \r
165 callback methods or callback interfaces.\r
168 (III) Canonical Function Structures\r
169 =============================================================================\r
171 0. Preamble\r
172 ----------------------------------------------------------------------------\r
174 Following are general function structures encouraged to be used for coding \r
175 all the program logic. Any algorithm with branching can be implemented\r
176 with these types of functions.\r
178 Using these function structures helps to make code clear and error-proof.\r
181 1. A Boolean Function\r
182 ----------------------------------------------------------------------------\r
184 The Boolean Function can be used to implement algorithms with conditional \r
185 branching.\r
187 bool PerformSomeAction(...)\r
189     bool bResult = false;\r
191     // Some linear code\r
193     if (...)\r
194     {\r
195         // Some linear code\r
197         if (...) // Optionally...\r
198         {\r
199             bResult = true;\r
200         }\r
201     }\r
202     // Optionally...\r
203     else if (...)\r
204     {\r
205         // Some linear code\r
206         \r
207         bResult = true;\r
208     }\r
210     return bResult;\r
213 The idea is to have result variable initialized with false at entry and then \r
214 have an arbitrary structure of conditional operators with some branches \r
215 changing result variable to true on exit.\r
218 2. A Validation Function\r
219 ----------------------------------------------------------------------------\r
221 The Validation Function is an alternative to Boolean Function to implement \r
222 conditional logic. It's mostly convenient for implementing multi-step \r
223 algorithms that may fail (like validations or initializations of multiple \r
224 items of non-uniform nature).\r
226 bool PerformSomeValidation(...)\r
228     bool bResult = false;\r
230     do\r
231     {\r
232         // Some linear code\r
234         // Optionally...\r
235         if ( !(...) )\r
236         {\r
237             // Some error handling // Optionally...\r
238             break;\r
239         }\r
241         // Optionally...\r
242         if (...)\r
243         {\r
244             // Some linear code\r
246             if ( !(...) )\r
247             {\r
248                 // Some error handling // Optionally...\r
249                 break;\r
250             }\r
252             // Some linear code\r
253         }\r
255         bResult = true;\r
256     }\r
257     while (false);\r
259     return bResult;\r
262 If function execution has side effects which need to be rolled back in case \r
263 of failures on subsequent steps the function structure can be altered to the\r
264 following form.\r
266 bool PerformSomeInitialization(...)\r
268     bool bResult = false;\r
270     bool bFirstSideEffectApplied = false, bSecondSideEffectApplied = false, ...;\r
272     do\r
273     {\r
274         // Some linear code\r
276         if ( !ExecuteFirstSideEffectApplication(...) )\r
277         {\r
278             // Some error handling // Optionally...\r
279             break;\r
280         }\r
282         bFirstSideEffectApplied = true\r
284         // Some linear code\r
286         if ( !ExecuteSecondSideEffectApplication(...) )\r
287         {\r
288             // Some error handling // Optionally...\r
289             break;\r
290         }\r
292         bSecondSideEffectApplied = true\r
294         ...\r
296         // Some linear code\r
298         if ( !ExecuteLastSideEffectApplication(...) )\r
299         {\r
300             // Some error handling // Optionally...\r
301             break;\r
302         }\r
304         bResult = true;\r
305     }\r
306     while (false);\r
308     if (!bResult)\r
309     {\r
310         if (bFirstSideEffectApplied)\r
311         {\r
312             if (bSecondSideEffectApplied)\r
313             {\r
314                 if (...)\r
315                 {\r
316                     ...\r
317                 }\r
319                 ExecuteSecondSideEffectRollback(...);\r
320             }\r
322             ExecuteFirstSideEffectRollback(...);\r
323         }\r
324     }\r
326     return bResult;\r
330 3. A Loop Validation Function\r
331 ----------------------------------------------------------------------------\r
333 The Loop Validation Function can be used for processing sequences of items \r
334 while the processing of each or some individual items can fail.\r
336 bool PerformLoopValidation(...)\r
338     bool bAnyFailure = false;\r
340     for (...) // Or any other loop control operator\r
341     {\r
342         // Some linear code\r
344         if ( !(...) )\r
345         {\r
346             // Some error handling // Optional\r
347             bAnyFailure = true;\r
348             break;\r
349         }\r
351         // Some linear code\r
352     }\r
354     bool bResult = !bAnyFailure;\r
355     return bResult;\r
358 In case if a loop processing function may apply side effects on each step \r
359 which need to be reverted in case of a failure on subsequent steps the \r
360 functions need to be organized in the following four-function two-level \r
361 structure.\r
363 bool PerformLoopInitialization(...)\r
365     bool bResult = false;\r
367     size_t nFailureItem;\r
369     if (DoPerformLoopInitialization(..., nFailureItem))\r
370     {\r
371         bResult = true;\r
372     }\r
373     else\r
374     {\r
375         DoPerformLoopFinalization(..., nFailureItem);\r
376     }\r
378     return bResult;\r
381 void PerformLoopFinalization(...)\r
383     DoPerformLoopFinalization(..., npos); // Here "npos" stands for the invalid item index\r
386 bool DoPerformLoopInitialization(..., size_t &nOutFailureItem)\r
388     bool bAnyFailure = false;\r
389     size_t nOutFailureItem = npos;\r
391     for (...) // Or any other loop control operator\r
392     {\r
393         // Some linear code\r
395         if ( !(...) )\r
396         {\r
397             // Some error handling // Optional\r
398             nOutFailureItem = ...;\r
399             bAnyFailure = true;\r
400             break;\r
401         }\r
403         // Some linear code\r
404     }\r
406     bool bResult = !bAnyFailure;\r
407     return bResult;\r
410 void DoPerformLoopFinalization(..., size_t nExternalFinalizationEndItem/*=npos*/)\r
412     size_t nFinalizationEndItem = nExternalFinalizationEndItem == npos \r
413         ? ... /* total item count */\r
414         : nExternalFinalizationEndItem;\r
416     for (... /* loop until nFinalizationEndItem */) // Or any other loop control operator\r
417     {\r
418         // Some linear code\r
419         RevertLoopItemSideEffects(...);\r
420     }\r