This is a list of programming aphorisms that I've come across over the years and have found to be proven useful and true over and over again. They can help realign you when you're off course, and they're pithy enough to be easily memorable.
Pure functions (functions with no side effects) are pleasant to work with because they are easy to reason about. The same goes for classes that follow the dependency injection pattern in OOP contexts. Any encapsulated unit of code should take everything it depends on as explicit arguments. This also makes testing pleasant because you can pass in mocks or alternative implementations of dependencies.
Side effects (random number generation, getting the current date and time, I/O, etc.) should be pushed out to the "shell" of the program, meaning they are passed in as arguments to the pure core.
Here's the original blog post for "Parse, don't validate."
The idea is that all of your input validation should be done by the time you have instantiated the types/classes your program's core logic depends on. The core of your program should never have to check for nullity or other illegal states of its input, because those states should be impossible to create in the first place.
Before applying this principle, you had a class/function that took some inputs, did some stuff with them, and had checks sprinkled throughout the actual logic for illegal states. After applying this principle, you separate out all of the illegal state-checking logic into the constructors of input types themselves (creating new types if necessary). This ensures that by the time you even have an instance of one of the input types to pass to your logic, you already know it has to be valid, so your core logic doesn't need to worry about performing those checks anymore.
You aren't removing the checks, you're separating them out and moving them as early as possible in the program, so that everything that comes after can breathe freely.
Whenever you think you want inheritance, you should probably use composition or implement an interface instead. They often accomplish the same things, but using composition and implementing interfaces allows for looser coupling and more flexibility when the code needs to change.
Date | Revision |
---|---|
2024-02-22 | Initial revision |