APIs Are Like Lasagna
Stuart McAndrew and I were talking a little about code. He’s a coding newbie, reading many libraries in order to make progress on building his own satellite (OzQube-1). He asked an interesting question about making code for other people.
Stuart is working on a driver for a PCAL6408A, a GPIO expander chip that runs over I2C. He needs to set up how the PCAL is going to work (what it does doesn’t matter for this post, it is just a widget that needs some configuration that is specific to each project). Stuart wanted to know where to put the configuration: In the library itself? As a PCAL register value passed in as a parameter to the initialization function? Individual settings for the part that the library builds up to set the registers? In a header file that the library uses?
Stuart says, “If I open source the library code, I don't necessarily want my specific config in there. Should I write a new init function that takes specific arguments?”
This is a good question. It is unanswerable though. The question Stuart is asking amounts to "what do I put between the layers of pasta in lasagna so everyone likes it?"
There is nothing that makes everyone happy. And if you like anchovies in your lasagna, I won't stop, you but don't ask me to eat it (and I won't denigrate you about your awful taste but I'll admit there are people who would).
(I'm loving this metaphor. API design is hard.)
So! How would I make the layers for what Stuart wants? (There is a chapter about this in my book, I’m not going to rehash it.)
I think that if Stuart wants to make it configurable, then he should make the configuration human readable, with parameters (not just pass in the PCAL’s register setting). But if everyone building what he is building needs the same configuration then he shouldn’t expose it at all. Hiding things is good. Apple has been very successful by making most of the decisions for their users.
However, I don’t think Stuart should do either one of those, not really, not at the start of his code design.
Let me introduce you to the YAGNI principle. It stands for "You Aren't Going to Need It" (ok, it stands for a non-grammatical version of that). The idea is that many people complicate their code by adding features because they think that someone, somewhere, might need it. Chances are no one will. And if you put it in, you have wasted your time and frustrated others with your complexity (which means they don't use your code, which means you really wasted your time). In short, do what you need and let the future people take care of themselves.
Understand? My subtext to Stuart reads, "Put the config value in a #define in the header file but don't expose the value to the user at all.” The #define would be something like
#define PCAL_CONFIG_OZQUBE1 0x35 // TODO: explain config here
So why a #define instead of just putting the hex values into a function? Naming them is good coding practice so that future-you will understand the configuration.