Cosmetic: A potential zero-division changed to explicit dInfinity assignment; minor...
[ode.git] / CSR.txt
blob129803a8fdf69117464903c599f8306d0a6151ad
1 CODING STYLE REQUIREMENTS\r
2 \r
3 Copyright (c) 2011-2016 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 the failure\r
39 ----------------------------------------------------------------------------\r
41 Function results must be chosen the way that binary zero value meant the \r
42 failure. Similarly, the 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. Enumerated types must be designed to have zero element and that\r
52 element to be the default element. Function default parameters must be chosen\r
53 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 the 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 to local \r
94 variables at function entry and then assigned their final values at function\r
95 exit.\r
96 Output parameters must be initialized at function entry and \r
97 assigned their final values immediately before the function result variable \r
98 assignment.\r
101 (II) Class Design Requirements\r
102 =============================================================================\r
104 1. Classes work with their fields on their own\r
105 ----------------------------------------------------------------------------\r
107 A function or method must not call several methods of other class some of\r
108 which used to return and the others used to assign its fields. Such a code \r
109 must be implemented as a method of that other class.\r
112 2. No direct access to the fields\r
113 ----------------------------------------------------------------------------\r
115 All the work with class fields (including fields of own class) must be \r
116 performed with aid of dedicated methods (accessors) that return and asign \r
117 field values. Exceptions can be made for constructors/destructors and methods\r
118 dedicated to field initialization/finalization.\r
121 3. Private fields only\r
122 ----------------------------------------------------------------------------\r
124 All class fields must be private.\r
127 4. No code in constructors and destructors\r
128 ----------------------------------------------------------------------------\r
130 Class constructors must not have raw code other than doing trivial field \r
131 initialization. If creation of contained objects is necessary or other \r
132 operations need to be done they are to be performed via calls to the class \r
133 methods rather than placed directly in constructor. Initial zero-assignment\r
134 to a field is always required even if that field is later to be \r
135 unconditionally assigned with a pointer to the contained object being \r
136 created.\r
137 Similarly, a destructor must free contained objects with calls to the class \r
138 methods rather than containing that code inline.\r
141 5. No code in callbacks\r
142 ----------------------------------------------------------------------------\r
144 Event handlers, callback interface methods and static callback methods must \r
145 not have meaningful code within them. Their implementation should validate \r
146 input arguments, convert them to proper internal types if necessary, and call \r
147 one or more other methods of the class. These methods must not be declated in\r
148 a public section.\r
151 6. No public virtual methods\r
152 ----------------------------------------------------------------------------\r
154 Methods declared as virtual must not be public. The public calls to such \r
155 methods must be wrapped with ordinary class methods.\r
158 7. No logical level violations\r
159 ----------------------------------------------------------------------------\r
161 Methods of lower logical levels must not call any methods of higher logical \r
162 levels of the class. In particular, methods declared as protected and private\r
163 must not call methods declared in public sections of own or ancestor classes.\r
164 Methods declared as public may only call protected and private methods.\r
165 Similarly classes of lower logical levels must not call public methods of \r
166 classes at higher logical levels. Such calls are only possible via dedicated \r
167 callback methods or callback interfaces.\r
170 (III) Canonical Function Structures\r
171 =============================================================================\r
173 0. Preamble\r
174 ----------------------------------------------------------------------------\r
176 Following are general function structures encouraged to be used for coding \r
177 all the program logic. Any algorithm with branching can be implemented\r
178 with these types of functions.\r
180 Using these function structures helps to make code clear and error-prone.\r
183 1. A Boolean Function\r
184 ----------------------------------------------------------------------------\r
186 The Boolean Function can be used to implement algorithms with conditional \r
187 branching.\r
189 bool PerformSomeAction(...)\r
191     bool bResult = false;\r
193     // Some linear code\r
195     if (...)\r
196     {\r
197         // Some linear code\r
199         if (...) // Optionally...\r
200         {\r
201             bResult = true;\r
202         }\r
203     }\r
204     // Optionally...\r
205     else if (...)\r
206     {\r
207         // Some linear code\r
208         \r
209         bResult = true;\r
210     }\r
212     return bResult;\r
215 The idea is to have result variable initialized with false at entry and then \r
216 have an arbitrary structure of conditional operators with some branches \r
217 changing result variable to true on exit.\r
220 2. A Validation Function\r
221 ----------------------------------------------------------------------------\r
223 The Validation Function is an alternative to Boolean Function to implement \r
224 conditional logic. It's mostly convenient for implementing multi-step \r
225 algorithms that may fail (like validations or initializations of multiple \r
226 items of non-uniform nature).\r
228 bool PerformSomeValidation(...)\r
230     bool bResult = false;\r
232     do\r
233     {\r
234         // Some linear code\r
236         // Optionally...\r
237         if ( !(...) )\r
238         {\r
239             // Some error handling // Optionally...\r
240             break;\r
241         }\r
243         // Optionally...\r
244         if (...)\r
245         {\r
246             // Some linear code\r
248             if ( !(...) )\r
249             {\r
250                 // Some error handling // Optionally...\r
251                 break;\r
252             }\r
254             // Some linear code\r
255         }\r
257         bResult = true;\r
258     }\r
259     while (false);\r
261     return bResult;\r
264 If function execution has side effects which need to be rolled back in case \r
265 of failures on subsequent steps the function structure can be altered to the\r
266 following form.\r
268 bool PerformSomeInitialization(...)\r
270     bool bResult = false;\r
272     bool bFirstSideEffectApplied = false, bSecondSideEffectApplied = false, ...;\r
274     do\r
275     {\r
276         // Some linear code\r
278         if ( !ExecuteFirstSideEffectApplication(...) )\r
279         {\r
280             // Some error handling // Optionally...\r
281             break;\r
282         }\r
284         bFirstSideEffectApplied = true\r
286         // Some linear code\r
288         if ( !ExecuteSecondSideEffectApplication(...) )\r
289         {\r
290             // Some error handling // Optionally...\r
291             break;\r
292         }\r
294         bSecondSideEffectApplied = true\r
296         ...\r
298         // Some linear code\r
300         if ( !ExecuteLastSideEffectApplication(...) )\r
301         {\r
302             // Some error handling // Optionally...\r
303             break;\r
304         }\r
306         bResult = true;\r
307     }\r
308     while (false);\r
310     if (!bResult)\r
311     {\r
312         if (bFirstSideEffectApplied)\r
313         {\r
314             if (bSecondSideEffectApplied)\r
315             {\r
316                 if (...)\r
317                 {\r
318                     ...\r
319                 }\r
321                 ExecuteSecondSideEffectRollback(...);\r
322             }\r
324             ExecuteFirstSideEffectRollback(...);\r
325         }\r
326     }\r
328     return bResult;\r
332 3. A Loop Validation Function\r
333 ----------------------------------------------------------------------------\r
335 The Loop Validation Function can be used for processing sequences of items \r
336 while the processing of each or some individual items can fail.\r
338 bool PerformLoopValidation(...)\r
340     bool bAnyFailure = false;\r
342     for (...) // Or any other loop control operator\r
343     {\r
344         // Some linear code\r
346         if ( !(...) )\r
347         {\r
348             // Some error handling // Optional\r
349             bAnyFailure = true;\r
350             break;\r
351         }\r
353         // Some linear code\r
354     }\r
356     bool bResult = !bAnyFailure;\r
357     return bResult;\r
360 In case if a loop processing function may apply side effects on each step \r
361 which need to be reverted in case of a failure on subsequent steps the \r
362 functions need to be organized in the following four-function two-level \r
363 structure.\r
365 bool PerformLoopInitialization(...)\r
367     bool bResult = false;\r
369     size_t nFailureItem;\r
371     if (DoPerformLoopInitialization(..., nFailureItem))\r
372     {\r
373         bResult = true;\r
374     }\r
375     else\r
376     {\r
377         DoPerformLoopFinalization(..., nFailureItem);\r
378     }\r
380     return bResult;\r
383 void PerformLoopFinalization(...)\r
385     DoPerformLoopFinalization(..., npos); // Here "npos" stands for the invalid item index\r
388 bool DoPerformLoopInitialization(..., size_t &nOutFailureItem)\r
390     bool bAnyFailure = false;\r
391     size_t nOutFailureItem = npos;\r
393     for (...) // Or any other loop control operator\r
394     {\r
395         // Some linear code\r
397         if ( !(...) )\r
398         {\r
399             // Some error handling // Optional\r
400             nOutFailureItem = ...;\r
401             bAnyFailure = true;\r
402             break;\r
403         }\r
405         // Some linear code\r
406     }\r
408     bool bResult = !bAnyFailure;\r
409     return bResult;\r
412 void DoPerformLoopFinalization(..., size_t nExternalFinalizationEndItem/*=npos*/)\r
414     size_t nFinalizationEndItem = nExternalFinalizationEndItem == npos \r
415         ? ... /* total item count */\r
416         : nExternalFinalizationEndItem;\r
418     for (... /* loop until nFinalizationEndItem */) // Or any other loop control operator\r
419     {\r
420         // Some linear code\r
421         RevertLoopItemSideEffects(...);\r
422     }\r