Quel framework choisir pour votre application REST en 2020 ?
Tags: rails, laravel, elixir, django
Published: 2020-10-24 13:23:49

Quelle solution choisir pour développer une API REST sur laquelle viendra s’appuyer votre application web ou mobile en 2020 ? Autrement dit, vous voulez construire une architecture logicielle pour créer des services web, mais vous hésitez entre plusieurs possibilités. Ou vous avez un framework fétiche et vous voulez le comparer avec des solutions existantes. Ce blog est certainement pour vous.
L’architecture REST n’est pas nouvelle. Elle a été popularisée par un livre de Leonard Richardson et Sam Ruby (rien à voir avec le langage même s’il y a contribué…) RESTful Web APIs publié en 2007 par O’Reilly qui souligne la puissance des technologies web: protocol http, norme URI,... Surtout, elle établit une interopérabilité entre ordinateurs sur internet:  une petite révolution car les solutions alternatives à l’époque étaient SOAP ou RPC étaient et restent souvent incompréhensibles pour le développeur web. Désormais, nous pouvions façonner le web autrement que pour produire des pages HTML ! Ce fut donc l’ouverture vers de nouveaux outils comme React, Angular ou Vuejs.
Toutefois, il faut garder en tête que l’architecture REST n’est pas un standard ou une norme, mais plutôt une somme de conventions et de pratiques. Il peut y avoir des différences entre les langages de programmation et frameworks. Nous verrons ici 3 solutions qui sont massivement utilisées comme serveur REST et qui sont comparables en termes d’utilisation.

## Ruby On Rails, la Mère des framework web

Les principes architecturaux REST ont été présenté en 2006 (avant la sortie du livre ci-dessous) lors de la Keynote de la Conférence Rails [2006 Discovering a World of Resources on Rails](https://fr.slideshare.net/vishnu/discovering-a-world-of-resources-on-rails).

### Routes 

L’architecture REST a donc très tôt été intégrée dans le framework (dès la version 1.2) et il a été très facile d’intégrer une API dans une application. Pour générer les routes, une instructions suffit. Par exemple, l’instruction suivante:

`resources :photos`

créée automatiquement les 7 routes emblématiques :

| **Verbe HTTP** | **URL**    | **Utilisation**                                            |
|------------|------------------|---------------------------------------------------------|
| GET        | /photos          | Affiche la liste de toutes les photos                   |
| GET        | /photos/new      | Retourne les informations pour créer une nouvelle photo |
| POST       | /photos          | Créée une photo                                         |
| GET        | /photos/:id      | Affiche une photo                                       |
| GET        | /photos/:id/edit | Retourne les information pour mettre à jour une photo   |
| PATCH/PUT  | /photos/:id      | Mets à jour une photo                                   |
| DELETE     | /photos/:id      | Efface une photo                                        |

### Vues

A partir d’une action (route), il est possible de retourner plusieurs formats avec l’instruction respond_to : 

```
respond_to do |format|
    format.html
    format.json { render json: @photos }
    format.xml { render xml: @photos }
 end
```

Notez également la simplicité pour générer du JSON ou XML à partir d’un enregistrement. Mais si vous avez besoin de rendre du contenu JSON plus complexe, il existe des langages de template comme [RABL](https://github.com/nesquena/rabl) :

```
collection @photos
cache @photos
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:taken_by) { |photo| photo.taken_by?(@user) }
```

### Spécificités

Si vous souhaitez utiliser RoR uniquement pour produire une API sans page HTML, vous pouvez utiliser la commande :

`rails new my_application --api`

qui va créer une application plus légère et rapide sans les ressource nécessaire pour gérer le format HTML.
Mais bien que Ruby on Rails (RoR) fut un des premier framework à embrasser l’architecture REST, les concepteurs fut frileux à utiliser javascript pour langage pour le frontend et a mis en avant d’autres technologies comme les turbolinks qui n’ont pas percés chez les développeurs. Sauf peut-être Yehuda Katz (ancien de JQuery également) qui quitta la “core team” pour lancer Ember.js, un des premier framework frontend JS.

### Conclusion

RoR reste un choix solide pour créer une dorsale (backend) REST, avec communauté vivante et aidante, une documentation pléthorique, une simplicité d’utilisation et de nombreuses entreprises qui l’utilisent (Github, Airbnb, Twitter, Shopify, Basecamp,...). Comme beaucoup de ses concepts sont repris dans d’autres langages, vous vous sentirez à l’aise si vous devez un jour changer d’environnements.

## Phoenix, fonctionnel à outrance

Phoenix est le framework web composé en Elixir, qui est un langage dynamique et fonctionnel qui compile votre code en Erlang. Si vous cherchez une solution évolutive et robuste, voilà ce qu’il vous faut. Erlang a été spécialement conçu pour être distribué, insensible aux pannes (Elixir propose des superviseurs qui peuvent démarrer des parties du système) et offrir une haute disponibilité.

Elixir est un langage fonctionnel. Cela signifie entre autres que les variables sont immutables, qu’il n’y a pas de notion “d’orienté objet” et que les itérations sont opérées par récursions. Mais le langage offre des expressions comme le filtrage par motif (pattern matching) ou les garde (guard), qui une fois goûtés, manquent terriblement dans les autres langages de programmations:

```
# Exemple de pattern matching
%Page{body: body, title: title, slug: slug} = Page.find("elixir-is-awesome")
title #=> "Elixir is awesome"
```

```
# Exemple de garde
def publish(%Page{body: body}) when not is_nil(body) do
  # Code that publish page
end
```

```
publish(Page.find("elixir-is-awesome"))
#=> fails if page body is nil
```

### Routes

La configuration de routes est simple et nous retrouvons l’instruction `resources` pour générer les routes REST canoniques :

```
defmodule MyApiServer.Router do
  use MyApiServer, :router
 
  pipeline :api do
    	plug :accepts, ["json"]
  end
 
  scope "/api", HelloWeb do
	pipe_through :api
	resources "/pages", PageController, except: [:new, :edit]
  end
end
```

Voici que serait une fonction du contrôleur pour restituer les informations d’une page en fonction du slug (en utilisant le pattern matching) :

```
defmodule MyApiServer.PageController do
  use MyApiServer, :controller
  alias MyApiServer.Page
 
  def show(conn, %{"id" => slug}) do
    page = Page.find(slug)
    render(conn, "show.json", page: page)
  end
end
```

### Vues

Et voici quelle serait le template pour retourner le JSON :

```
defmodule MyApiServer.PageView do
  use MyApiServer, :view
  def render("show.json", %{page: page}) do
	%{slug: page.slug, title: page.title}
  end
end
```

### Spécificités

Si vous voulez développer une application web réactive sans utiliser utiliser les frameworks en Javascript (React, Vuejs, Angular,...), le framework propose quelque chose de vraiment unique: LiveView. Il permet une communication bidirectionnelle via WebSocket sur des pages HTML traditionnelles. Le cycle de développement est simplifié : un langage, une application. 

### Conclusion

Phoenix et Elixir ont été co-créé par José Valim, qui est un ancien développeur de Ruby on Rails. C’est donc tout normalement que l’on retrouve les principes qui fait le succès de ce framework et du langage Ruby : architecture MVC, conventions au lieu de configurations, productivité et plaisir de coder :-) Mais grâce à Erlang, Phoenix dispose de ses propres avantages : performance, évolutivité et une incroyable stabilité.

## Laravel, la Renaissance 

Au début il y avait le verbe, et le verbe était PHP. Au démarrage du web, le choix des langages de programmation était plutôt mince. Pas tous le monde ne pouvait se permettre d’acquérir une station NeXT (le premier navigateur a été développé en Objective C sur NeXT). Certains se lancèrent avec Perl. Mais très vite un nouveau langage fut développé et fut largement adopté: PHP. Ce fut une période de forte expérimentation qui déboucha sur des applications web bancales et difficilement maintenables, véritables Tours de Babel. Beaucoup de développeurs se brûlèrent les doigts et quittèrent ce langage déçus.
Néanmoins, le développeur Taylor Otwell, fort de ses expériences tirées d’autres langages, présenta en 2011 un nouveau framework (très inspiré de Ruby on Rails) qui apporta espoire à la communauté des artisans de web.

## Routes

Concernant la définitions de routes, il n’y a pas de fonction pour produire les routes, il faut les coder à la main :

```
Route::get('pages', 'PagesController@index');
Route::get('pages/{id}', 'PagesController@show');
Route::post('pages', 'PagesController@store');
Route::put('pages/{id}', 'PagesController@update');
Route::delete('pages/{id}', 'PagesController@delete');
```

### Vues

Le rendu en JSON se fait très naturellement :

```
return response()->json([
    'title' => 'The best REST framework',
    'content' => 'The best REST framework is the one you use.',
]);
```

Laravel propose le concept de “Ressource” comme couche de transformation entre le modèle et la réponse en JSON:

```
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
 
class Page extends JsonResource
{
    public function toArray($request)
    {
        return [
            'slug' => $this->slug,
            'title' => $this->title,
            'body' => $this->body,
        ];
    }
}
```

La ressource peut être appelée directement dans la route :

```
use App\Http\Resources\Pase as PageResource;
use App\Page;
 
Route::get('/pages', function () {
    return PageResource::collection(Page::all());
```

### Conclusion

Laravel est un framework solide qui vous permet de construire rapidement une API. Largement utilisé, il intègre les bonnes pratiques issues de plusieurs années d’expérience en PHP et, c’est ce qui est important, des autres langages. Par ailleurs, il embarque plusieurs librairies officielle pour faciliter le développement. Comme par exemple [Passport](https://laravel.com/docs/8.x/passport) pour l’authentification des API, [Sanctum](https://laravel.com/docs/8.x/sanctum) pour l’authentification des Single Page Application ou [Telescope](https://laravel.com/docs/8.x/telescope) pour le débugage et le suivi des performance.

# Django, le framework qui swing

Django est le framework phare du langage Python. La première version sort en 2005, la même année que RoR. Il a été utilisé par de nombreuses startups à succès comme Disqus, Instagram, Youtube,... Mais toutefois, vous ne pourrez pas (ou difficilement) développer une API avec Django. Et oui: Vous serez obligé de passer par un autre framework en complément : le [Django Rest Framework](https://www.django-rest-framework.org/)

Django offre une architecture Modèle-Vue-Contrôleur sans contrôleur… \o/ Ce qui est une grande source de confusion dans la prise main. Ici, les vues peuvent être considérées comme les contrôleurs et les templates comme les vues. Mais une fois passé cette étape, Django est une framework très productifs, pensé pour les développeurs avec une excellente documentation. Couplé avec Django Rest, vous pouvez très rapidement construire une API web.

## Serialization

Un des premier élément à définir est le “Serializer” qui permet de représenter un objet ou une liste d’objet en JSON. Ce qui peut être fait rapidement :

```
class PageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Page
        fields = ['id', 'title', ‘slug’, 'descrition', 'body']
```

##Routes

La prochaine étape consiste à rédiger les routes (dans un fichier qui se nomme urls.py) qui permettent de lire, écrire, modifier et effacer une ressource (Page):

```
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from pages import views
```

```
urlpatterns = [
    path('pages/', views.PageList.as_view()),
    path('pages/<int:pk>/', views.PageDetail.as_view()),]
 
urlpatterns = format_suffix_patterns(urlpatterns)
```

### Vues

Il est possible de produire les vues (contrôleurs) très rapidement en utilisant les vues génériques (qui suivent les bonnes pratiques REST): 

```
from pages.models import Page
from pages.serializers import PageSerializer
from rest_framework import generics
 
 
class PageList(generics.ListCreateAPIView):
    queryset = Page.objects.all()
    serializer_class = PageSerializer
 
 
class PageDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Page.objects.all()
    serializer_class = PageSerializer
```

### Spécificités
Django Rest Framework génère automatique un outil de navigation de votre API qui vous permet comme développeur de tester votre application: https://restframework.herokuapp.com/. Cela ressemble à Postman mais en plus simple.

### Conclusion

Django Rest Framework est à la fois un outil flexible avec lequel vous pourrez produire rapidement des API web avec les fonctionnalités performantes. Les outils de serialization supportent tant les source directement liées à un modèle (ORM) ou des sources plus complexes (non-ORM). La documentation est complète et vous bénéficierez également d’une grande communauté de développeurs.

## Maintenant, quel framework choisir ?

Tous les frameworks sont de haute qualités et répondront très probablement à vos besoins. Ils bénéficient tous de plusieurs années d'expériences et ont fait leur preuves dans tout type de projets. Ma proposition est de choisir le framework dans la langue de programmation que vous connaissez le mieux. Vous serez directement productif et vous pourrez apprendre rapidement.

Toutefois certains framework peuvent avoir certains avantages en fonction de ce que vous recherchez.

Si votre projet réclame performance et stabilité, *Phoenix* sera le meilleur. Elle est l'arme secrète de quelques agences web.

Si vous voulez produire une API et des pages HTML simultanément, *Ruby on Rails* sera plus adapté.

Si vous avez besoin d’une API et d’un outil de gestion de contenu (à la Wordpress), *Django Rest Framework* se marie très bien avec [Wagtail](https://wagtail.io/) qui est un CMS efficace.