Skip to the relevant sections if needed.
Quite a lot of different people have been on the same trail of thought. Gary Bernhardt's formulation of a "functional core, imperative shell" seems to be the most voiced.
"Imperative shell" that wraps and uses your "functional core".. The result of this is that the shell has fewer paths, but more dependencies. The core contains no dependencies, but encapsulates the different logic paths. So we’re encapsulating dependencies on one side, and business logic on the other side. Or put another way, the way to figure out the separation is by doing as much as you can without mutation, and then encapsulating the mutation separately. Functional core — Many fast unit tests. Imperative shell — Few integration tests
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <ctype.h> | |
#include <openssl/rsa.h> | |
#include <openssl/engine.h> | |
#include <openssl/pem.h> | |
// I'm not using BIO for base64 encoding/decoding. It is difficult to use. | |
// Using superwills' Nibble And A Half instead |
The following rules of programming style are excerpted from the book "The Elements of Programming Style" by Kernighan and Plauger, published by McGraw Hill. Here is quote from the book: "To paraphrase an observation in The Elements of Style by Strunk and White, the rules of programming style, like those of English, are sometimes broken, even by the best writers. When a rule is broken, however, you will usually find in the program some compensating merit, attained at the cost of the violation. Unless you are certain of doing as well, you will probably do best to follow the rules."