What's the standard way to write an API for a phoenix app?

phoenix

#1

Phoenix encourages developers to employ DDD. What if I wanted my phoenix application to be simply an API ?

The way I see it I have 3 options:

  • I could forget about DDD. Have RESTful resources and API endpoints that interact directly with them

  • I could forget about REST and have the API endpoints mimic the domains and their methods

  • I could have RESTful endpoints that interact with the Restful resources through domains

How should I write my API ? Any resource I can watch/read ?


#2

Phoenix isn’t really opinionated about how you structure the code.

The code generators are helpful for learning the framework, but once you are familiar with it you can organize functions and modules in whatever way makes sense for your app.

If there is very little business logic behind the API then having the controller modules call into the schema modules to build queries changesets might be all you need.


#3

Phoenix is no more than a set of helpers to create MVC web application.
While here everything is defined explicitly, you can do whatever you actually want.

You are not bind to REST as in other MVC frameworks. Think about GraphQL, JsonRPC, SOAP-XML APIs - everything can be easily implemented here.

Now, about DDD. I’ve never seen any mentions of DDD in Phoenix. May be you are speaking about Contexts in Ecto? But Ecto is not Phoenix, for first, for second - Ecto’s context and DDD’s “Bounded context” have nothing in common.

So, as conclusion: Elixir Ecosystem in general, and Phoenix framework concrete, are not “rails”, form which you can’t make a step aside.
You should decide firstly: “How my API should looks like, how it should be structured, which concepts should be behind”, and then simply make it come true.


#4

In my experience the key point of an API is the “I” or interface. The API is one way of looking at, and interacting with, a domain that is modeled in computer code. Another example of an interface is a Graphical User Interface.

I know… I sound like an idiot spouting terminology definitions that are self-evident. Please bear with me.

Important to the ideas here is the fact that you have a model and that model lives in a problem domain. Domain Driven Design provides you with a set of concepts - tools to help you design a model that will solve specific problems in a domain using a computer. That activity, generally speaking is valid work in-of-itself. If you don’t solve the problem you’re work is wrong or incomplete. The result of solving the problem gives you source code that presents a programmatic interface to the solution. The term I personally use for this is the implementation model of the solution.

Now you want to expose that programmatic interface to the outside world. One of the difficulties with API design is that it is another programmatic interface, and so our first instincts are to simply expose that programmatic interface through the API layer. I cannot speak for others, but my experience has been that this is a mistake. I have found that the implementation of the solutions - the models that make up the solution in the domain can change even when you don’t want the API to change. (you don’t want to impose the burden of an API change on folks using the API.

Having said that, here are the options you presented and my personal opinions:

  • I could forget about DDD. Have RESTful resources and API endpoints that interact directly with them

If your domain and problems are very, very simple then you might get away with this for a time. I have found that simple solutions like this, if successful, have the annoying tendency to grow in complexity and quickly overwhelm this approach. You can get away with this so long as you are willing to refactor on a hair trigger if things get even slightly more complex. This is a great approach for prototyping but you have to have the discipline to throw out the prototype rather than trying to grow it.

  • I could forget about REST and have the API endpoints mimic the domains and their methods

I have had very, very bad experiences with this approach. Exposing the implementation details of your system through an API in this fashion leads a painfully unstable environment for the folks unfortunate enough to have to use your API. When your core model changes - to accommodate new solutions, your API must change right along with it. Either that, or YOU must compromise your core model in order to maintain support for older versions of the API.

Now, having said this - it is the case that some aspects of your core model will be exposed to your customers. If your problem space involves setting up virtual machines then chances are you will have some kind of virtual machine entity both in the programmatic, core domain model, and in the conceptual model presented through the interface (and you want that conceptual model as presented through the interface to be fairly consistent between all interfaces API, GUI, or otherwise). But I suggest avoiding the temptation to tying user-facing models directly to programmatic implementation models.

  • I could have RESTful endpoints that interact wit h the Restful resources through domains

I, personally, have had the most success with this. Modeling the solution, and it’s programatic interface, in a domain layer, and then having (one or more) separate Interface Layer(s) built on top of it. It gives me the most flexibility to change the core model AND adapt to those changes in the interface layer. The Interface layer gives you a point of transition - a translation or anti-corruption space - between the user’s mental model (or conceptual model) of your system and the actual implementation model. In functional programming/transformation terms it’s the point at which you transform the user’s intent into actual execution in your domain model.

Now… up to this point I haven’t mentioned Phoenix at all. As others have pointed out, Phoenix itself is rather agnostic to how you do or do not tie your API to your programmatic interface. What I have tried to do (in a very small space, and perhaps with not as much brevity as folks might like) is to offer some benefits of my hard-won (or hard-worn) experience.

In terms of resources, and things to read, several years ago I found a lot of support and help from a book by a company called apigee:


I have no connection to the company and was never in a position to buy any of their products, but I did enjoy their white papers on API design and style.

I don’t have direct links to other reading I did on the subject I’m afraid. At the time I was looking at “API Gateways” and found that the folks who design such things usually had something to say on the subject of API design.


#5

I made a screencast about just this that may help you get started. The full source code is on GitHub as well.