0024413: Visualization - get rid of projection shift from orthographic camera definition
[occt.git] / dox / dev_guides / contribution / coding_rules.md
CommitLineData
f6e968a7 1Coding Rules {#dev_guides__coding_rules}
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.
39- In OCAF, packages that define transient, persistent data classes and drivers to map between them, have similar names prefixed by *T*, *P*, and *M* correspondingly (e.g. *TDocStd*, *PDocStd*, *MDocStd*).
40- Packages ending with <i>...Test</i> define Draw Harness plugins.
41- Methods starting with *Get...* and *Set...* are usually responsible for correspondingly retrieving and storing data.
f6e968a7 42
43### Related names
49663e13 44
45Names related to a logically connected functionality should have the same prefix (start with the same letters) or, at least, have any other common part.
46For example, method *GetCoord* returns a triple of real values and is defined for directions, vectors and points. The logical connection is obvious.
f6e968a7 47
48### Camel Case style
49Camel Case style is preferred for names.
50For example:
51
52~~~~~{.cpp}
53Standard_Integer awidthofbox; // this is bad
54Standard_Integer width_of_box; // this is bad
55Standard_Integer aWidthOfBox; // this is OK
56~~~~~
57
49663e13 58@subsection occt_coding_rules_2_2 Names of development units
f6e968a7 59
49663e13 60Usually 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 61
49663e13 62### No underscores in unit names [MANDATORY]
f6e968a7 63
49663e13 64Names of units should not contain underscores, unless the use of underscores is allowed explicitly.
f6e968a7 65
49663e13 66### File name extensions [MANDATORY]
67
68The following extensions should be used for source files, depending on their type:
f6e968a7 69
49663e13 70* <i>.cdl</i> - CDL declaration files
71* <i>.cxx</i> - C++ source files
72* <i>.hxx</i> - C++ header files
73* <i>.lxx</i> - headers with definitions of inline methods (CDL packages)
f6e968a7 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~~~~~
86 <package-name>_<class-name>.cxx (or .hxx, or .cdl)
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.
49663e13 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 *_my*.
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
f6e968a7 241Delete unused code instead of commenting it or using #define.
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.
253* For better readability it is also recommended to surround conventional operators by a space character. See the following examples:
f6e968a7 254
255~~~~~{.cpp}
256while (true) // NOT: while( true ) ...
257{
258 DoSomething (theA, theB, theC, theD); // NOT: DoSomething(theA,theB,theC,theD);
259}
260for (anIter = 0; anIter < 10; ++anIter) // NOT: for (anIter=0;anIter<10;++anIter){
261{
262 theA = (theB + theC) * theD; // NOT: theA=(theB+theC)*theD
263}
264~~~~~
265
266### Separate logical blocks
49663e13 267
f6e968a7 268Separate logical blocks of code with one blank line and comments.
49663e13 269
f6e968a7 270See the following example:
271
272~~~~~{.cpp}
273// check arguments
274Standard_Integer anArgsNb = argCount();
275if (anArgsNb < 3 || isSmthInvalid)
276{
277 return THE_ARG_INVALID;
278}
279
280// read and check header
281...
282...
283
284// do our job
285...
286...
287~~~~~
288
289Notice that multiple blank lines should be avoided.
290
291### Separate function bodies [MANDATORY]
49663e13 292
f6e968a7 293Use function descriptive blocks to separate function bodies from each other.
49663e13 294Each descriptive block should contain at least a function name and purpose description.
295
f6e968a7 296See the following example:
297
298~~~~~{.cpp}
299// ----------------------------------------------
300// function : TellMeSmthGood
301// purpose : Gives me good news
302// ----------------------------------------------
303void TellMeSmthGood()
304{
305 ...
306}
307
308// ----------------------------------------------
309// function : TellMeSmthBad
310// purpose : Gives me bad news
311// ----------------------------------------------
312void TellMeSmthBad()
313{
314 ...
315}
316~~~~~
317
318### Block layout [MANDATORY]
49663e13 319Figure brackets <i>{ }</i> and each operator <i>(for, if, else, try, catch)</i> should be written on a dedicated line.
320
321In general, the layout should be as follows:
f6e968a7 322
323~~~~~{.cpp}
324while (expression)
325{
326 ...
327}
328~~~~~
329
49663e13 330Entering a block increases and leaving a block decreases the indentation by one tabulation.
f6e968a7 331
332### Single-line operators
49663e13 333
334Single-line conditional operators <i>(if, while, for,</i> etc.) can be written without brackets on the following line.
f6e968a7 335
336~~~~~{.cpp}
337if (!myIsInit) return Standard_False; // bad
338
339if (thePtr == NULL) // OK
340 return Standard_False;
341
342if (!theAlgo.IsNull()) // preferred
343{
344 DoSomething();
345}
346~~~~~
347
49663e13 348Having all code in the same line is less convenient for debugging.
f6e968a7 349
49663e13 350### Alignment
351
352Use alignment wherever it enhances the readability. See the following example:
f6e968a7 353
354~~~~~{.cpp}
355MyPackage_MyClass anObject;
356Standard_Real aMinimum = 0.0;
357Standard_Integer aVal = theVal;
358switch (aVal)
359{
360 case 0: computeSomething(); break;
361 case 12: computeSomethingElse (aMinimum); break;
362 case 3:
363 default: computeSomethingElseYet(); break;
364}
365~~~~~
366
367### Indentation of comments
49663e13 368
369Comments 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.
370
371The text of the comment should be separated from the slash character by a single space character.
372
f6e968a7 373See the following example:
374
375~~~~~{.cpp}
376while (expression) //bad comment
377{
378 // this is a long multi-line comment
379 // which is really required
380 DoSomething(); // maybe, enough
381 DoSomethingMore(); // again
382}
383~~~~~
384
385### Early return statement
49663e13 386
387Use an early return condition rather than collect indentations.
388
389Write like this:
f6e968a7 390
391~~~~~{.cpp}
392Standard_Integer ComputeSumm (const Standard_Integer* theArray,
393 const Standard_Size theSize)
394{
395 Standard_Integer aSumm = 0;
396 if (theArray == NULL || theSize == 0)
397 {
398 return 0;
399 }
400
401 ... computing summ ...
402 return aSumm;
403}
404~~~~~
405
49663e13 406Rather than:
f6e968a7 407
408~~~~~{.cpp}
409Standard_Integer ComputeSumm (const Standard_Integer* theArray,
410 const Standard_Size theSize)
411{
412 Standard_Integer aSumm = 0;
413 if (theArray != NULL && theSize != 0)
414 {
415 ... computing summ ...
416 }
417 return aSumm;
418}
419~~~~~
420
49663e13 421This helps to improve readability and reduce the unnecessary indentation depth.
f6e968a7 422
423### Trailing spaces
49663e13 424
425Trailing spaces should be removed whenever possible.
426Spaces at the end of a line are useless and do not affect functionality.
f6e968a7 427
428### Headers order
49663e13 429
430Split headers into groups: system headers, headers per each framework, project headers; sort the list of includes alphabetically.
431
432This rule improves readability, allows detecting useless multiple header inclusions and makes 3rd-party dependencies clearly visible.
f6e968a7 433
434~~~~~{.cpp}
435// system headers
436#include <iostream>
437#include <windows.h>
438
439// Qt headers
440#include <QDataStream>
441#include <QString>
442
443// OCCT headers
444#include <gp_Pnt.hxx>
445#include <gp_Vec.hxx>
446#include <NCollection_List.hxx>
447~~~~~
448
49663e13 449@section occt_coding_rules_4 Documentation rules
f6e968a7 450
451The source code is one of the most important references for documentation.
49663e13 452The comments in the source code should be complete enough to allow understanding the corresponding code and to serve as basis for other documents.
f6e968a7 453
49663e13 454The main reasons why the comments are regarded as documentation and should be maintained are:
455- The comments are easy to reach - they are always together with the source code;
456- It is easy to update a description in the comment when the source is modified;
457- The source by itself is a good context to describe various details that would require much more explanations in a separate document;
458- As a summary, this is the most cost-effective documentation.
f6e968a7 459
460The comments should be compatible with Doxygen tool for automatic documentation generation (thus should use compatible tags).
461
462### Documenting classes [MANDATORY]
49663e13 463
f6e968a7 464Each class should be documented in its header file (.hxx or .cdl).
49663e13 465The comment should give enough details for the reader to understand the purpose of the class and the main way of work with it.
f6e968a7 466
467### Documenting class methods [MANDATORY]
49663e13 468
f6e968a7 469Each class or package method should be documented in the header file (.hxx or .cdl).
49663e13 470
f6e968a7 471The comment should explain the purpose of the method, its parameters, and returned value(s).
472Accepted style is:
473
474@verbatim
475//! Method computes the square value.
476//! @param theValue the input value
477//! @return squared value
478Standard_Export Standard_Real Square (Standard_Real theValue);
479@endverbatim
480
481### Documenting C/C++ sources
49663e13 482
f6e968a7 483It is very desirable to put comments in the C/C++ sources of the package/class.
f6e968a7 484
49663e13 485They should be detailed enough to allow any person to understand what each part of code does.
486
487It 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.
488
489There are also some rules that define how comments should be formatted, see <a href="#occt_coding_rules_3">Formatting Rules</a>.
490
491Following 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 492
49663e13 493@section occt_coding_rules_5 Application design
494
495The following rules define the common style, which should be applied by any developer contributing to the open source.
496
497### Allow possible inheritance
f6e968a7 498
f6e968a7 499Try to design general classes (objects) keeping possible inheritance in mind.
49663e13 500This rule means that the user who makes possible extensions of your class should not encounter problems of private implementation.
f6e968a7 501Try to use protected members and virtual methods wherever you expect extensions in the future.
502
503### Avoid friend declarations
49663e13 504
505Avoid using 'friend' classes or functions except for some specific cases (for example, iteration) 'Friend' declarations increase coupling.
f6e968a7 506
507### Set/get methods
49663e13 508
f6e968a7 509Avoid providing set/get methods for all fields of the class.
510Intensive set/get functions break down encapsulation.
511
512### Hiding virtual functions [MANDATORY]
49663e13 513
f6e968a7 514Avoid hiding a base class virtual function by a redefined function with a different signature.
515Most of the compilers issue warning on this.
516
517### Avoid mixing error reporting strategies
49663e13 518
519Try not to mix different error indication/handling strategies (exceptions or returned values) on the same application level.
f6e968a7 520
521### Minimize compiler warnings [MANDATORY]
49663e13 522
f6e968a7 523When compiling the source pay attention to and try to minimize compiler warnings.
524
49663e13 525### Avoid unnecessary inclusions
f6e968a7 526
49663e13 527Try to minimize compilation dependencies by removing unnecessary inclusions.
f6e968a7 528
49663e13 529@section occt_coding_rules_6 General C/C++ rules
530
531This section defines the rules for writing a portable and maintainable C/C++ source code.
f6e968a7 532
533### Wrapping of global variables [MANDATORY]
49663e13 534
535Use package or class methods returning reference to wrap global variables to reduce possible name space conflicts.
f6e968a7 536
537### Avoid private members
49663e13 538
539Use *protected* members instead of *private* wherever reasonable to enable future extensions.
540Use *private* fields if future extensions should be disabled.
f6e968a7 541
542### Constants and inlines over defines [MANDATORY]
49663e13 543
f6e968a7 544Use constant variables (const) and inline functions instead of defines (#define).
545
546### Avoid explicit numerical values [MANDATORY]
49663e13 547
f6e968a7 548Avoid usage of explicit numeric values. Use named constants and enumerations instead.
49663e13 549Numbers produce difficulties for reading and maintenance.
f6e968a7 550
551### Three mandatory methods
49663e13 552
553If a class has a destructor, an assignment operator or a copy constructor, it usually needs the other two methods.
f6e968a7 554
555### Virtual destructor
49663e13 556
f6e968a7 557A class with virtual function(s) ought to have a virtual destructor.
558
559### Default parameter value
49663e13 560
f6e968a7 561Do not redefine a default parameter value in an inherited function.
562
563### Use const modifier
49663e13 564
565Use *const* modifier wherever possible (functions parameters, return values, etc.)
f6e968a7 566
567### Usage of goto [MANDATORY]
49663e13 568Avoid *goto* statement unless it is really needed.
f6e968a7 569
570### Declaring variable in for() header
49663e13 571
572Declare a cycle variable in the header of the *for()* statement if not used out of cycle.
f6e968a7 573
574~~~~~{.cpp}
575Standard_Real aMinDist = Precision::Infinite();
576for (NCollection_Sequence<gp_Pnt>::Iterator aPntIter (theSequence);
577 aPntIter.More(); aPntIter.Next())
578{
579 aMinDist = Min (aMinDist, theOrigin.Distance (aPntIter.Value()));
580}
581~~~~~
582
583### Condition statements within zero
49663e13 584
f6e968a7 585Avoid usage of C-style comparison for non-boolean variables:
586
587~~~~~{.cpp}
588void Function (Standard_Integer theValue,
589 Standard_Real* thePointer)
590{
591 if (!theValue) // bad style - ambiguous logic
592 {
593 DoSome();
594 }
595
596 if (theValue == 0) // OK
597 {
598 DoSome();
599 }
600
601 if (thePointer != NULL) // OK, predefined NULL makes pointer comparison cleaner to reader
602 { // (nullptr should be used instead as soon as C++11 will be available)
603 DoSome2();
604 }
605}
606~~~~~
607
49663e13 608@section occt_coding_rules_7 Portability issues
f6e968a7 609
610This chapter contains rules that are critical for cross-platform portability.
611
49663e13 612### Provide code portability [MANDATORY]
613
614The source code must be portable to all platforms listed in the official 'Technical Requirements'.
f6e968a7 615The term 'portable' here means 'able to be built from source'.
616
617The C++ source code should meet C++03 standard.
49663e13 618Any 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 619
620### Avoid usage of global variables [MANDATORY]
49663e13 621
622Avoid usage of global variables. Usage of global variables may cause problems when accessed from another shared library.
623
624Use global (package or class) functions that return reference to static variable local to this function instead of global variables.
625
f6e968a7 626Another possible problem is the order of initialization of global variables defined in various libraries that may differ depending on platform, compiler and environment.
627
628### Avoid explicit basic types
f6e968a7 629
49663e13 630Avoid 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.
631
632### Use *sizeof()* to calculate sizes [MANDATORY]
f6e968a7 633
49663e13 634Do not assume sizes of types. Use *sizeof()* instead to calculate sizes.
635
636### Empty line at the end of file [MANDATORY]
637
638In accordance with C++03 standard source files should be trailed by an empty line.
f6e968a7 639It is recommended to follow this rule for any plain text files for consistency and for correct work of git difference tools.
640
49663e13 641@section occt_coding_rules_8 Stability issues
f6e968a7 642
643The rules listed in this chapter are important for stability of the programs that use Open CASCADE Technology libraries.
644
49663e13 645### Use *OSD::SetSignal()* to catch exceptions
646
647When using Open CASCADE Technology in an application, call *OSD::SetSignal()* function when the application is initialized.
648
649This 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
650that use *try {...} catch (Standard_Failure) {...}* blocks.
651
f6e968a7 652The above rule is especially important for robustness of modeling algorithms.
653
654### Cross-referenced handles
f6e968a7 655
49663e13 656Take 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 657
49663e13 658See the following example:
659
660In *MyPackage.cdl* :
661
662~~~~
f6e968a7 663 class MyFirstHandle;
664 class MySecondHandle;
665 pointer MySecondPointer to MySecondHandle;
666 ...
49663e13 667~~~~
f6e968a7 668
49663e13 669In *MyPackage_MyFirstHandle.cdl* :
f6e968a7 670
49663e13 671~~~~
f6e968a7 672 class MyFirstHandle from MyPackage
673 ...
674 is
675 ...
676 SetSecondHandleA (me: mutable; theSecond: MySecondHandle from MyPackage);
677 SetSecondHandleB (me: mutable; theSecond: MySecondHandle from MyPackage);
678 ...
679 fields
680 ...
681 mySecondHandle : MySecondHandle from MyPackage;
682 mySecondPointer : MySecondPointer from MyPackage;
683 ...
684 end MyFirstHandle from MyPackage;
49663e13 685~~~~
f6e968a7 686
49663e13 687In *MyPackage_MySecondHandle.cdl* :
f6e968a7 688
49663e13 689~~~~
f6e968a7 690 class MySecondHandle from MyPackage
691 ...
692 is
693 ...
694 SetFirstHandle (me: mutable; theFirst: MyFirstHandle from MyPackage);
695 ...
696 fields
697 ...
698 myFirstHandle : MyFirstHandle from MyPackage;
699 ...
700 end MySecondHandle from MyPackage;
49663e13 701~~~~
f6e968a7 702
703In C++ code:
704
705~~~~~{.cpp}
706void MyFunction()
707{
708 Handle(MyPackage_MyFirstHandle) anObj1 = new MyPackage_MyFirstHandle();
709 Handle(MyPackage_MySecondHandle) anObj2 = new MyPackage_MySecondHandle();
710 Handle(MyPackage_MySecondHandle) anObj3 = new MyPackage_MySecondHandle();
711
712 anObj1->SetSecondHandleA(anObj2);
713 anObj1->SetSecondHandleB(anObj3);
714 anObj2->SetFirstHandle(anObj1);
715 anObj3->SetFirstHandle(anObj1);
716
717 // memory is not freed here !!!
718 anObj1.Nullify();
719 anObj2.Nullify();
720
721 // memory is freed here
722 anObj3.Nullify();
723}
724~~~~~
725
726### C++ memory allocation
f6e968a7 727
49663e13 728In C++ use *new* and *delete* operators instead of *malloc()* and *free()*. Try not to mix different memory allocation techniques.
729
730### Match *new* and *delete* [MANDATORY]
731
f6e968a7 732Use the same form of new and delete.
733
734~~~~~{.cpp}
735aPtr1 = new TypeA[n]; ... ; delete[] aPtr1;
736aPtr2 = new TypeB(); ... ; delete aPtr2;
737aPtr3 = Standard::Allocate (4096); ... ; Standard::Free (aPtr3);
738~~~~~
739
740### Methods managing dynamical allocation [MANDATORY]
49663e13 741
f6e968a7 742Define a destructor, a copy constructor and an assignment operator for classes with dynamically allocated memory.
743
744### Uninitialized variables [MANDATORY]
49663e13 745
f6e968a7 746Every variable should be initialized.
747
748~~~~~{.cpp}
749Standard_Integer aTmpVar1; // bad
750Standard_Integer aTmpVar2 = 0; // OK
751~~~~~
752
49663e13 753Uninitialized variables might be kept only within performance-sensitive code blocks and only when their initialization is guaranteed by subsequent code.
f6e968a7 754
49663e13 755### Do not hide global *new*
756
757Avoid hiding the global *new* operator.
f6e968a7 758
759### Assignment operator
49663e13 760
761In *operator=()* assign to all data members and check for assignment to self.
f6e968a7 762
763### Float comparison
49663e13 764
f6e968a7 765Don't check floats for equality or non-equality; check for GT, GE, LT or LE.
766
767~~~~~{.cpp}
768if (Abs (theFloat1 - theFloat2) < theTolerance)
769{
770 DoSome();
771}
772~~~~~
773
49663e13 774Package *Precision* provides standard values for SI units and widely adopted by existing modeling algorithms:
775
776- *Precision::Confusion()* for lengths in meters;
777- *Precision::Angular()* for angles in radians.
f6e968a7 778
49663e13 779as well as definition of infinite values within normal range of double precision:
780- *Precision::Infinite()*
781- *Precision::IsInfinite()*
782- *Precision::IsPositiveInfinite()*
783- *Precision::IsNegativeInfinite()*
f6e968a7 784
785### Non-indexed iteration
49663e13 786
f6e968a7 787Avoid usage of iteration over non-indexed collections of objects.
49663e13 788If such iteration is used, make sure that the result of the algorithm does not depend on the order of iterated items.
f6e968a7 789
49663e13 790Since 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.
791
792It 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 793
794### Do not throw in destructors
49663e13 795
796Do not throw from within a destructor.
f6e968a7 797
798### Assigning to reference [MANDATORY]
f6e968a7 799
49663e13 800Avoid the assignment of a temporary object to a reference. This results in a different behavior for different compilers on different platforms.
801
802@section occt_coding_rules_9 Performance issues
f6e968a7 803
804These rules define the ways of avoiding possible loss of performance caused by ineffective programming.
805
806### Class fields alignment
49663e13 807
808Declare fields of a class in the decreasing order of their size for better alignment.
f6e968a7 809Generally, try to reduce misaligned accesses since they impact the performance (for example, on Intel machines).
810
811### Fields initialization order [MANDATORY]
49663e13 812
f6e968a7 813List class data members in the constructor's initialization list in the order they are declared.
814
815~~~~~{.cpp}
816class MyPackage_MyClass
817{
818
819public:
820
821 MyPackage_MyClass()
822 : myPropertyA (1),
823 myPropertyB (2) {}
824
825// NOT
826// : myPropertyB (2),
827// myPropertyA (1) {}
828
829private:
830
831 Standard_Integer myPropertyA;
832 Standard_Integer myPropertyB;
833
834};
835~~~~~
836
837### Initialization over assignment
49663e13 838
839Prefer initialization over assignment in class constructors.
f6e968a7 840
841~~~~~{.cpp}
842MyPackage_MyClass()
843: myPropertyA (1) // preferred
844{
845 myPropertyB = 2; // not recommended
846}
847~~~~~
848
849### Optimize caching
49663e13 850
851When 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:
852
f6e968a7 853On x86 this code
854
855~~~~~{.cpp}
856Standard_Real anArray[4096][2];
857for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
858{
859 anArray[anIter][0] = anArray[anIter][1];
860}
861~~~~~
862
49663e13 863is more efficient then
f6e968a7 864
865~~~~~{.cpp}
866Standard_Real anArray[2][4096];
867for (Standard_Integer anIter = 0; anIter < 4096; ++anIter)
868{
869 anArray[0][anIter] = anArray[1][anIter];
870}
871~~~~~
872
49663e13 873since linear access does not invalidate cache too often.
874
875@section occt_coding_rules_10 Draw Harness command
876
877Draw Harness provides TCL interface for OCCT algorithms.
878
879There is no TCL wrapper over OCCT C++ classes, instead interface is provided through the set of TCL commands implemented in C++.
880
881There is a list of common rules which should be followed to implement well-formed Draw Harness command.
882
883### Return value
884
885Command 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.
886
887### Validate input parameters
888
889Command arguments should be validated before usage. The user should see a human-readable error description instead of a runtime exception from the executed algorithm.
890
891### Validate the number of input parameters
892
893Command should warn the user about unknown arguments, including cases when extra parameters have been pushed for the command with a fixed number of arguments.
894
895~~~~~{.cpp}
896 if (theArgsNb != 3)
897 {
898 std::cout << "Syntax error - wrong number of arguments!\n";
899 return 1;
900 }
901
902 Standard_Integer anArgIter = 1;
903 Standard_CString aResName = theArgVec[anArgIter++];
904 Standard_CString aFaceName = theArgVec[anArgIter++];
905 TopoDS_Shape aFaceShape = DBRep::Get (aFaceName);
906 if (aFaceShape.IsNull()
907 || aFaceShape.ShapeType() != TopAbs_FACE)
908 {
909 std::cout << "Shape " << aFaceName << " is empty or not a Face!\n";
910 return 1;
911 }
912 DBRep::Set (aResName, aFaceShape);
913 return 0;
914~~~~~
915
916### Message printing
917
918Informative messages should be printed into standard output *std::cout*, whilst command results (if any) - into Draw Interpreter.
919
920Information printed into Draw Interpreter should be well-structured to allow usage in TCL script.
921
922### Long list of arguments
923
924Any command with a long list of obligatory parameters should be considered as ill-formed by design.
925Optional parameters should start with flag name (with '-' prefix) and followed by its values:
926
927~~~~~{.tcl}
928myCommand -flag1 value1 value2 -flag2 value3
929~~~~~
f6e968a7 930
49663e13 931### Arguments parser
f6e968a7 932
49663e13 933- Integer values should be read using *Draw:Atoi()* function.
934- Real values should be read using *Draw:Atof()* function.
935- Flags names should be checked in case insensitive manner.
936
937Functions *Draw:Atof()* and *Draw:Atoi()* support expressions and read values in C-locale.
938
939~~~~~{.cpp}
940 Standard_Real aPosition[3] = {0.0, 0.0, 0.0};
941 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
942 {
943 Standard_CString anArg = theArgVec[anArgIter];
944 TCollection_AsciiString aFlag (anArg);
945 aFlag.LowerCase(); //!< for case insensitive comparison
946 if (aFlag == "position")
947 {
948 if ((anArgIt + 3) >= theArgsNb)
949 {
950 std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
951 return 1;
952 }
953 aPosition[0] = Draw::Atof (theArgVec[++anArgIt]);
954 aPosition[1] = Draw::Atof (theArgVec[++anArgIt]);
955 aPosition[2] = Draw::Atof (theArgVec[++anArgIt]);
956 }
957 else
958 {
959 std::cout << "Syntax error! Unknown flag '" << anArg << "'\n";
960 return 1;
961 }
962 }
963~~~~~
964
965@section occt_coding_rules_11 Examples
966
967### Sample documented class
f6e968a7 968
969@verbatim
f6e968a7 970class Package_Class
971{
972
973public: //! @name public methods
974
975 //! Method computes the square value.
976 //! @param theValue the input value
977 //! @return squared value
978 Standard_Export Standard_Real Square (const Standard_Real theValue);
979
49663e13 980private: //! \@name private methods
f6e968a7 981
982 //! Auxiliary method
983 void increment();
984
49663e13 985private: //! \@name private fields
f6e968a7 986
987 Standard_Integer myCounter; //!< usage counter
988
989};
49663e13 990
991
f6e968a7 992@endverbatim
993
49663e13 994~~~~~
f6e968a7 995#include <Package_Class.hxx>
f6e968a7 996// ==========================================================
997// function : Square
998// purpose : Method computes the square value
999// ==========================================================
1000Standard_Real Package_Class::Square (const Standard_Real theValue)
1001{
1002 increment();
1003 return theValue * theValue;
1004}
1005
1006// ==========================================================
1007// function : increment
1008// purpose :
1009// ==========================================================
1010void Package_Class::increment()
1011{
1012 ++myCounter;
1013}
1014~~~~~
1015
49663e13 1016### TCL script for Draw Harness
1017
f6e968a7 1018~~~~~{.tcl}
1019# show fragments (solids) in shading with different colors
1020proc DisplayColored {theShape} {
1021 set aSolids [uplevel #0 explode $theShape so]
1022 set aColorIter 0
1023 set THE_COLORS {red green blue1 magenta1 yellow cyan1 brown}
1024 foreach aSolIter $aSolids {
1025 uplevel #0 vdisplay $aSolIter
1026 uplevel #0 vsetcolor $aSolIter [lindex $THE_COLORS [expr [incr aColorIter] % [llength $THE_COLORS]]]
1027 uplevel #0 vsetdispmode $aSolIter 1
1028 uplevel #0 vsetmaterial $aSolIter plastic
1029 uplevel #0 vsettransparency $aSolIter 0.5
1030 }
1031}
1032
1033# load modules
1034pload MODELING VISUALIZATION
1035
1036# create boxes
1037box bc 0 0 0 1 1 1
1038box br 1 0 0 1 1 2
1039compound bc br c
1040
1041# show fragments (solids) in shading with different colors
1042vinit View1
1043vclear
1044vaxo
1045vzbufftrihedron
1046DisplayColored c
1047vfit
1048vdump $imagedir/${casename}.png 512 512
1049~~~~~
1050
49663e13 1051### GLSL program:
f6e968a7 1052~~~~~{.fs}
1053vec3 Ambient; //!< Ambient contribution of light sources
1054vec3 Diffuse; //!< Diffuse contribution of light sources
1055vec3 Specular; //!< Specular contribution of light sources
1056
1057//! Computes illumination from light sources
1058vec4 ComputeLighting (in vec3 theNormal,
1059 in vec3 theView,
1060 in vec4 thePoint)
1061{
1062 // clear the light intensity accumulators
1063 Ambient = occLightAmbient.rgb;
1064 Diffuse = vec3 (0.0);
1065 Specular = vec3 (0.0);
1066 vec3 aPoint = thePoint.xyz / thePoint.w;
1067 for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)
1068 {
1069 int aType = occLight_Type (anIndex);
1070 if (aType == OccLightType_Direct)
1071 {
1072 directionalLight (anIndex, theNormal, theView);
1073 }
1074 else if (aType == OccLightType_Point)
1075 {
1076 pointLight (anIndex, theNormal, theView, aPoint);
1077 }
1078 }
1079
1080 return vec4 (Ambient, 1.0) * occFrontMaterial_Ambient()
1081 + vec4 (Diffuse, 1.0) * occFrontMaterial_Diffuse()
1082 + vec4 (Specular, 1.0) * occFrontMaterial_Specular();
1083}
1084
1085//! Entry point to the Fragment Shader
1086void main()
1087{
1088 gl_FragColor = computeLighting (normalize (Normal),
1089 normalize (View),
1090 Position);
1091}
1092~~~~~