6 ms·
API-first architecture, or the fat vs. thin server debate
- tunesmith 13y agoA problem in general is that all these terms are highly overloaded. Models: For some, models are backend structures that are closely related to database entities. For others, models are data structures that are passed around closer to the front, or structures that controllers pass to views. Some also equate models with domains that have behavior as well as state. Servers/services: These are often used interchangeably when they are really not. For instance, your API call has to go to a web accessible server, which might in turn rely on a separate (SOA) service that is not web accessible. Client: This can mean the browser or mobile device (client/server), but it can also mean the consumer of a service (client/service). This consumer might also be sending serialized data structures or page responses to a browser or mobile device. Controller: This can refer to the logic in a mobile device that is making requests and unpacking json requests. Similarly, it can refer to a part of the javascript in a dynamic frontend that is doing the same. Or, it can also refer to the application that is receiving the network request (and in turn invoking business logic in other layers or making service calls to remote/private services) and then responding with json. So, imagine a browser or mobile device that makes a request to a remote "server" and receives a javascript application. The javascript has its own MVC architecture. Ensuing requests to the remote server will receive json responses. The js app might unpack the json in the js app's controller, and repack it into different models (data structures) that get passed to the js app's views. In turn, the remote "server" could have a controller that receive the initial request and returns a "view" that is the javascript app, but also another controller (more accurately a "resource") that would receive the RESTful requests and respond with json. These controllers/resources could in turn have a bit of business logic to help them make calls - via REST or SOAP - to internal/private "services". These services (on different servers) could have additional business logic to interact with private databases through daos that act on models (which somewhat-but-not-exactly represent the database schema because of ORM). I guess my point is that past a certain point, "fat" versus "thin" doesn't really capture the essence of the tradeoffs. It's more a series of questions of what is consuming what, what the consumer shouldn't have, what the consumer needs, and what the consumer is going to do with it. The big reason "controllers" (?) are getting "thicker" (?) is because there is a push to make the consumer-facing front-end more interactive and dynamic. I think that what the original article is saying is that if you want that, you should do what you can to return your API data structures (whether json or whatever) in as direct a fashion as possible, rather than manually constructing them through a templating technology and a bunch of views that would normally be used to return html. But more generally, I'd say that unless you're talking with a team that knows exactly what you're referring to (from previous discussions), it's best to just completely define what you mean by client/service/server/controller/model/etc in each case, because these days, it seems like everyone is using them differently.
- NathanKP 13y agoOne massive advantage of the API first architecture that wasn't mentioned in this article is that it makes proper unit testing much easier because of the clear distinction between the server side API code and the client side JavaScript/Mobile app. Of course it is possible to test a "fat" server that does view and presentation logic, but it is much easier and more efficient to test a thin server and have a separate suite of tests for the client side app.
- vojant 13y agoTotally agree, when I first time used this architecture it was first time when I had over 80% of the server side tested.
- PLejeck 13y agoI've always been curious how people do integration tests on things with multiple servers (like SOA stuff), it seems like it'd be dreadful, unless you use Vagrant to (quite slowly) spawn a new VM every time you want to test. Anyone with experience care to enlighten me?
- saryant 13y agoWe heavily utilize Akka clustering for our backend and we do this using Akka's multi-node testing feature. http://doc.akka.io/docs/akka/2.2.1/dev/multi-node-testing.html http://doc.akka.io/docs/akka/2.2.1/dev/multi-node-testing.ht... For the most part we only spin up multiple JVMs on the same machine but it's not a huge leap to use multiple machines. We don't do so regularly because, as you said, Vagrant takes forever to spin up a new VM. Our Jenkins server does spin up multiple JVMs for our integration tests though.
- AznHisoka 13y agoI don't have such a problem, but in my current project, I am integrating with various APIs such as Twitter + Facebook, and unit testing my code can be a nightmare at times since I'm dependent on them being stable.
- tunesmith 13y ago
- pearjuice 13y agoPlease note that the thin server should never be too thin. Logic should always happen in the server domain, handle the client as merely a presentation unit.
- meowface 13y ago>Logic should always happen in the server domain, handle the client as merely a presentation unit. Angular/Ember users would disagree with you. There is a fair bit of logic that can be done on the clientside, sometimes even raw computational logic. It really just depends on the kind of application, and also what the developer thinks is best.
- yeukhon 13y agoNot all logic. You can do simple input verification on client side. You can do in pace filter and yielding from client side. Bu anything tht requires extracting db and saving o db must go bough server side to ensure security is met.
- sjwright 13y agoInput verification and pace filtering must be duplicated on the server side as well. You can do this on the client side as well, but only to aid good user interaction, not to actually verify input.
- yeukhon 13y agohence why i said anything that has to go through db and save to db has to go through server.
- joesb 13y agoWhich is the point of pearjuice's post about the logic not being too thin. Also duplicating same verification logic on both client and server does not make the server thinner, it only makes the client fatter.
- jacques_chester 13y agoI remember when this sort of thing used to be called SOA. Before that there was n-tier, before that client-server, before that people used to talk about terminals. What has been will be again, what has been done will be done again; there is nothing new under the sun. The best place to park different parts of the logic varies according to the algo-economics of the day. Right now people have fast client environments, so the balance is tipping back to heavy clients.
- 1qaz2wsx3edc 13y agoSOA (Service-oriented architecture) is a pattern to split an application into discrete pieces of software providing application functionality as services to other applications. Fat vs Thin is more over a debate about where to place logic. Thin implies controllers are small, and models have a wider responsibility. Fat is the inverse, where controller do the majority of work, and models are a small abstraction. My point is this: They are not the same thing. SOA helps in designing scalable, robust systems. Fat vs Thin helps you decide where logic should go. I'm proponent of SO design and thin controllers.
- PaulHoule 13y agoWell, unless you design them for high performance from the very beginning, SOA also helps in building slow systems that your customers will hate and that will fail in the marketplace if the people who buy the software actually use it. (I was at Altassian's San Francisco office a few months ago and I said half-jokingly that I quit my last job because I couldn't stand waiting for Confluence, and all the other off-brand webapps my employer used, to load.) Now I use Github, which offers true interactive performance even over crappy DSL connections. I'm not going to work for anybody who makes me use some off-brand webapp that makes me wait 30 seconds to put time on a ticket or to edit a Wiki page. SOA can be part of the solution rather than the problem, but it takes a clear architectural view from day one and a commitment to avoid stupid and obvious mistakes, as the article points out.
- Gigablah 13y ago
- joshfraser 13y agoOne of the biggest benefits I see to API-first is that it encourages you to document everything well, and that process usually leads to better organization and greater consistency. As far as fat vs. thin, I worry that this article could be a bit misleading. It's great if you have an API that responds in 20ms as very few people can achieve that. But it doesn't matter much in a world where mobile network latency can easily be 200-500ms. If you're worried about app performance, I'd focus first and foremost on the number of requests you are making and making sure none of them are blocking. The network is the slow part. I know a lot of companies with blazing fast API's and sluggish apps, because they're optimizing the wrong thing.
- PLejeck 13y agoWhen developing an API, I like to practice "documentation-oriented design." The first thing I do is write documentation of the API, and then I write APIs to fit that documentation (iterating both in parallel once I start writing the API). I figure that the documentation is the first thing a developer faces when using an API, so it should also be the first thing I write.
- dreamfactory 13y agoA related approach is client-driven development (just made it up). Write client code (or controller) in the most thin, elegant, and obvious brain-dead simple way, then build an API (or model) to service it.
- PLejeck 13y agoIt's okay, I totally just made up "documentation-driven development" too. And yeah, that's the best way I find. Always build a consumer and then build the supplier, you'll usually end up with a great experience.
- jamesmccann 13y agoThis is a good description of the difference between available architectures, but more detail is probably required to backup some of the discussion points, beyond the fact that reducing presentation is beneficial for response times. An API server is still required to render JSON responses?
- AYBABTME 13y agoThis article suggest that MVC implies a fat server, and that using newer patterns with thin servers breaks away from MVC. Using a thin server with a Javascript heavy app basically means keeping the Model/Controller on the server, then having Views/Controllers on the client. So in the end, you're still with a MVC pattern, you just spread your Controller over two machines with RPC in between.
- dreamfactory 13y agoTo me a controller is just another thin client and models provide an (internal) API. What breaks this and leads to fat clunking controllers is ActiveRecord and 'model as table row' mindset (particularly when a model doesn't handle collections). The missing part here is turning that API into an external one, which requires a layer in any case to cover things like authorisation, caching, queuing, reporting, QoS, orchestration.
- PLejeck 13y agoThe article makes the implication that MVC is inherently slow. It's not, in fact it can be quite fast if you use the right framework. I'm assuming they only know that Rails is slow (which it can be, especially for a case where caching can't help much like in an API) and assume that's because of MVC and not because Rails is monolithic and Ruby-based. Before I used Rails, I used an MVC consisting of Mongoose + Handlebars + Express in Node.js, and I regularly had pages render in under 10ms. The biggest bottleneck was consistently the communication with MongoDB, something I had very little control over. So to conclude, stop blaming the architecture, start blaming the frameworks.
- meowface 13y ago>The biggest bottleneck was consistently the communication with MongoDB, something I had very little control over. Interesting you say that, because one of Mongo's few redeeming features is that it's supposed to be pretty fast for both reading and writing. Exactly which part was the bottleneck? Was your app more read-heavy or write-heavy?
- PLejeck 13y agoThe problem I ran into was that I needed to perform roughly 20 interdependent queries in a short period of time. At most, I could do 5 queries in parallel due to the interdependent nature, but I still ran into trouble with the database being slow. In the end, I added Redis as a caching layer, which cut time-per-query down a few ms per request, which was significant in this case. I can only imagine how bad it could've been if I had block for each request instead of using the asynchronicity of node.
- meowface 13y agoRight, caching is usually the easiest way to solve problems in those situations. >I can only imagine how bad it could've been if I had block for each request instead of using the asynchronicity of node. All modern web servers/frameworks are going to be asynchronous in one way or another, whether they spawn a new thread or process for each request (and for each database query), or whether they use polling and an event loop like Node. Node and HTTP servers like it are only a boon when you expect to have so many concurrent requests that threads/processes will begin to hog too many resources. So unless your server was really being hammered with queries for hundreds or thousands of concurrent users every second, I imagine using Node was neither a significant advantage or disadvantage. And if it's the database or database driver that can't handle concurrency, then Node would do absolutely nothing to help there.
- nickthemagicman 13y agoBUmp
- deleted 13y ago[deleted]
- ubersoldat2k7 13y agoIn my last three projects we've aimed at an API first approach, and the flexibility of having the same API serve content for web or native mobile apps is the biggest win. We used Play on two of this projects and Jersey for another and the speed is very slow at first since the browser has to load a bunch of JS (AngularJS in this case) but then, the whole user experience is seamless. Our biggest problem with this approach were localization and authentication/session handling. Tackling this problems were hard at first and I've never felt confident about the solutions we did for them, specially for authentication.