Showing posts with label API Design. Show all posts
Showing posts with label API Design. Show all posts

Sunday, 10 May 2015

Machine Learning and APIs: introducing Mills in REST API Design

Level [C3]

REST (REpresentational State Transfer) was designed with the "state" at its heart, literally, standing for the S in the middle of the acronym.

TL;DR: Mill is a special type of resource where server's authority purely comes from exposing an algorithm, rather than "defining, exposing and maintaining integrity of a state". Unlike an RPC style endpoint, it has to adhere to a set of 5 constraints (see below). 

Historically, when there were only a few thousand servers around, the state was predominantly documents. People were creating, editing and sharing a lot of text documents, and some HTML. With HTTP 1.1, caching and concurrency was built into the protocol and enabled it to represent richer distributed computing concerns and we have been building . With the rising popularity of REST over the last 10 years, much of today's web has been built on top of RESTful thinking, whether what is visible or what is behind the presentation (most external layer) servers. Nowadays when we talk of state, we normally mean data or rather records persisted in a data store (relational or non-relational). A lot of today's data, directly or indirectly, is created, updated and deleted using REST APIs. And this is all cool, of course.

When we design APIs, we map the state into REST Resources. It is very intuitive to think of resources as collection and instance. It is unambiguous and useful to communicate these concepts when for example we refer to /books and /books/123 URLs, as the collection or instance resources, respectively. We interact with these resources using verbs, and although HTTP verbs are not meant to be used just for CRUD operations, interacting with the state that exists on the server is inherent in the design.

But that is not all the story. Mainstream adoption of Machine Learning in the industry means we need to expose Machine Learning applications using APIs. The problem is the resource oriented approach of REST (where the state is at the heart of the design) does not work very well.

By the way, I am NOT 51...
How-old.net is an example of a Machine Learning application where instead of being an application, it could have been an API. For example (just for illustration, you could use other media types too):

POST /age_gender_classifier HTTP/1.1
Content-Type: image/jpeg
And the response:
200 OK
Content-Type: application/json

{
    "gender":"M"
    "age":37
}

Server is generating a response to the request by carrying out complex face recognition and running a model, most likely a deep network model. Server is not returning a state stored on the server, in fact this whole process is completely stateless.

And why does this matter? Well I feel if REST is supposed to move forward with our needs and use cases, it should define, clarify, internalise and finally digest edge cases. While such edge cases were pretty uncommon, with the rise and popularity of Machine Learning, such endpoints will be pretty standard.

A few days ago, on the second day of APIdays Mediterranea 2015 conference, I presented a talk on Machine Learning and APIs. And in this talk I presented simple concept of Mills. Mills, where you take your wheat to be ground and you carry back the flour.



Basically, it all goes back to the origin of a server's authority. To bring an example, a "Customer Profile" service, exposed by a REST API, is the authority to go to when another service requires access to a customer's profile. The "Customer Profile" service has defined a state, which is profile of the customers, and is responsible for ensuring integrity of the state (enforcing business rules on the state). For example, marketing email preference can have values of None, WeeklyDigest or All, it should not allow the value to be set to MonthlyDigest. We are quite used to these type of services and building REST APIs on top: CustomerProfile becomes a resource that we can query or interact with.

On the other hand, a server's authority could be exposing an algorithm. For example, tokenisation of text is a non-trivial problem that requires not only breaking the text to its words, but also maintaining muti-words and named entities intact. A REST API that exposes this functionality will be a mill.

5 constraints of a Mill

1) It encapsulates an algorithm not a state

Which was discussed ad nauseum, however, the distinction is very important. For example let's say we have an algorithm that you provide the postcode and it returns to you houses within 1 mile radius of that postcode - this is not an example of a mill.

2) Raw data in, processed data out

For example you send your text and get back the translation.

3) Calls are both safe and idempotent

Calling the endpoint should not directly change any state within the server. For example, the endpoint should not be directly mapped to the ML training engine, e.g. sending a text 1000 times skew the trained model for that text. The training endpoint is usually a normal resource, not a mill - see my slides

4) It has a single specialty

And as such, it accepts a single HTTP verb apart from OPTIONS, normally POST (although a GET with entity payload would be more semantically correct but not my preferred option for practical reasons).

5) It is named not as a verb but as a tool

A mill that exposes tokenisation, is to be called tokeniser. In a similar way, classifier would be the appropriate name for a system that classifies on top of a neural network, for example. Or normalising text, would have a normaliser mill.



No this is not the same as an RPC endpoint. No RPC smell. Honest :) That is why those 5 constraints exists.



Saturday, 29 November 2014

Health Endpoint in API Design: slippery slope that it is

Level [C3]

Health Endpoint is a common practice in building APIs. Such an endpoint, unlike other resources of a REST API, instead of achieving a business activity, returns the status of the service and while it can gather and return some data, it is the HTTP status that defines whether the service is "Up or Down". These endpoints commonly go and check a bunch configurations and connectivity with the dependent services, and even make a few calls for a "Test Customer" to make sure business activity can be achieved.

There is something above that just doesn't feel right to me - and this post is an exercise to define what I mean by it. I will explain what are the problems with the Health API and I am going to suggest how to "fix" it.

What is the health of an API anyway? The server up and running and capable of returning the status 200? Server and all its dependencies running and returning 200? Server and all its dependencies running capable of returning 200 in a reasonable amount of time? API able to accomplish some business activity? Or API able to accomplish a certain activity for a test user? API able to accomplish all activities within reasonable time? API able to accomplish all activities with its 95% percentile falling within an agreed SLA?

A Service is a complex beast. While its complexity would be nowhere near a living organism, it is useful to draw a parallel with a living organism. I remember from my previous medical life that the definition of health - provided by none other than WHO - would go like this:
"Health is a state of complete physical, mental and social well-being and not merely the absence of disease or infirmity."
In other words, defining health of an organism is a complex and involved process requiring deep understanding of the organism and how it functions. [Well, we are lucky that we are only dealing with distributed systems and their services (or MicroServices if you like) and not living organisms.] For servies, instead of health, we define the Quality of Service as a quantitative measure of a service's health.

Quality Of Servie is normally a bunch of orthogonal SLAs each defining a measurement for one aspect of the service. In terms of monitoring, Availability of a service is the most important aspect of the service to guage and closely follow. Availability of the service cannot simply be measured by the amount of time the servers dedicated to a service have been up. Apart from being reachable, service needs to respond within acceptable time (Low Latency) and has to be able to achieve its business activity (Functional) - no point server being reachable and return 503 error within milliseconds. So the number of error responses (as a deviation from the baseline which can be normal validation and business rule errors) also come into play.

So the question is how can we, expose an endpoint inside a service that can aggregate all above facets and report the health of a service. Simple answer is we cannot and should not commit ourselves to do it. Why? Let's take some simple help from algebra.
API/Service maps an input domain to an output domain (codomain). Also availability is a function of the output domain.

A service (f) is basically a function that maps the input domain (I) to an output domain (O). So:
O = f(I)
The output domain is a set of all possible responses with their status codes and latencies. Availability (A) is a function (a) of the output domain since it has to aggregate errors, latencies, etc:
A = a(O)
So in other words:
A = a(f(I))
So in other words, A cannot be measured without I - which for a real service is a very large set. And also it needs all of f - not your subset bypass-authentication-use-test-customer method.

So one approach is to sit outside the service and only deal with the output domain in a sort of proxy or monitoring server logs. Netflix have done a ton of work on this and have open sourced it as Hysterix) and no wonder I have not heard anything about the magical Health Endpoint in there (now there is an alternative endpoint which I will explain later). But if you want to do it within the service you need all the input domain and not just your "Test Customer" to make assertions about the health of your service. And this kind of assertion is not just wrong, it is dangerous as I am going to explain.

First of all, gradually - especially as far as the ops are concerned - that green line on the dashboard that checks your endpoint becomes your availability. People get used to trust it and when things go wrong out there and customers jump and shout, you will not believe it for quite a while because your eye sees that green line and trusts it.

And guess what happens when you have such an incident? There will be a post-mortem meeting and all tie-and-suits will be there and they identify the root cause as the faulty health-check and you will be asked to go back and fix your Health Check endpoint. And then you start building more and more complexity into your endpoint. Your endpoint gets to know about each and every dependency, all their intricacies. And before your know it, you could build a complete application beside your main service. And you know what, you have to do it for each and every service, as they are all different.

So don't do it. Don't commit yourself to what you cannot achieve.

So is there no point in having a simplistic endpoint which tells us basic information about the status of the service? Of course there is. Such information are useful and many load balancers or web proxies require such an endpoint.

But first we need to make absolutely clear what the responsibility of such an endpoint is.

Canary Endpoint

A canary endpoint (the name is courtesy of Jamie Beaumont) is a simplistic endpoint which gathers connectivity status and latency of all dependencies of a service. It absolutely does not trigger any business activity, there is no "Test Customer" of any kind and is not a "Health Endpoint". If it is green, it does not mean your service is available. But if it is red (your canary is dead) then you definitely have a problem.



So how does a canary endpoint work? It basically checks connectivity with its immediate dependencies - including but not limited to:
  • External services
  • SQL Databases
  • NoSQL Stores
  • External distributed caches
  • Service brokers (Azure RabbitMQ, Service Bus)
A canary result contains name of the dependency, latency and the status code. If any of the results has non-success code, endpoint returns a non-success code. Status code returned is used by simple callers such as load balancers. Also in all cases, we return a payload which is aggregated canary result. Such results can be used to feed various charts and draw heuristics into significance of variability of the latencies.

You probably noticed that External Services appear in Italic i.e. it is a bit different. Reason is if an external service has a canary endpoint itself, instead of just a connectivity check, we call its canary endpoint and add its aggregated result to the result we are returning. So usually the entry point API will generate a cascade of canary chirps that will tell us how things are.

Implementation of the connectivity check is generally dependent on the underlying technology. For a Cache service, it suffices to Set a constant value and see it succeeding. For a SQL Database a SELECT 1; query is all that is needed. For an Azure Storage account, it would be enough to connect and get the list of tables. The point being here is that none of these are anywhere near a business activity, so that you could not - in the remotest sense - think that its success means your business is up and running.

So there you have it. Don't do health endpoints, do canary instead.

Canary Endpoint implementation

A canary endpoint normally gets implemented as an HTTP GET call which returns a collection of connectivity check metrics. You can abstract the logic of checking various dependencies in a library and allow API developers to implement the endpoint by just declaring the dependencies.

We are currently working on an implementation in ASOS (C# and ASP.NET Web API) and there is possibility of open sourcing it.

Security of the Canary Endpoint

I am in favour of securing Canary Endpoint with a constant API key - normally under SSL. This does not provide highest level of security but it is enough to make it much more difficult to break into. At the end of the day, a canay endpoint lists all internal dependencies, components and potentially technologies of a system that can be used by hackers to target components.

Performance impact of Canary Endpoint

Since canary endpoint does not trigger any business activity, its performance footprint should be minimal. However, since calling the canary endpoint generates a cascade of calls, it might not be wise to iterate through all canary endpoints and just call them every few seconds since deeper canary endpoints in a highly layered architecture get called multiple times in each round. 


Monday, 29 September 2014

Performance Counters for your HttpClient

Level [T2]

Pure HTTP APIs (aka REST APIs) are very popular at the moment. If you are building/maintaining one, you have probably learnt (perhaps the hard way) that having a monitoring on your API is one of your top cross-cutting concerns. This monitoring involves different aspects of the API, one of which is the performance.

There has been many approaches to solving cross-cutting concerns on APIs. Proxying has been a popular one and there has been proliferation of proxy type services such as Mashery or Apigee which basically sit in front of your API and provide an abstraction which can solve your security and access control, monetizing or performance monitoring.

This is a popular approach but comes with its headaches. One of these problems is that if you already have a security mechanism in place, it can clash with the one provided by the service. Also the geographic distribution of these services, although are getting better, is not as good as the one provided by many cloud vendors. This can mean that your traffic could be bouncing across the Atlantic ocean a couple of times before getting to your end users - and this is bad, really really bad. On the other hand, these will not tell you what is happening inside your application which you have to solve differently using classic monitoring approaches. So in a sense, I would say you might as well just byte! the bullet and just implement it yourself.

PerfIt was a library I built a couple of years ago to provide performance counters for ASP.NET Web API. Creating and managing performance counters for windows is not a rocket science but is clumsy and once you do it over and over and for every service, this is just a bit too much overhead. So this was designed to make it really simple for you... well, actually for myself :) I have been using PerfIt over the last two years - in production - and it serves the purpose.

Now, it is all well and good to know what is the performance characteristics of your API. But this gets really more complicated when you have taken a dependency on other APIs and degradation of your API is the result of performance issues in your dependent APIs.




This is really a blame game: considering the fact that each MicroServie is managed by a single team and in an ideal DevOps world, the developers must support their services and you would love to blame another team rather than yourself especially if this is truly the direct result of performance degradation in a dependent service.

One solution is have access to performance metrics of the dependent APIs but really this might not be possible and kinda goes against the DevOps model of operations. On the other hand, what if this is due to an issue in an intermediary - such as a Proxy?

The real solution is to benchmark and monitor the calls you are making out of your API. And I have implemented a new DelegatingHandler to do that measurement for you!


PerfIt! for HttpClient

So HttpClient is the de-facto class for accessing HTTP APIs. If you are using something else then either you have a really really good reason to do so or you are just doing it wrong.

PerfIt for client provides 4 standard counters out of the box:

  • Total # of operations
  • Average time taken (in seconds)
  • Time taken for the last operation (in ms)
  • # of operations per second

These are the 4 counters that you would normally need. If you need another, just get in touch with me but remember these counters must be business-independent.

First step is to install PerfIt using NuGet:
PM> Install-Package PerfIt
And then you just need to install the counters for your application. This can be done by running this simple code (categoryName is the performance counter grouping):
PerfItRuntime.InstallStandardCounters("<categoryName>");
Or by using an installer class as explained on the GitHub page and then running InstallUtil.exe.

Now, just add PerfitClientDelegatingHandler to your HttpClient and make some requests against a couple of websites:
using System;
using System.Net.Http;
using PerfIt;
using RandomGen;

namespace PerfitClientTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var httpClient = new HttpClient(new PerfitClientDelegatingHandler("ClientTest")
            {
                InnerHandler = new HttpClientHandler()
            });

            var randomSites = Gen.Random.Items(new[]
            {
                "http://google.com",
                "http://yahoo.com",
                "http://github.com"
            });
            for (int i = 0; i < 100; i++)
            {
                var httpResponseMessage = httpClient.GetAsync(randomSites()).Result;  
                Console.Write("\r" + i);  
            }
           
        }
    }
}
And now you should be seeing this (we have chosen "ClientTest" for the category name):

So as you can see, instance names are the host names of the APIs and this should provide you with enough information for you to monitor your dependencies. Any deeper information than this and then you really need tracing rather than monitoring - which is a completely different thing...



So as you can see, it is extremely easy to set this up and run it. I might expose the part of the code that defines the instance name which will probably be coming in the next versions.

Please use the GitHub page to ask questions or provide feedbacks.


Thursday, 21 November 2013

HTTP Content Negotiation on higher levels of media type

[Level T3]

TLDR; [This is a short post but anyhow] You can now achieve content negotiation on Domain Model or even Version (levels 4 and 5) in the same ASP.NET Web API controller.

As I explained in the previous post, there are real opportunities in adopting 5LMT. On one hand, semantic separation of all these levels of media type helps with organic development of a host of clients with different capabilities and needs. On the other hand, it solves some existing challenges of REST-based APIs.



In the last post we explored how we can have a Roy-correct resource organisation (URLs I mean, of course) and take advantage of content-based action selection which is not natively possible in ASP.NET Web API.

Content Negotiation is an important aspect of HTTP. This is the dance between client and server to negotiate on the optimum media type to get a resource. Most common implementation of content negotiation is the server-side one which server decides the format based on the client's preferences expressed by the content of Accept, Accept-Language, Accept-Encoding, etc headers.

For example, the page you are viewing is probably the result of this content negotiation:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

This basically mean give me HTML or XHTML if you can (q=1.0 is implied here), if not XML should be OK, and if not then I can live with image/webp format - which is Google's experimental media type as I was using Chrome.

So, let's have a look at media types expressed above

text/html  -> Format
application/xhtml+xml -> Format/Schema
image/webp  -> Format

So as we can see, content negotiation at this request mainly deals with format and schema (levels 2 and 3). This level of content negotiation comes out of the box in ASP.NET Web API. Responsibility of this server-side content negotiation falls on MediaTypeFormatters and more importantly  IContentNegotiator implementations. The latter is a simple interface taking the type to be serialised, the request and a list of formatters and returns a ContentNegotiationResult:

IContentNegotiator

public interface IContentNegotiator
{
    ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, 
        IEnumerable<mediatypeformatter> formatters);
}

This is all well and good. But what if we want to ask for SomeDomainModel or AnotherDomainModel(level 4)? Or even more complex: asking for a particular version of the media type (level 5)? Unfortunately ASP.NET Web API does not provide this feature out of the box, however, using 5LMT this is very easy.

Let's imagine you have two different representation of the same resource - perhaps one was added recently and can be used by some clients. This representation can be a class with added properties or even more likely, removal of some existing properties which results in a breaking change. How would you approach this? Using 5LMT, we add a new action to the same controller returning the new representation:

public class MyController
{
    // old action
    public SomeDomainModel Get(int id)
    {
        ...
    }

    // new action added
    public AnotherDomainModel GetTheNewOne(int id)
    {
        ...
    }
}
And the request to return each of will be based on the value of the accept
GET /api/My
Accept: application/SomeDomainModel+json
or to get the new one:
GET /api/My
Accept: application/AnotherDomainModel+json
In order to achieve this, all you have to do is to replace your IHttpActionSelector in the Services of your configuration with MediaTypeBasedActionSelector.

This is the non-canonical representation of media type. You may also use the 5LMT representation which I believe is superior:
GET /api/My
Accept: application/json;domain-model=SomeDomainModel
or to get the new one:
GET /api/My
Accept: application/json;domain-model=AnotherDomainModel

In order to use this feature, get the NuGet package:
PM> Install-Package AspNetWebApi.FiveLevelsOfMediaType
and then add this line to your WebApiConfig.cs:
config.AddFiveLevelsOfMediaType();
MediaTypeBasedActionSelector class provides two extensibility points:

  • domainNameToTypeNameMapper which is a delegate and gets the name passed in the domain-name parameter and returns the class name of the type to be returned (if they are not the same although it is best to keep them the same)
  • Another one which deserves its own blog post, allows for custom versioning.

Happy coding...

Wednesday, 13 November 2013

Content-based action selection in ASP.NET Web API

[Level T3]

TLDR; You can now achieve content-based action selection in ASP.NET Web API

You probably will not remember but last year, I proposed an implementation of media type based on parameters that separates different levels of media type - Five Levels of Media Type or 5LMT. This discussion is mainly theoretical and focuses on media type semantics and problems of the popular (yet non-canonical) approaches to media types that are prevalent in the community. The article identified 5 levels (human illegibility, format, schema, domain model and version) and separating these will help different clients with different capabilities to use levels they are capable of understanding without having to fully comprehend all levels.

But really, is this not just nitpicking on trivial issues and arguing issues which have to practical importance? Well, I think not - and here is why. If you would like to see some code instead of endless dry discussions, you will not be disappointed.

If you visit StackOverflow and look for ASP.NET Web API (or alternatively REST APIs), there are many questions on REST resource design. Coming from an RPC mindset, it is difficult to map all methods to GET, POST, PUT and DELETE. And sometimes we run out of verbs and we resort back to RPC-style APIs.

Let's imagine you are designing a digital music player API and you have identified these resources and operations:

Play  PUT  /api/player
Stop  DELETE  /api/player
Vol up  POST  /api/player/volume
Vol down POST  /api/player/volume
Next  POST  /api/player/song
Previous POST  /api/player/song
Back to first PUT  /api/player/song

This is a RESTful resource design (note idempotent verbs have been mapped to PUT or DELETE) and looks good. But there is a problem: we have same verbs twice or more on some routes and ASP.NET Web API will throw exception and complain about ambiguous actions.

At this time, some finally give in to defining /api/player/song/next and /api/player/song/previous i.e RPC-style URLs. And this is a downward spiral when you resources are verbs rather than noun.

The solution is to go back to REST. One of the tenets of REST is self-descriptive messages as such we should be able to express our intention with the HTTP messages. In other words, sending this message to up the volume:
POST /api/player/volume HTTP/1.1
Content-Type: application/json;domain-model=IncreaseVolumeCommand

{"notch":"11"}
And that is it. Our HTTP message provides enough information for our Web API to distinguish as long as our action has been defined as something like

public void Post(IncreaseVolumeCommand command)
{
   ...
}
or
public void Post(HttpRequestMessage request, IncreaseVolumeCommand command, ...)
{
   ...
}
And how is this achieved? Well, a little utility in 5LMT library called MediaTypeBasedActionSelector does it. To get the library, just add the NuGet package:
PM> Install-Package AspNetWebApi.FiveLevelsOfMediaType
And then your WebApiConfig class, add the line below:
config.AddFiveLevelsOfMediaType();
What this line does is to replace default action selector with MediaTypeBasedActionSelector and wrap your media type formatters in a decorator. As such, make sure you add this line after you have done all changes to your media type formatters.

After this change, your API will send 5LMT parameters. For example:
Content-Type:application/json; charset=utf-8; domain-model=InventoryItemDetail; version=1.0.0.0; format=application%2fjson; schema=application%2fjson; is-text=True

Another useful feature is the support for non-canonical media types. For example you can send this HTTP request instead of the POST discussed above:
POST /api/player/volume HTTP/1.1
Content-Type: application/vnd.MyCompany.IncreaseVolumeCommand-1.0.0.0+json

{"notch":"11"}

While use of this media type is discouraged by RFC 2616 (since above media type is not registered by IANA), this still works with 5LMT library.

One last thing is that this library is dependent on AspNetWebApi.ApiActionSelector which makes action selection implementation of ASP.NET Web API extensible. Unfortunately, most of the implementation is internal and does not expose extensibility points and AspNetWebApi.ApiActionSelector had to achieve this by a lot of cope and paste :)

The code for this library is hosted on GitHub.

Happy coding...

Sunday, 27 October 2013

REST APIs and restaurants [Take II*]

[Level C3]



 - "... and sauteed with the finest aromatic saffron - we import directly from our suppliers in Tibet - and garnished with the finest quality ocra from the heart of Morocco and ..."

- : ".. hmmm, bu..."

- : " and Sir, the King Shrimps day fresh from our suppliers in Belgium mildly cooked with a hint of lime zest and aromatic Thai basil snuggled with a swirl of Cornish Creme Fraiche and blossoms of Burmese jasmine and ..."

- : "... I mean, ..."

- : " and I should remind you that our head chef has used a special blend of exotic spices, marinated for 42 minutes exact, to create a sensual oriental effect of ... "

- : "I REALLY DON'T CARE! This stuff is awful!"



⚑  ⚑  ⚑

In more than one way a REST API is similar to a restaurant. They both hide a very complex process of accomplishing a service (serving food or data) behind a nice, warm and welcoming presentation. And we need to bear in mind that presentation is the key: no matter what goes on behind the scene in the kitchen, the food and its presentation is the key. And your API is the menu, the door to the services provided by the server. Whatever goes on in the kitchen (your server's internal domain) is not the concern of your customers as long as the output and presentation is good.

Commonly, the perspective in which we look at our services is wrong. They are server-centric. [I have talked before about the definition of server (and client) and their interaction] In brief, when we talk about the server, this is what comes in mind (as per CSDS):


This view is useful when building a server. It highlights inherent complexity of the server and how it should hide its complexity behind its API. But it is way too easy to get attached to the bird's eye view of the server where all internals of the server is visible.

And it is too easy to forget that this is how the client sees the server:

Client perspective of a server, where it sees a black box (here it's blue!) and
the gateway to the server is through its API.
When talking of the domain in an API, we are very likely to mean the server's private domain - its internals and complex process. Reality is server's internal domain does not surface beyond the API layer. API Layer is responsible to define resources which in turn define a coherent public domain composed of API and its messages - abstracted away from server's internal domain. If the server is an online retail API, I can create, edit or cancel orders. The fact that this is achieved through contact to many suppliers and their own custom processes is not a concern of the client.

In fact, in the same way that kitchen of a restaurant and its dining area are completely abstracted away, server's public domain is an abstraction on the top of server's internal domain. This is good for the chef and the customer. It is true the food that is served comes out of the kitchen but the whole process of preparation is irrelevant for the customer. 

Why talking of server's public domain is important? Because we commonly look down on the public domain. When we talk of the DTO messages passed to and fro, we regard them as View Models so they are not even proper models, they are just DTOs, no behaviour just some property bag. We use a mapper to strip down the sensitive data from our real models and spit out the view models to the client. And when we talk about DDD, we only mean server - we think view models do not deserve the love of care of DDD.

But this results in a brittle API that has to be changed by every change of the server. It becomes a cut down version of the server's internal API. We all know examples of good and bad API but too many changes in an API is a sign of bad design usually from Server Chauvinism. So always do a separate DDD for your server's public domain. It might sound strange since I am in favour of no-business-logic-in-api-layer. Well, it is true - we do not implement any business logic in the API Layer but the biggest responsibility of API Layer is talking HTTP. This translates to defining resources in REST.

So practice DDD in your API Layer. Define its aggregate roots, entities and value types - it is simplistic to think such concepts can be entirely hidden from the clients. Specify the commands and queries - with commands usually being the payload of the PUT, DELETE and POST and queries usually expressed in the URL itself to make them cache friendly.



What we see in the above picture define server's public domain: it is API (set of resources), input messages (commands and queries) and output messages (entities and value types). The case of queries - as we said - is a bit special since it is normally expressed in URL. This has the benefit of cacheability in contract with sending a payload (using other methods) which not suitable for caching. As an example, here is twitter's API for getting status timelines:

Get /1.1/statuses/user_timeline.json?screen_name=twitterapi&count=2

Defining parameters as query strings is useful as they can also imply optionality. One downside to this approach is the fact that ordering of parameters cannot be expressed in query string and while any combination can be valid, semantically equal combinations will be considered different resources and cached separately. For example, screen_name=twitterapi&count=2 and screen_name=twitterapi&count=2 are semantically equal while they are considered different resources. This reduces effectiveness of caching for GET requests. For this reason, URL segments separated by / are superior although in a big API can result in prohibitive complexity of routing.

Items returned in this API are Entities. it is evident by having an ID (id_str) which is returned as part of data.


Looking at what each timeline contains, we can see list of urls, where each url returned is a Value Type. It has three properties: url, indices and expanded_url.

In the case of commands, we have a similar situation. Looking at an example in twitter, tweeting (sending a tweet) is achieved using this command:

POST /1.1/statuses/update.json

status=Maybe%20he%27ll%20finally%20find%20his%20keys.%20%23peterfalk

Perhaps a better implementation would have been to omit the update.json totally - as this naming has an RPC smell. Using singular or plural is mainly down to taste - although I prefer singular. The command can be expressed by the simple class below:



Not all commands have to have a payload. Deleting a tweet can get send an ID in the URL with the DELETE command to /1.1/statuses/update.json although actual twitter API uses a POST instead.

Resources are basically all that can be accessed through the API although a more useful definition is the grouping around identities. For example Flickr API defines cameras, people, photos, photo comments, etc. It is true that Flickr is not considered a good example of a REST API when it comes to HTTP semantics, however, it does a good job in defining a coherent domain represented by resources while hiding its internals. A simple example is how it sends you previous and next photo instead of letting the client guess what these are based on the internal implementations.

In brief, it is responsibility of the API to create a coherent set of resources that can layout a cohesive picture in front of the client.

Common Anti-Patterns

As we said, the main danger is to have a server-centric perspective and neglect the public domain of your API.

While performing appropriate-sized DDD exercise is important, we need to be careful not expose too much of the server. One common anti-pattern is exposing server's internal to outside world. OData is a RESTful protocol which defines semantics for querying (mainly tabular) data store.

GET /api/products?$filter=name eq 'Gizmo 3'&$orderby=price desc&$top=1

While OData itself is not necessarily prescribing exposing server's internals, most of the implementations are actually built straight on the top of an RDBMS exposing its internal schema and and potentially allowing ad-hoc changes using SQL-like commands rather than domain-rich commands. Netflix who initially warmed up to the idea of exposing its films database to the public, reached the conclusion this is not such a RESTful idea and retired its OData service.

Another issue is the server-centric design: server assuming how its services will be used. I believe (Sorry Roy!) HATEOAS touches the subjects discussed here. When we talk of Hypermedia As The Engine OF Application State, which application do we mean? OK, let's consider Twitter's API. How can you think same hypermedia can equally drive the state of a twitter client, a game that posts scores on twitter, 4Square app that declares you a mayor on twitter or a twitter realtime map showing location of tweets using the firehose data pipe? The relationship from clients to servers are not one-to-one any more and effectiveness of HATEOAS is questionable. Application is defined by the client and not the server, as such server's hypermedia cannot be the engine of the application.

At the end of the day, none of us want to sound like the pompous chef who bores the customers with self-flattery. Server serves, so design it for servant-hood.


* this post was originally posted slightly differently under the name: "Server Chauvinism - API's public domain"

Saturday, 12 October 2013

API Layer and its responsibilities - a REST viewpoint

[Level C4] With the emergence and popularity of REST APIs, there is a need to define a layer dedicated to the performing API-related functions. This article tries to define these responsibilities and separate it from the responsibility of other layers.

TLDR; If you are putting business logic of your domain in your API Layer (which is the presentation layer of your service), you are doing it wrong.


Layered (Tiered or N-Tiered) Architecture is a software design pattern that implements a software system in a stack of layers. Each layer has a distinct responsibility and has a dependency upon the deeper layer - with the deepest layer normally accessing a relational database.

This pattern, also known as the Layers pattern, was formalised in the book Pattern-Oriented Software Architecture: Layers pattern "helps to structure applications that can be
decomposed into groups of subtasks in which each group of subtasks is at a particular level of abstraction." This pattern emerged as a replacement to the Client-Server architecture and became very popular in late 90s and early 2000s.

Service Oriented Architecture (SOA) did not change the popularity and importance of tiered architecture since each service contains the tiers inside it (Figure 1)

Figure 1 - Layered Architecture in SOA
Layers are usually domain-agnostic and can be uniquely identified across different implementations and systems. The layers themselves are not necessarily physical, i.e. deployed on different machines; they can be simply logical implementations in different libraries - or even in the same library. What identifies a layer is its responsibility not its physical location.

There are different approaches in identifying and naming layers across a system stack. Historically, three tiers have been identified: Presentation Layer, Business Layer and Data Access Layer (Figure 2).
Figure 2 - Traditional Layers
This traditional layering is still prevalent and popular in the industry. As the names imply:

  • Presentation Layer deals with user interactions
  • Business Layer contains the business logic of the domain
  • Data Access Layer is concerned with the persistence of the domain objects
Sometimes a Service Façade Layer is identified between Business Layer and Presentation Layer which is responsible to organise the business services as a coarsely granular set of services. This layer is usually very thin.

However, Eric Evans in his Domain Driven Design book introduced an alternative layering which was a better fit for DDD: Presentation Layer, Application Layer, Domain Layer and Infrastructure Layer. (Figure 3)
Figure 3 - Layers according to DDD (two alternative interpretations)

In this model, responsibilities of each layer is defined as below:

  • Presentation Layer has the same responsibility as the traditional model: user interaction (user could equally be a machine or human)
  • Application Layer which I prefer to call Workflow Layer is the thin layer that connects and coordinates coarse granular business tasks. This layer can have state regarding the state of a business activity. 
  • Domain Layer is the heart of the system which contains all the business logic
  • Infrastructure Layer is responsible for persistence, passing messages to buses and providing a framework and utility across other layers. As such, all layers could have access to this layer. 

API Layer

In none of the above we saw any mention of an API Layer, so what is an API Layer? API Layer is the outermost layer of a service and is concerned with presentation of a bounded context services through the API. In other words, in an SOA, we can call the Presentation Layer of an SOA Services its API Layer.

This layer was very thin or non-existent in services exposed through SOAP but it is an important layer when it comes to REST. The reason for its lack of importance in SOAP services is the fact that an RPC service can be easily exposed through SOAP with some configuration and little or no coding - using various tools and frameworks that make this possible with a click of a button. WCF is an example of this in the Microsoft stack while IBM Websphere is a popular tool in the Java world capable of achieving this.

API Layer Responsibilities

With REST, however, API requires a distinct layer that is responsible for translating the HTTP semantics to and from the code world. It also responsible for cross-cutting concerns such as monitoring, logging, identity, etc. We will be looking into each and expanding the meaning and examples.

Table 1 - API Layer responsibilities (in REST)
Bear in mind, none of the above involves any domain-related business logic. In other words, API Layer can use a common framework that can be equally used among different services since it is mainly domain-agnostic and does not implement any.business logic. As such, this IBM's online article (Figure 4) turns into How Not To Do API Layer since it puts Domain classes in the API Layer.

Figure 4 - This is IBM's view of an API Layer according to this article.
However, I will call it How Not To Design An API LAYER.
(Source: http://www.ibm.com/developerworks/library/j-ts3/layers.gif)
So let's look into each responsibility in depth. But before we do that it is important to define what we mean by no-business-logic. Since API Layer has an access to underlying layers, it is bound to touch the higher level abstractions of the domain. However it does not implement any of the business logic and simply directs the calls to the layers below.

HTTP Semantics

Talking HTTP is the most important responsibility of a REST API. HTTP provides different axis of sending intent or data which cannot be easily mapped to an RPC method's parameters. This problem is known as the impedance mismatch between RPC and HTTP.

Figure 5 - Impedance mismatch between HTTP/REST and RPC.
Challenge of shaping HTTP requests and responses from RPC methods
is the most important responsibility of the API Layer. (From the book Pro ASP.NET Web API)
Different frameworks provide different solutions to this problem but it is important to bear in mind that exposing a REST endpoint for your service means you need to a lot more to take advantage of all the flexibilities of HTTP messages.

Table 2 lists important HTTP semantics that are responsibility of a REST API Layer.

Table 2 - HTTP Semantics that are responsibility of a REST API Layer
A few points are important to consider. While, none of above are truly dependent on a domain's business logic, it is possible that it could require business decision in some form of configuration. For example, cache expiry interval is usually a concern that the business stakeholders need to understand and happy with. Or Hypermedia exposes the relationship of resources in your API but the API Layer should really just take the natural relationship defined in your domain and expose in HTTP.

Monitoring

If you have an API that you do not monitor its health, performance and usage, then this is not a serious API. Bear in mind that Quality of Service (QoS) is one of the mainstays of an API which can be translated into SLA. Regardless of whether your API is public or private, you have to monitor your API against its baseline.

Identity and Authentication

Very rarely, if ever, an API allows anonymous clients. Even if your API is free, you should build an identity mechanism such as an API Key. API Layer is responsible for turning identity/authentication mechanisms (Basic Authentication, OAuth, OAuth 2.0, Windows Authentication) into rich claim-based identity.

Please note that we did not mention Authorization. Authorization is a concern of deeper layers of the system and fully ingrained with Business Logic - as such is not suited for implementation in the API Layer.

Logging, tracing and documentation

Developing against an API is not an easy task and you should make it very easy for the clients of your API to be able to build, debug and deploy. This is most neglected feature of an API that can endanger success of your public API or private API within a big enterprise.

Monetisation and Capping?

Similar to Authorization, I am on the belief that monetisation and usage capping of an API is heavily dependent on business logic and information that are available in deeper layers. As such, I believe that monetisation and usage capping of an API must be implemented in deeper layers and not in the API Layer.

What about the relationship of the API with Server-side generated views?

A common question that crops up in the stackoverflow is how to lay out the architecture of web applications that historically were based around Server-side MVC Frameworks. For example, should a RoR web application use a Ruby-based API layer? Or if you are in the Microsoft world, should an ASP.NET MVC application use ASP.NET Web API services?

Well it depends. API Layer and Server-side MVC Frameworks both sit at the Presentation Layer. So you should not really add the networking and serialisation overhead of accessing an API Layer from Server-side MVC Frameworks if they are part of the same application. As we said, API Layer is a thin layer that is only responsible with the API centric responsibilities. In most cases, MVC Frameworks should directly use deeper layers of the system and sit side-by-side with the API Layer. However, if API Layer is the presentation layer of an SOA service and the MVC Framework uses multiple APIs to build the views, then it is OK to separate it from the API Layer.