diff --git a/developer-handbook.md b/developer-handbook.md index ebe6e4db..dc852fd0 100644 --- a/developer-handbook.md +++ b/developer-handbook.md @@ -2,12 +2,13 @@ ## About -The purpose of the Developer Handbook is similar to that of the README. The -README should be viewed as a prerequisite to the Developer Handbook. The README -should provide information needed to build the project, which might be used by -an advanced user or a person trying to build and package the project. The -Developer Handbook should focus on information needed by a developer working on -the project. +The purpose of the Developer Handbook is similar to that of the README. +The README should be viewed as a prerequisite to the Developer Handbook. +The README should provide information needed to build the project, which might +be used by an advanced user or a person trying to build and package the +project. +The Developer Handbook should focus on information needed by a developer +working on the project. ## Project Structure @@ -65,14 +66,16 @@ The C++ language designers aren't stupid. Question them, but don't ignore them. #### Casting -Do not use C-style casts. C++ casts are more readable, and more explicit about -the type of cast being used. Do not use ```dynamic_cast``` in code building for the -GBA, as RTTI is disabled in GBA builds. +Do not use C-style casts. +C++ casts are more readable, and more explicit about the type of cast being +used. +Do not use ```dynamic_cast``` in code building for the GBA, as RTTI is disabled +in GBA builds. #### Library Usage -C++ libraries should generally be preferred to C libraries. C libraries are -allowed, but pay extra attention. +C++ libraries should generally be preferred to C libraries. +C libraries are allowed, but pay extra attention. This example from nostalgia::core demonstrates the type of problems that can arise from idiomatically mixed code. @@ -115,37 +118,41 @@ int main() { The code base where this was observed actually got away with this for the most part, as the std::vector implementation used evidently waited until the internal array was needed before initializing and the memory was zeroed out -because the allocation occurred early in the program's execution. While the -std::vector implementation in question worked with this code and the memory leak -is not noticeable because the std::vector was meant to exist for the entire life -of the process, other classes likely will not get away with it due to more -substantial constructors and more frequent instantiations of the classes in -question. +because the allocation occurred early in the program's execution. +While the std::vector implementation in question worked with this code and the +memory leak is not noticeable because the std::vector was meant to exist for +the entire life of the process, other classes likely will not get away with it +due to more substantial constructors and more frequent instantiations of the +classes in question. ### Pointers vs References Pointers are generally preferred to references. References should be used for optimizing the passing in of parameters and for returning from accessor -operators (e.g. ```T &Vector::operator[](size_t)```). As parameters, references -should always be const. A non-const reference is generally used because the -parameter value is changed in the function, but it will look like it was passed -in by value where it is called and thus not subject to change. The reference -operator makes it clear that the value can and likely will change. +operators (e.g. ```T &Vector::operator[](size_t)```). +As parameters, references should always be const. +A non-const reference is generally used because the parameter value is changed +in the function, but it will look like it was passed in by value where it is +called and thus not subject to change. +The reference operator makes it clear that the value can and likely will change. ### Error Handling Exceptions are clean and nice and gleefully encouraged in userland code running in environments with expansive system resources, but absolutely unacceptable in -code running in restrictive bare metal environments. The GBA build has them -disabled. Exceptions cause the compiler to generate a great deal of extra code -that inflates the size of the binary. The binary size bloat is often cited as -one of the main reasons why many embedded developers prefer C to C++. +code running in restrictive bare metal environments. +The GBA build has them disabled. +Exceptions cause the compiler to generate a great deal of extra code that +inflates the size of the binary. +The binary size bloat is often cited as one of the main reasons why many +embedded developers prefer C to C++. Instead of throwing exceptions, all engine code must return error codes. Nostalgia and Ox both use ```ox::Error``` to report errors. ```ox::Error``` is a struct that has overloaded operators to behave like an integer error code, -plus some extra fields to enhance debuggability. If instantiated through the -```OxError(x)``` macro, it will also include the file and line of the error. +plus some extra fields to enhance debuggability. +If instantiated through the ```OxError(x)``` macro, it will also include the +file and line of the error. The ```OxError(x)``` macro should only be used for the initial instantiation of an ```ox::Error```. @@ -192,18 +199,20 @@ Lastly, there are a few macros available to help in passing ```ox::Error```s back up the call stack, ```oxReturnError```, ```oxThrowError```, ```oxIgnoreError```, and ```oxRequire```. -```oxReturnError``` is by far the more helpful of the two. ```oxReturnError``` -will return an ```ox::Error``` if it is not 0 and ```oxThrowError``` will throw -an ```ox::Error``` if it is not 0. Because exceptions are disabled for GBA -builds and thus cannot be used in the engine, ```oxThrowError``` is only really -useful at the boundary between engine libraries and Nostalgia Studio. +```oxReturnError``` is by far the more helpful of the two. +```oxReturnError``` will return an ```ox::Error``` if it is not 0 and +```oxThrowError``` will throw an ```ox::Error``` if it is not 0. +Because exceptions are disabled for GBA builds and thus cannot be used in the +engine, ```oxThrowError``` is only really useful at the boundary between +engine libraries and Nostalgia Studio. -```oxIgnoreError``` does what it says, it ignores the error. Since -```ox::Error```s always nodiscard, you must do something with them. +```oxIgnoreError``` does what it says, it ignores the error. +Since ```ox::Error```s always nodiscard, you must do something with them. In extremely rare cases, you may not have anything you can do with them or you may know the code will never fail in that particular instance. -This should be used very sparingly. At the time of this writing, it has only -been used 4 times in 20,000 lines of code. +This should be used very sparingly. +At the time of this writing, it has only been used 4 times in 20,000 lines of +code. ```cpp