CppFunctionDesign.md

January 10, 2018 ยท View on GitHub

(C++) function design

Function design is the correct design of a function.

Advice

General

  • Avoid writing long functions [1-2,5,35]
  • Avoid using functions with a large number of arguments [36]
  • Prefer functions over macros [23,24]
  • If a function may have to be evaluated at compile time, declare it constexpr [7]

The name of the function should say what it does

  • Do use names like Swap, IsPrime, StrToInt
  • Do not use names like DoIt, Transmogrify, Stuff
  • Exceptions: Transmogrify is a function name commonly used in the literature to denote a function you are not aware of what it is doing

A function should perform a single logical operation [4]

  • Do not use names with 'And' in it, like SwapAndGetMean
  • Do use two functions instead, Swap and GetMean
  • Exceptions: some mathematical functions can cooperate and so improve runtime speed: MeanAndStdDev executes faster then calling the seperate functions for Mean and StdDev

Interface

The return type is expected from the name of the function

  • If a function cannot return, mark it [[noreturn]] [8]
  • Do give a function a void return type when it has no return type
  • Do return a non-pointer non-reference object when a function is expected to always execute successfully on the assumptions that its arguments are valid
  • Return a result as a return value rather than modifying an object through an argument [11]
  • Do return a pointer (or better: a smart pointer) to a data type when the return type can be null, that is: empty. If the pointer needs to be read-only, make it const (for example 'const T * const GetT()', where GetT is a function that returns a pointer to a T)
  • Do not make a function return a reference to a function's local variable [6,31], this leads to undefined behavior
  • Do not make a function return an error code, use exceptions instead [32]

The function arguments are expected from the name of the function

  • A function declared with an empty parameter list takes no arguments [37]. Or: write 'int f()' instead of 'int f(void)' [37]
  • Prefer pass-by-reference-to-const to pass-by-value [30]
  • Use pass-by-non-const-reference only if you have to [14]
  • Do use a non-pointer reference object for expensive-to-copy data types, like std::string, std::vector<int> or Database. Make the argument const if it must be marked read-only [10]
  • Do use a non-pointer non-reference object for standard data types like int [9]. Make the argument const if it must be marked read-only
  • Do use a pointer (or better: a smart pointer) to a data type when the argument can be nullptr/null/empty [13]. If the pointer needs to be read-only, make it const (for example 'void CoutT(const T * const t)', where CoutT is a function that uses std::cout on a T)
  • Avoid passing arrays as pointers [16]
  • Assume that a char* or a const char* argument points to a C-style string [15]
  • Use rvalue references to implement move and forwarding [12]
  • Pass a homogeneous list of unknown length as an std::initializer_list or as some other container [17]
  • Avoid unspecified numbers of arguments (...) [18]
  • Prefer to pass function objects (including lambdas) and virtual functions to pointers to functions [22]

Specify preconditions and postconditions for your functions [21,25-28,38,40]

  • Do use Expects (preferred [39]) and exceptions to make clear to the client which input the function cannot handle. For example, the square root of a negative number does not exist
  • Prefer Ensures to express postconditions [48]
  • Do not use error codes as return types, use exceptions instead [32]

Exception handling

Function overloading

  • Use overloading when functions perform conceptually the same task on different types [19]
  • When overloading on integers, provide functions to eliminate common ambiguities [20]

See also

References

  • [1] Herb Sutter, Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Item 20: 'Avoid long functions. Avoid deep nesting'
  • [2] Joint Strike Fighter Air Vehicle C++ Coding Standards for the System Development and Demonstration Program. Document Number 2RDU00001 Rev C. December 2005. AV Rule 1: 'Any one function (or method) will contain no more than 200 logical source lines of code.'
  • [3] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[1] "Package meaningful operations as carefully named functions'
  • [4] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[2] A function should perform a single logical operation'
  • [5] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[3] Keep functions short'
  • [6] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[4] Don't return pointers or references to local variables'
  • [7] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[5] If a function may have to be evaluated at compile time, declare it constexpr'
  • [8] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[6] If a function cannot return, mark it [[noreturn]]'
  • [9] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[7] Use pass-by-value for small objects'
  • [10] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[8] Use pass-by-const-reference to pass large values that you don't need to modify'
  • [11] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[9] Return a result as a return value rather than modifying an object through an argument'
  • [12] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[10] Use rvalue references to implement move and forwarding'
  • [13] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[11] Pass a pointer if "no object" is a valid alternative (and represent "no object" by nullptr)'
  • [14] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[12] Use pass-by-non-const-reference only if you have to'
  • [15] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[14] Assume that a char* or a const char* argument points to a C-style string'
  • [16] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[15] Avoid passing arrays as pointers'
  • [17] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[16] Pass a homogeneous list of unknown length as an initializer_list (or as some other container)'
  • [18] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[17] Avoid unspecified numbers of arguments (...)'
  • [19] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[18] Use overloading when functions perform conceptually the same task on different types'
  • [20] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[19] When overloading on integers, provide functions to eliminate common ambiguities'
  • [21] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[20] Specify preconditions and postconditions for your functions'
  • [22] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[21] Prefer function objects (including lambdas) and virtual functions to pointers to functions'
  • [23] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 12.7. Advice. page 341: '[22] Avoid macros'
  • [24] Herb Sutter, Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. 2005. ISBN: 0-32-111358-6. Item 16: 'Avoid macro's'.
  • [25] Herb Sutter, Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Chapter 68: 'Assert liberally to document internal assumptions and invariants'
  • [26] Bjarne Stroustrup. The C++ Programming Language (3rd edition). 1997. ISBN: 0-201-88954-4. Advice 24.5.18: 'Explicitly express preconditions, postconditions, and other assertions as assertions'
  • [27] Steve McConnell. Code Complete (2nd edition). 2004. ISBN: -735619670. Chapter 8.2 'Assertions', paragraph 'Guidelines for using asserts': 'Use assertions to document and verify preconditions and postconditions'
  • [28] Steve McConnell. Code Complete (2nd edition). 2004. ISBN: -735619670. Chapter 8.2 'Assertions', paragraph 'Guidelines for using asserts': 'Use assertions for conditions that should never occur'.
  • [29] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 13.7. Advice. page 387: '[8] 'Don't try to catch every exception in every function'
  • [30] Scott Meyers. Effective C++ (3rd edition). ISBN: 0-321-33487-6. Item 20: Prefer pass-by-reference-to-const to pass-by-value.
  • [31] Scott Meyers. Effective C++ (3rd edition). ISBN: 0-321-33487-6. Item 21: Don't try to return a reference when you must return an object.
  • [32] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 13.7. Advice. page 386: '[3] Use exceptions for error handling'
  • [33] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 13.7. Advice. page 387: '[33] Assume that every exception that can be thrown by a function will be thrown'
  • [34] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 13.7. Advice, page 387: '[23] If your function may not throw, declare it noexcept'
  • [35] Bruce Eckel. Thinking in C++, second edition, volume 1. 2000. ISBN: 0-13-979809-9. Chapter B: Programming Guidelines. Item 15: 'Watch for long member function definitions. A function that is long and complicated is difficult and expensive to maintain, and is probably trying to do too much all by itself. If you see such a function, it indicates that, at the least, it should be broken up into multiple functions. It may also suggest the creation of a new class.'
  • [36] Bruce Eckel. Thinking in C++, second edition, volume 1. 2000. ISBN: 0-13-979809-9. Chapter B: Programming Guidelines. Item 16: 'Watch for long argument lists. Function calls then become difficult to write, read and maintain. Instead, try to move the member function to a class where it is (more) appropriate, and/or pass objects in as arguments.'
  • [37] Working Draft, Standard for Programming Language C++. 2014-08-22. N3936. Paragraph C.1.7. First change. 'In C++, a function declared with an empty parameter list takes no arguments. In C, an empty parameter list means that the number and type of the function arguments are unknown.'
  • [38] C++ Core Guidelines: I.5: State preconditions (if any)
  • [39] C++ Core Guidelines: I.6: Prefer Expects() for expressing preconditions
  • [40] C++ Core Guidelines: I.7: State postconditions
  • [41] Scott Meyers. Effective C++ (3rd edition). ISBN: 0-321-33487-6. Item 18: Make interfaces easy to use correctly and hard to use incorrectly.
  • [42] John Lakos. Large-Scale C++ Software Design. 1996. ISBN: 0-201-63362-0. Chapter 2.6: Document the interfaces so that they are usable by others. Have at least one other developer review each interface
  • [43] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 7.8. Advice. page 199: '[13] Use const pointers and const references to express immutability in interfaces'
  • [44] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 16.4. Advice. page 479: '[2] Seperate the interface of a class from its implementation'
  • [45] Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 20.7. Advice. page 611: '[11] Prefer public members for interfaces'
  • [46] C++ Core Guidelines: I.1: Make interfaces explicit
  • [47] C++ Core Guidelines: I.4: Make interfaces precisely and strongly typed
  • [48] C++ Core Guidelines: I.8: Prefer Ensures() for expressing postconditions