Applications sur-mesure
Vos processus dans un outil conçu pour eux, pas contre eux
Quand le tableur a atteint ses limites et qu’aucun logiciel du marché ne correspond vraiment. Application métier, service en ligne, API : développée sur mesure et hébergée sur notre propre infrastructure, à Nantes.
- Symfony, Python, Java, Kotlin, Go ou Node.js selon le besoin
- Hébergée sur notre propre infrastructure
- Évolutions au fil de vos besoins
- Le code et les données vous appartiennent
Le principe
Le moment où le sur-mesure devient moins cher
Le signe qui ne trompe pas
Ce n’est pas la taille de l’entreprise, c’est l’écart entre votre métier et l’outil. Quand chaque semaine ajoute une colonne au tableur, quand deux personnes savent seules faire tourner le fichier, quand on ressaisit les mêmes données dans trois endroits — le coût est déjà payé, il est simplement invisible parce qu’il se compte en heures plutôt qu’en factures.
Un logiciel du marché reste préférable quand il existe et qu’il correspond : il sera moins cher et mieux maintenu. Le sur-mesure se justifie quand la particularité est votre métier, et qu’on vous demanderait de l’abandonner pour rentrer dans l’outil.
L’outil suit le besoin
Nous ne partons pas d’une technologie. Selon ce que l’application doit faire, nous employons Symfony quand PHP est déjà en place et que l’économie d’hébergement compte, Python avec FastAPI pour les API et les traitements asynchrones, Java ou Kotlin avec Micronaut ou Spring quand la fiabilité et la charge priment — la compilation native via GraalVM produisant alors un binaire optimisé — Go pour les services réseau dédiés à une tâche précise, Node.js pour ce qui doit encaisser beaucoup de requêtes simultanées.
Ce ne sont pas des préférences d’école : chacun de ces outils tourne déjà chez nous, y compris pour nos propres besoins internes.
Commencer petit, exprès
Le projet qui échoue est celui qui livre tout en une fois, deux ans plus tard, et découvre alors que le besoin avait bougé. Nous préférons une première version volontairement étroite — le processus qui coûte le plus cher aujourd’hui — mise en service vite, puis élargie.
C’est aussi ce qui permet de s’arrêter. Une application qui rend déjà service après trois mois est un actif ; une application à moitié faite après deux ans est une perte sèche.
Modéliser le métier avant d’écrire le code
C’est le principe du Domain-Driven Design, et il tient dans une exigence : le code doit parler la même langue que vous. Si vos équipes disent « dossier », « avenant » et « relance », ces mots doivent se retrouver tels quels dans le code — pas traduits en « objet », « modification » et « notification » par un développeur qui a interprété.
Cela paraît anecdotique. C’est en réalité ce qui décide de la facilité avec laquelle on modifiera l’application dans trois ans : un code qui emploie vos mots se relit avec vous, et une règle métier qui change se retrouve à un seul endroit.
Deux conséquences pratiques. D’abord, nous passons du temps avec ceux qui font le métier, pas seulement avec ceux qui commandent le projet. Ensuite, nous découpons l’application en domaines cohérents : la facturation et le suivi de production ne parlent pas de la même chose même quand ils emploient le mot « commande », et vouloir leur imposer un modèle unique produit une usine à cas particuliers.
Les Value Objects : rendre l’invalide impossible
C’est la brique la plus concrète du DDD, et la plus rentable en matière de sécurité. L’idée : cesser de faire circuler des chaînes de caractères et des nombres nus dans l’application.
Une adresse e-mail n’est pas une chaîne : c’est une adresse e-mail, avec ses règles. Un IBAN non plus. Ni un SIRET, ni un montant, ni un code postal. Quand on les représente par des types dédiés, la règle de validité vit dans le type lui-même : l’objet ne peut pas exister s’il n’est pas valide, parce que sa construction échoue.
Pourquoi c’est une question de sécurité
Le défaut que cela corrige porte un nom — l’obsession du primitif — et une conséquence directe : quand tout est chaîne de caractères, chaque fonction qui reçoit une donnée doit la revalider. Il y en a des dizaines, elles sont écrites par des gens différents à des moments différents, et celle qui oublie est le trou.
Avec un type dédié, la validation se fait une fois, à la frontière — au moment où la donnée entre dans le système, dans l’adaptateur qui la reçoit. Au delà de ce point, plus rien d’invalide ne circule, et aucune fonction n’a à s’en soucier. On ne déplace pas le contrôle : on le rend structurellement inutile ailleurs.
Deux propriétés s’ajoutent :
- L’immuabilité. Un objet valeur ne change pas après sa création. On ne peut donc pas le valider puis le modifier avant usage — un enchaînement qui est à l’origine d’une famille entière de failles.
- L’impossibilité de confondre. Un identifiant de client et un identifiant de commande sont deux chaînes indiscernables ; ce sont deux types distincts qu’on ne peut pas intervertir par inadvertance. L’erreur devient une erreur de compilation ou de construction, pas un incident en production.
Ce que ça donne en pratique
Les contrôles cessent d’être dispersés dans les écrans et les traitements pour se concentrer là où la donnée arrive. Les messages d’erreur deviennent cohérents, puisqu’ils viennent d’un seul endroit. Et surtout, une règle de validité qui évolue — un format qui change, une contrainte qui s’ajoute — se modifie à un seul endroit au lieu d’être traquée dans toute l’application.
C’est peu spectaculaire, cela ne se voit pas sur une démonstration, et c’est l’une des choses qui distingue le plus nettement une application qui vieillit bien d’une application qu’on finit par ne plus oser toucher.
Le Repository : le métier ignore où sont les données
Un traitement métier a besoin de lire et d’écrire. La façon la plus courante de s’y prendre consiste à interroger la base directement là où on en a besoin : une requête dans l’écran de liste, une autre dans le traitement de validation, une troisième dans l’export du soir. Elles se ressemblent sans être identiques, et personne ne sait plus laquelle fait foi.
Le Repository renverse la chose. Le domaine déclare ce dont il a besoin, en une interface qui parle sa langue : « la commande portant ce numéro », « les dossiers en attente de validation », « enregistrer ce contrat ». Il ne dit rien de MariaDB, de PostgreSQL, d’un service distant ou d’un fichier déposé la nuit. C’est l’infrastructure qui fournit ensuite l’implémentation correspondante.
Ce que ça règle concrètement
- Les requêtes vivent à un seul endroit. Quand une liste devient lente, il y a un fichier à ouvrir, pas des fragments de SQL dispersés dans des contrôleurs et des gabarits.
- Le vocabulaire reste celui du métier. Une méthode nommée d’après la question posée se relit avec vous ; une jointure sur trois tables, non.
- Les règles se testent sans base de données. Une implémentation qui garde simplement les objets en mémoire suffit à faire tourner les tests du domaine — c’est ce qui rend possible la suite de tests qui s’exécute en quelques secondes, plutôt qu’en un quart d’heure.
- Changer de stockage ne touche pas le métier. Passer d’une base à une autre, ou déplacer une donnée vers un service tiers, se règle dans l’implémentation.
Le piège, et il est fréquent
Un Repository qui se contente de recopier les possibilités de l’ORM — une méthode générique qui accepte n’importe quel critère et renvoie n’importe quoi — n’apporte rien. Ce n’est plus qu’un autre nom pour l’outil qu’il enveloppe, avec une couche de code en plus et aucun bénéfice.
L’interface doit rester courte et intentionnelle : quelques questions métier, formulées comme le métier les pose. Si elle enfle jusqu’à trente méthodes, c’est en général que le découpage en domaines est à revoir, pas qu’il faut une trente et unième méthode.
Deux précisions honnêtes : la plupart des ORM proposent déjà un objet qu’ils appellent « repository », et en employer le nom ne donne pas le bénéfice décrit ici. Et sur une application qui n’est qu’un formulaire posé sur une table, cette couche est une cérémonie inutile — nous ne la mettons pas.
L’architecture hexagonale : le métier au centre
Aussi appelée ports et adaptateurs. L’idée est simple : les règles de votre métier ne doivent dépendre de rien — ni du framework, ni de la base de données, ni du fait que la demande arrive par une page web plutôt que par une API ou un fichier déposé la nuit.
Ces éléments deviennent des adaptateurs branchés autour du domaine, et non la structure sur laquelle il repose. Trois bénéfices concrets :
- Les règles métier se testent sans base ni serveur — donc vite, donc souvent, donc réellement.
- Changer de technologie n’oblige pas à réécrire le métier. Passer de MariaDB à PostgreSQL, ou d’une version majeure de framework à la suivante, touche l’adaptateur, pas le cœur.
- On lit ce que fait l’application en ouvrant le domaine, sans traverser des couches d’infrastructure.
C’est aussi ce qui rend une application reprenable par une autre équipe — le critère qui compte le plus dans la durée.
CQRS : quand lire et écrire divergent
Command Query Responsibility Segregation consiste à séparer le modèle qui écrit de celui qui lit. Dans une application classique, les deux sont confondus : la même structure sert à enregistrer une commande et à l’afficher dans un tableau de bord. Cela va bien jusqu’au jour où les deux besoins tirent dans des directions opposées.
Le signal est reconnaissable : l’écriture réclame des règles strictes et un modèle riche, pendant que la lecture réclame des jointures massives et des agrégats que ce modèle rend coûteux. On finit par dégrader l’un pour servir l’autre.
Séparer les deux permet de traiter chaque besoin pour ce qu’il est : un modèle d’écriture qui protège les règles, et une ou plusieurs vues de lecture préparées pour les questions qu’on pose réellement.
La contrepartie doit être dite : dès que les vues de lecture sont alimentées de façon différée, il existe un instant où l’écran ne reflète pas encore ce qui vient d’être écrit. C’est acceptable sur un tableau de bord, inacceptable sur un écran de saisie. C’est un arbitrage à poser explicitement, domaine par domaine — jamais une règle appliquée partout.
L’Event Sourcing : garder ce qui s’est passé
CQRS ouvre souvent la porte à une question plus radicale : et si l’on enregistrait les événements plutôt que l’état ?
Une application classique conserve la situation actuelle. Quand une commande change d’adresse de livraison, l’ancienne est écrasée : la base sait où livrer, elle ne sait plus qu’on a changé d’avis, ni quand, ni qui l’a décidé. L’Event Sourcing inverse : on enregistre la suite des faits — commande créée, adresse modifiée, paiement reçu — et l’état courant se déduit en les rejouant.
Quand cela vaut vraiment le coup
Quand l’histoire est le métier, pas un sous-produit. Trois cas reviennent :
- Une activité réglementée, où il faut pouvoir démontrer qui a fait quoi et quand — et où la piste d’audit est une obligation plutôt qu’un confort.
- Un domaine sujet à litige : facturation, assurance, contrats. Reconstituer l’état du dossier au 12 mars vaut alors plusieurs journées d’enquête.
- Un métier dont on ne connaît pas encore les questions. Les événements conservés permettent de répondre plus tard à une interrogation qu’on n’avait pas anticipée, là où un état écrasé a définitivement perdu l’information.
Le bénéfice le moins évoqué est le diagnostic : reproduire un incident en rejouant la séquence exacte qui y a mené vaut mieux que toutes les suppositions.
Ce que cela coûte, et il faut le savoir avant
C’est l’approche la plus exigeante des quatre, et la plus souvent adoptée pour de mauvaises raisons :
- On ne corrige plus une donnée, on ajoute un événement qui la corrige. C’est un changement d’habitude profond pour une équipe, et pour l’exploitation.
- Un format d’événement ne se supprime jamais. Les anciens événements doivent rester relisibles indéfiniment, donc chaque évolution du modèle traîne ses versions passées derrière elle.
- Les performances demandent des instantanés : rejouer dix ans d’historique à chaque lecture n’est pas tenable, il faut périodiquement figer l’état.
- Le droit à l’effacement pose une vraie question. Un journal conçu pour n’être jamais modifié se concilie mal avec l’obligation de supprimer des données personnelles. Cela se traite — chiffrement par personne dont on détruit la clé, notamment — mais c’est un sujet à instruire avant de choisir l’approche, pas après une demande de suppression.
Notre position : l’Event Sourcing sur un domaine où l’histoire compte vraiment, jamais sur l’ensemble d’une application par principe.
Ce que nous n’imposons pas
Aucune de ces approches. Le travers le plus répandu de ceux qui les pratiquent est de les appliquer partout, y compris là où une application de saisie classique aurait suffi — on obtient alors trois fois plus de code pour le même résultat, et une équipe qui ne sait plus où corriger un libellé.
Notre règle est inverse : on commence simple, et on introduit ces outils là où la complexité du métier les justifie. Beaucoup d’applications n’en ont besoin nulle part. Certaines en ont besoin sur un seul de leurs domaines. Nous vous dirons dans quel cas vous êtes, et nous le dirons avant le devis.
Le TDD : écrire le test d’abord
Tout le monde dit tester son code. Le Test-Driven Development dit autre chose, et c’est une contrainte réelle : on écrit le test avant l’implémentation. Il échoue, puis on écrit le minimum de code qui le fait passer, puis on range.
Ce n’est pas une question de discipline morale. Écrire le test d’abord oblige à formuler ce que le code doit faire avant de décider comment il le fera — et c’est là que se trouve le vrai bénéfice, bien plus que dans la couverture obtenue. Un test écrit après coup valide ce que le code fait, y compris ses erreurs ; un test écrit avant décrit ce qu’on attend de lui.
Effet de bord, et il rejoint l’architecture hexagonale : du code écrit test-d’abord est testable par construction. On ne se retrouve pas avec des règles métier enfouies dans un contrôleur, impossibles à éprouver sans monter une base et un serveur — parce qu’un tel code aurait été pénible à écrire de cette façon.
Ce que ça rapporte, et quand
Pas au moment de la livraison. À la livraison, une application testée et une application non testée se ressemblent — la seconde a même coûté moins cher.
Le bénéfice arrive au dix-huitième mois, quand il faut modifier une règle métier écrite par quelqu’un qui est parti. Avec des tests, on change et on sait tout de suite ce qu’on a cassé. Sans, on n’ose pas toucher — alors on contourne, on duplique, et l’application devient chaque mois plus coûteuse à faire évoluer.
C’est aussi ce qui rend les montées de version possibles. Passer une application à la version majeure suivante de son framework sans filet est une opération que personne ne veut lancer ; avec une suite de tests, c’est une journée de travail.
Nos réserves, parce qu’il y en a
- La couverture est un mauvais objectif. Couvrir 100 % d’un code trivial ne prouve rien, et l’on y arrive en testant des accesseurs. Ce qui compte est que les règles métier soient couvertes, pas le pourcentage global.
- Tout ne mérite pas un test. Un gabarit d’affichage, une configuration, un appel direct à une bibliothèque : les tester coûte plus qu’ils ne rapportent.
- Les interfaces se testent mal ainsi. Le test-d’abord donne le meilleur sur la logique métier, et de piètres résultats sur ce qui se voit à l’écran, où d’autres méthodes valent mieux.
- Cela coûte au démarrage. Nous ne prétendrons pas l’inverse : c’est un investissement, et il ne se justifie que sur une application destinée à vivre. Sur un outil jetable, ce serait de l’argent perdu.
Ce qui vous appartient
Le code et les données sont à vous. L’application est hébergée sur notre infrastructure, en France — ce qui nous permet de la dimensionner et de l’exploiter — mais rien ne vous y attache techniquement : ni format fermé, ni dépendance qui rendrait le départ impossible.
Nous savons ce que vaut cette promesse pour l’avoir tenue sur nos propres produits, comme Factelia.
Les formats
Ce que nous construisons
-
Application métier
Vos processus internes outillés : saisie, validation, suivi, restitution. Le format le plus fréquent, et celui qui rend le plus vite.
-
Intranet et extranet
Un espace privé pour vos équipes ou vos partenaires, avec des accès par rôle et un branchement sur vos outils existants.
-
Logiciel en mode SaaS
Un service en ligne pour vos propres clients, multi-comptes, facturé à l’usage, exploité par nos équipes. C’est ce que nous faisons pour Factelia.
-
API et services
REST, gRPC ou GraphQL, pour faire parler vos systèmes entre eux ou exposer vos données à une application front.
-
Interface front
Une application web rapide adossée à vos API existantes, en VueJS ou React, découplée du back-office.
-
L’exploitation
Hébergement dimensionné, sauvegarde, supervision et astreinte. Développer l’application et la faire tourner sont deux métiers — nous faisons les deux.
Questions fréquentes
Développement : vos questions
Une autre question ? Le support répond directement, sans intermédiaire, de 9h à 12h et de 14h à 17h.
Ne vaut-il pas mieux un logiciel du marché ?
Quand il existe et qu’il correspond, oui — il sera moins cher et mieux maintenu, et nous vous le dirons. Le sur-mesure se justifie quand votre particularité est précisément ce qui fait votre métier, et que l’outil du marché vous demanderait d’y renoncer pour rentrer dans ses cases.
Quelle technologie allez-vous employer ?
Celle qui correspond au besoin : Symfony si PHP est déjà en place, Python avec FastAPI pour les API et l’asynchrone, Java ou Kotlin quand la charge et la fiabilité priment, Go pour un service réseau dédié, Node.js pour beaucoup de requêtes simultanées. Nous justifions le choix, et il se discute.
Combien de temps, et combien ça coûte ?
Sur devis, après avoir regardé le processus à outiller. Nous cherchons systématiquement à réduire la première version au périmètre qui rend déjà service : une application utile après trois mois vaut mieux qu’un projet complet après deux ans, et elle permet de s’arrêter si le reste ne se justifie plus.
Le code nous appartient-il ?
Oui, le code comme les données. L’application est hébergée sur notre infrastructure en France, ce qui nous permet de la dimensionner et de l’exploiter, mais rien ne vous y attache techniquement.
Employez-vous le DDD, l’hexagonal, le CQRS, l’Event Sourcing ?
Quand le métier le justifie, oui — et pas ailleurs. Le travers le plus répandu de ceux qui pratiquent ces approches est de les appliquer partout : on obtient trois fois plus de code pour le même résultat, et une équipe qui ne sait plus où corriger un libellé. Nous commençons simple et introduisons ces outils là où la complexité l’exige, souvent sur un seul domaine de l’application.
Faut-il abandonner notre ORM pour travailler ainsi ?
Non. L’ORM reste, mais il descend d’un étage : il sert à écrire l’implémentation, pas à structurer le métier. Le domaine, lui, ne connaît qu’une interface qui parle sa langue — « les dossiers en attente de validation » plutôt qu’une jointure sur trois tables. C’est ce qui permet de tester les règles sans base de données, et de changer de stockage sans réécrire le métier.
Comment évitez-vous les erreurs de saisie et les données invalides ?
En cessant de faire circuler des chaînes de caractères nues. Une adresse e-mail, un IBAN, un SIRET ou un montant sont représentés par des types dédiés qui portent leur propre règle de validité : l’objet ne peut pas exister s’il est invalide. La validation se fait une fois, là où la donnée entre dans le système, au lieu d’être répétée dans chaque fonction — c’est celle qui oublie qui fait le trou.
Vos développements sont-ils testés ?
Oui, et écrits test-d’abord sur la logique métier — ce qui n’est pas la même chose que d’ajouter des tests après coup pour atteindre un pourcentage. Nous ne visons pas une couverture totale : couvrir 100 % d’un code trivial ne prouve rien. Ce qui compte est que vos règles métier soient couvertes, parce que ce sont elles qu’il faudra modifier dans deux ans.
À quoi servent les tests si l’application fonctionne ?
À la faire évoluer. À la livraison, une application testée et une application non testée se ressemblent — la seconde a même coûté moins cher. La différence apparaît au dix-huitième mois, quand il faut modifier une règle écrite par quelqu’un qui est parti : avec des tests on change et on sait ce qu’on a cassé, sans on n’ose plus toucher. C’est aussi ce qui rend possible une montée de version majeure du framework.
L’Event Sourcing est-il compatible avec le RGPD ?
C’est la bonne question, et elle doit être posée avant de choisir l’approche. Un journal d’événements conçu pour n’être jamais modifié se concilie mal avec le droit à l’effacement. Cela se traite — en chiffrant les données personnelles par personne et en détruisant la clé, notamment — mais c’est un sujet à instruire en amont, pas au moment où une demande de suppression arrive.
Concrètement, qu’est-ce que ça change pour nous ?
Trois choses vérifiables. Le code emploie vos mots plutôt que ceux d’un développeur, donc il se relit avec vous. Les règles métier se testent sans base ni serveur, donc elles sont réellement testées. Et changer de base de données ou de version de framework ne demande pas de réécrire le métier. Ce sont des propriétés qui se constatent au bout de deux ans, pas au moment de la livraison.
Pouvez-vous reprendre une application existante ?
Cela s’étudie, et la réponse dépend d’un point : est-elle documentée et redéployable ? Une application dont personne ne sait reconstruire l’environnement se reprend, mais la première étape est de retrouver comment elle tourne — ce qui relève d’un travail d’architecture avant tout développement.
Quel processus vous coûte le plus cher aujourd’hui ?
C’est par lui qu’il faut commencer, et c’est souvent un périmètre bien plus petit qu’on ne l’imagine. Décrivez-le nous.