Don't design your own REST back end
plus.google.com
plus.google.com
For example:
There seems to be an implicit assumption that all of the REST endpoints are just maps to CRUD operations. Perhaps for the most barebones, basic API this is true, but service APIs are more than just CRUD ops. They're abstracted interfaces to a complex series of tasks (for the sake of argument, we'll call them 'orchestrations' ). Just because you're doing a "POST" to /user/foo doesn't mean that the service is only doing a simple insert. It might be looking up similar users, sending out notifications, validating data, de-duping, etc.
The more I think about this the less sense it makes. Perhaps I'm missing something.
1 & 2 mean that you should name a resource something for identification only and that name should be used no matter what you are doing to it. In HTTP you use a combination of verbs and request body data to tell the server what to do with a resource. HTTP implements #3 though status codes including verbose descriptions in the response body. HATEOAS (Hypermedia as the engine of application state) means that 100% of functionality must be accessible through a browser.
It's important to understand that a RESTful system doesn't necessarily expose a true model of the underlying data store. You could have an invoicing system that contains Customer and Invoice models. I see developers confusing that to mean "you have /customer/ and /invoice/ endpoints and never the twain shall meet". If you need to embed customer details into invoices and/or invoice details into customers, then feel free to do that if it makes sense for your application.
There's more to it than that, and I've mostly just described how common HTTP-based RESTful systems work. Fielding gave a lot more detail in his thesis: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...
I'd recommend reading it, as it helps clarify a few things. Also read up on the term HATEOAS, which details how information should be interlinked where possible, so your system can be (theoretically) crawled for more information.
Decoupling has loads of benefits - for example, it gives separate development cycles, and in this case provides a point of scalability too - not all REST dbs cache brilliantly or aggressively enough for all use cases.
The point about using delayed syncing between client and server is separate. I can see how it can help in certain use cases (Google docs doesn't auto-save every single letter you type in for example I suspect, but probably bulks them up into a save every x seconds) but at other times this kind of strategy sounds like it will add unnecessary complication.
Getting syncing right is tricky, though, because you do need to think through your possible conflict resolution issues in case the user moves from device to device, potentially while one or both devices lack a connection.
Everyone should be writing their REST back end and the API should be as specialized as possible. One HTTP call should give you back everything you need for a page/view w/e.
Behind that public front everything can change and routes can be added, if things change majorly you version it. But never is it a good idea to map the db operations directly to the rest urls, so much more has to happen in production.
The public api layer is sometimes mapped more manual as auto generation rest apis rarely aren't leaky abstractions. ORMs, data layers, authentication etc behind the scenes may be generated or flexible to change.
Public apis might even have public objects that aren't objects from the database in full or at all i.e. meta/tracking fields, private info.
Public apis offer multiple levels of service: direct data/json, mvvm views, tools, syncing, per-view state (multiple objects), authentication etc. The term REST has colluded it a bit but ultimately REST is representational state transfer, it doesn't have to be web to db without an application layer.
An API is a public definition that should be as concrete as possible for the service use cases and public apis provide a flexible abstraction to expose a service to other consumers. So I will keep writing my public apis, I'll generate boilerplate behind that but I won't be locked to any implementation other than a uniquely designed api for my service, features needed and use case.
I don't even think it's possible to do that if you have a bit more complicated application. Because every API that does more than the very basic CRUD needs something else besides interfacing with the database.
That mega-JOIN that brings back the entire client context is more awesome for db throughput, than plethoras of single-object calls. THIS IS WHY you build an API, rather than exposing CRUD. CRUD is not an API.
"Now you hit an API that has to do some async behaviour and now your screwed. There are some solutions for that but they make the code really complex, even Node.js."
What does that even mean?
The protocol I wrote just sent a job-ID to the client and the client started polling for the result.
Since AJAX is already asynchronous I could write a JavaScript library for the browser, which made the whole thing transparent for the client.
The only problem I ran into were multiple long running jobs, which caused parallel polling. But since the communication between server and client was hidden behind the client-lib, I could change the protocol later, to merge multiple polling requests in one etc.
[1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10...
→ POST /resource
← 202 Accepted
← Location: /jobs/XXX > A lot of the Internet is going over unreliable wireless
> technologies. So your beautiful REST calls are now riddled
> with exception handling, because there are so many ways of
> things going wrong.
Let me get this straight, you want do to representational state transfer (REST[1]), that is, keep all long-lived state on the server, and all (single) state changes confined to a single request - and you're worried about your clients intermittent internet connection?You might have a problem with your architecture, but your architecture doesn't appear to be a REST architecture.
[1] https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...
Indeed, CouchDB/PouchDB already solved this problem, and redoing it can be considered waste. I think the author cut a bit too many corners for the argument to stick, but in principle it's entirely true.
The "sad" thing is that if I'd use Couch for this, I'd get more than what I asked for: I also get a database, document-oriented, with a big map-reduce component, difficult to add custom queries, difficult to extract management information from, limited admin tooling. It might fit certain problems well, but it also fits many problems badly.
I'd love for a Couch/Pouch kind of tool for replication/sync that somehow allows me to plug my own datastore on the backend and my own model structure on the frontend. I'm not sure what that would look like - there's a good reason data storage and sync are so tied together in Couch. But still, "you shouldn't design your own API and the only way not to is to use this particular database here" just doesn't feel like we're done with this debate.
there's rarely enough data in pouch for me to have to index that way though.
That's not REST, that's something else. Bit of a strawman.
> So then you don't have beautiful URLs right.
You never needed them.
Why not?
I think "beautiful" is the wrong word. It should be logical and should try to convey what it does. I don't care what an URL looks like, as long as I can understand what it supposed to do.
APIs are for developers, not for search engines and definitely not for the end user.
For anyone interested, I recently wrote a library called Hustle (https://github.com/orthecreedence/hustle) which implements a beanstalk-like queuing system on top of indexeddb, allowing you to queue up writes to your local data to be synced remotely.
Don't get me wrong, CouchDB is awesome, but it isn't the answer to everything.
You are still vulnerable to CouchDB as a project folding, but since it is all Open Source and open discussions, that one is easy to find early on.
And finally, you could just use one of the other implementations of the CouchDB API available :)
MySQL was the product of a private company. It was always possible for it to be purchased, and that eventually happened. The same is true for many modern databases, including most of the major NoSQL databases. CouchDB cannot be. Yes, there's risk of the project could die in a variety of ways, but there is an entire class of risks that CouchDB is not subject to, when most of its competitors are. If you really want to avoid having your DB purhcased and killed by Oracle, you'd actually prefer CouchDB over, eg, MongoDB.
Beyond that, you say: "You'll have to clone Couch's REST API". That's actually the other half of what makes CouchDB a safer bet: The HTTP protocol is itself open source, well documented, and has already been cloned repeatedly. It's used by quite a few different projects in different ways, including PouchDB, CouchDB, TouchDB, Hoodie.io, BigCouch, and CouchBase Lite.
If you're curious about the topic, I recommend this blog post: http://caolanmcmahon.com/posts/couchdb_is_not_a_database/
https://github.com/ServiceStack/ServiceStack
https://servicestack.net/features
Doesn't use ASP.NET. Runs on Mono.
Don't bother with WebAPI.
I agree that for a hobbyist the new license fees are too high. For a company those costs are a no-brainer though.
What Demis has done with ServiceStack (and now having made it his full-time job after leaving Stack Exchange) deserves remuneration in my opinion.
90% of the time I end up just proxying connections to couch and doing sanitizing/filtering on the data on the fly.
The views are bit annoying, but I just plug in elasticsearch once it becomes even moderately complex. It just automatically indexes the data by listening to the _changes feed.
I withdrew after "Whether that it's tried and tested of MySQL or shiny and new of MongoDB. This choice is probably going to affect how you scale." It was not worth continuing after that.
Couldn't this be easily solved by: a) putting the server behind nginx to terminate slow connections after several seconds, and b) adding retry logic to the client?
This isn't a rhetorical question - would this approach actually work if a client was part way through sending data when it lost network connectivity, or am I missing something?
I read the article, it definitely sounds exactly like what I've been through. What I didn't get from the article is, what to do next? What is the right step to take here?