3 ms·
Aftee a decade as a professional developer, the key practice I've found that makes all the difference is this: make it very difficult for someone using my code
by mabbo 5y ago
Aftee a decade as a professional developer, the key practice I've found that makes all the difference is this: make it very difficult for someone using my code to use it wrong. Because no matter how well I write my code, I'm just one developer in a much larger system.
An example: imagine I have an API that takes in a users tax id. In the US, let's presume that's an SSN. In Canada, a SIN. In Brazil, a CPF/CNPJ, and so on.
One option is to give a free form field that let's you say country id and tax ID. Simple, works for all countries, extensible later, no problem. Except that okay, in Brazil we also need a tax address. Fine, add an address field as well. But now when a user is using this API to submit Canadian tax numbers, there's a field for tax address. What's that? Do I need it? I guess I'll give the users home address? And a developer trying to submit Brazilian tax IDs sees that the address field is optional, so I guess I don't need that. ("Why didn't they read the docs that said it wasn't in this case?" Because no one does!).
I've made it possible to use this API incorrectly. I did it to save myself effort and blamed the other developer for using it wrong.
On the other hand, if my API had a different input type for each country's tax ID, with required fields saying they are, it becomes impossible to use it wrong. You can't have a bug, a mistake, because the type enforces correct usage. Go even further and have the constructor for the input type for that county explicitly require the fields it must have, and now you're really making it hard to do it wrong.
Types are powerful tools to prevent bugs. A bug caught sooner is less expensive to fix, and how much sooner can you get than "the moment you wrote it"?
- larrik 5y ago> if my API had a different input type for each country's tax ID Like you just add a new field for every country you support? I can imagine quite a few ways to break that. For instance, my system has users from USA and CA, and I just send you everything in the SSN field, because I didn't consider the CA users when I wrote it. The simple way would have just worked, but now the API is broken for me.
- jerf 5y agoNo, add a new type. If your SSN is of type "USSocialSecurity" and the canadian system needs "CanadianTaxID" (sorry, I don't know what it is) then the API will not accept the wrong thing in the wrong place. "But what if I label it incorrectly and send it along?" Then that's a bug in your code. No amount of my API design can prevent bugs in your code. All my API can do is not help you write bugs in your code. I can't stop you from reading the random number generator and claiming its output is a USSocialSecurity number, but at least I've done my best for a reviewer of your code to be able to look at that and ask you what you're doing calling that a USSocialSecurity.
- deleted 5y ago[deleted]
- jfrunyon 5y ago> On the other hand, if my API had a different input type for each country's tax ID, Then you've significantly increased the work (and opportunity for bugs) required of a downstream programmer, and also made it significantly more likely that they won't support all countries, and of course they could also still send the wrong type...
- kazinator 5y agoPlus, this stuff likely has to go into a database. Now we have polymorphic OOP stuff needing to be connected to records and fields in a table. Maybe just have a generic "taxblob" fields which is a serialized object which indicates its type and all the properties by name.
- fragmede 5y agoThis seems like a good place to link the seminal work Falsehoods Programmers Believe About Time. https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time https://infiniteundo.com/post/25326999628/falsehoods-program...