2 votes

Traitement fonctionnel des données en clojure

Je suis à la recherche d'une solution architecturale au problème auquel je suis confronté. Je suis aux prises avec un énorme pipeline qui traite data (qui est une structure très complexe). De manière générale, on peut l'illustrer comme suit :

(defn process [data]
  (-> data
    do-something-1
    do-something-2
    do-something-3
    do-something-4
    ...
    do-something-20
)

où chacun des do-something-* Les fonctions peuvent être tout aussi complexes. Mon problème est qu'il y a beaucoup de couplage entre les fonctions dans une telle chaîne de traitement. Par exemple do-something-3 ajouter quelque chose aux données qui seront ensuite requises par do-something-9 qui ajoute un autre élément requis par do-something-18 et ainsi de suite. Ainsi, les données sont essentiellement enrichies par toutes ces fonctions lors de la descente en cascade de la macro de filtrage. Il est très difficile de garder la trace de ce qui se passe et quand. Tenir toute la chaîne de traitement dans ma tête est tout simplement une charge cognitive trop importante (ou du moins, j'ai trop peu de mémoire vive dans ma tête). Comment gérer de tels cas ? Je sais qu'il n'y a pas de solution miracle, mais peut-être y a-t-il quelque chose qui m'échappe (j'ai commencé à apprendre Clojure il y a quelques mois).

0voto

Alan Thompson Points 325

Je n'ai jamais aimé les longs pipelines tels que vous les décrivez en raison des difficultés que vous rencontrez.

Dans un premier temps, vous pourriez simplement diviser le pipeline et donner un nom (même temporaire) à chaque étape :

(defn process [data]
  (let [x01 (do-something-1 data)
        x02 (do-something-2 x01)
        x03 (do-something-3 x02)
        x04 (do-something-4 x03)
        ; ...
        x20 (do-something-20 x19)]
    x20))

Ensuite, vous pouvez ajouter des instructions de débogage et/ou de validation entre les deux, si nécessaire. Je suggérerais également d'utiliser Plumatic Schema pour documenter l'entrée/sortie de chaque élément du système. do-something-* (ou peut-être Malli ; je n'aime pas spec). J'espère que les noms des fonctions sont également descriptifs ; vous pourriez les améliorer comme un autre plus.

Vous pouvez également regrouper les fonctions dans une hiérarchie au lieu d'une simple chaîne linéaire :

A
 - A1
 - A2
 - A3
 - A4
B
 - B1 
 - B2
 - B3
C 
 ...etc...

Le pipeline de premier niveau ne compte donc que 3 ou 4 appels, chacun d'entre eux pouvant comporter 2 ou 5 sous-appels.

Bien sûr, j'espère que vous avez de bons tests unitaires pour chaque fonction à tous les niveaux afin de documenter le comportement attendu et les entrées/sorties typiques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X