PHP API Design – Chain-of-Command/Responsibility Pattern for Simple API: A Good Idea?

api-designPHP

I need to write a simple API for a project I'm working on. This API will be used internally to perform some server side actions that were triggered by AJAX calls.

To make things easier for me, I thought of using the Chain-of-Command/Responsibility pattern.

Here are more details about what I want to do:

I am creating a "dashboard" where admins of my app will be able to update information (meta data) about items stored in a database.

To make things easy and simple for the admins, I chose to use AJAX. So, if an admin wants to delete an item, (s)he clicks on the "delete button". A POST request is then sent to edit.php page with all the information needed to perform the deletion (action : delete, element : link, id : xx …). Where action, element and of course id can change.

This is why I opted for a mini-API that will, depending on the action and the element data, call a different function from a different class.

Now, to implement the API, I decided to use Chain-of-Responsibility design pattern. Why? Because I can easily add, delete or update classes without having to modify the API itself.

Is the Chain of Responsibility design pattern good fit for my case?

Best Answer

The idea of the chain-of-command pattern is to build a chain of handlers and pass a command along this chain until one of the handlers handles the command. This behavior is typically found in event processing, where, say, a click event from a UI button bubbles up the hierarchy of UI elements till it reaches an element that has a respective handler attached. This handler can then decided whether it handles the command -- effectively ending the event processing -- or not -- in which case the event is propagated further along the chain.

Let's now assume we use that pattern for you web API. What you describe sounds like a classical CRUD(L) interface to me, where your actions are (a subset of) create, read, update, and delete. You say you have delete requests and I'm assume that you want some kind of update requests, too. Let's assume further that you wrote respective handlers hupd and hdel for these kinds requests. Following the chain-of-command pattern, you then build the chain [hupd,hdel] to handle requests to your API. What happens is that every update request passed into the chain gets immediately handled by hupd, while every delete request is rejected by hupd and passed along to hdel, which handles it. This behavior shows a fixed mapping between actions and handlers that actually makes the chain unnecessary. (In fact, the chain even lowers your system's performance, because of the check and the passing along of every delete request). Why does this happen? Because there are no two handlers responsible for different subsets of requests with the same action type. What you really want to have here is a direct mapping ["update" => hupd, "delete" => hdel] and a dispatcher that takes respective requests and passes them directly to the respective handler. Such a design can still be extendible with regard to new actions, if there is a dynamic registry holding the mapping.

Now you could say, that you want to have different handlers for, say, the deletion of elements of type A and B. What gives you handlers for subsets of requests with the same action type. But once again, you have a direct and fixed mapping between the handlers and the element type, i.e., you can repeatedly dispatch requests based on the target element type. This gives you a two-level dispatch, where with a chain-of-command you would pass the request through number-of-actions times number-of-element-types handlers, in the worst case.

Conclusion: I would not recommend the chain-of-command pattern to implement this kind of API. For the pattern to have value, you need a scenario where you want to dynamically add and remove handlers and where the condition of when a handler actually handles an event is not expressible by a simple mapping from constants.