ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

Pipes and Filters

Le pattern de structure d'architecture le plus cité du catalogue. Un pipeline d'intégration EDI n'est pas un gros bloc : c'est une chaîne d'étages atomiques (parse, valider, enrichir, traduire, livrer) reliés par des canaux. Chaque étage est isolable, testable, remplaçable.

Problème

Un message EDI entrant doit subir une dizaine de transformations avant d'atterrir dans l'ERP : détecter le format, parser, valider la syntaxe, valider les règles métier, résoudre les identifiants, traduire vers le canonique, traduire vers le schéma de l'ERP, livrer. Écrire ce parcours comme une seule fonction monolithique produit du code intransportable : tout changement impacte tout, le test unitaire devient impossible, on ne peut pas changer une étape sans risquer les autres. Il faut décomposer le pipeline.

Forces

  • Séparation des responsabilités. Chaque étage résout une seule classe de problème. La parseuse ne valide pas, le validateur ne traduit pas.
  • Composabilité. Ajouter une étape (par exemple anonymisation pour le RGPD) = brancher un nouveau filtre entre deux existants, pas réécrire.
  • Testabilité unitaire. Chaque filtre a un contrat de message en entrée et en sortie ; on le teste isolément avec des golden files.
  • Parallélisme natif. Plusieurs messages peuvent traverser le pipeline en parallèle, chaque filtre étant un consommateur indépendant sur son canal d'entrée.
  • Coût d'orchestration. Chaque filtre = un processus, une queue, un déploiement. Plus de pièces à monitorer.

Solution

EIP §70 (Hohpe & Woolf, 2003), repris depuis l'architecture UNIX (Doug McIlroy, 1964, formalisé dans Software Tools de Kernighan & Plauger, 1976). Décomposer le traitement en filtres — unités atomiques qui consomment un message sur un canal d'entrée, le transforment, le déposent sur un canal de sortie — reliés par des pipes (les canaux). Chaque filtre respecte un contrat : même type de message en entrée et en sortie (l'enveloppe canonique reste stable), seul le contenu évolue. Cela permet de réordonner ou de substituer un filtre sans casser la chaîne.

plaintext topology.txt
┌───────┐   ┌───────┐   ┌─────────┐   ┌─────────┐   ┌──────┐
   │ parse │──▶│ valid │──▶│ enrich  │──▶│ trans-  │──▶│ ship │
   │ AS2   │   │ ate   │   │ (GLN→   │   │ late    │   │      │
   │ EDI   │   │ schema│   │ adresse)│   │ canon.  │   │ to   │
   └───────┘   └───────┘   └─────────┘   └─────────┘   │ part │
        │           │            │             │       │ ner  │
        ▼           ▼            ▼             ▼       └──────┘
     pipe        pipe         pipe          pipe
     (queue)     (queue)      (queue)       (queue)

   Each filter:
     - one input pipe, one (or many) output pipes
     - same message envelope contract
     - stateless if possible (state in canonical message)

Implémentation EDI

Le pipeline typique d'un INVOIC entrant :

yaml invoic-pipeline.yaml
# Pipeline EDIFACT INVOIC entrant
filters:
  - id: sniff-format
    in:   edi.inbound.raw
    out:  edi.detected.edifact     # autre filtre pour x12 / ubl
    role: detect EDIFACT vs X12 vs UBL

  - id: parse-edifact
    in:   edi.detected.edifact
    out:  edi.canonical.invoic.raw
    role: parse UN/EDIFACT INVOIC D96A → JSON canonical

  - id: schema-validate
    in:   edi.canonical.invoic.raw
    out:  edi.canonical.invoic.validated
    fail: edi.deadletter.invalid
    role: JSON-schema + business rules

  - id: enrich-gln
    in:   edi.canonical.invoic.validated
    out:  edi.canonical.invoic.enriched
    role: GLN→party master, GTIN→product master

  - id: translate-erp
    in:   edi.canonical.invoic.enriched
    out:  erp.bookkeeping.invoice.in
    role: canonical → SAP IDoc INVOIC02

Chaque filtre a son propre canal d'entrée et de sortie, sa propre DLQ (edi.deadletter.*), sa propre observabilité. On peut faire évoluer indépendamment : ajouter anonymize-pii entre schema-validate et enrich-gln, ou remplacer parse-edifact par une nouvelle implémentation sans toucher au reste. La règle d'or est que chaque filtre publie sur sa sortie un message du même type canonique que celui qu'il a consommé, enrichi ou allégé ; jamais un autre type. Cela distingue les pipes-and-filters d'un workflow où chaque étage parle son propre dialecte.

Parallélisme & ordre

Le parallélisme est natif : chaque filtre peut tourner en N instances (competing consumers sur sa queue d'entrée). Mais cela casse l'ordre. Si l'ordre compte (par exemple un ORDERS suivi d'un ORDCHG sur la même PO), il faut partitionner par clé (Kafka avec key = controlRef) ou imposer une sériale dans le filtre concerné. Les autres filtres peuvent rester parallèles.

Anti-patterns

  • Filtre god-object. Un filtre qui parse, valide ET traduit. On retombe sur les couplages.
  • Filtres qui partagent une base de données. Couplage par la donnée : un changement de schéma bloque deux filtres. Préférer le canonique passé en message.
  • Pas de DLQ par étape. Si un message échoue dans enrich-gln, il ne doit pas remonter à parse-edifact ; il doit aller en DLQ de l'étape, avec contexte.
  • Type de message qui change à chaque filtre. Si la sortie de parse-edifact est un objet, celle de validate un autre, celle de enrich un troisième, on a perdu le contrat canonique — toute substitution devient impossible.

Patterns liés

Sources

  • Hohpe G., Woolf B. — Enterprise Integration Patterns, pattern Pipes and Filters (§70). enterpriseintegrationpatterns.com — Pipes and Filters
  • Kernighan B., Plauger P.Software Tools, Addison-Wesley, 1976. La formalisation pédagogique du concept de pipe UNIX dont s'inspire le pattern.
  • Shaw M., Garlan D.Software Architecture: Perspectives on an Emerging Discipline, Prentice Hall, 1996. Chapitre sur les styles d'architecture, dont le style pipes-and-filters.
  • Apache Camel — la totalité du framework est organisée autour du pattern. Les routes Camel sont des pipelines pipes-and-filters. camel.apache.org — Pipeline