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