Lets face it. Every piece of software you write, unless you are an eremite, is for another developer. It’s well known that you therefore should follow a bunch of principles to make your code more maintainable, easier to understand etc. It’s also well known that tests not only ensure quality, but provides others with some kind of an initial low-level documentation describing how the interaction with your API should look like.
Now, this API could be facing an internal team or could be written for an external consumer; another remote system. That system in turn is also maintained by developers. Peers. And for them, your domain might not be crystal clear, and they might not be on the same level of expertise. For them, your API might feel like Pandora’s box. Or Daedalus labyrinth, designed for keeping the Minotaur (part man, part bull) in. So what can we as developers do to provide others with a better experience?
Remember, you write for other peers. You have to continuously be having this in your mind as you design your API. Humans are lazy. We try to cut corners and we usually don’t want to wrestle to get simple tasks going. What does this mean? It means, it must be dead simple to get started with your API. Look at them as customers coming to your web shop to buy something. What happens if your site is ineffective? What if it’s to hard to navigate and hard to find what you seek? They leave. Without having a simple and quick “Getting started tutorial” or interactive guide, you will need to be lucky if you should draw focus from any competitors in the same context. Sure there could be agreements signed by managers, tying consumers to your product, but if not. You are doomed if you try to compete with one that does provide simple and clear guidance.
Think of MacGyver. MacGyver took small parts and built anything out of nothing. Do not create a system that has one interface: IHandleEverything
. That would implicitly be like having an interface called: IComplicateThings
. Provide the minimum amount of features needed in the context to solve the problem. Lets say you are building an API for data storage (like I have). You could provide one big-bloated component that provides you all nifty features of mappings, repositories, change-tracking etc. Or you could provide a core. A core that could be used to easily build the other “fluff” upon. Which one do you think would be easier to integrate against and switch if needed? Which one do you think will cause the least amount of errors? Try and be small and provide the customer with building blocks. Of course there’s a balance. But you are the expert of your domain and are the one that would know what components would be logical.
You will break stuff. I’m not talking about the fact that you will introduce errors. But the fact that you will redesign your API which will introduce backwards incompatibilities. Select a strategy of how to communicate this. Not only via some obscure little tweet or message on a blog. Select a versioning scheme that is easy to understand and that expresses these kind of changes. An example could be: Semantic versioning.
Strive for an intuitive contract. In the best of worlds, as a consumer, you would not have to read any documentation. Your API would have intuitive and consistent naming and intuitive ordering of sub-contexts. That way you would get a high degree of discoverability. E.g. building a generic interface allowing key-value argument passing, will give you a contract that has no meta what so ever in the form of either named parameters or object-passing. In a case like that, it will be pretty darn impossible to now what to pass and you will need to consolidate the documentation. Provide meaningful names and be consistent in the use of your verbs.
Could there be two domain languages? You are the master of your domain and within that domain you have developed an internal ubiquitous domain language, which hopefully makes perfect sense within your walls. However, it might not be making sense to your customers to the same degree. I’m not saying you should ditch your language, I’m saying reflect on it. Will the broad mass of your customers be sharing it? Are you targeting customers that are in the same domain? If not, perhaps it could be wise to have an external simplified language? I once worked as a contractor in the medical industry. The system was about ECG analysis were studies were performed on how certain substances affected peoples ECGs. In this area the people were not called “patients”, but “subjects”. Later on I moved to a new project. Still within healthcare, but now the term shifted to “patient”. So, what if you would consume the first system from the latter? I would say for most “inexperienced” developers within the area of healthcare, then both nursing and medicals etc., would be thrown into the same bucket and the most common expected name would be patient. In another project, we handled car repairs. The car could travel in different stages and be undergoing different kind of repairs. In that system we had the term of a bucket. It was to be seen as a connection between a certain function in the process, where each function could have x-num of resources and handle x-num of cars. Imagine someone coming and integrating with our system. Bucket? For me, buckets has nothing to do with car repairs, but I do get a lot of other associations. Cleaning, fishing crabs, an upset stomach…
Design and act as if it was your first line of defense. You should have some kind of “Getting started tutorial”. You should have documentation. You should have clear, intuitive and consistent naming and non generic interfaces. If not for other peers, then at least out of one selfish reason: “You don’t want to act support! You want to write software!”. I didn’t include tests in this list, but I should not have to. Trustworthy tests means quality. And quality means less support as well. Less support means more grateful managers and customers and of course a more happy you. Happiness is one important success factor. And that’s what it’s all about.
Cheers,
//Daniel