C++ Core Guidelines: Philosophy
Philisophy
The first proper section lays out some guiding philosophies for writing good C++. This is a combination of C++ specific advice and just good general pratice in programming languages, so I won't cover everything exhaustively, but here's the list for completness.
- Express ideas directly in code
- Write in ISO Standard C++
- Express intent
- Ideally, a program should be statically type safe
- Prefer compile-time checking to run-time checking
- What cannot be checked at compile time should be checkable at run time
- Catch run-time errors early
- Don't leak any resources
- Don't waste time or space
- Prefer immutable data to mutable data
- Encapsulate messy constructs, rather than spreading through the code
- Use supporting tools as appropriate
- Use support libraries as appropriate
To talk about them more, I've packaged these ideas into a few broad categories.
Be a Good (Object-Oriented) Programmer
1 and 3 are just good advice in any programming language. Methods, classes, and variables should be self-documenting if at all possible, b/c comments can get seperated from the logic it documents, but you can't seperate logic from itself. I do think "Compilers don't read comments... and neither do many programmers..." is a pretty funny way to state this imperative, though.
6 and 7 are reminders to check boundaries and "if you're going to fail, fail fast".
9 contains is a reminder that "time and space you spend well to achieve a goal is not wasted", attached to a general reminder to be efficient. I think it was probably good to precede this with 8, don't leak any resources, because that is probably the one place where quality-of-life at other stages in development won't matter.
10 is a reminder to prefer immutability when you don't intend to mutate something.
11 Is about abstracting tricky functions into their own objects/functions, and 13 extends this into selecting supporting libraries that have already done the encapsulating/testing for you.
Calling this section "Be a good programmer" maybe seems a bit dismissive of the utility of these principles in C++, so I want to take a minute to say the opposite. These things make you a competent object-oriented programmer, and C++ very much likes object abstraction, so to use C++ competently you need to be aware of these preferences and know how to use the C++ constructs that support them. Do you know how to make a value constant? How about making an object immutable? How readable is the code you're writing, and how would you make it more readable? I needed to refresh a lot of my own C++ knowledge to understand the examples provided here b/c while every OO language favors these points to some extent, they do so through different constructs. A C++ guide needs to talk about OO principles in order to talk about the C++ features that undergird these fundamentals.
Take Advantage of Static Typing and your Compiler
4 reduces to "make programs type safe" which is worth encouraging over the unholy pointer-casting mess I used to churn out for school.
5 took me a little bit of time to understand, because compile-time checking combines static typing (mentioned above) with a feature I was less familiar with: static assertions. As a quick aside, static assertions apply some logic at compile time (like sizing a data type), rather than spending time executing instructions in the final binary.
12 encourages you to use other tools like static analyzers to enforce coding standards, which isn't necessarily a compiler-advantage, but it any tool that you run your code through provides some pre-compile utility that should benefit the final program.
Be Aware that this is a lower-level language
2 enforces the ISO whenever possible, which makes sense b/c it's the portable logic. However, I hadn't meditated on the implications of this when writing system-specific code that uses non-ISO extensions. Of course anything outside of the ISO should be abstracted away behind and interface so that funcitonality doesn't make the rest of your code too architecture-specific. It's obvious that this makes your code easier to extend to other architectures later.
In most programming language I wouldn't think about this, because the libraries that handle that abstraction are already implemented for me (often in C/C++).
I think this subset contains some of the best C++-specific points in this section. While a lot of the time your C++ logic is implementing Java objects with more memory management, you have the features and responsabilities of an object-specific architecture.