Use support libraries as appropriate
Reason
Using a well-designed, well-documented, and well-supported library saves time and effort; its quality and documentation are likely to be greater than what you could do if the majority of your time must be spent on an implementation. The cost (time, effort, money, etc.) of a library can be shared over many users. A widely used library is more likely to be kept up-to-date and ported to new systems than an individual application. Knowledge of a widely-used library can save time on other/future projects. So, if a suitable library exists for your application domain, use it.
Example
std::sort(begin(v), end(v), std::greater<>());
Unless you are an expert in sorting algorithms and have plenty of time, this is more likely to be correct and to run faster than anything you write for a specific application. You need a reason not to use the standard library (or whatever foundational libraries your application uses) rather than a reason to use it.
Note
By default use
Note
If no well-designed, well-documented, and well-supported library exists for an important domain, maybe you should design and implement it, and then use it.
I: Interfaces
An interface is a contract between two parts of a program. Precisely stating what is expected of a supplier of a service and a user of that service is essential. Having good (easy-to-understand, encouraging efficient use, not error-prone, supporting testing, etc.) interfaces is probably the most important single aspect of code organization.
Interface rule summary:
- I.1: Make interfaces explicit
- I.2: Avoid non-
constglobal variables - I.3: Avoid singletons
- I.4: Make interfaces precisely and strongly typed
- I.5: State preconditions (if any)
- I.6: Prefer
Expects()for expressing preconditions - I.7: State postconditions
- I.8: Prefer
Ensures()for expressing postconditions - I.9: If an interface is a template, document its parameters using concepts
- I.10: Use exceptions to signal a failure to perform a required task
- I.11: Never transfer ownership by a raw pointer (
T*) or reference (T&) - I.12: Declare a pointer that must not be null as
not_null - I.13: Do not pass an array as a single pointer
- I.22: Avoid complex initialization of global objects
- I.23: Keep the number of function arguments low
- I.24: Avoid adjacent parameters that can be invoked by the same arguments in either order with different meaning
- I.25: Prefer empty abstract classes as interfaces to class hierarchies
- I.26: If you want a cross-compiler ABI, use a C-style subset
- I.27: For stable library ABI, consider the Pimpl idiom
- I.30: Encapsulate rule violations
See also: