… or what’s the idea behind canned.
Let’s face it designing an API is really hard.
The interface should be easy to use from the outside, as well as simple
from the inside. In the web world this normally means that the backend
should not have to go through extensive trouble to build up the response,
and the consuming code should not need to munge through huge amounts of data, just
to get it into a usable form. So this is what API design is all about.
The backend
When building a backend we normally try to be reasonable about the amount
of data we query from the database, and also try to minimize conversion of it, because this takes time. If it would take hundreds of queries while
sifting through JSON building up just the right response for this exact
case, our app will probably not be very responsive. So
the way to go is build up a REST (or at least somewhat REST-like) API
which serves the object backed by the database in a simple form making it easy to handle a lot of
requests.
But those guys on the other side…
Normally when the first (alpha whatever) version of the API is ready to go the
consumer side starts building, this might be Javascript frontend code,
or any other app consuming our maybe JSON / XML. Now we can either be really
lucky and the app is just so simple (or we are just so awesome at API design)
that everything is great and we can keep our simple API just how we liked it.
Actually more likely is that there are new requirements based on object
interaction in on the cosumer side we did not think about, or even willingly
ignored as it seemed not important and would have cluttered our backend.
… can’t we just add X?
Since we were kind of unsure what the API consumer really needed, and they
couldn’t really tell us as well without trying it out our API is build around
what we can serve there is a natural bias to build what is easy for the backend.
So when the frontend finally can start implementing they realize all those
little things which just don’t work with the current API output quite as they
should, and so we are in the classic ‘Can’t we just add X?’ or ‘I can just build
this in the frontend!’ mode where we start to not really work with our API but
against it. On the backend we drag to add features to our so nice and simple
code, while on the frontend we hate to just munge another JSON object into
another JSON object just to combine field X and Y which should have been
together in the first place. But didn’t TDD / BDD teach us to design outside in
from a user / consumer perspektive?
So why can’t we do better?
Even though designing code outside in (BDD style) has become really popular,
it’s not really happening when building an API at least for most apps. In most
cases the API is backend focused when it comes to design, it just serves what
the backend can serve easily. So how about the frontend and backend developers
working together? Why not designing the API from a ‘consumer perspective’ and
implementing the real code later? Isn’t this how it should be? And by doing so we can
really provide a nice API which at least works great for our current front-end,
and if it works great for one chances are it will work for something else as
well.
Enabling outside in API development: A workflow with canned responses
So far nice theory, but now let’s get some actual code going! I have to say I am
just trying things but this works currently, and to me makes a nice workflow:
Mock the API consumer side first
Writeup the responses the API should serve first, and try to use this exact data
in the front-end code, see how it works, and what needs change. Would providing
additional field X provide a significant improvement to the consumer code? You
can just do this inside the consumer itself via a mock.
Responses are just data, treat them as such
Now after an initial version is kind of working, move it out of a mock and into
it’s own file, this is where canned, a little api mock server, comes
into play. It let’s you serve those responses just via normal files instead of
having to create a big backend. By using the underlying folder structure and
some special keywords (any, index) we can easily make it act like a basic REST
API.
Your acceptance test are right there!
Backend development can now start it’s own outside in
development process, since it can verify the responses against the files
extracted to be served via canned, they can easily check what works and what
doesn’t. What makes the responses complex? Can we remove that? By having a common basis we can propose changes early, while
checking their impact immediatly on both sides, and evaluate.
Conclusion
Splitting the response data from the server implementation opens up a great way
to independently develop server side and client side code without integration
troubles. It can speed up development by facilitating parallel work on consumer
and client API side, as well as provide documentation as a by product.
I would by no means call myself an expert on this but to me it seems like a nice way to build, and so far it seems to really work great. Further refinement is probably needed for better
automation of the verification process. Also serving responses from files has
it’s limits, but actually those limit seems to work towards a nice API not
against it. Currently canned is just
a quick extraction of a concept I kept implementing again and again, so feedback is
greatly appriciated.
Any furthur ideas? hit me up on twitter and checkout canned in
npm or on github.
Have an awesome day!