StyleGuide.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. .. ################################################################################
  2. # HPCC SYSTEMS software Copyright (C) 2012-2018 HPCC Systems®.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ################################################################################
  16. ==================
  17. Coding conventions
  18. ==================
  19. ***********************
  20. Why coding conventions?
  21. ***********************
  22. Everyone has their own ideas of what the best code formatting style is, but most
  23. would agree that code in a mixture of styles is the worst of all worlds. A
  24. consistent coding style makes unfamiliar code easier to understand and navigate.
  25. In an ideal world, the HPCC sources would adhere to the coding standards described
  26. perfectly. In reality, there are many places that do not. These are being cleaned up
  27. as and when we find time.
  28. **********************
  29. C++ coding conventions
  30. **********************
  31. Unlike most software projects around, HPCC has some very specific
  32. constraints that makes most basic design decisions difficult, and often
  33. the results are odd to developers getting acquainted with its code base.
  34. For example, when HPCC was initially developed, most common-place
  35. libraries we have today (like STL and Boost) weren't available or stable
  36. enough at the time.
  37. Also, at the beginning, both C++ and Java were being considered as
  38. the language of choice, but development started with C++. So a C++
  39. library that copied most behaviour of the Java standard library (At the
  40. time, Java 1.4) was created (see jlib below) to make the transition, if
  41. ever taken, easier. The transition never happened, but the decisions
  42. were taken and the whole platform is designed on those terms.
  43. Most importantly, the performance constraints in HPCC can make
  44. no-brainer decisions look impossible in HPCC. One example is the use of
  45. traditional smart pointers implementations (such as boost::shared_ptr or
  46. C++'s auto_ptr), that can lead to up to 20% performance hit if used
  47. instead of our internal shared pointer implementation.
  48. The last important point to consider is that some
  49. libraries/systems were designed to replace older ones but haven't got
  50. replaced yet. There is a slow movement to deprecate old systems in
  51. favour of consolidating a few ones as the elected official ways to use
  52. HPCC (Thor, Roxie) but old systems still could be used for years in
  53. tests or legacy sub-systems.
  54. In a nutshell, expect re-implementation of well-known containers
  55. and algorithms, expect duplicated functionality of sub-systems and
  56. expect to be required to use less-friendly libraries for the sake of
  57. performance, stability and longevity.
  58. For the most part out coding style conventions match those
  59. described at http://geosoft.no/development/cppstyle.html, with a few
  60. exceptions or extensions as noted below.
  61. Source files
  62. ============
  63. We use the extension .cpp for C++ source files, and .h or .hpp for header files.
  64. Header files with the .hpp extension should be used for headers that are internal
  65. to a single library, while header files with the .h extension should be used for
  66. the interface that the library exposes. There will typically be one .h file per
  67. library, and one .hpp file per cpp file.
  68. Source file names within a single shared library should share a common prefix to aid
  69. in identifying where they belong.
  70. Header files with extension .ipp (i for internal) and .tpp (t for template) will
  71. be phased out in favour of the scheme described above.
  72. Java-style
  73. ==========
  74. We adopted a Java-like inheritance model, with macro
  75. substitution for the basic Java keywords. This changes nothing on the
  76. code, but make it clearer for the reader on what's the recipient of
  77. the inheritance doing with it's base.
  78. * **interface** (struct): declares an interface (pure virtual class)
  79. * **extends** (public): One interface extending another, both are pure virtual
  80. * **implements** (public): Concrete class implementing an interface
  81. There is no semantic check, which makes it difficult to enforce
  82. such scheme, which has led to code not using it intermixed with code
  83. using it. You should use it when possible, most importantly on code
  84. that already uses it.
  85. We also tend to write methods inline, which matches well with
  86. C++ Templates requirements. We, however, do not enforce the
  87. one-class-per-file rule.
  88. See the `Interfaces`_ section for more information on our implementation of
  89. interfaces.
  90. Identifiers
  91. ===========
  92. Class and interface names are in CamelCase with a leading
  93. capital letter. Interface names should be prefixed capital I followed
  94. by another capital. Class names may be prefixed with a C if there is a
  95. corresponding I-prefixed interface name, e.g. when the interface is primarily used to create an opaque type, but
  96. need not be otherwise.
  97. Variables, function and method names, and parameters use camelCase starting with a lower case letter. Parameters may
  98. be prefixed with underscore when the parameter is used to initialize a member variable of the same name. Common cases
  99. are constructors and setter methods.
  100. Example::
  101. class MySQLSuperClass
  102. {
  103. bool haslocalcopy = false;
  104. void mySQLFunctionIsCool(int _haslocalcopy, bool enablewrite)
  105. {
  106. if (enablewrite)
  107. haslocalcopy = _haslocalcopy;
  108. }
  109. };
  110. Pointers
  111. ========
  112. Use real pointers when you can, and smart pointers when you have
  113. to. Take extra care on understanding the needs of your pointers and
  114. their scope. Most programs can afford a few dangling pointers, but a
  115. high-performance clustering platform cannot.
  116. Most importantly, use common sense and a lot of thought. Here are a few guidelines:
  117. * Use real pointers for return values, parameter passing.
  118. * For local variables use real pointers if their lifetime is
  119. guaranteed to be longer than the function (and no exception
  120. is thrown from functions you call), shared pointers otherwise.
  121. * Use Shared pointers for member variables - unless there is
  122. a strong guarantee the object has a longer lifetime.
  123. * Create Shared<X> with either:
  124. - Owned<X>: if your new pointer will take ownership of the pointer
  125. - Linked<X>: if you are sharing the ownership (shared)
  126. Warning: Direct manipulation of the ownership might
  127. cause Shared<> pointers to lose the pointers, so subsequent
  128. calls to it (like o2->doIt() after o3 gets ownership) **will** cause
  129. segmentation faults.
  130. Refer to `Reference counted objects` for more information on our smart pointer
  131. implementation, Shared<>.
  132. Methods that return pointers to link counted objects, or that use them,
  133. should use a common naming standard:
  134. * Foo * queryFoo()
  135. Does not return a linked pointer since lifetime is guaranteed for a set period. Caller should link if it
  136. needs to retain it for longer.
  137. * Foo * getFoo()
  138. Returned value is linked and should be assigned to an owned, or returned directly.
  139. * void setFoo(Foo * x)
  140. Generally parameters to functions are assumed to be owned by the caller, the callee needs to link them if they
  141. are retained.
  142. * void setFoo(Foo * ownedX)
  143. Some calls do transfer ownership of parameters - the parameter should be named to indicate this. If the function
  144. only has a single signficant parameter then sometimes the name of the function indicates the ownership.
  145. Indentation
  146. ===========
  147. We use 4 spaces to indent each level. TAB characters should not be used.
  148. The { that starts a new scope and the corresponding } to close it are placed on a
  149. new line by themselves, and are not indented. This is sometimes known as the Allman
  150. or ANSI style.
  151. Comments
  152. ========
  153. We generally believe in the philosophy that well written code is self-documenting. Comments are also
  154. encouraged to describe *why* something is done, rather than how - which should be clear from the code.
  155. javadoc-formatted comments for classes and interfaces are being added.
  156. Classes
  157. ========
  158. The virtual keyword should be included on the declaration of all virtual functions - including those in derived
  159. classes, and the override keyword should be used on all virtual functions in derived classes.
  160. Namespaces
  161. ==========
  162. MORE: Update!!!
  163. We do not use namespaces. We probably should, following the Google style guide's
  164. guidelines - see http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces
  165. Other
  166. =====
  167. We often pretend we are coding in Java and write all our class members inline.
  168. C++11
  169. =====
  170. ************************
  171. Other coding conventions
  172. ************************
  173. ECL code
  174. ========
  175. The ECL style guide is published separately.
  176. Javascript, XML, XSL etc
  177. ========================
  178. We use the commonly accepted conventions for formatting these files.
  179. ===============
  180. Design Patterns
  181. ===============
  182. ********************
  183. Why Design Patterns?
  184. ********************
  185. Consistent use of design patterns helps make the code easy to understand.
  186. Interfaces
  187. ==========
  188. While C++ does not have explicit support for interfaces (in the java sense), an
  189. abstract class with no data members and all functions pure virtual can be used
  190. in the same way.
  191. Interfaces are pure virtual classes. They are similar concepts to
  192. Java's interfaces and should be used on public APIs. If you need common
  193. code, use policies (see below).
  194. An interface's name must start with an 'I' and the base class for
  195. its concrete implementations should start with a 'C' and have the same
  196. name, ex::
  197. CFoo : implements IFoo { };
  198. When an interface has multiple implementations, try to stay as
  199. close as possible to this rule. Ex::
  200. CFooCool : implements IFoo { };
  201. CFooWarm : implements IFoo { };
  202. CFooALot : implements IFoo { };
  203. Or, for partial implementation, use something like this::
  204. CFoo : implements IFoo { };
  205. CFooCool : public CFoo { };
  206. CFooWarm : public CFoo { };
  207. Extend current interfaces only on a 'is-a' approach, not to
  208. aggregate functionality. Avoid pollution of public interfaces by having
  209. only the public methods on the most-base interface in the header, and
  210. internal implementation in the source file. Prefer pImpl idiom
  211. (pointer-to-implementation) for functionality-only requirements and
  212. policy based design for interface requirements.
  213. Example 1: You want to decouple part of the implementation from
  214. your class, and this part does not implements the interface your
  215. contract requires.::
  216. interface IFoo
  217. {
  218. virtual void foo()=0;
  219. };
  220. // Following is implemented in a separate private file...
  221. class CFoo : implements IFoo
  222. {
  223. MyImpl *pImpl;
  224. public:
  225. virtual void foo() override { pImpl->doSomething(); }
  226. };
  227. Example2: You want to implement the common part of one (or more)
  228. interface(s) in a range of sub-classes.::
  229. interface ICommon
  230. {
  231. virtual void common()=0;
  232. };
  233. interface IFoo : extends ICommon
  234. {
  235. virtual void foo()=0;
  236. };
  237. interface IBar : extends ICommon
  238. {
  239. virtual void bar()=0;
  240. };
  241. template <class IFACE>
  242. class Base : implements IFACE
  243. {
  244. virtual void common() override { ... };
  245. }; // Still virtual
  246. class CFoo : public Base<IFoo>
  247. {
  248. void foo() override { 1+1; };
  249. };
  250. class CBar : public Base<IBar>
  251. {
  252. void bar() override { 2+2; };
  253. };
  254. NOTE: Interfaces deliberately do not contain virtual destructors. This is to help ensure that they are never
  255. destroyed by calling delete directly.
  256. Reference counted objects
  257. =========================
  258. Shared<> is an in-house intrusive smart pointer implementation. It is
  259. close to boost's intrusive_ptr. It has two derived implementations:
  260. Linked and Owned, which are used to control whether the pointer is
  261. linked when a shared pointer is created from a real pointer or not,
  262. respectively. Ex::
  263. Owned<Foo> myFoo = new Foo; // Take owenership of the pointers
  264. Linked<Foo> anotherFoo = = myFoo; // Shared ownership
  265. Shared<> is thread-safe and uses atomic reference count
  266. handled by each object (rather than by the smart pointer itself, like
  267. boost's shared_ptr).
  268. This means that, to use Shared<>, your class must implement the Link() and Release() methods - most commonly by
  269. extending the CInterfaceOf<> class, or the CInterface class (and using the IMPLEMENT_IINTERFACE macro in the public
  270. section of your class declaration).
  271. This interface controls how you Link() and Release() the pointer.
  272. This is necessary because in some inner parts of HPCC, the use of a
  273. "really smart" smart pointer would add too many links and releases (on
  274. temporaries, local variables, members, etc) that could add to a
  275. significant performance hit.
  276. The CInterface implementation also include a virtual function beforeDispose() which is called before the object is
  277. deleted. This allows resources to be cleanly freed up, with the full class hierarchy (including virtual functions)
  278. available even when freeing items in base classes. It is often used for caches that do not cause the objects to be
  279. retained.
  280. STL
  281. ===
  282. MORE: This needs documenting
  283. =================================
  284. Structure of the HPCC source tree
  285. =================================
  286. MORE!
  287. Requiring more work:
  288. * namespaces
  289. * STL
  290. * c++11
  291. * Review all documentation
  292. * Better examples for shared