1 <html> 2 3 <head> 4 <title>drawElements Coding Guidelines</title> 5 6 <style type="text/css"> 7 div.body { 8 width: 800px; 9 margin-top: 50px; 10 margin-left: auto; 11 margin-right: auto; 12 border: 1px solid silver; 13 background-color: #eee; 14 } 15 16 div.title { 17 text-align: center; 18 font-size: 24pt; 19 margin-top: 1.5em; 20 margin-bottom: 0.5em; 21 } 22 23 div.quote { 24 font-style: italic; 25 text-align: center; 26 width: 48%; 27 margin-left: auto; 28 margin-right: auto; 29 } 30 31 div.copyright { 32 font-style: italic; 33 text-align: center; 34 margin-top: 3em; 35 margin-left: auto; 36 margin-right: auto; 37 } 38 39 div.author { 40 font-style: italic; 41 text-align: center; 42 margin-bottom: 2em; 43 margin-left: auto; 44 margin-right: auto; 45 } 46 47 /* All heading elements */ 48 ol > li > .heading { 49 font-family: arial; 50 } 51 52 /* Heading 1 elements */ 53 ol.h1 { 54 font-size: 15pt; 55 margin-top: 1em; 56 padding-left: 1em; 57 list-style: upper-roman; 58 list-style-position: inside; 59 } 60 61 ol.h1 > li { 62 margin-top: 2.0em; 63 } 64 65 ol.h1 > li > .heading { 66 } 67 68 /* Heading 2 elements */ 69 ol.h2 { 70 font-size: 13pt; 71 margin-top: 1.0em; 72 margin-bottom: 0.5em; 73 74 padding-left: 1em; 75 } 76 77 ol.h2 > li { 78 margin-top: 1.25em; 79 } 80 81 ol.h2 > li > .heading { 82 83 } 84 85 ul { 86 margin-bottom: 0.5em; 87 } 88 89 p { 90 font-size: 12pt; 91 margin: 0.6em; 92 margin-left: 1.3em; 93 border: 0px; 94 } 95 96 table { 97 font-size: 12pt; 98 margin: 0.6em; 99 margin-left: 1.6em; 100 border: 0px; 101 } 102 103 table td { 104 padding-right: 10px; 105 } 106 107 .prettyprint { 108 font-size: 10pt; 109 margin: 0px; 110 margin-left: 2.0em; 111 margin-bottom: 1.0em; 112 padding: 0.1em; 113 padding-left: 0.2em; 114 border: 1px solid black; 115 background-color: #ddd; 116 width: 93%; 117 } 118 119 .codeTitle { 120 font-style: italic; 121 font-size: 11pt; 122 margin-top: 0.5em; 123 margin-left: 2.0em; 124 margin-bottom: 0px; 125 } 126 127 </style> 128 129 <!-- \todo embed --> 130 <link href="prettify.css" type="text/css" rel="stylesheet" /> 131 <script type="text/javascript" src="prettify.js"></script> 132 133 </head> 134 135 <body onLoad="prettyPrint()"> 136 137 <div class="body"> 138 139 <div class="title">drawElements Coding Guidelines</div> 140 <hr width="50%" /> 141 <div class="quote">"Always code as if the person who will maintain your code is a maniac serial killer that knows where you live."</div> 142 143 <div class="copyright">Copyright 2014 The Android Open Source Project</div> 144 145 <ol class="h1"> 146 <li><span class="heading">Table of Contents</span> 147 <ol class="h2"> 148 TODO: fill in, with links (use JavaScript?) 149 </ol> 150 </li> 151 152 <li><span class="heading">Introduction</span> 153 <ol class="h2"> 154 <li><span class="heading">Goal and philosophy</span> 155 <p>This document describes the drawElements coding style for C and C++ languages.</p> 156 157 <p>The intention of the drawElements coding guidelines is to allow us to produce code written in a 158 consistent fashion, so that our product line will look similar throughout the line. The guiding 159 philosophy for choosing the described coding style is to avoid bugs when writing code, keep the code 160 maintainable, and also aim to make it beautiful. Some of the decisions are purely a matter of taste, 161 but have been made to keep the code consistent overall (say, camelCasing versus underscore_usage in 162 variable names.</p> 163 164 <p>There are also many areas which are not covered by this document and there is some room to bring 165 your own style into the soup. Some of the ways of writing code are just purely matters of opinion. 166 The use of whitespace in code is a good example.</p> 167 168 <p>This document is *not* the law of drawElements. If there is a good reason to deviate from it, you 169 should do that. However, if the reason is purely a matter of taste, then please follow the rules set 170 in here. Also, we want to encourage discussion about these guidelines and contributing to them, in 171 case you disagree or know a way of doing something better. This is meant to be an evolving document 172 that follows us as we learn as a group.</p> 173 174 <p>A lot of examples are included in this document to make things easily readable and unambiguous. 175 For more source material, feel free to browse the source code of whichever drawElements projects 176 you have visibility to. You should see at least <i>debase</i> and <i>depool</i> libraries, if nothing 177 else.</p> 178 </li> 179 180 <li><span class="heading">Languages of choice</span> 181 <p>The main languages at drawElements are Ansi C89 and ISO C++ 98. Ansi C is used for developing 182 driver or middleware IP, while C++ can be used for stand-alone applications.</p> 183 184 <p>The reason for using C for middleware IP development is that we build software for 185 mobile devices and the compilers there are often of dubious quality, especially when it comes to 186 support of C++. Same goes for C99. In addition C++ runtime library is a non-trivial dependency.</p> 187 188 <p>Stand-alone userspace applications can be written in C++. By now almost all relevant 189 platforms have reasonable C++ support. While all ISO C++ 1998 features, including standard template 190 library, can be used, C++11 features must not be exercised.</p> 191 192 <p>For utility and tool development, other languages may also be used. So far, Python has been used 193 for all such development and is encouraged to be used in future tools as well. If there are strong 194 reasons, other languages may also be considered.</p> 195 </li> 196 197 <li><span class="heading">C code example</span> 198 199 <p>Let's get started with some sample drawElements code. The code files below show a simple random 200 "class" implemented in C89. The code is taken from the drawElements base portability library, debase.</p> 201 <div class="codeTitle">deRandom.h: The header file.</div> 202 <pre class="prettyprint"> 203 #ifndef _DERANDOM_H 204 #define _DERANDOM_H 205 /*------------------------------------------------------------------------- 206 * drawElements Base Portability Library 207 * ------------------------------------- 208 * 209 * Copyright 2014 The Android Open Source Project 210 * 211 * Licensed under the Apache License, Version 2.0 (the "License"); 212 * you may not use this file except in compliance with the License. 213 * You may obtain a copy of the License at 214 * 215 * http://www.apache.org/licenses/LICENSE-2.0 216 * 217 * Unless required by applicable law or agreed to in writing, software 218 * distributed under the License is distributed on an "AS IS" BASIS, 219 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 220 * See the License for the specific language governing permissions and 221 * limitations under the License. 222 * 223 * Id: $Id$ 224 *//*! 225 * \file 226 * \brief Random number generation. 227 *//*--------------------------------------------------------------------*/ 228 229 #ifndef _DEDEFS_H 230 # include "deDefs.h" 231 #endif 232 233 DE_BEGIN_EXTERN_C 234 235 /*--------------------------------------------------------------------*//*! 236 * \brief Random number generator. 237 * 238 * Uses the Xorshift algorithm for producing pseudo-random numbers. The 239 * values are generated based on an initial seed and the same seed always 240 * produces the same sequence of numbers. 241 * 242 * See: http://en.wikipedia.org/wiki/Xorshift 243 *//*--------------------------------------------------------------------*/ 244 typedef struct deRandom_s 245 { 246 deUint32 x; /*!< Current random state. */ 247 deUint32 y; 248 deUint32 z; 249 deUint32 w; 250 } deRandom; 251 252 void deRandom_init (deRandom* rnd, deUint32 seed); 253 deUint32 deRandom_getUint32 (deRandom* rnd); 254 float deRandom_getFloat (deRandom* rnd); 255 deBool deRandom_getBool (deRandom* rnd); 256 257 DE_END_EXTERN_C 258 259 #endif /* _DERANDOM_H */ 260 </pre> 261 <div class="codeTitle">deRandom.c: The implementation file.</div> 262 <pre class="prettyprint"> 263 /*------------------------------------------------------------------------- 264 * drawElements Base Portability Library 265 * ------------------------------------- 266 * 267 * Copyright 2014 The Android Open Source Project 268 * \todo insert legalese here. 269 * 270 * Id: $Id$ 271 *//*! 272 * \file 273 * \brief Random number generation. 274 *//*--------------------------------------------------------------------*/ 275 276 #include "deRandom.h" 277 278 #include <float.h> 279 #include <math.h> 280 281 DE_BEGIN_EXTERN_C 282 283 /*--------------------------------------------------------------------*//*! 284 * \brief Initialize a random number generator with a given seed. 285 * \param rnd RNG to initialize. 286 * \param seed Seed value used for random values. 287 *//*--------------------------------------------------------------------*/ 288 void deRandom_init (deRandom* rnd, deUint32 seed) 289 { 290 rnd->x = (deUint32)(-(int)seed ^ 123456789); 291 rnd->y = (deUint32)(362436069 * seed); 292 rnd->z = (deUint32)(521288629 ^ (seed >> 7)); 293 rnd->w = (deUint32)(88675123 ^ (seed << 3)); 294 } 295 296 /*--------------------------------------------------------------------*//*! 297 * \brief Get a pseudo random uint32. 298 * \param rnd Pointer to RNG. 299 * \return Random uint32 number. 300 *//*--------------------------------------------------------------------*/ 301 deUint32 deRandom_getUint32 (deRandom* rnd) 302 { 303 const deUint32 w = rnd->w; 304 deUint32 t; 305 306 t = rnd->x ^ (rnd->x << 11); 307 rnd->x = rnd->y; 308 rnd->y = rnd->z; 309 rnd->z = w; 310 rnd->w = w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 311 return w; 312 } 313 314 /*--------------------------------------------------------------------*//*! 315 * \brief Get a pseudo random float in range [0, 1[. 316 * \param rnd Pointer to RNG. 317 * \return Random float number. 318 *//*--------------------------------------------------------------------*/ 319 float deRandom_getFloat (deRandom* rnd) 320 { 321 return (deRandom_getUint32(rnd) & 0xFFFFFFFu) / (float)(0xFFFFFFFu+1); 322 } 323 324 /*--------------------------------------------------------------------*//*! 325 * \brief Get a pseudo random boolean value (DE_FALSE or DE_TRUE). 326 * \param rnd Pointer to RNG. 327 * \return Random float number. 328 *//*--------------------------------------------------------------------*/ 329 deBool deRandom_getBool (deRandom* rnd) 330 { 331 deUint32 val = deRandom_getUint32(rnd); 332 return ((val & 0xFFFFFF) < 0x800000); 333 } 334 335 DE_END_EXTERN_C 336 </pre> 337 </li> 338 <li><span class="heading">C++ code example</span> 339 340 <p>The following code, taken from deutil demonstrates how C++ classes should look like.</p> 341 <div class="codeTitle">deUniquePtr.hpp: Unique pointer template.</div> 342 <pre class="prettyprint"> 343 #ifndef _DEUNIQUEPTR_HPP 344 #define _DEUNIQUEPTR_HPP 345 /*------------------------------------------------------------------------- 346 * drawElements C++ Base Library 347 * ----------------------------- 348 * 349 * Copyright 2014 The Android Open Source Project 350 * 351 * Licensed under the Apache License, Version 2.0 (the "License"); 352 * you may not use this file except in compliance with the License. 353 * You may obtain a copy of the License at 354 * 355 * http://www.apache.org/licenses/LICENSE-2.0 356 * 357 * Unless required by applicable law or agreed to in writing, software 358 * distributed under the License is distributed on an "AS IS" BASIS, 359 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 360 * See the License for the specific language governing permissions and 361 * limitations under the License. 362 * 363 *//*! 364 * \file 365 * \brief Unique pointer. 366 *//*--------------------------------------------------------------------*/ 367 368 #ifndef _DEDEFS_HPP 369 # include "deDefs.hpp" 370 #endif 371 372 namespace de 373 { 374 375 /*--------------------------------------------------------------------*//*! 376 * \brief Unique pointer 377 * 378 * UniquePtr is smart pointer that retains sole ownership of a pointer 379 * and destroys it when UniquePtr is destroyed (for example when UniquePtr 380 * goes out of scope). 381 * 382 * UniquePtr is not copyable or assignable. Pointer ownership cannot be 383 * transferred between UniquePtr's. 384 *//*--------------------------------------------------------------------*/ 385 template<typename T, class Deleter = DefaultDeleter<T> > 386 class UniquePtr 387 { 388 public: 389 explicit UniquePtr (T* const ptr, Deleter deleter = Deleter()); 390 ~UniquePtr (void); 391 392 T* get (void) const throw() { return m_ptr; } //!< Get stored pointer. 393 T* operator-> (void) const throw() { return m_ptr; } //!< Get stored pointer. 394 T& operator* (void) const throw() { return *m_ptr; } //!< De-reference stored pointer. 395 396 operator bool (void) const throw() { return !!m_ptr; } 397 398 private: 399 UniquePtr (const UniquePtr<T>& other); // Not allowed! 400 UniquePtr operator= (const UniquePtr<T>& other); // Not allowed! 401 402 T* const m_ptr; 403 Deleter m_deleter; 404 }; 405 406 /*--------------------------------------------------------------------*//*! 407 * \brief Construct unique pointer. 408 * \param ptr Pointer to be managed. 409 * 410 * Pointer ownership is transferred to the UniquePtr. 411 *//*--------------------------------------------------------------------*/ 412 template<typename T, class Deleter> 413 inline UniquePtr<T, Deleter>::UniquePtr (T* const ptr, Deleter deleter) 414 : m_ptr (ptr) 415 , m_deleter (deleter) 416 { 417 } 418 419 template<typename T, class Deleter> 420 inline UniquePtr<T, Deleter>::~UniquePtr (void) 421 { 422 m_deleter(m_ptr); 423 } 424 425 } // de 426 427 #endif // _DEUNIQUEPTR_HPP 428 </pre> 429 </li> 430 </ol> 431 </li> 432 433 <li><span class="heading">Naming conventions and formatting</span> 434 <ol class="h2"> 435 <li><span class="heading">Basic naming conventions</span> 436 <p>Each project should have a prefix of its own. For drawElements base libraries, 437 the prefix <i>de</i> is used. Other projects should use a different, arbitrary prefix. 438 For instance, the stitcher project uses the <i>xo</i> prefix.</p> 439 440 <p>Anything which has a reasonable possibility of causing a naming conflict should be 441 prefixed. This includes files, structs, enums, functions (except private ones), macros, etc. 442 In C projects, just about everything in the code needs to be prefixed (files, struct, enums, 443 global functions, etc.), but in C++ code, namespaces remove the need for most prefixing. 444 File names and macros should still be prefixed in C++ code as well. Note that members 445 of classes (either C or C++), or structs or unions do not need to be prefixed with the 446 package prefix.</p> 447 448 <p>Identifiers are generally typed in camelCase. This applies to file names, structs, 449 enums, local variables, and struct members. In some cases, prefixes are used to clarify 450 the behavior of a variable. Static variables are prefixed with <i>s_</i>, global variables 451 with <i>g_</i>, and C++ class member variables with <i>m_</i>. Macros and enum entries should 452 always be written in UPPER_CASE with underscores separating the words. Members of C classes 453 don't need to be prefixed.</p> 454 455 <p>When emulating classes in C, the class name itself should be written in CamelCase, but 456 starting with a upper-case letter. Usually the classes are prefixed: <i>xoArmEmu</i>, 457 <i>deRandom</i>, but if the class only exists within a single .c file, the prefix can be 458 omitted: <i>StringBuilder</i>. The member functions of the class should be prefixed with 459 the full class name and an underscore, followed by a camelCased function name: 460 <i>xoArmEmu_emulateCode().</i></p> 461 462 <p>Examples of correctly named identifiers:</p> 463 <ul> 464 <li><i>dePool.c, dePool.h, deUniquePtr.hpp, deThread.cpp</i> -- file names</li> 465 <li><i>deRandom, xoStitcher</i> -- structs / classes</li> 466 <li><i>deMemPoolFlag, xoConditionCode</i> -- enums</li> 467 <li><i>DE_COMPILER_MSC</i> -- macros</li> 468 <li><i>XO_BACKEND_NEON</i> -- enum entry</li> 469 <li><i>setTableSize()</i> -- local (static) function</li> 470 <li><i>xoArmEmu_emulateCode()</i> -- C class member function</li> 471 <li><i>numVariables</i> -- local variable</li> 472 <li><i>m_itemHash</i> -- member variable in a C++ class</li> 473 <li><i>s_rcpTable</i> -- static variable in a function</li> 474 <li><i>g_debugFlag</i> -- global variable</li> 475 </ul> 476 </li> 477 478 <li><span class="heading">Choosing good names</span> 479 <p>Naming your variables is somewhat of a black art, but the main goal of giving a name should 480 be clarity. You want to communicate what the contents of the variable mean. The more obscure 481 the purpose of a variable is, the longer (and more descriptive) a name you should invent for it. 482 Also, the longer the life time of a variable is, the longer a name it deserves. For example, a 483 loop counter which is alive for page worth of code should be named something like <i>vertexNdx</i>, 484 whereas a loop counter which lives only a couple of lines can be named simply <i>i</i> or <i>ndx</i>.</p> 485 486 <p>Most variables should be declared const and never changed (see coding philosophy section). 487 Thus one often successful approach for variable naming is to give name for the value instead. 488 For example when querying first child of node and storing it in variable, that should be named 489 as <i>firstChild</i> instead of <i>node</i>.</p> 490 491 <p>Consistency is one important factor in naming variables. When a similar kind of name is needed 492 in multiple places, choose a way of devising the name and stick to that. E.g., if you query the 493 number of elements in an array to a local variable in several functions, always use the same name 494 in each of the functions.</p> 495 496 <p>When dealing with counts or numbers (number of elements in an array, etc.), you should always 497 clearly indicate with the name that this is the case, e.g., <i>numElements</i> (preferred), 498 <i>elementCount</i>, etc. Which ever prefix or postfix you choose to use, stick to it.</p> 499 500 <p>Function parameters that have an unit of measure (e.g. seconds or bytes) should have the unit 501 as part of the name, for example <i>timeLimitMs</i> and <i>chunkSizeKb</i>.</p> 502 503 <p>Use American English instead of English English. Choose gray over grey, color over colour, 504 and so forth.</p> 505 </li> 506 <li><span class="heading">Canonical abbreviations</span> 507 <table border="0" cellspacing="0"> 508 <tr><td>buffer </td> <td>buf</td></tr> 509 <tr><td>destination </td> <td>dst</td></tr> 510 <tr><td>index </td> <td>ndx</td></tr> 511 <tr><td>source </td> <td>src</td></tr> 512 <tr><td>variable </td> <td>var</td></tr> 513 </table> 514 </li> 515 516 <li><span class="heading">Struct and enum typedeffing</span> 517 <p>For enums and structs, the types should always be typedeffed and used without the struct or 518 enum prefix in actual code.</p> 519 520 <div class="codeTitle">Example.</div> 521 <pre class="prettyprint"> 522 /* Declaration. */ 523 typedef enum xoConditionCode_e 524 { 525 ... 526 } xoConditionCode; 527 528 typedef struct deMempool_s 529 { 530 ... 531 } deMemPool; 532 533 /* Usage. */ 534 deMemPool* memPool; 535 xoConditionCode condCode; 536 </pre> 537 </li> 538 539 <li><span class="heading">Header files and including</span> 540 <p>All header files should have include guards in them to avoid processing them multiple times 541 in case they are included from multiple places. The style used for the macro is <i>_FILENAME_H</i>, 542 for example: <i>_DEDEFS_H</i>. Whenever including other headers from a header file, you should 543 always use external include guards as well. The external include guards considerably reduce the 544 number of file accesses that the compiler needs to make, resulting in faster compile times.</p> 545 546 <p>Each implementation file should have matching header file and vice versa. The implementation 547 file must include the corresponding header file first. By doing that, it is guaranteed that the 548 header file includes all of its dependencies.</p> 549 550 <p>Each header file should first include <i>deDefs.h</i>, or alternatively project-specific 551 <i>xxDefs.h/hpp</i> file that in turn includes deDefs.h. That way all the usual types and macros 552 are always properly defined.</p> 553 554 <div class="codeTitle">External include guard example.</div> 555 <pre class="prettyprint"> 556 #ifndef _DEDEFS_H 557 # include "deDefs.h" 558 #endif 559 #ifndef _DEINT32_H 560 # include "deInt32.h" 561 #endif 562 #ifndef _DEUNIQUEPTR_HPP 563 # include "deUniquePtr.hpp" 564 #endif 565 </pre> 566 567 <p>The include order of files should start from <i>debase</i> (esp. <i>deDefs.h</i>), go thru 568 other base libraries, then your own project header files, and lastly the system header files. 569 Also, a <i>.c</i> file must include its own header file first. E.g., <i>deMemPool.c</i> must 570 first include <i>deMemPool.h</i>.</p> 571 572 <p>Every include path must also end up including <i>deDefs.h</i> before any actual code is processed. 573 This ensures that the basic portability macros (<i>DE_OS</i>, <i>DE_COMPILE</i>, etc.) have been 574 defined.</p> 575 </li> 576 577 <li><span class="heading">Indenting and whitespace</span> 578 <p>Code should be indented with tabs (instead of spaces) and a tab-width of 4 characters should 579 be used.</p> 580 581 <p>Always put braces on their own lines. This applies to functions, structs, enums, ifs, loops, 582 everything. The only exception are single-line scopes. For one-statement ifs or loops, braces 583 should not be used. Also, put <i>else</i> and <i>else if</i> on their own lines as well.</p> 584 585 <div class="codeTitle">Brace usage</div> 586 <pre class="prettyprint"> 587 void main (int argc, const char** argv) 588 { 589 if (argc > 1) 590 parseArgs(argv[1]); 591 else 592 { 593 printf("Usage:\n"); 594 printf("...\n"); 595 } 596 } 597 </pre> 598 599 <p>In addition to only indenting your code, things like variable names in a list of 600 declarations or comments at the end of line, should also be aligned such that they start at 601 the same column. Compare the following two examples of the same code, only with differing 602 alignments in the text.</p> 603 604 <div class="codeTitle">Aligned variable declarations and comments.</div> 605 <pre class="prettyprint"> 606 struct deMemPool_s 607 { 608 deUint32 flags; /*!< Flags. */ 609 deMemPool* parent; /*!< Pointer to parent (null for root pools). */ 610 deMemPoolUtil* util; /*!< Utilities (callbacks etc.). */ 611 int numChildren; /*!< Number of child pools. */ 612 deMemPool* firstChild; /*!< Pointer to first child pool in linked list. */ 613 deMemPool* prevPool; /*!< Previous pool in parent's linked list. */ 614 deMemPool* nextPool; /*!< Next pool in parent's linked list. */ 615 ... 616 }; 617 </pre> 618 619 <div class="codeTitle">No alignments used.</div> 620 <pre class="prettyprint"> 621 struct deMemPool_s 622 { 623 deUint32 flags; /*!< Flags. */ 624 deMemPool* parent; /*!< Pointer to parent (null for root pools). */ 625 deMemPoolUtil* util; /*!< Utilities (callbacks etc.). */ 626 int numChildren; /*!< Number of child pools. */ 627 deMemPool* firstChild; /*!< Pointer to first child pool in linked list. */ 628 deMemPool* prevPool; /*!< Previous pool in parent's linked list. */ 629 deMemPool* nextPool; /*!< Next pool in parent's linked list. */ 630 ... 631 }; 632 </pre> 633 </li> 634 635 <li><span class="heading">Other formatting</span> 636 637 <p>Always use C-style comments in C code: /* This is a C comment. */ Only use 638 the C++ // end-of-line comments in C++ code.</p> 639 640 <div class="codeTitle">Comment styles.</div> 641 <pre class="prettyprint"> 642 /* Use this kind of comments in C code. */ 643 644 // This kind of comments may only be used in C++ code. 645 </pre> 646 647 <div class="codeTitle">Pointer and references.</div> 648 <pre class="prettyprint"> 649 // Good: pointers and references are a part of the type 650 void* ptr; 651 deInt32* colorBuffer; 652 xoArmEmu* armEmu; 653 Array<int>& intArray; 654 void doBlend (deUint32* dst, const deUint32* src); 655 656 // Bad: pointer symbol should not be a part of the name 657 void *ptr; 658 void doBlend (deUint32 *dst, const deUint32 * src); 659 </pre> 660 661 <div class="codeTitle">Formatting of function declarations.</div> 662 <pre class="prettyprint"> 663 // Good: void if empty param list, empty space after name, braces on own line 664 void doStuff (void) 665 { 666 } 667 668 // Bad: horrible function name! 669 void doStuff() { 670 } 671 672 // Good: separate arguments with spaces, function name 673 ShapeList getIntersectingShapes (float x, float y, float z) 674 { 675 } 676 677 // Bad: function name (list of what volumes?), no space after commas in arg list 678 ShapeList getShapeList (float x,float y,float z) 679 { 680 } 681 682 // Exception: sometimes simple function are best written as one-liners 683 float deFloatAbs (float f) { return (f < 0.0f) ? -f : f; } 684 685 </pre> 686 687 <div class="codeTitle">Formatting of control statements.</div> 688 <pre class="prettyprint"> 689 // Good: no extra braces for one-liner if cases 690 if (a.isZero) 691 result = 0.0f; 692 else 693 result = a.value * (1.0 / 65536.0f); 694 695 // Bad: extraneous braces, bad whitespace usage 696 if (a.isZero) 697 { 698 result=0.0f; 699 } 700 else 701 { 702 result=a.value*(1.0 / 65536.0f); 703 } 704 705 // Good: expression easy to read 706 if (a.isZero && b.isZero) 707 { 708 ... 709 } 710 711 // Bad: missing spaces around && operator, missing space after 'if' 712 if(a.isZero&&b.isZero) 713 { 714 ... 715 } 716 717 // Good: else on its own line 718 if (alpha == 0) 719 { 720 ... 721 } 722 else if (alpha == 255) 723 { 724 ... 725 } 726 else 727 { 728 ... 729 } 730 731 // Bad: else on same line as closing brace 732 if (alpha == 0) 733 { 734 ... 735 } else if (...) 736 { 737 ... 738 } else 739 { 740 ... 741 } 742 743 // Good: note space after 'while' 744 while (numTriangles--) 745 { 746 ... 747 } 748 749 // Bad: whitespace usage 750 while(numTriangles --) 751 { 752 ... 753 } 754 755 // Good: while on same line as closing brace 756 do 757 { 758 ... 759 } while (--numTriangles); 760 761 // Bad: while on its own line, missing whitespace after 'while' 762 do 763 { 764 ... 765 } 766 while(--numTriangles); 767 768 // Good: easy to read 769 for (ndx = 0; ndx < numTriangles; ndx++) 770 771 // Bad: missing spaces all over (whitespace should be used to separate expressions) 772 for(ndx=0;ndx<numTriangles;ndx ++) 773 774 // Good: note missing braces for while, correct usage of whitespace 775 while (numTriangles--) 776 area += computeArea(triangle[ndx++]); 777 778 // Bad: don't put unnecessary braces, avoid extraneous whitespace in expressions 779 while (numTriangles--) 780 { 781 area+=computeArea( triangle [ndx++] ); 782 } 783 </pre> 784 785 <div class="codeTitle">Formatting switch cases.</div> 786 <pre class="prettyprint"> 787 // Good: case-statements indented, code indented another level (including breaks) 788 switch (blendMode) 789 { 790 case XX_BLENDMODE_NORMAL: // no variable declarations 791 ... 792 break; 793 794 case XX_BLENDMODE_SRC_OVER: // need braces if declaring variables inside 795 { 796 int alpha = ...; 797 break; 798 } 799 800 case XX_BLENDMODE_XYZ: 801 ... 802 // FALLTHRU! -- make non-breaked cases very explicit! 803 804 default: // handles the final blendmode (DISABLED) with an assertion! 805 DE_ASSERT(blendMode == XX_BLENDMODE_DISABLED); 806 807 break; // always put break! 808 } 809 810 // Bad: 811 switch(blendMode) 812 { 813 case XX_BLENDMODE_NORMAL: // always indent case labels 814 ... 815 break; // put break on same level as indented code! 816 817 case XX_BLENDMODE_SRC_OVER: 818 { 819 ... 820 break; 821 } 822 823 case XX_BLENDMODE_XYZ: 824 ... 825 826 case XX_BLENDMODE_DISABLED: // always comment the case fall-through (like above) 827 ... 828 } // default case missing! always need to handle it (and assert if illegal!) 829 </pre> 830 831 <div class="codeTitle">Formatting of expressions.</div> 832 <pre class="prettyprint"> 833 // Good: parenthesis or whitespace used to indicate evaluation order 834 array[(a * b) + c]; 835 array[a*b + c]; 836 837 // Bad: order unclear 838 array[a*b+c]; 839 840 // Good: parenthesis (or whitespace) makes evaluation order unambiguous 841 array[(a && b) || (c == 0)] 842 array[a==0 || b==0 || c==0] // in some cases spaces can be used instead of parenthesis 843 844 // Bad: unclear evaluation order 845 array[a&&b || c==0] // does this even work? 846 array[a == 0 || b == 0 || c == 0] 847 848 // Good: easy to see different parts of evaluation (whitespace where it matters) 849 array[triangle->index0 - cache.baseIndex]; 850 851 // Bad: hard to read (whitespace around brackets doesn't help readability!) 852 array[ triangle->index0-cache.baseIndex ]; 853 array [triangle -> index0 - cache.baseIndex]; 854 855 // Good: easy to see all function arguments 856 computeArea(vtx0.x, vtx0.y, vtx1.x, vtx1.y, vtx2.x, vtx2.y); 857 858 // Bad: missing spaces makes it hard to read, no space after function name when calling 859 computeArea ( vtx0.x,vtx0.y,vtx1.x,vtx1.y,vtx2.x,vtx2.y ); 860 861 // Good: readable (the code itself is a made-up example and thus incomprehensible) 862 // Consider: would probably make more readable code to use temporary variables here 863 if (sizeArray[a+5] > getSize(getFoo()+2)) 864 if (sizeArray[a + 5] > getSize(getFoo() + 2)) 865 866 // Bad: whitespace usage confuses rather than helps 867 if(sizeArray[a+5]>getSize(getFoo()+2)) 868 if ( sizeArray [ a + 5 ] > getSize ( getFoo () + 2 ) ) 869 870 // Bad: unclear (and wrong) evaluation order 871 if (bitMask & (1<<bit) == 0) 872 </pre> 873 874 <div class="codeTitle">Other formatting.</div> 875 <pre class="prettyprint"> 876 #if defined(DE_DEBUG) // prefer #if defined() to #ifdef 877 ... 878 #endif /* DE_DEBUG */ // only put ending comment if #if is far away 879 880 </pre> 881 </li> 882 </ol> 883 </li> 884 885 <li><span class="heading">Base library services</span> 886 <p>TODO: explain all of these</p> 887 888 <ol class="h2"> 889 <li><span class="heading"><b>debase</b>/deDefs.h</span> 890 <pre> 891 - DE_COMPILER, DE_OS, DE_CPU 892 - basic types (deUint8, deIntptr, deBool==int, ..) 893 - DE_NULL 894 - DE_DEBUG -- #if defined(DE_DEBUG) 895 - DE_INLINE 896 - DE_ASSERT(), DE_VERIFY(), DE_TEST_ASSERT(), DE_STATIC_ASSERT() 897 - DE_BREAKPOINT() 898 - DE_SWAP() 899 - DE_LENGTH_OF_ARRAY() 900 - DE_OFFSET_OF() 901 - DE_UNREF() 902 - DE_BEGIN_EXTERN_C, DE_END_EXTERN_C 903 - DE_NULL_STATEMENT</pre> 904 </li> 905 906 <li><span class="heading">Other <b>debase</b> headers</span> 907 <pre> 908 - deInt32.h: deInRange32(), deInBounds32(), hashing 909 - deFloat16.h: fp16<->fp32 910 - deMath.h: generic float math 911 - deRandom.h: random number generation 912 - deMemory.h: allocating memory, deMemset(), deMemcpy(), DE_NEW(), DE_DELETE() 913 - deString.h:</pre> 914 </li> 915 916 <li><span class="heading"><b>depool</b> services</span> 917 <pre> 918 - memory pools (deMemPool) 919 - pooled data structures 920 * Array 921 * Set 922 * Hash 923 * HashArray 924 * HashSet</pre> 925 </li> 926 </ol> 927 </li> 928 929 <li><span class="heading">Commenting code</span> 930 <ol class="h2"> 931 <li><span class="heading">File comment boxes</span> 932 <p>Each source file should contain the following comment box. In header files the comment is placed after 933 the #ifdef-#endif pair. On implementation files the comment box is placed at the beginning.</p> 934 <pre class="prettyprint"> 935 /*------------------------------------------------------------------------- 936 * Full Module Name 937 * ---------------- 938 * 939 * Copyright 2014 The Android Open Source Project 940 * 941 * Licensed under the Apache License, Version 2.0 (the "License"); 942 * you may not use this file except in compliance with the License. 943 * You may obtain a copy of the License at 944 * 945 * http://www.apache.org/licenses/LICENSE-2.0 946 * 947 * Unless required by applicable law or agreed to in writing, software 948 * distributed under the License is distributed on an "AS IS" BASIS, 949 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 950 * See the License for the specific language governing permissions and 951 * limitations under the License. 952 * 953 *//*! 954 * \file 955 * \brief Short description of the contents. 956 * 957 * Followed by longer description if necessary (such as high-level algorithm 958 * description). 959 *//*--------------------------------------------------------------------*/ 960 <pre> 961 </li> 962 963 <li><span class="heading">Structs/classes/enums comment boxes</span> 964 <p>TODO: </p> 965 </li> 966 967 <li><span class="heading">Other Doxygen comment boxes (/** ... */ and /*!< ... */)</span> 968 <p>TODO: single-line, multi-line</p> 969 </li> 970 971 <li><span class="heading">Code comments</span> 972 <p>Below and example of code commenting for C. When doing C++, you can replace C-style comments with C++-comments.</p> 973 <pre class="prettyprint"> 974 callFoo(&a); 975 976 /* Comment about following block (Note empty line before and after)*/ 977 978 callBar(&b); 979 c = a + b; /* Why we need to do this op */ 980 doItAll(a, b, c); 981 982 /* Badness starts with this comment */ 983 callBar(&b); 984 /* Why we need to do this op */ 985 c = a + b; 986 doItAll(a, b, c); 987 988 </pre> 989 </li> 990 991 <li><span class="heading">Tags</span> 992 <p>Todo-comments should use the following syntax:</p> 993 <pre class="prettyprint"> 994 /* \todo [2012-01-26 pyry] Give a longer description of todo-usage in code. */ 995 </pre> 996 <p>If you wish to communicate to fellow developer about some unexpected behavior or corner-case 997 that is not obvious, <i>\note</i> tag can be used.</p> 998 <pre class="prettyprint"> 999 /* \note Tangent may be zero. */ 1000 </pre> 1001 </li> 1002 </ol> 1003 </li> 1004 1005 <li><span class="heading">Generic programming</span> 1006 <ol class="h2"> 1007 <li><span class="heading">Classes in C</span> 1008 <p>TODO: explain</p> 1009 </li> 1010 1011 <li><span class="heading">Const correctness</span> 1012 <p>When declaring function arguments, local variables, or class members, all non-mutable ones 1013 must be declared const. Declaring variable const communicates clearly your intent to not modify 1014 the given value. This is especially important in function argument lists.</p> 1015 1016 <p>Declaring local variables, or function arguments that are passed by value, const, may be a bit 1017 controversial. There are indeed a lots of existing code that doesn't follow this rule. However, 1018 adding extra constness has proven to improve code readability a quite bit and thus all new code 1019 must use const correctly. The only exception is function arguments passed by value; for those 1020 const keyword can be omitted. By-value function arguments are however considered to be const 1021 for all purposes.</p> 1022 1023 <div class="codeTitle">Example.</div> 1024 <pre class="prettyprint"> 1025 // Function example. Note const qualifier on maxDepth as well which is passed by value. 1026 static glu::VarType generateRandomType (const int maxDepth, int& curStructIdx, vector<const StructType*>& structTypesDst, Random& rnd) 1027 { 1028 const bool isStruct = maxDepth > 0 && rnd.getFloat() < 0.2f; 1029 const bool isArray = rnd.getFloat() < 0.3f; 1030 1031 ... 1032 } 1033 1034 // Class members 1035 class Node 1036 { 1037 public: 1038 Node (Node* const parent); 1039 ~Node (void); 1040 1041 ... 1042 private: 1043 Node* const m_parent; 1044 }; 1045 1046 Node::Node (Node* const parent) 1047 : m_parent(parent) // Const members can be initialized 1048 { 1049 } 1050 </pre> 1051 </li> 1052 1053 <li><span class="heading">Declaring variables</span> 1054 <p>All variables should be declared at the beginning of a block. If variables are introduced in 1055 the middle of code, nested block must be used. This is what ANSI C requires, and the same style must 1056 be used in C++ code as well. The only exception for this is loop counters in C++; they may be 1057 declared in loop init expression.</p> 1058 1059 <p>Having variable declarations always at the beginning of the block makes code easier to read 1060 as no new state is introduced in the middle of code. It also guides towards writing smaller 1061 functions that don't use too many variables.</p> 1062 1063 <div class="codeTitle">Example.</div> 1064 <pre class="prettyprint"> 1065 static void logTransformFeedbackVaryings (TestLog& log, const glw::Functions& gl, const deUint32 program) 1066 { 1067 int numTfVaryngs = 0; 1068 int maxNameLen = 0; 1069 1070 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &numTfVaryngs); 1071 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxNameLen); 1072 GLU_EXPECT_NO_ERROR(gl.getError(), "Query TF varyings"); 1073 1074 { 1075 vector<char> nameBuf(maxNameLen+1); 1076 1077 for (int ndx = 0; ndx < numTfVaryngs; ndx++) 1078 { 1079 ... 1080 </pre> 1081 </li> 1082 1083 <li><span class="heading">Variable life-time</span> 1084 <p>TODO: minimize life-time of a variable (may sometimes need additional scopes in C)</p> 1085 </li> 1086 1087 <li><span class="heading">Enumerations</span> 1088 <p>TODO: assign zero to first, let compiler assign others (in typical lists)</p> 1089 <p>TODO: use ENUM_LAST</p> 1090 <p>TODO: mask values</p> 1091 <p>TODO: use instead of #defines</p> 1092 <p>TODO: typedef xxEnumName_e trick (already explained above?)</p> 1093 </li> 1094 1095 <li><span class="heading">Error handling</span> 1096 <p>There are generally two types of errors that can occur in code; errors that stem from environment 1097 or bad input, and errors that are caused by logic error in the code. Former ones are typically 1098 outside our control (such as running into a network error) and latter are simply programming mistakes.</p> 1099 1100 <p>External errors must be handled in a graceful way. Depending on the project it may include handling 1101 out-of-memory situations as well (most certainly when doing drivers or middleware). In C function return 1102 value should be used for communicating whether external error was hit. In C++ code exceptions can 1103 be used as well. Assertions must not be used for checking external error conditions.</p> 1104 1105 <p>Internal logic errors must be checked with assertions. See next section.</p> 1106 </li> 1107 1108 <li><span class="heading">Assertions</span> 1109 <p>Assertions are a form of code documentation. They explicitly declare what the code expects from 1110 input values or current state. They are tremendously useful when trying to understand how certain 1111 piece of code should be used. In addition they are a very nice debugging aid as they help catch logic 1112 errors early on before those errors get chance to corrupt program state.</p> 1113 1114 <p>Functions should assert all non-trivial input data and conditions. The one notorious exception is 1115 that pointer validity doesn't need to be asserted if the pointer is dereferenced immediately. 1116 Non-trivial computation results should also be checked with assertions.</p> 1117 1118 <div class="codeTitle">Example.</div> 1119 <pre class="prettyprint"> 1120 // Examples of good assertions: 1121 void* deMemPool_alignedAlloc (deMemPool* pool, int numBytes, deUint32 alignBytes) 1122 { 1123 void* ptr; 1124 DE_ASSERT(pool); // Must be asserted since not dereferenced but passed to another function 1125 DE_ASSERT(numBytes > 0); // Assertion on input data condition 1126 DE_ASSERT(deIsPowerOfTwo32((int)alignBytes)); // Non-trivial input condition 1127 ptr = deMemPool_allocInternal(pool, numBytes, alignBytes); 1128 DE_ASSERT(deIsAlignedPtr(ptr, alignBytes)); // Assertion on computation result 1129 return ptr; 1130 } 1131 1132 // Badness starts here 1133 1134 void getTextureWidth (const Texture* texture) 1135 { 1136 DE_ASSERT(texture); // Bad: unnecessary, will crash anyway if texture is null 1137 return texture->width; 1138 } 1139 1140 void doStuff (void) 1141 { 1142 int i = 3; 1143 i += 2; 1144 DE_ASSERT(i == 5); // Bad: assertion on trivial computation result 1145 1146 FILE* f = fopen("myfile.txt", "rb"); 1147 DE_ASSERT(f); // Bad: there are legitimate reasons for failure 1148 } 1149 </pre> 1150 1151 </li> 1152 1153 <li><span class="heading">Lookup tables</span> 1154 <p>TODO: DE_STATIC_ASSERT lookup table size - should usually match to ENUM_TYPE_LAST</p> 1155 1156 <pre class="prettyprint"> 1157 typedef enum xxBlendEquation_e 1158 { 1159 XX_BLEND_EQUATION_ADD = 0, 1160 XX_BLEND_EQUATION_SUBTRACT, 1161 XX_BLEND_EQUATION_REVERSE_SUBTRACT, 1162 1163 XX_BLEND_EQUATION_LAST 1164 } xxBlendEquation; 1165 1166 // Note: size is left for compiler to figure out 1167 static const s_blendModeMap[] = 1168 { 1169 GL_FUNC_ADD, // XX_BLEND_EQUATION_ADD 1170 GL_FUNC_SUBTRACT, // XX_BLEND_EQUATION_SUBTRACT 1171 GL_FUNC_REVERSE_SUBTRACT // XX_BLEND_EQUATION_REVERSE_SUBTRACT 1172 }; 1173 // This will cause compilation failure lookup table size gets out of date 1174 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_blendModeMap) == XX_BLEND_EQUATION_LAST); 1175 </pre> 1176 </li> 1177 1178 <li><span class="heading">Struct size</span> 1179 <p>TODO: DE_STATIC_ASSERT of struct sizes</p> 1180 <p>TODO: use small datatypes (deUint8 instead of deBool) when size matters.</p> 1181 </li> 1182 1183 <li><span class="heading">Extraneous code</span> 1184 <p>TODO: avoid too verbose code.</p> 1185 1186 <div class="codeTitle">Example.</div> 1187 <pre class="prettyprint"> 1188 // Good: compact without sacrificing readability 1189 return (a < 0.0f) ? -a : a; 1190 1191 // Bad: waste of space 1192 float result; 1193 if (a < 0.0f) 1194 { 1195 result = -a; 1196 } 1197 else 1198 { 1199 result = a; 1200 } 1201 return result; 1202 </pre> 1203 1204 </li> 1205 </ol> 1206 </li> 1207 1208 <li><span class="heading">C++ topics</span> 1209 <ol class="h2"> 1210 <li><span class="heading">Class declarations</span> 1211 <p>TODO: how declaration looks like (already shown in example..)</p> 1212 <p>TODO: function definitions inside class ok if single-line, other special cases</p> 1213 </li> 1214 1215 <li><span class="heading">Class boilerplate</span> 1216 <p>TODO: copy ctor, assignment operator</p> 1217 </li> 1218 1219 <li><span class="heading">Code Formatting</span> 1220 <pre class="prettyprint"> 1221 1222 // Constructors 1223 FooAtom::FooAtom(int proton, float electron) 1224 : m_proton (proton) // Note aligning member initializers. 1225 , m_electron (electron) 1226 { 1227 1228 } 1229 1230 // Remember to add the name of the namespace at the end of the namespace 1231 namespace foo 1232 { 1233 1234 // Namespaces aren't indented 1235 class Proton; 1236 1237 ... 1238 } // foo 1239 </pre> 1240 </li> 1241 <li><span class="heading">RAII</span> 1242 <p>Everyone should get familiar with RAII. In a nutshell, "resource acquisition is initialization" 1243 means that a class destructor must always release all resources (such as memory or OS handles) 1244 that have been allocated during the whole lifetime of the object.</p> 1245 1246 <p>RAII is essential for exception-safe code. You should always make sure that if an exception is 1247 thrown, including out-of-memory cases, your code behaves properly and releases all allocated resources.</p> 1248 </li> 1249 1250 <li><span class="heading">Pointers and references</span> 1251 <p>In C++ references should be generally preferred over pointers. The main difference between pointers 1252 and references is that references can not change, and are not expected to be null. References should be 1253 used instead of pointers for passing objects when both conditions hold; object can not be null nor 1254 reference won't be modified once initialized.</p> 1255 <p>Pointers are used when there is need to change the address, or it can be null for a valid reason. 1256 Additionally, pointers are always used for passing basic type or object arrays.</p> 1257 </li> 1258 1259 <li><span class="heading">Containers</span> 1260 <p>TODO: describe stl container usage policies</p> 1261 </li> 1262 1263 <li><span class="heading">Exceptions</span> 1264 <p>TODO: exceptions can be used, custom ones must be based on std::exception</p> 1265 </li> 1266 1267 <li><span class="heading">Polymorphism</span> 1268 <p>TODO: when to use virtual functions, virtual destructor</p> 1269 </li> 1270 1271 <li><span class="heading">Namespaces</span> 1272 <p>TODO: namespace naming</p> 1273 <p>TODO: using statement, never using in headers</p> 1274 </li> 1275 1276 </ol> 1277 </li> 1278 1279 <li><span class="heading">Tools</span> 1280 <ol class="h2"> 1281 <li><span class="heading">Git</span> 1282 <p>Git is currently the weapon of choice for source control management. Even though it is 1283 not the perfect solution, it gets job done well, or at least better than most other solutions.</p> 1284 1285 <p>Our repositories are hosted on github.com. You are allowed and encouraged to push any number 1286 of new branches to the github repositories. Remember to clean up the obsolete ones after they 1287 have been merged to master. But never delete a remote branch that hasn't been created by you.</p> 1288 1289 <p>Before you commit anything, make sure <i>user.name</i> and <i>user.email</i> are properly set up.</p> 1290 <pre class="prettyprint"> 1291 git config --global user.name "Veijo Elements" 1292 git config --global user.email "veijo.elements (a] drawelements.com" 1293 </pre> 1294 1295 <p>The standard line ending format for all text files is Unix-style. The best way to handle 1296 line endings on Windows systems is to set <i>core.autocrlf</i> to <i>input</i>. That causes 1297 conversion to Unix-style line endings on commit only (i.e. not in checkout).</p> 1298 <pre class="prettyprint"> 1299 git config --global core.autocrlf input 1300 </pre> 1301 1302 <p>In order to keep trailing whitespace out of source tree, a standard pre-commit hook must 1303 be placed in each local clone of any source repositories.</p> 1304 <pre class="prettyprint"> 1305 # in repository directory 1306 cp ~/Dropbox/drawElements/Misc/git/pre-commit .git/hooks/ 1307 </pre> 1308 </li> 1309 1310 <li><span class="heading">Build systems and IDEs</span> 1311 <p>CMake is used as an official project file generator. CMake can be used to generate makefiles 1312 or project files for most IDEs. Unless there is a good reason, you should use project files 1313 generated by CMake.</p> 1314 1315 <p>You are free to choose any IDE or editor you like. At least Visual Studio, vim and 1316 emacs have been successfully used in the past. Good debugger integration is strongly recommended.</p> 1317 </li> 1318 </ol> 1319 </li> 1320 1321 <li><span class="heading">Coding philosophy</span> 1322 <ol class="h2"> 1323 <li><span class="heading">Designing classes</span> 1324 <p>Each class should have only a single purpose to fulfill, and it should encapsulate that 1325 entirely. All functionality that is secondary and doesn't require access to classes' internal 1326 implementation should not be part of that class. This is called <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"> 1327 single responsibility principle</a>. It is probably easier to grasp it with an example.</p> 1328 1329 <p>Consider a <i>Texture2D</i> class that manages 2D-dimensional texture data. Such class is clearly 1330 responsible for managing lifetime of the associated memory, and storing properties such as 1331 size and format. Now, one could need a function for blitting (copying) portion of one texture 1332 to some position in an another texture. This could be added as a method to texture class, but 1333 it most certainly isn't core responsibility of that class. So correct way to implement that 1334 is either as a plain function operating on publicly accessible methods of <i>Texture2D</i> class, 1335 or as a separate <i>Blitter</i> class. Same applies to things such as reading texture from a file, 1336 clearing the texture to a certain color and so forth.</p> 1337 1338 <div class="codeTitle">Texture class example.</div> 1339 <pre class="prettyprint"> 1340 class Texture2D 1341 { 1342 public: 1343 Texture2D (const TextureFormat format, const int width, const int height); 1344 Texture2D (const char* const filename); // Bad: not core functionality 1345 ~Texture2D (void); 1346 1347 // Good methods: essential functionality 1348 Vec4 getPixel (const int x, const int y) const; 1349 void setPixel (const int x, const int y, const Vec4& c); 1350 const deUint8* getPixelPtr (void) const; 1351 1352 // Bad: non-essential 1353 void clear (const Vec4& c); 1354 bool containsColor (const Vec4& c) const; 1355 void setInitialized (void); // Why texture would store bit that belongs outside? 1356 1357 private: 1358 // Good: essential, minimum data set 1359 vector<deUint8> m_pixels; 1360 TextureFormat m_format; 1361 int m_width; 1362 int m_height; 1363 1364 // deUint8* m_pixels; // Bad: explicit mem. mgmt, not core functionality 1365 bool m_initialized; // Bad: extraneous information 1366 }; 1367 1368 // Good: independent functions operating on textures 1369 void clearTexture (Texture2D& texture, const Vec4& color); 1370 Texture2D* createFromFile (const char* const filename); 1371 </pre> 1372 <p>One sign of a successful class design is that the interface feels natural to use. Thus when 1373 designing a new class from a scratch, you should start by writing the use cases first. Class 1374 interface can be refined until it suits the most important use cases, and only then the 1375 implementation is filled in. Doing things in reverse order often leads to interfaces that are 1376 later found to be inadequate.</p> 1377 1378 <p>When writing the internal implementation a lot of thought should be put on maintaining 1379 consistent state, or more formally, <a href="http://en.wikipedia.org/wiki/Class_invariant">class invariant</a>. 1380 Member variables in a class are a form of global state and thus special care must be taken 1381 when manipulating that state. If class requires a lot of state, it can be helpful to group 1382 some of the members into separate state-only classes whose sole responsibility is maintaining 1383 the class invariant for that set of members. Another good pattern is to write a state validation 1384 function that is called in debug builds after each non-trivial state change.</p> 1385 1386 <p>Only a minimal set of class member variables should ever be used. If some value can be derived 1387 with a relatively little effort from the minimal set of members, it must not be stored as a 1388 member variable. In the <i>Texture2D</i> class example, length of a pixel row or image size can 1389 be derived from size and format and thus member variables must not be used for them.</i> 1390 1391 <!-- TODO: code example --> 1392 1393 </li> 1394 1395 <li><span class="heading">Global state</span> 1396 <p>Pretty much everyone can agree that relying on global state is undesirable. However, what 1397 is not always obvious is what counts as a global state. Global variables are clearly such state, 1398 but many more can be considered as well. For example state encapsulated in shared objects, state 1399 retained in library API, or even state passed in member variables between member functions 1400 could be counted as a form global state. Another way to define global state is that it is anything 1401 that can be passed from one function to another without including it in function call arguments.</p> 1402 1403 <p>All forms of global state should be used only when necessary. Excluding some very rare cases, 1404 mutable global variables are never necessary. Singletons are really just a fancier version of 1405 global variables. Instead of using for example singleton for application log object, it should be 1406 passed in explicitly to all objects and functions that require logging.</p> 1407 1408 1409 </li> 1410 1411 <li><span class="heading">Variables vs. immutable values</span> 1412 <p>Traditional imperative programming puts emphasis on variables. They are thought of being 1413 limited resource, used for storing immediate computation results for brief periods of time. 1414 In early C days it was even common to declare variable <i>register</i> in order to communicate 1415 the compiler that it should place the variable into a register. Things have changed a lot since 1416 then, and it is no longer necessary to limit use of variables for performance reasons.</p> 1417 1418 <p>Functional languages declare variables immutable, i.e. they are not really <i>var</i>ying 1419 values, but instead named values. This often greatly improves code clarity and correctness, 1420 as variables can not change unexpectedly. While imperative languages certainly need some amout 1421 of mutability, the concept of immutable values certainly has advantages.</p> 1422 1423 <p>As discussed in variable naming section, you often should name a single value, not some 1424 storage slot for arbitrary set of values. In such case it makes a lot of sense to treat that 1425 as immutable named value, not mutable varibale. In C and C++ that can be explicitly declared 1426 with use of <i>const</i> qualifier.</p> 1427 1428 <p>In general the amount of state that is considered mutable in any given context should be 1429 minimized. Understanding code is a much more easier if number of things that can change is 1430 small. This also guides code towards natural separation into smaller functions.</p> 1431 1432 <p>Limiting number of mutable variables leads to a more functional programming style, where a 1433 lot of computation done in initializer expressions at the beginning of a block. This is not 1434 necessarily a bad thing as it requires separating any non-trivial computation into separate 1435 functions. Most often we only need the result of such computation anyway, and how the 1436 value itself is computed is not important for the problem at hand.</i> 1437 1438 <div class="codeTitle">Complex code example.</div> 1439 <pre class="prettyprint"> 1440 std::vector<Node*> topologicalSortFromRoot (Node* const root) 1441 { 1442 // Returning containers is OK if called functions are local and compiler 1443 // can easily do return value optimization. 1444 const std::vector<Node*> allNodes = collectAllNodesFromRoot(root); // Reduce number of mutables by computing outside 1445 std::map<Node*, int> useCounts = computeUseCounts(allNodes); // Uses allNodes value, mutable 1446 std::vector<Node*> liveSet; // Mutable as well 1447 std::vector<Node*> sortedNodes; // Used as return value - only appended to 1448 1449 // We have multiple mutables here. Invariant is that each node that has zero in useCount 1450 // must be either in liveSet or sortedNodes, but not in both. 1451 1452 for (std::vector<Node*>::iterator nodeIter = allNodes.begin(); 1453 nodeIter != allNodes.end(); 1454 ++nodeIter) 1455 { 1456 // Note that nodeIter is not considered mutable here - instead it is iteration-specific 1457 // immutable value. 1458 if (useCounts[*nodeIter] == 0) 1459 liveSet.push_back(*nodeIter); // liveSet is used as return value here 1460 } 1461 1462 while (!liveSet.empty()) 1463 { 1464 Node* const curNode = liveSet.back(); 1465 liveSet.pop_back(); 1466 1467 sortedNodes.push_back(curNode); 1468 1469 ... 1470 } 1471 1472 return sortedNodes; 1473 } 1474 </pre> 1475 </li> 1476 1477 <li><span class="heading">Pure functions</span> 1478 <p>Pure functions have two properties. Firstly, the result depends only on the input values and 1479 always produces same output value given same set of input values. Secondly, the function does not 1480 cause any observable side effects or changes to global state. For example <i>sin(x)</i> is pure 1481 function as it always returns the same value for same argument value and does not cause any side effects.</p> 1482 1483 <p>As much of the code as possible should be kept pure. Moving pure parts of logic and computation 1484 into separate functions is recommended. Unit testing those pure functions is then much easier.</p> 1485 1486 <p>Mutating objects passed in counts as a side effect. Instead pure functions must return a completely 1487 new value. This may not always be feasible and some functions may need to be impure for performance 1488 reasons. One way to work around that while remaining as pure as possible is to use separate output-only 1489 argument for output value. Perhaps the most ubiquitous example of such function is <i>memcpy()</i>.</p> 1490 1491 <div class="codeTitle">Examples</div> 1492 <pre class="prettyprint"> 1493 // Good: pure function (assuming that it doesn't touch global state) 1494 vector<int> findUniqueNumbers (const vector<int>& numbers); 1495 1496 // Good: single output-only parameter 1497 void findUniqueNumbers (vector<int>& dst, const vector<int>& numbers); 1498 1499 // Bad: copying a lot of data for sake of pureness 1500 LargeStateObject setStateX (const LargeStateObject& state, const int value); 1501 1502 // Bad: manipulates input for no reason 1503 void removeDuplicates (vector<string>& words); 1504 1505 </pre> 1506 </li> 1507 </ol> 1508 1509 <!-- 1510 Coding philosophy TODO: 1511 - composition vs. inheritance 1512 - dependency injection 1513 - function design 1514 - do not duplicate state (local or remote) 1515 1516 Patterns TODO: 1517 - iterator pattern 1518 - iterate() pattern for long computation 1519 + state machines for interactive processing? 1520 - accessor class pattern 1521 --> 1522 1523 </li> 1524 1525 <!--- 1526 <li><span class="heading">Something else</span> 1527 </li> 1528 --> 1529 1530 </ol> <!-- h1 --> 1531 1532 </div> <!-- body --> 1533 1534 </body> 1535 1536 </html> 1537