Pouvons-nous faciliter l'ajout de flux de données entre des parties distantes d'une grande base de code?

10

Lorsque j'apporte des modifications à de grands systèmes, je suis souvent confronté au problème selon lequel certaines fonctionnalités doivent obtenir des données d'une autre pièce, mais elles se trouvent dans différentes parties d'une arborescence d'appels profonde et ramifiée, pouvant éventuellement circuler dans des écouteurs d'événements, des appels différés, etc. De cette façon, un simple changement peut gonfler rapidement.

Une citation connexe du billet de blog de Yossi Kreinin à http://www.yosefk.com/blog/i-want-a-struct-linker.html :

Vous avez une sorte de structure de données que vous transmettez beaucoup. Bientôt, la chose la plus précieuse de la structure n'est pas les données qu'elle conserve, mais le fait qu'elle est disponible tout au long d'un flux de contrôle velu.

Les variables globales sont un moyen classique de laisser le code "crier" vers du code distant, mais elles sont connues pour être problématiques. Les variables à portée dynamique sont un moyen plus restreint, mais elles sont également problématiques.

Existe-t-il des recherches sur les langages de programmation visant à résoudre ce problème? Pouvons-nous faciliter l'ajout de flux de données imprévus à une grande base de code, tout en ayant des vérifications statiques, des tests unitaires faciles et d'autres avantages?

Vladimir Slepnev
la source
La façon dont vous formulez votre question, je suppose que vous avez le flux de données dans un seul processus à l'esprit, pas de communication interprocessus. Alors, quel type de problème voyez-vous qui ne peut pas être résolu par les mécanismes standard d'envoi / écouteur d'événements?
Doc Brown
Un exemple artificiel: imaginez qu'au plus profond de votre système, il y a du code qui envoie à l'utilisateur un message texte. Et vous obtenez une nouvelle exigence selon laquelle le texte du message doit dépendre de l'heure actuelle dans le fuseau horaire de l'utilisateur. La pile d'appels ressemble à ceci: du code qui connaît le fuseau horaire de l'utilisateur, appelle une méthode qui appelle une méthode qui (... répéter 15 fois) appelle une méthode qui génère le texte du message. Ceci est un exemple simple selon mes normes, car il implique une communication uniquement vers le bas, mais vous devez toujours modifier les signatures de 15 méthodes pour effectuer votre changement trivial.
Vladimir Slepnev
Eh bien, je suppose que ce qui peut aider est de modéliser explicitement le flux de données et de séparer les composants du flux de données. L'ingénieur logiciel allemand écrit beaucoup sur ce sujet, la plupart des articles en allemand. Voici un article d'entrée en anglais de lui: geekswithblogs.net/theArchitectsNapkin/archive/2011/03/19/…
Doc Brown
Je pense qu'une API interne singleton pourrait aider. Il serait accessible partout dans l'application et encapsulerait toute la logique de récupération des données.
superM

Réponses:

1

Vous faites référence à CDI (Context Dependency Injection) AKA IoC (Inversion of Control). Java JSF et Spring Framework en sont quelques exemples. ASP.NET MVC a des plugins comme Unity. Javascript commence à avoir des structures organisées utilisant des bibliothèques comme RequireJS, qui a un comportement d'injection vu dans de nombreux frameworks JS modernes. C'est pour le câblage des applications locales et distantes.

Pour un couplage lâche entre les réseaux, les entreprises aiment utiliser les services Web avec SOAP, REST, AJAX ou les appels à distance réguliers avec RPC. En Java, vous pouvez utiliser JAX-WS ou .NET WCF pour créer des services distribués. Ensuite, vous les alignez dans un bus de service ou un "flux de données" à partir de n'importe quelle langue ou plate-forme en tant que client. Ruby, Python, Scala, Java, C #, ... n'importe quoi.

Le couplage lâche vous permet de diviser et de vaincre les problèmes, et les services sont souvent le point d'entrée d'une base de données pour extraire des données. En montant l'échelle, nous avons la bête appelée Message Queue. Cette route mène à des cadres de type entreprise et infrastructure.

Si votre projet n'insiste sur aucun réseau, cependant, il existe des langages comme Scala, Akka, NodeJS etc. qui sont conçus pour un flux de données élevé au sein d'une seule application. Ils fonctionnent également avec certaines ou toutes les technologies mentionnées précédemment pour des projets complexes. Par exemple, Scala peut être utilisé avec les services JAX-RS REST pour extraire une sorte de «données globales» d'une source de données et avoir Spring pour le câblage interne IoC. Il existe également de nombreux cadres d'exécution ou de workflow dans JBoss, .NET et les outils GUI comme MuleESB. En développement, Eclipse et Netbeans vous permettent de faire glisser et déposer des services dans un écran d'organigramme visuel.

Enfin, Java a toujours des beans Singleton. Pour ajuster vos méthodes au moment de l'exécution, utilisez des cadres de proxy ou de réflexion. Mais honnêtement, c'est le cas en 1999.

Si vous effectuez autant d'appels pour envoyer un message à un utilisateur en fonction de son fuseau horaire, à mon avis, il existe probablement un moyen en deux étapes pour obtenir le même effet que l'utilisateur voit. Mais oui, les frameworks CDI sont portés par les langages existants comme un manteau qui leur donne tous les pouvoirs flexibles que vous avez mentionnés. J'aime l'appeler subconscient de mon programme, en prenant soin du travail sale de manière transparente.

Développeur Senor
la source
Les files d'attente de messages peuvent être exagérées, mais la messagerie est le moyen idéal pour déclencher des événements dans tous les domaines. Java utilise des Message Driven Beans (MDB) et cela devrait permettre à votre programme d'envoyer ou de recevoir des «conversations» les uns avec les autres. Vous pouvez le faire de cette façon pour le bonus asynchrone.
Développeur Senor
Merci pour les pointeurs! Cela me fait définitivement me demander à quoi pourrait ressembler un langage s'il était conçu à partir de zéro pour prendre en charge l'injection de dépendance et des modèles similaires.
Vladimir Slepnev
0

La façon la plus simple de le faire à grande échelle est en fait d'utiliser une sorte d'API d'encapsulation de données. Cela peut être un magasin NoSQL ou un RDBMS encapsulé (ou il peut en fait être à la fois à des moments et à des endroits différents dans la même application - il n'y a aucune raison pour laquelle vous ne pouvez pas avoir un RDBMS gérant à long terme et une base de données NoSQL gérant le contrôle d'état à court terme). Il pourrait même s'agir d'une série d'objets singleton.

Vos structures de données peuvent ensuite être mises à disposition dans une sorte d'espace neutre, d'une manière quelque peu gérée. C'est l'approche que nous adoptons avec LedgerSMB (mais avec quelques variables semi-globales pour ce qui est essentiellement des singletons cachés, mais encore une fois ceux-ci sont gérés, nous avons choisi de cacher directement l'objet parce que cela rendait la gestion des variables un peu plus facile, mais il y a ensuite tous les 4).

Bien sûr, toute approche a des compromis et vous ne pouvez pas contourner ces compromis. La clé est de regarder quels sont les compromis (gestion vs performances vs propreté du code vs pièges de codage potentiels) et prendre une décision en fonction de ce qui est le mieux pour votre application.

Chris Travers
la source
Merci d'avoir répondu! Il me semble que la recherche en langage de programmation pourrait aider à résoudre ce problème. Par exemple, si le code lit certaines données d'une base de données globale ou de singletons cachés, il pourrait y avoir une garantie statique / déclarative sur les données dont il a besoin.
Vladimir Slepnev
-1

Si vous utilisez (ou citez) les mots

hairy flow of control

alors je suppose que votre code est vraiment un gâchis. Vous devez le laisser tomber immédiatement. Si vous utilisez la modularisation / séparation des préoccupations, il n'y a pas de "flux de contrôle velu". Votre code manque simplement de simplicité, ce qui est également inférable par le fait que vous avez fait référence à des variables globales :-).

user127749
la source
Pourquoi le downvote? La citation manquait de l'introduction qui soutient exactement mon point de vue: "(il est probablement classé comme un" Antipattern "ou un" Code Smell "et en tant que tel a un nom dans les cercles appropriés, mais je ne sais pas, donc je vais laissez-le sans nom) "
user127749
2
Ce n'est pas vraiment une réponse à la question, c'est probablement la raison du downvote
Daniel Gratzer
Ensuite, laissez-moi reformuler la question: existe-t-il une astuce magique pour défaire le désordre de code qui viole l'un des principes les plus élémentaires de la conception de logiciels: KISS (garder les choses simples, stupides)? L'astuce n'est pas magique, c'est soit un programmeur qui ne peut pas être remplacé car il connaît tous les détails pas si évidents (qui vont tuer l'entreprise à long terme), soit pour restructurer la base de code. Malheureusement, de nombreuses entreprises ne se soucient pas initialement de la conception appropriée du code ou n'en comprennent même pas les conséquences, puis doivent réécrire leur code au moins une fois, beaucoup le réécrivent même plusieurs fois ...
user127749