This is a list of design notes that should server as a guide for API writing, notes taken from the book API Design which I highly recommend for C++ programmers. This list is not yet grammar correct.
if you can't find a valid reason to have something, don't write it
ask questions with helper functions e.g - bool isValueFloat
Identify, find your API requirements - we need to be able to...
aim for surreal
There is no single correct Object Model for a given problem domain. Different demands on an API may require a different object model to best represent those demands
The goal of object modeling is to identify the collection of major objects, the operations that they provide, and how they relate to each other.
The task of creating an object model should be driven by the specific requirements for the API.
check for namespaces, don't allow free floating functions or variables, either use static keyword or anonymous namespace e.g. - namespace {
start with basic objects in the problem domain, make sure to use helper classes for any type of class usage functions.
Keep the class focused and free of anything that the class should not be responsible for.
Refer to Chapter 4 in API Design for inventing key objects
Make a list of architectural constraints to conceive a better overview of supported options
Make a list of definate libraries used and consider a manager to support variations
Consider wrapper classes to encompass used libraries
use const unless modification is neccessary
prefer references to pointers
prefer composition to inheritance
use templates when an object must handle many types
use include guards
use namespaces to avoid name clashes
List responsibilities for each object
graph objects from big to small, large classes to sub-classes
Identify which objects are likely to change during API development to accomodate extensibility
Stay at design level until you are comfortable with the extensibility offered
plan for extensibility
Ask whether or not we should have a manager for an object so multiple objects of that type can be managed more appropriately
Ask how the object is going to recieve updates, if any.
Does the object need to communicate with other objects? How will inter-object communication occur?
Should callbacks, event-system, observer pattern - pg 101, or notifications be employed? Consider boost::signals for simple intra-class communications
Consider which objects may need threading and how threads safety can be employed.
Write out a class-decision flowchart, should it be a template calss, a helper class, a regular class?
write out object description, what the class will handle and what classes it possibly needs to communicate with
write out a resource creation flowchart
seperate function behaviors from visual behavious. Functions should trigger visual behaviours possibly via event system instead of a direct call
keep includes at a minimum, don't pull in unecessary headers.
consider "Holder" objects for object usages to avoid direct object usage ex - EventSystem / EventSystemObject, EventSystemObject has an EventSystem object and uses it through public functions. REmember,
you're designing an API, not the API's usage, yet :) keep the API seperate from it's usage, design a helper library to use the API
decide how much abstraction is neccesary to keep the API seperate from it's usage. The API should not be used directly!
prefer passing arguments by const reference
use include guards for individual include headers to avoid rendundant including
avoid polluting the global namespace with defines or const definitions, use static const public class members instead
defer optimizations to helper libraries, don't over-optimize the API!
provide constructor implementations and initialization lists in the .cpp file, not the header file
avoid assignment in the class constructor, prefer initialization lists in the cpp file to avoid construction calls pg 220.
prefer std::vector to arrays
keep your API minimally complete.
Don't add virtual methods until you need them
make a list of needed class parameters and make them private using a pimpl
hide as many implementation details as possible from the header files to keep them clean.
cluster member variables by types to optimize object size.
use bool bit flags to reduce structure size pg. 224
consider generic template types
make classes keep track of their own work, don't use friends
use default arguments
turn methods that do not need access to private or protected member into free functions to reduce coupling, this includes operators
use function design options pg 142
use private inheritance for a was-a relationship, or preferably, composition, pg 137
use inheritance if you have to pg 134
class design options pg 133
Write out class dependency information in it's header
use callbacks with factories to defer instantion after registering a class with a type registration system
use LoD pg 140
use Open/Closed principle pg 139
Use extensible factories to follow OCP, pg 88
write out an event system along with different event types that can occur.
write out a behaviour flow chart system per class functions
Event System - write out notification types on a per object level, including sending and receving
Plan for a client server system
Consider an ArgList or struct passing to condense function arguments, use bit flags for bools.
use private functions for internal class work.
use the pimpl Idiom to hide private class members
make class members private until they need to have higher access rights
don't add includes to the header if you don't have to
use forward references if possible instead of includes
make all class functions and members private until it is known that the function or member must be accessed from outside the class
look into triggers and whether or not they are neccesary
Don't try to handle too much in one class, keep classes simplified and use composition for manager classes.