Maedow
Architecture

Le domaine métier reste séparé de l’interface et l’infrastructure interchangeable. Les frontières ne dépendent pas de la mémoire de l’équipe : le linter les vérifie.

Vous avez déjà un projet

~ npx maedow-arch check

L’audit lit votre code sans rien installer ni modifier, et rend un rapport ordonné par ce qui débloque le reste. Adopter sur un projet existant

Vous en démarrez un

~ npx create-maedow-arch-app mon-projet

La structure des quatre couches, le Result Pattern et les générateurs, en une commande. Voir l’arborescence

L’architecture ne bouge pas quand ceci change. Le domaine ignore la base, l’authentification et le framework.

TypeScriptReactNext.jsViteTailwind CSSVitestESLintZod
PostgreSQLDrizzlePrismaSupabaseFirebaseIndexedDBBetterAuthAuth.jsJWTREST

Ce que la machine vérifie à votre place

Une architecture qui repose sur la discipline se dégrade au premier sprint tendu. Celle-ci tient parce qu’un outil refuse ce qui la contredit.

La règle

Le flux de dépendance
  1. approutes et pages
  2. featurescas d’usage
  3. coredomaine et contrats
  4. libutilitaires purs

Le sens inverse est refusé. Un import de core vers features fait échouer le lint, et donc la CI, avant d’atteindre la revue.

La dépendance descend, jamais l’inverse. Un écran peut appeler le domaine, le domaine ignore qu’un écran existe. Tout le reste vient de là.

Le garde-fou

Le lint refuse
error Maedow Arch : core ne peut pas importer components

Pas une convention d’équipe que l’on se rappelle. Une erreur, à chaque commit.

Deux exigences

Light

Trois couches, pour un projet qui doit sortir.

Full

Le domaine isolé, pour un projet qui doit durer.

Choisir son mode

Ce qui est généré

app/
features/
  checkout/
  _shared/
core/
  billing/
    types.ts
    service.ts
components/ui/
lib/

Les erreurs

type Result<T, E> =
  | { ok: true; value: T }
  | { ok: false; error: E };

L’échec est une donnée typée que le compilateur oblige à traiter, pas une exception que l’on oublie d’attraper.

À chaque commit

20

projets générés, puis lintés, typés et construits

23

contrôles verts exigés avant toute fusion

next et vite, Light et Full, npm, pnpm et bun

Une commande

L’arborescence, les frontières et les générateurs, déjà en place.

Un projet déjà commencé ? npx maedow-arch check dit ce que l’adoption coûterait, sans rien installer.

~ npx create-maedow-arch-app mon-projet

Une règle de gestion n’a rien à faire dans un composant

Le seuil de remise ci-dessous est une décision de l’entreprise. À gauche, il faut monter un arbre React pour la tester. À droite, c’est une fonction.

Sans la règle

Le métier est pris dans le rendu.
Pour le vérifier, il faut simuler une interface.

Facture.tsx

export function Facture({ lignes }) {
  const total = lignes.reduce(
    (s, l) => s + l.prix * l.qte,
    0,
  );
  const remise = total > 500 ? total * 0.1 : 0;

  return <p>{total - remise} €</p>;
}

Avec la règle

Le métier vit en TypeScript pur.
Il se teste sans navigateur, et se réutilise côté serveur.

core/facturation/service.ts, puis features/facturation/Facture.tsx

export function montantARegler(lignes: Ligne[]) {
  const total = lignes.reduce(
    (s, l) => s + l.prix * l.qte,
    0,
  );
  return total - remiseDePalier(total);
}

// Le composant ne fait plus que montrer.
<p>{montantARegler(lignes)} €</p>

Le jour où le seuil passe à 800, une seule ligne change, et un test le prouve en millisecondes.

Les cinq formes de données