0028877: Documentation - fix unclosed tag in coding_rules.md
[occt.git] / dox / dev_guides / contribution / coding_rules.md
CommitLineData
ba06f8bb 1Coding Rules {#occt_dev_guides__coding_rules}
f6e968a7 2======================================
3
4@tableofcontents
5
49663e13 6@section occt_coding_rules_1 Introduction
f6e968a7 7
49663e13 8The purpose of this document is to define a common programming style for Open CASCADE Technology.
f6e968a7 9
49663e13 10The common style facilitates understanding and maintaining a code developed cooperatively by several programmers. In addition, it enables construction of tools that incorporate knowledge of these standards to help in the programming.
f6e968a7 11
49663e13 12OCCT programming style follows common and appropriate best practices, so some guidelines have been excerpted from the public domain.
13
14The guide can be improved in the future as new ideas and enhancements are added.
15
16@subsection occt_coding_rules_1_1 Scope of the document
17
18Rules in this document refer to C++ code. However, with minor exceptions due to language restrictions, they are applicable to any sources in Open CASCADE Technology framework, including:
f6e968a7 19- C/C++
20- GLSL programs
21- OpenCL kernels
22- TCL scripts and test cases
23
49663e13 24@section occt_coding_rules_2 Naming Conventions
f6e968a7 25
49663e13 26@subsection occt_coding_rules_2_1 General naming rules
f6e968a7 27
49663e13 28The names considered in this section mainly refer to the interface of Open CASCADE Technology libraries or source code itself.
f6e968a7 29
30### International language [MANDATORY]
49663e13 31
32Open CASCADE Technology is an open source platform available for an international community, thus all names need to be composed of English words or their abbreviations.
33
34### Meaningful names
35
36Names should be meaningful or, at least, contain a meaningful part. To better understand this requirement, let us examine the existing names of toolkits, packages, classes and methods:
37- Packages containing words *Geom* or *Geom2d* in their names are related to geometrical data and operations.
38- Packages containing words *TopoDS* or *BRep* in their names are related to topological data and operations.
49663e13 39- Packages ending with <i>...Test</i> define Draw Harness plugins.
40- Methods starting with *Get...* and *Set...* are usually responsible for correspondingly retrieving and storing data.
f6e968a7 41
42### Related names
49663e13 43
44Names related to a logically connected functionality should have the same prefix (start with the same letters) or, at least, have any other common part.
45For example, method *GetCoord* returns a triple of real values and is defined for directions, vectors and points. The logical connection is obvious.
f6e968a7 46
47### Camel Case style
48Camel Case style is preferred for names.
49For example:
50
51~~~~~{.cpp}
52Standard_Integer awidthofbox; // this is bad
53Standard_Integer width_of_box; // this is bad
54Standard_Integer aWidthOfBox; // this is OK
55~~~~~
56
49663e13 57@subsection occt_coding_rules_2_2 Names of development units
f6e968a7 58
49663e13 59Usually a unit (e.g. a package) is a set of classes, methods, enumerations or any other sources implementing a common functionality, which is self-contained and independent from other parts of the library.
f6e968a7 60
49663e13 61### No underscores in unit names [MANDATORY]
f6e968a7 62
49663e13 63Names of units should not contain underscores, unless the use of underscores is allowed explicitly.
f6e968a7 64
49663e13 65### File name extensions [MANDATORY]
66
67The following extensions should be used for source files, depending on their type:
f6e968a7 68
3f812249 69* <i>.cxx</i> -- C++ source files
70* <i>.hxx</i> -- C++ header files
d3013f55 71* <i>.lxx</i> -- additional headers containing definitions of inline methods and auxiliary code
f6e968a7 72
629362c6 73Note that .lxx files should be avoided in most cases - inline method should be placed in header file instead.
74
49663e13 75### Prefix for toolkit names [MANDATORY]
76
77Toolkit names are prefixed by *TK*, followed by a meaningful part of the name explaining the domain of functionality covered by the toolkit (e.g. *TKOpenGl*).
f6e968a7 78
79### Names of classes
f6e968a7 80
49663e13 81Usually the names of source files located in a unit start from the unit name separated from the other part of the file name by underscore "_".
82
83Thus, the names of files containing sources of C++ classes that belong to a package are constructed according to the following template:
84
85~~~~~
04c2daa4 86 <package-name>_<class-name>.cxx (or .hxx)
49663e13 87~~~~~
f6e968a7 88
49663e13 89For example, file *Adaptor2d_Curve2d.cxx* belongs to the package *Adaptor2d*
f6e968a7 90
49663e13 91Files that contain sources related to the whole unit are called by the unit name with appropriate extension.
f6e968a7 92
93### Names of functions
49663e13 94
95The term **function** here is defined as:
f6e968a7 96- Any class method
97- Any package method
98- Any non-member procedure or function
99
49663e13 100It is preferred to start names of public methods from an upper case character and to start names of protected and private methods from a lower case character.
101
f6e968a7 102
103~~~~~{.cpp}
104class MyPackage_MyClass
105{
106
107public:
108
109 Standard_Integer Value() const;
110 void SetValue (const Standard_Integer theValue);
111
112private:
113
114 void setIntegerValue (const Standard_Integer theValue);
115
116};
117~~~~~
118
49663e13 119@subsection occt_coding_rules_2_3 Names of variables
120
121There are several rules that describe currently accepted practices for naming variables.
f6e968a7 122
123### Naming of variables
49663e13 124
125Name of a variable should not conflict with the existing or possible global names (for packages, macros, functions, global variables, etc.).
126
127The name of a variable should not start with an underscore.
f6e968a7 128
129See the following examples:
130
131~~~~~{.cpp}
132Standard_Integer Elapsed_Time = 0; // this is bad - possible class name
133Standard_Integer gp = 0; // this is bad - existing package name
134Standard_Integer aGp = 0; // this is OK
135Standard_Integer _KERNEL = 0; // this is bad
136Standard_Integer THE_KERNEL = 0; // this is OK
137~~~~~
138
139### Names of function parameters
49663e13 140
141The name of a function (procedure, class method) parameter should start with prefix *the* followed by the meaningful part of the name starting with a capital letter.
f6e968a7 142
143See the following examples:
144
145~~~~~{.cpp}
146void Package_MyClass::MyFunction (const gp_Pnt& p); // this is bad
147void Package_MyClass::MyFunction (const gp_Pnt& theP); // this is OK
148void Package_MyClass::MyFunction (const gp_Pnt& thePoint); // this is preferred
149~~~~~
150
151### Names of class member variables
49663e13 152
153The name of a class member variable should start with prefix *my* followed by the meaningful of the name starting with a capital letter.
f6e968a7 154
155See the following examples:
156
157~~~~~{.cpp}
158Standard_Integer counter; // This is bad
159Standard_Integer myC; // This is OK
160Standard_Integer myCounter; // This is preferred
161~~~~~
162
163### Names of global variables
49663e13 164
f6e968a7 165It is strongly recommended to avoid defining any global variables.
4ee1bdf4 166However, as soon as a global variable is necessary, its name should be prefixed by the name of a class or a package where it is defined followed with <i>_my</i>.
f6e968a7 167
168See the following examples:
169
170~~~~~{.cpp}
171Standard_Integer MyPackage_myGlobalVariable = 0;
172Standard_Integer MyPackage_MyClass_myGlobalVariable = 0;
173~~~~~
174
49663e13 175Static constants within the file should be written in upper-case and begin with prefix *THE_*:
f6e968a7 176~~~~~{.cpp}
177namespace
178{
179 static const Standard_Real THE_CONSTANT_COEF = 3.14;
180};
181~~~~~
182
183### Names of local variables
f6e968a7 184
49663e13 185The name of a local variable should be distinguishable from the name of a function parameter, a class member variable and a global variable.
186
187It is preferred to prefix local variable names with *a* and *an* (or *is*, *to* and *has* for Boolean variables).
188
189See the following example:
f6e968a7 190
191~~~~~{.cpp}
192Standard_Integer theI; // this is bad
193Standard_Integer i; // this is bad
194Standard_Integer index; // this is bad
195Standard_Integer anIndex; // this is OK
196~~~~~
197
198### Avoid dummy names
49663e13 199Avoid dummy names, such as <i>i, j, k</i>. Such names are meaningless and easy to mix up.
200
201The code becomes more and more complicated when such dummy names are used there multiple times with different meanings, or in cycles with different iteration ranges, etc.
f6e968a7 202
203See the following examples for preferred style:
204
205~~~~~{.cpp}
206void Average (const Standard_Real** theArray,
207 Standard_Integer theRowsNb,
208 Standard_Integer theRowLen,
209 Standard_Real& theResult)
210{
211 theResult = 0.0;
212 for (Standard_Integer aRow = 0; aRow < aRowsNb; ++aRow)
213 {
214 for (Standard_Integer aCol = 0; aCol < aRowLen; ++aCol)
215 {
216 theResult += theArray[aRow][aCol];
217 }
218 theResult /= Standard_Real(aRowsNb * aRowLen);
219 }
220}
221~~~~~
222
49663e13 223@section occt_coding_rules_3 Formatting rules
f6e968a7 224
49663e13 225To improve the open source readability and, consequently, maintainability, the following set of rules is applied.
f6e968a7 226
227### International language [MANDATORY]
49663e13 228
f6e968a7 229All comments in all sources must be in English.
230
231### Line length
49663e13 232
233Try to stay within the limit of 120 characters per line in all sources.
f6e968a7 234
235### C++ style comments
49663e13 236
f6e968a7 237Prefer C++ style comments in C++ sources.
238
239### Commenting out unused code
49663e13 240
ba06f8bb 241Delete unused code instead of commenting it or using \#define.
f6e968a7 242
243### Indentation in sources [MANDATORY]
49663e13 244
f6e968a7 245Indentation in all sources should be set to two space characters.
246Use of tabulation characters for indentation is disallowed.
247
248### Separating spaces
49663e13 249
250Punctuation rules follow the rules of the English language.
251* C/C++ reserved words, commas, colons and semicolons should be followed by a space character if they are not at the end of a line.
252* There should be no space characters after '(' and before ')'. Closing and opening brackets should be separated by a space character.
564c82b4 253* For better readability it is also recommended to surround conventional operators by a space character.
254Examples:
f6e968a7 255
256~~~~~{.cpp}
257while (true) // NOT: while( true ) ...
258{
259 DoSomething (theA, theB, theC, theD); // NOT: DoSomething(theA,theB,theC,theD);
260}
261for (anIter = 0; anIter < 10; ++anIter) // NOT: for (anIter=0;anIter<10;++anIter){
262{
263 theA = (theB + theC) * theD; // NOT: theA=(theB+theC)*theD
264}
265~~~~~
266
564c82b4 267### Declaration of pointers and references
268
269In declarations of simple pointers and references put asterisk (*) or ampersand (&) right after the type without extra space.
270
271Since declaration of several variables with mixed pointer types contrudicts this rule, it should be avoided. Instead, declare each variable independently with fully qualified type.
272
273Examples:
274
275~~~~~{.cpp}
276Standard_Integer *theVariable; // not recommended
277Standard_Integer * theVariable; // not recommended
278Standard_Integer* theVariable; // this is OK
279
280Standard_Integer *&theVariable; // not recommended
281Standard_Integer *& theVariable; // not recommended
282Standard_Integer*& theVariable; // this is OK
283
284Standard_Integer **theVariable; // not recommended
285Standard_Integer ** theVariable; // not recommended
286Standard_Integer** theVariable; // this is OK
287
288Standard_Integer *theA, theB, **theC; // not recommended (declare each variable independently)
289~~~~~
290
f6e968a7 291### Separate logical blocks
49663e13 292
f6e968a7 293Separate logical blocks of code with one blank line and comments.
49663e13 294
f6e968a7 295See the following example:
296
297~~~~~{.cpp}
298// check arguments
299Standard_Integer anArgsNb = argCount();
300if (anArgsNb < 3 || isSmthInvalid)
301{
302 return THE_ARG_INVALID;
303}
304
305// read and check header
306...
307...
308
309// do our job
310...
311...
312~~~~~
313
314Notice that multiple blank lines should be avoided.
315
316### Separate function bodies [MANDATORY]
49663e13 317
f6e968a7 318Use function descriptive blocks to separate function bodies from each other.
49663e13 319Each descriptive block should contain at least a function name and purpose description.
320
f6e968a7 321See the following example:
322
323~~~~~{.cpp}
f3fb84ce 324// =======================================================================
f6e968a7 325// function : TellMeSmthGood
326// purpose : Gives me good news
f3fb84ce 327// =======================================================================
f6e968a7 328void TellMeSmthGood()
329{
330 ...
331}
332
f3fb84ce 333// =======================================================================
f6e968a7 334// function : TellMeSmthBad
335// purpose : Gives me bad news
f3fb84ce 336// =======================================================================
f6e968a7 337void TellMeSmthBad()
338{
339 ...
340}
341~~~~~
342
343### Block layout [MANDATORY]
49663e13 344Figure brackets <i>{ }</i> and each operator <i>(for, if, else, try, catch)</i> should be written on a dedicated line.
345
346In general, the layout should be as follows:
f6e968a7 347
348~~~~~{.cpp}
349while (expression)
350{
351 ...
352}
353~~~~~
354
49663e13 355Entering a block increases and leaving a block decreases the indentation by one tabulation.
f6e968a7 356
357### Single-line operators
49663e13 358
359Single-line conditional operators <i>(if, while, for,</i> etc.) can be written without brackets on the following line.
f6e968a7 360
361~~~~~{.cpp}
362if (!myIsInit) return Standard_False; // bad
363
364if (thePtr == NULL) // OK
365 return Standard_False;
366
367if (!theAlgo.IsNull()) // preferred
368{
369 DoSomething();
370}
371~~~~~
372
49663e13 373Having all code in the same line is less convenient for debugging.
f6e968a7 374
564c82b4 375### Comparison expressions with constants
376
377In comparisons, put the variable (in the current context) on the left side and constant on the right side of expression.
378That is, the so called "Yoda style" is to be avoided.
379
380~~~~~{.cpp}
381if (NULL != thePointer) // Yoda style, not recommended
382if (thePointer != NULL) // OK
383
384if (34 < anIter) // Yoda style, not recommended
385if (anIter > 34) // OK
386
387if (theNbValues >= anIter) // bad style (constant function argument vs. local variable)
388if (anIter <= theNbValues) // OK
389
390if (THE_LIMIT == theValue) // bad style (global constant vs. variable)
391if (theValue == THE_LIMIT) // OK
392~~~~~
393
49663e13 394### Alignment
395
396Use alignment wherever it enhances the readability. See the following example:
f6e968a7 397
398~~~~~{.cpp}
399MyPackage_MyClass anObject;
400Standard_Real aMinimum = 0.0;
401Standard_Integer aVal = theVal;
402switch (aVal)
403{
404 case 0: computeSomething(); break;
405 case 12: computeSomethingElse (aMinimum); break;
406 case 3:
407 default: computeSomethingElseYet(); break;
408}
409~~~~~
410
411### Indentation of comments
49663e13 412
413Comments should be indented in the same way as the code to which they refer or they can be in the same line if they are short.
414
415The text of the comment should be separated from the slash character by a single space character.
416
f6e968a7 417See the following example:
418
419~~~~~{.cpp}
420while (expression) //bad comment
421{
422 // this is a long multi-line comment
423 // which is really required
424 DoSomething(); // maybe, enough
425 DoSomethingMore(); // again
426}
427~~~~~
428
429### Early return statement
49663e13 430
431Use an early return condition rather than collect indentations.
432
433Write like this:
f6e968a7 434
435~~~~~{.cpp}
436Standard_Integer ComputeSumm (const Standard_Integer* theArray,
437 const Standard_Size theSize)
438{
439 Standard_Integer aSumm = 0;
440 if (theArray == NULL || theSize == 0)
441 {
442 return 0;
443 }
444
445 ... computing summ ...
446 return aSumm;
447}
448~~~~~
449
49663e13 450Rather than:
f6e968a7 451
452~~~~~{.cpp}
453Standard_Integer ComputeSumm (const Standard_Integer* theArray,
454 const Standard_Size theSize)
455{
456 Standard_Integer aSumm = 0;
457 if (theArray != NULL && theSize != 0)
458 {
459 ... computing summ ...
460 }
461 return aSumm;
462}
463~~~~~
464
49663e13 465This helps to improve readability and reduce the unnecessary indentation depth.
f6e968a7 466
467### Trailing spaces
49663e13 468
469Trailing spaces should be removed whenever possible.
470Spaces at the end of a line are useless and do not affect functionality.
f6e968a7 471
472### Headers order
49663e13 473
474Split headers into groups: system headers, headers per each framework, project headers; sort the list of includes alphabetically.
629362c6 475Within the class source file, the class header file should be included first.
49663e13 476
477This rule improves readability, allows detecting useless multiple header inclusions and makes 3rd-party dependencies clearly visible.
629362c6 478Inclusion of class header on top verifies consistency of the header (e.g. that header file does not use any undefined declarations due to missing includes of dependencies).
f6e968a7 479
629362c6 480An exception to the rule is ordering system headers generating a macros declaration conflicts (like "windows.h" or "X11/Xlib.h") - these headers should be placed in the way solving the conflict.
f6e968a7 481
629362c6 482~~~~~{.cpp}
483// the header file of implemented class
484#include <PackageName_ClassName.hxx>
f6e968a7 485
486// OCCT headers
487#include <gp_Pnt.hxx>
488#include <gp_Vec.hxx>
489#include <NCollection_List.hxx>
629362c6 490
491// Qt headers
492#include <QDataStream>
493#include <QString>
494
495// system headers
496#include <iostream>
497#include <windows.h>
f6e968a7 498~~~~~
499
49663e13 500@section occt_coding_rules_4 Documentation rules
f6e968a7 501
502The source code is one of the most important references for documentation.
49663e13 503The comments in the source code should be complete enough to allow understanding the corresponding code and to serve as basis for other documents.
f6e968a7 504
49663e13 505The main reasons why the comments are regarded as documentation and should be maintained are:
3f812249 506- The comments are easy to reach -- they are always together with the source code;
49663e13 507- It is easy to update a description in the comment when the source is modified;
508- The source by itself is a good context to describe various details that would require much more explanations in a separate document;
509- As a summary, this is the most cost-effective documentation.
f6e968a7 510
511The comments should be compatible with Doxygen tool for automatic documentation generation (thus should use compatible tags).
512
513### Documenting classes [MANDATORY]
49663e13 514
04c2daa4 515Each class should be documented in its header file (.hxx).
49663e13 516The comment should give enough details for the reader to understand the purpose of the class and the main way of work with it.
f6e968a7 517
518### Documenting class methods [MANDATORY]
49663e13 519
04c2daa4 520Each class or package method should be documented in the header file (.hxx).
49663e13 521
f6e968a7 522The comment should explain the purpose of the method, its parameters, and returned value(s).
523Accepted style is:
524
525@verbatim
526//! Method computes the square value.
527//! @param theValue the input value
528//! @return squared value
529Standard_Export Standard_Real Square (Standard_Real theValue);
530@endverbatim
531
532### Documenting C/C++ sources
49663e13 533
f6e968a7 534It is very desirable to put comments in the C/C++ sources of the package/class.
f6e968a7 535
49663e13 536They should be detailed enough to allow any person to understand what each part of code does.
537
538It is recommended to comment all static functions (like methods in headers), and to insert at least one comment per each 10-100 lines in the function body.
539
67d7f07f 540There are also some rules that define how comments should be formatted, see @ref occt_coding_rules_3 "Formatting Rules".
49663e13 541
542Following these rules is important for good comprehension of the comments. Moreover, this approach allows automatically generating user-oriented documentation directly from the commented sources.
f6e968a7 543
49663e13 544@section occt_coding_rules_5 Application design
545
546The following rules define the common style, which should be applied by any developer contributing to the open source.
547
548### Allow possible inheritance
f6e968a7 549
f6e968a7 550Try to design general classes (objects) keeping possible inheritance in mind.
49663e13 551This rule means that the user who makes possible extensions of your class should not encounter problems of private implementation.
f6e968a7 552Try to use protected members and virtual methods wherever you expect extensions in the future.
553
554### Avoid friend declarations
49663e13 555
556Avoid using 'friend' classes or functions except for some specific cases (for example, iteration) 'Friend' declarations increase coupling.
f6e968a7 557
558### Set/get methods
49663e13 559
f6e968a7 560Avoid providing set/get methods for all fields of the class.
561Intensive set/get functions break down encapsulation.
562
563### Hiding virtual functions [MANDATORY]
49663e13 564
f6e968a7 565Avoid hiding a base class virtual function by a redefined function with a different signature.
566Most of the compilers issue warning on this.
567
568### Avoid mixing error reporting strategies
49663e13 569
570Try not to mix different error indication/handling strategies (exceptions or returned values) on the same application level.
f6e968a7 571
572### Minimize compiler warnings [MANDATORY]
49663e13 573
f6e968a7 574When compiling the source pay attention to and try to minimize compiler warnings.
575
49663e13 576### Avoid unnecessary inclusions
f6e968a7 577
49663e13 578Try to minimize compilation dependencies by removing unnecessary inclusions.
f6e968a7 579
49663e13 580@section occt_coding_rules_6 General C/C++ rules
581
582This section defines the rules for writing a portable and maintainable C/C++ source code.
f6e968a7 583
584### Wrapping of global variables [MANDATORY]
49663e13 585
586Use package or class methods returning reference to wrap global variables to reduce possible name space conflicts.
f6e968a7 587
588### Avoid private members
49663e13 589
590Use *protected* members instead of *private* wherever reasonable to enable future extensions.
591Use *private* fields if future extensions should be disabled.
f6e968a7 592
593### Constants and inlines over defines [MANDATORY]
49663e13 594
ba06f8bb 595Use constant variables (const) and inline functions instead of defines (\#define).
f6e968a7 596
597### Avoid explicit numerical values [MANDATORY]
49663e13 598
f6e968a7 599Avoid usage of explicit numeric values. Use named constants and enumerations instead.
49663e13 600Numbers produce difficulties for reading and maintenance.
f6e968a7 601
602### Three mandatory methods
49663e13 603
604If a class has a destructor, an assignment operator or a copy constructor, it usually needs the other two methods.
f6e968a7 605
606### Virtual destructor
49663e13 607
f6e968a7 608A class with virtual function(s) ought to have a virtual destructor.
609
a3157439 610### Overriding virtual methods
611
612Declaration of overriding method should contains specifiers "virtual" and "override"
613(using Standard_OVERRIDE alias for compatibility with old compilers).
614
615~~~~~{.cpp}
616class MyPackage_BaseClass
617{
618
619public:
620
621 Standard_EXPORT virtual Standard_Boolean Perform();
622
623};
624
a3157439 625class MyPackage_MyClass : public MyPackage_BaseClass
626{
627
628public:
629
630 Standard_EXPORT virtual Standard_Boolean Perform() Standard_OVERRIDE;
631
632};
633~~~~~
634
635This makes class definition more clear (virtual methods become highlighted).
636
637Declaration of interface using pure virtual functions protects against
638incomplete inheritance at first level, but does not help when method is overridden multiple times within nested inheritance
639or when method in base class is intended to be optional.
640
641And here "override" specifier introduces additional protection against situations when interface changes might be missed
642(class might contain old methods which will be never called).
643
f6e968a7 644### Default parameter value
49663e13 645
f6e968a7 646Do not redefine a default parameter value in an inherited function.
647
648### Use const modifier
49663e13 649
650Use *const* modifier wherever possible (functions parameters, return values, etc.)
f6e968a7 651
652### Usage of goto [MANDATORY]
49663e13 653Avoid *goto* statement unless it is really needed.
f6e968a7 654
655### Declaring variable in for() header
49663e13 656
657Declare a cycle variable in the header of the *for()* statement if not used out of cycle.
f6e968a7 658
659~~~~~{.cpp}
660Standard_Real aMinDist = Precision::Infinite();
661for (NCollection_Sequence<gp_Pnt>::Iterator aPntIter (theSequence);
662 aPntIter.More(); aPntIter.Next())
663{
664 aMinDist = Min (aMinDist, theOrigin.Distance (aPntIter.Value()));
665}
666~~~~~
667
668### Condition statements within zero
49663e13 669
f6e968a7 670Avoid usage of C-style comparison for non-boolean variables:
671
672~~~~~{.cpp}
673void Function (Standard_Integer theValue,
674 Standard_Real* thePointer)
675{
676 if (!theValue) // bad style - ambiguous logic
677 {
678 DoSome();
679 }
680
681 if (theValue == 0) // OK
682 {
683 DoSome();
684 }
685
686 if (thePointer != NULL) // OK, predefined NULL makes pointer comparison cleaner to reader
687 { // (nullptr should be used instead as soon as C++11 will be available)
688 DoSome2();
689 }
690}
691~~~~~
692
49663e13 693@section occt_coding_rules_7 Portability issues
f6e968a7 694
695This chapter contains rules that are critical for cross-platform portability.
696
49663e13 697### Provide code portability [MANDATORY]
698
699The source code must be portable to all platforms listed in the official 'Technical Requirements'.
f6e968a7 700The term 'portable' here means 'able to be built from source'.
701
702The C++ source code should meet C++03 standard.
49663e13 703Any usage of compiler-specific features or further language versions (for example, C++11, until all major compilers on all supported platforms implement all its features) should be optional (used only with appropriate preprocessor checks) and non-exclusive (an alternative implementation compatible with other compilers should be provided).
f6e968a7 704
705### Avoid usage of global variables [MANDATORY]
49663e13 706
707Avoid usage of global variables. Usage of global variables may cause problems when accessed from another shared library.
708
709Use global (package or class) functions that return reference to static variable local to this function instead of global variables.
710
f6e968a7 711Another possible problem is the order of initialization of global variables defined in various libraries that may differ depending on platform, compiler and environment.
712
713### Avoid explicit basic types
f6e968a7 714
49663e13 715Avoid explicit usage of basic types (*int*, *float*, *double*, etc.), use Open CASCADE Technology types from package *Standard: Standard_Integer, Standard_Real, Standard_ShortReal, Standard_Boolean, Standard_CString* and others or a specific *typedef* instead.
716
717### Use *sizeof()* to calculate sizes [MANDATORY]
f6e968a7 718
49663e13 719Do not assume sizes of types. Use *sizeof()* instead to calculate sizes.
720
721### Empty line at the end of file [MANDATORY]
722
723In accordance with C++03 standard source files should be trailed by an empty line.
f6e968a7 724It is recommended to follow this rule for any plain text files for consistency and for correct work of git difference tools.
725
49663e13 726@section occt_coding_rules_8 Stability issues
f6e968a7 727
728The rules listed in this chapter are important for stability of the programs that use Open CASCADE Technology libraries.
729
49663e13 730### Use *OSD::SetSignal()* to catch exceptions
731
732When using Open CASCADE Technology in an application, call *OSD::SetSignal()* function when the application is initialized.
733
734This will install C handlers for run-time interrupt signals and exceptions, so that low-level exceptions (such as access violation, division by zero, etc.) will be redirected to C++ exceptions
735that use *try {...} catch (Standard_Failure) {...}* blocks.
736
f6e968a7 737The above rule is especially important for robustness of modeling algorithms.
738
739### Cross-referenced handles
f6e968a7 740
49663e13 741Take care about cycling of handled references to avoid chains, which will never be freed. For this purpose, use a pointer at one (subordinate) side.
f6e968a7 742
49663e13 743See the following example:
744
04c2daa4 745~~~~{.cpp}
746 class Slave;
49663e13 747
04c2daa4 748 class Master : public Standard_Transient
749 {
f6e968a7 750 ...
04c2daa4 751 void SetSlave (const Handle(Slave)& theSlave)
752 {
753 mySlave = theSlave;
754 }
f6e968a7 755 ...
04c2daa4 756 private:
757 Handle(Slave) theSlave; // smart pointer
f6e968a7 758 ...
04c2daa4 759 }
f6e968a7 760
04c2daa4 761 class Slave : public Standard_Transient
762 {
f6e968a7 763 ...
04c2daa4 764 void SetMaster (const Handle(Master)& theMaster)
765 {
766 myMaster = theMaster.get();
767 }
f6e968a7 768 ...
04c2daa4 769 private:
770 Master* theMaster; // simple pointer
f6e968a7 771 ...
04c2daa4 772 }
49663e13 773~~~~
f6e968a7 774
f6e968a7 775### C++ memory allocation
f6e968a7 776
49663e13 777In C++ use *new* and *delete* operators instead of *malloc()* and *free()*. Try not to mix different memory allocation techniques.
778
779### Match *new* and *delete* [MANDATORY]
780
f6e968a7 781Use the same form of new and delete.
782
783~~~~~{.cpp}
784aPtr1 = new TypeA[n]; ... ; delete[] aPtr1;
785aPtr2 = new TypeB(); ... ; delete aPtr2;
786aPtr3 = Standard::Allocate (4096); ... ; Standard::Free (aPtr3);
787~~~~~
788
789### Methods managing dynamical allocation [MANDATORY]
49663e13 790
f6e968a7 791Define a destructor, a copy constructor and an assignment operator for classes with dynamically allocated memory.
792
793### Uninitialized variables [MANDATORY]
49663e13 794
f6e968a7 795Every variable should be initialized.
796
797~~~~~{.cpp}
798Standard_Integer aTmpVar1; // bad
799Standard_Integer aTmpVar2 = 0; // OK
800~~~~~
801
49663e13 802Uninitialized variables might be kept only within performance-sensitive code blocks and only when their initialization is guaranteed by subsequent code.
f6e968a7 803
49663e13 804### Do not hide global *new*
805
806Avoid hiding the global *new* operator.
f6e968a7 807
808### Assignment operator
49663e13 809
810In *operator=()* assign to all data members and check for assignment to self.
f6e968a7 811
812### Float comparison
49663e13 813
f6e968a7 814Don't check floats for equality or non-equality; check for GT, GE, LT or LE.
815
816~~~~~{.cpp}
817if (Abs (theFloat1 - theFloat2) < theTolerance)
818{
819 DoSome();
820}
821~~~~~
822
49663e13 823Package *Precision* provides standard values for SI units and widely adopted by existing modeling algorithms:
824
825- *Precision::Confusion()* for lengths in meters;
826- *Precision::Angular()* for angles in radians.
f6e968a7 827
49663e13 828as well as definition of infinite values within normal range of double precision:
829- *Precision::Infinite()*
830- *Precision::IsInfinite()*
831- *Precision::IsPositiveInfinite()*
832- *Precision::IsNegativeInfinite()*
f6e968a7 833
834### Non-indexed iteration
49663e13 835
f6e968a7 836Avoid usage of iteration over non-indexed collections of objects.
49663e13 837If such iteration is used, make sure that the result of the algorithm does not depend on the order of iterated items.
f6e968a7 838
49663e13 839Since the order of iteration is unpredictable in case of a non-indexed collection of objects, it frequently leads to different behavior of the application from one run to another, thus embarrassing the debugging process.
840
841It mostly concerns mapped objects for which pointers are involved in calculating the hash function. For example, the hash function of *TopoDS_Shape* involves the address of *TopoDS_TShape* object. Thus the order of the same shape in the *TopTools_MapOfShape* will vary in different sessions of the application.
f6e968a7 842
843### Do not throw in destructors
49663e13 844
845Do not throw from within a destructor.
f6e968a7 846
847### Assigning to reference [MANDATORY]
f6e968a7 848
49663e13 849Avoid the assignment of a temporary object to a reference. This results in a different behavior for different compilers on different platforms.
850
851@section occt_coding_rules_9 Performance issues
f6e968a7 852
853These rules define the ways of avoiding possible loss of performance caused by ineffective programming.
854
855### Class fields alignment
49663e13 856
857Declare fields of a class in the decreasing order of their size for better alignment.
f6e968a7 858Generally, try to reduce misaligned accesses since they impact the performance (for example, on Intel machines).
859
860### Fields initialization order [MANDATORY]
49663e13 861
f6e968a7 862List class data members in the constructor's initialization list in the order they are declared.
863
864~~~~~{.cpp}
865class MyPackage_MyClass
866{
867
868public:
869
870 MyPackage_MyClass()
871 : myPropertyA (1),
872 myPropertyB (2) {}
873
874// NOT
875// : myPropertyB (2),
876// myPropertyA (1) {}
877
878private:
879
880 Standard_Integer myPropertyA;
881 Standard_Integer myPropertyB;
882
883};
884~~~~~
885
886### Initialization over assignment
49663e13 887
888Prefer initialization over assignment in class constructors.
f6e968a7 889
890~~~~~{.cpp}
891MyPackage_MyClass()
892: myPropertyA (1) // preferred
893{
894 myPropertyB = 2; // not recommended
895}
896~~~~~
897
898### Optimize caching
49663e13 899
900When programming procedures with extensive memory access, try to optimize them in terms of cache behavior. Here is an example of how the cache behavior can be impacted:
901
f6e968a7 902On x86 this code
903
904~~~~~{.cpp}
905Standard_Real anArray[4096][2];
906for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
907{
908 anArray[anIter][0] = anArray[anIter][1];
909}
910~~~~~
911
49663e13 912is more efficient then
f6e968a7 913
914~~~~~{.cpp}
915Standard_Real anArray[2][4096];
916for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
917{
918 anArray[0][anIter] = anArray[1][anIter];
919}
920~~~~~
921
49663e13 922since linear access does not invalidate cache too often.
923
924@section occt_coding_rules_10 Draw Harness command
925
926Draw Harness provides TCL interface for OCCT algorithms.
927
928There is no TCL wrapper over OCCT C++ classes, instead interface is provided through the set of TCL commands implemented in C++.
929
930There is a list of common rules which should be followed to implement well-formed Draw Harness command.
931
932### Return value
933
934Command should return 0 in most cases even if the executed algorithm has failed. Returning 1 would lead to a TCL exception, thus should be used in case of a command line syntax error and similar issues.
935
936### Validate input parameters
937
938Command arguments should be validated before usage. The user should see a human-readable error description instead of a runtime exception from the executed algorithm.
939
940### Validate the number of input parameters
941
942Command should warn the user about unknown arguments, including cases when extra parameters have been pushed for the command with a fixed number of arguments.
943
944~~~~~{.cpp}
945 if (theArgsNb != 3)
946 {
947 std::cout << "Syntax error - wrong number of arguments!\n";
948 return 1;
949 }
950
951 Standard_Integer anArgIter = 1;
952 Standard_CString aResName = theArgVec[anArgIter++];
953 Standard_CString aFaceName = theArgVec[anArgIter++];
954 TopoDS_Shape aFaceShape = DBRep::Get (aFaceName);
955 if (aFaceShape.IsNull()
956 || aFaceShape.ShapeType() != TopAbs_FACE)
957 {
958 std::cout << "Shape " << aFaceName << " is empty or not a Face!\n";
959 return 1;
960 }
961 DBRep::Set (aResName, aFaceShape);
962 return 0;
963~~~~~
964
965### Message printing
966
3f812249 967Informative messages should be printed into standard output *std::cout*, whilst command results (if any) -- into Draw Interpreter.
49663e13 968
969Information printed into Draw Interpreter should be well-structured to allow usage in TCL script.
970
971### Long list of arguments
972
973Any command with a long list of obligatory parameters should be considered as ill-formed by design.
974Optional parameters should start with flag name (with '-' prefix) and followed by its values:
975
976~~~~~{.tcl}
977myCommand -flag1 value1 value2 -flag2 value3
978~~~~~
f6e968a7 979
49663e13 980### Arguments parser
f6e968a7 981
f8eb9b17 982- Integer values should be read using *Draw::Atoi()* function.
983- Real values should be read using *Draw::Atof()* function.
49663e13 984- Flags names should be checked in case insensitive manner.
985
f8eb9b17 986Functions *Draw::Atof()* and *Draw::Atoi()* support expressions and read values in C-locale.
49663e13 987
988~~~~~{.cpp}
989 Standard_Real aPosition[3] = {0.0, 0.0, 0.0};
990 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
991 {
992 Standard_CString anArg = theArgVec[anArgIter];
993 TCollection_AsciiString aFlag (anArg);
994 aFlag.LowerCase(); //!< for case insensitive comparison
995 if (aFlag == "position")
996 {
997 if ((anArgIt + 3) >= theArgsNb)
998 {
999 std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
1000 return 1;
1001 }
1002 aPosition[0] = Draw::Atof (theArgVec[++anArgIt]);
1003 aPosition[1] = Draw::Atof (theArgVec[++anArgIt]);
1004 aPosition[2] = Draw::Atof (theArgVec[++anArgIt]);
1005 }
1006 else
1007 {
1008 std::cout << "Syntax error! Unknown flag '" << anArg << "'\n";
1009 return 1;
1010 }
1011 }
1012~~~~~
1013
1014@section occt_coding_rules_11 Examples
1015
1016### Sample documented class
f6e968a7 1017
1018@verbatim
f6e968a7 1019class Package_Class
1020{
1021
1022public: //! @name public methods
1023
1024 //! Method computes the square value.
1025 //! @param theValue the input value
1026 //! @return squared value
1027 Standard_Export Standard_Real Square (const Standard_Real theValue);
1028
49663e13 1029private: //! \@name private methods
f6e968a7 1030
1031 //! Auxiliary method
1032 void increment();
1033
49663e13 1034private: //! \@name private fields
f6e968a7 1035
1036 Standard_Integer myCounter; //!< usage counter
1037
1038};
49663e13 1039
1040
f6e968a7 1041@endverbatim
1042
49663e13 1043~~~~~
f6e968a7 1044#include <Package_Class.hxx>
f6e968a7 1045// ==========================================================
1046// function : Square
1047// purpose : Method computes the square value
1048// ==========================================================
1049Standard_Real Package_Class::Square (const Standard_Real theValue)
1050{
1051 increment();
1052 return theValue * theValue;
1053}
1054
1055// ==========================================================
1056// function : increment
1057// purpose :
1058// ==========================================================
1059void Package_Class::increment()
1060{
1061 ++myCounter;
1062}
1063~~~~~
1064
49663e13 1065### TCL script for Draw Harness
1066
f6e968a7 1067~~~~~{.tcl}
1068# show fragments (solids) in shading with different colors
1069proc DisplayColored {theShape} {
1070 set aSolids [uplevel #0 explode $theShape so]
1071 set aColorIter 0
1072 set THE_COLORS {red green blue1 magenta1 yellow cyan1 brown}
1073 foreach aSolIter $aSolids {
1074 uplevel #0 vdisplay $aSolIter
1075 uplevel #0 vsetcolor $aSolIter [lindex $THE_COLORS [expr [incr aColorIter] % [llength $THE_COLORS]]]
1076 uplevel #0 vsetdispmode $aSolIter 1
1077 uplevel #0 vsetmaterial $aSolIter plastic
1078 uplevel #0 vsettransparency $aSolIter 0.5
1079 }
1080}
1081
1082# load modules
1083pload MODELING VISUALIZATION
1084
1085# create boxes
1086box bc 0 0 0 1 1 1
1087box br 1 0 0 1 1 2
1088compound bc br c
1089
1090# show fragments (solids) in shading with different colors
1091vinit View1
1092vclear
1093vaxo
1094vzbufftrihedron
1095DisplayColored c
1096vfit
1097vdump $imagedir/${casename}.png 512 512
1098~~~~~
1099
49663e13 1100### GLSL program:
f6e968a7 1101~~~~~{.fs}
1102vec3 Ambient; //!< Ambient contribution of light sources
1103vec3 Diffuse; //!< Diffuse contribution of light sources
1104vec3 Specular; //!< Specular contribution of light sources
1105
1106//! Computes illumination from light sources
1107vec4 ComputeLighting (in vec3 theNormal,
1108 in vec3 theView,
1109 in vec4 thePoint)
1110{
1111 // clear the light intensity accumulators
1112 Ambient = occLightAmbient.rgb;
1113 Diffuse = vec3 (0.0);
1114 Specular = vec3 (0.0);
1115 vec3 aPoint = thePoint.xyz / thePoint.w;
1116 for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)
1117 {
1118 int aType = occLight_Type (anIndex);
1119 if (aType == OccLightType_Direct)
1120 {
1121 directionalLight (anIndex, theNormal, theView);
1122 }
1123 else if (aType == OccLightType_Point)
1124 {
1125 pointLight (anIndex, theNormal, theView, aPoint);
1126 }
1127 }
1128
1129 return vec4 (Ambient, 1.0) * occFrontMaterial_Ambient()
1130 + vec4 (Diffuse, 1.0) * occFrontMaterial_Diffuse()
1131 + vec4 (Specular, 1.0) * occFrontMaterial_Specular();
1132}
1133
1134//! Entry point to the Fragment Shader
1135void main()
1136{
1137 gl_FragColor = computeLighting (normalize (Normal),
1138 normalize (View),
1139 Position);
1140}
1141~~~~~