Fait avec Chinaski

Simplicité

Chinaski est construit pour être petit aujourd'hui et encore compréhensible demain : quelques programmes Perl faits pour la tâche, un fichier de base de données SQLite, et un serveur web qui distribue des fichiers. Pas de service mesh, pas de runtime de plugins, pas de remous de framework. Cette page parcourt les pièces, et les omissions délibérées, qui rendent le système simple.

Deux programmes, pas une flotte

Le produit entier, c'est :

  • Le CMS: une application Perl qui gère le contenu et vous montre une interface d'administration dans le navigateur. Tout ce qu'elle connaît vit dans un fichier de base de données SQLite.
  • Le builder: un processus Perl séparé qui lit la même base, rend la sortie Template Toolkit, et écrit du HTML statique sur disque. Il tourne quand un build est demandé (bouton du dashboard, webhook, ou à la main), jamais comme effet de bord en arrière-plan, et chaque exécution laisse un journal.
  • Le serveur web: un reverse proxy (Caddy dans les exemples du projet) sert les fichiers statiques directement depuis le disque ; le processus CMS n'est jamais dans le chemin des requêtes publiques.

Donc « un monolithe » dans l'esprit, avec une exception que le README rend explicite : les builds se passent dans leur propre processus, exprès, parce que ce sont des opérations longues avec leurs propres journaux. Le builder effectue sa bascule atomiquement (renommage en place), si bien qu'un proxy ne sert jamais une sortie à moitié écrite.

Une base de données, un fichier de schéma

Tout l'état (contenu, utilisateurs, réglages, journaux) est des tables dans un unique chinaski.db. Pas d'ORM, pas de serveur de base de données, pas d'identifiants à gérer. Le schéma vit dans un fichier schema.sql, et un script de gardien compare à la demande le fichier de schéma aux migrations appliquées, en sortant visiblement avec un code non nul quand les deux divergent pour que la dérive ne puisse pas se cacher.

Lisible plutôt qu'ingénieux

Le code est simple par conception :

  • L'implémentation vit dans un petit nombre de fichiers, stratifiés avec des commentaires qui incluent des références au gestionnaire d'incidents, si bien que l'histoire d'un changement est aussi lisible que sa forme actuelle.
  • Une petite bibliothèque de modules (DB.pm, I18n.pm, Media.pm, Migrations.pm, Util.pm, Webhook.pm et une poignée de modules de plugins) porte juste la machinerie partagée ; il n'y a pas de framework dans le framework.
  • Là où des copies de la logique s'étaient un jour détachées, le projet a consolidé vers un unique helper canonique (le helper d'ouverture de base existe précisément pour que les scripts cessent de rouler leurs propres copies) au lieu d'ajouter une couche d'abstraction pour masquer la différence.
  • Les aides en ligne de commande d'admin sont de petits scripts suivant tous les mêmes conventions d'environnement : mêmes noms de variables, mêmes défauts.

La visibilité de la complexité fait aussi partie de la lisibilité : le builder lui-même consigne des minutages par phase, et le garde de build mesure le nombre de pages et les liens cassés avant de promouvoir quoi que ce soit : pas parce que le code est ingénieux, mais parce que le système vous dit ce qu'il a fait.

Peu de points de configuration, une forme de déploiement

  • Les unités systemd standard utilisent un template d'instance : une définition sert un nombre quelconque d'instances (chinaski@1, chinaski@prod, …). Tout le reste d'un déploiement, ce sont deux variables d'environnement plus une ligne ou deux de reverse proxy.
  • Là où une complexité transitoire existe, elle est nommée, bornée et programmée pour la suppression : la migration de l'habillage d'admin est l'exemple travaillé : un système de classes cible, une couche de compatibilité ascendante explicitement à ne pas étendre, et un suivi par fichier jusqu'à ce que les noms hérités aient disparu.
  • Arborescence de répertoires à plat : le fichier de l'application, le schéma, le fichier de dépendances, le builder, les templates d'admin, les arborescences de sortie par langue, les assets publics. Ce que fait chaque partie se voit depuis son nom de fichier.

Ce que cette simplicité achète, et coûte

  • Exploitation : deux services systemd et un timer, des arborescences de sortie transparentes que vous pouvez rsync, des sauvegardes qui sont une copie de fichier, pas de gestionnaire de paquets en propre.
  • Les changements restent lisibles : la base de code est riche en commentaires avec des références d'incidents, structurée pour qu'une correction n'exige pas d'archéologie.
  • Le coût est énoncé honnêtement par le projet : pas d'architecture de plugins, pas de registre de plugins, pas de place de marché de thèmes, tout ce que vous en tireriez doit être soit un changement de code, soit pas fait.

La règle d'or

La réponse par défaut de Chinaski à « devrions-nous ajouter ceci ? » est « cela aura-t-il encore du sens pour quelqu'un qui le lit à froid à 2 h du matin ? » : un monolithe par processus, peu de pièces mobiles, et du code lisible qui bat les abstractions ingénieuses.

Lisez ce site en