0

We are developping an app and I am not really pro at rest API etc. We decided that a maximum of business logic should be in the backend and started to do "business" route. But sometime I wonder if i don't split too much my api/controller.

For example, let's say we have a "car" object, in my backend. it's stored in "car" table in database, with somes other tables (like "owner" or "accessories").

Let's say I have to be able to change the name of the car, the color. change the ownership of the car, or add accessories.

I could have just one "update" route. which take a car id and properties to update the car.

Or i could split up in multiple route like :

  • update /car/:id -> change the name/color
  • /car/:id/sell -> to change the owner (supposing in the futur maybe i will want to add transaction table etc).
  • post /car/:id/accessories (or even post /accessories?carid= , i don't even know what is the best to do).

I can even split the first one in /car/:id/paint and /car/:id/name ??

I mean, for the front-end it gonna be easier to use and they don't have to understand anything about my business logic. but it seem totally stupid to have api with action naming.

I'm a little bit lost. I took a "simple" exemple but sometime it's more complex. I totaly gave up the "restfull api crud ...". I'm in a little bit lack of resources to understand what is the best to do.

1
  • Web API design is a lot easier to do when you already have all the business implemented. Remember that Web APIs are a mere and tiny layer on top of your application. It's a facade to make your application operable through HTTP or from the WWW. Regarding the endpoints, your reference is the consumer app (if any). Don't make super generic and versatile APIs. For the same reason, you do make super generic and abstract code. Keep it simple.
    – Laiv
    Jun 14, 2022 at 10:09

2 Answers 2

1

You should have a single UpsertCar(Car c) command which adds or changes the car to whatever data is sent.

That's your basic functionality. Now say you want to add a business process SellCar(carId, newOwner) you add a new method/endpoint for that but you are worried that it can be bypassed by calling UpsertCar with a new ownerId.

No problem, you still want to be able to change the ownerId without selling, say you made a mistake or the sale fell through but you dont have that in your business process yet etc.

But you can add a check on the UpsertCar endpoint, if the owner is changing check that the user is admin or whatever. Or maybe you allow the change but keep all versions of the Car so you can audit it later.

Its a common mistake to not add the simple CRUD commands to an endpoint, assuming that your business processes cover all eventualities. But they never do; and one thing you want to avoid at all costs is having to bypass the API and edit the database directly when you have some problem to resolve or admin function that needs doing.

1

Should i use one update route or multiple for each business logic functionality

A good heuristic to use for anything "REST" - think about how it would work as a website.

Let's suppose we have three business processes we are interested in (buy-a-car, sell-a-car, update-registration). We could create an interface to those processes that is a single web page with one form on it that can handle inputs to all of the different processes.

But we're a bit more likely to have many different forms (much like a bureaucracy has many different paper forms specialized for its different processes) -- see Task Based UI. The landing page would have a bunch of links to help the client navigate to the specific form that they want.

So we have three forms on the front end, and three business processes in the back end. Does that imply that we also have three resources in the middle? and three controllers?

Not necessarily.

There's not a lot of difference between having three resources, each of which is the entry to a different process, vs having one resource that thinks about the payload and chooses the appropriate process.

In particular, notice that the client doesn't care which way things are implemented (the customer is submitting the form, assuming it will go to the right place), and the browser doesn't care which way things are implemented (because the metadata of the form tells the browser what the target URI should be).

Web caches care a little bit, because the resource identifier of the request tells the cache which previously cached responses should be invalidated when the form is submitted. (That's a very coarse summary, review the HTTP Caching specification if you need to get into the weeds).

What this tells us is that, for caching purposes, we want the target of the form submission to be the most important document that gets changed as a result of successfully processing the form.

It might be, for example, that we have a single web page that shows the client's entire fleet of vehicles, and each of these business processes will cause the representation of that web page to change -- therefore, we consider sending all of the form submissions to the same resource, because that's the most important one to update in all three cases.

But it's a trade off - we get smarter cache behavior, but the cost is somewhat more complicated request routing code (some of which we may need to implement ourselves, depending on the sophistication of the routing code that is being used and our willingness to adapt to it).

It's not wrong to go the other way - imagine a write-only resource that is a list of form submissions to be processed. Because the resource identifier is unique to processing that specific flavor of form, routing is trivial -- but general purpose caches aren't going to know to invalidate other relevant cached responses.

(Not entirely - see the HTTP Caching specification, but as far as I know we don't have a general purpose mechanism to communicate arbitrary response invalidation to caches. Linked Cache Invalidation stalled, and I haven't found a substitute that is doing better.)


Note that, ultimately, REST and HTTP don't have anything to say about "controllers" - controllers are an implementation detail hidden behind the HTTP facade.

Your web framework, on the other hand, may have severe opinions about how your controllers MUST be arranged to match a particular resource model.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.