Können wir es einfacher machen, Datenflüsse zwischen entfernten Teilen einer großen Codebasis hinzuzufügen?

10

Wenn ich Änderungen an großen Systemen vornehme, habe ich häufig das Problem, dass einige Funktionen Daten von einem anderen Teil abrufen müssen, sich jedoch in verschiedenen Teilen eines tiefen und verzweigten Anrufbaums befinden und möglicherweise durch Ereignis-Listener, verzögerte Anrufe usw. usw. Auf diese Weise kann eine einfache Änderung schnell in die Höhe schnellen.

Ein verwandtes Zitat aus Yossi Kreinins Blogbeitrag unter http://www.yosefk.com/blog/i-want-a-struct-linker.html :

Sie haben eine Art Datenstruktur, die Sie häufig weitergeben. Bald ist das Wertvollste an der Struktur nicht die Daten, die sie speichert, sondern die Tatsache, dass sie während eines haarigen Kontrollflusses verfügbar sind.

Globale Variablen sind eine klassische Methode, um Code in entfernten Code "schreien" zu lassen, aber sie sind bekanntermaßen problematisch. Variablen mit dynamischem Gültigkeitsbereich sind eingeschränkter, aber auch problematisch.

Gibt es Programmiersprachenforschung, um dieses Problem zu lösen? Können wir es einfacher machen, unerwartete Datenflüsse zu einer großen Codebasis hinzuzufügen, während wir weiterhin statische Überprüfungen, einfache Komponententests und andere Extras haben?

Vladimir Slepnev
quelle
Die Art und Weise, wie Sie Ihre Frage formulieren Ich denke, Sie haben den Datenfluss in einem einzigen Prozess im Auge, keine Interprozesskommunikation. Was für ein Problem sehen Sie also, das mit Standardmechanismen für Absender / Listener von Ereignissen nicht gelöst werden kann?
Doc Brown
Ein erfundenes Beispiel: Stellen Sie sich vor, tief in Ihrem System befindet sich Code, der dem Benutzer eine Textnachricht sendet. Und Sie erhalten eine neue Anforderung, dass der Text der Nachricht von der aktuellen Zeit in der Zeitzone des Benutzers abhängen muss. Der Callstack sieht folgendermaßen aus: Ein Code, der die Zeitzone des Benutzers kennt, ruft eine Methode auf, die eine Methode aufruft, die (... 15 Mal wiederholen) eine Methode aufruft, die den Nachrichtentext generiert. Dies ist nach meinen Maßstäben ein einfaches Beispiel, da die Kommunikation nur nach unten erfolgt. Sie müssen jedoch die Signaturen von 15 Methoden ändern, um Ihre triviale Änderung vorzunehmen.
Vladimir Slepnev
Nun, ich denke, was helfen kann, ist den Datenfluss explizit zu modellieren und Komponenten vom Datenfluss zu trennen. Der deutsche Softwareentwickler schreibt viel über dieses Thema, die meisten Artikel auf Deutsch. Hier ist ein Artikel in englischer Sprache von ihm: geekswithblogs.net/theArchitectsNapkin/archive/2011/03/19/…
Doc Brown
Ich denke, eine interne Singleton-API könnte helfen. Es wäre in der gesamten Anwendung zugänglich und würde die gesamte Datenabruflogik kapseln.
SuperM

Antworten:

1

Sie beziehen sich auf CDI (Context Dependency Injection) AKA IoC (Inversion of Control). Java JSF und Spring Framework sind einige Beispiele. ASP.NET MVC verfügt über Plugins wie Unity. Javascript beginnt, Strukturen mithilfe von Bibliotheken wie RequireJS zu organisieren, deren Injektionsverhalten in vielen modernen JS-Frameworks zu beobachten ist. Dies dient zur Verkabelung lokaler und entfernter Anwendungen.

Für die lose Kopplung zwischen Netzwerken verwenden Unternehmen gerne Webdienste mit SOAP, REST, AJAX oder regulären Remote-Methodenaufrufen mit RPC. In Java können Sie JAX-WS oder .NET WCF verwenden, um verteilte Dienste zu erstellen. Dann ordnen Sie sie als Client in einem Servicebus oder "Datenfluss" aus einer beliebigen Sprache oder Plattform an. Ruby, Python, Scala, Java, C #, ... alles.

Durch die lose Kopplung können Sie Probleme aufteilen und überwinden, und Dienste sind häufig der Einstiegspunkt in eine Datenbank zum Abrufen von Daten. Wenn wir die Leiter hinaufsteigen, haben wir das Biest namens Message Queue. Dieser Weg führt zu Rahmenbedingungen für Unternehmen und Infrastrukturen.

Wenn Ihr Projekt jedoch auf keinem Netzwerk besteht, gibt es Sprachen wie Scala, Akka, NodeJS usw., die für einen hohen Datenfluss innerhalb einer einzelnen Anwendung ausgelegt sind. Sie arbeiten auch mit einigen oder allen der zuvor genannten Technologien für komplexe Projekte. Scala kann beispielsweise mit JAX-RS REST-Diensten zum Abrufen von "globalen Daten" aus einer Datenquelle verwendet werden und verfügt über Spring für die interne IoC-Verkabelung. Es gibt auch viele Business Execution- oder Workflow-Frameworks in JBoss-, .NET- und GUI-Tools wie MuleESB. In der Entwicklung können Sie mit Eclipse und Netbeans Dienste in einen visuellen Flussdiagrammbildschirm ziehen und dort ablegen.

Schließlich hat Java noch Singleton-Beans. Verwenden Sie zum Anpassen Ihrer Methoden zur Laufzeit Proxy- oder Reflection-Frameworks. Aber ehrlich gesagt ist das so 1999.

Wenn Sie so viele Anrufe tätigen, um einem Benutzer eine Nachricht basierend auf seiner Zeitzone zu senden, gibt es meiner Meinung nach wahrscheinlich einen zweistufigen Weg, um den gleichen Effekt zu erzielen, den der Benutzer sieht. Aber ja, CDI-Frameworks werden von vorhandenen Sprachen wie ein Mantel getragen, der ihnen alle von Ihnen erwähnten flexiblen Kräfte verleiht. Ich nenne es gerne das Unterbewusstsein meines Programms und kümmere mich nahtlos um schmutzige Arbeit.

Senor Entwickler
quelle
Message Queues sind zwar übertrieben, aber Messaging ist der perfekte Weg, um Ereignisse auf breiter Front auszulösen. Java verwendet Message Driven Beans (MDB) und dies sollte es Ihrem Programm ermöglichen, "Konversation" miteinander zu senden oder zu empfangen. Sie können dies auf diese Weise für den asynchronen Bonus tun.
Senor Developer
Danke für die Hinweise! Ich frage mich auf jeden Fall, wie eine Sprache aussehen könnte, wenn sie von Grund auf so konzipiert wäre, dass sie die Abhängigkeitsinjektion und ähnliche Muster unterstützt.
Vladimir Slepnev
0

Der einfachste Weg, dies in großem Maßstab zu tun, ist die Verwendung einer Art Datenkapselungs-API. Dies kann ein NoSQL-Speicher oder ein gekapseltes RDBMS sein (oder es kann sich tatsächlich zu unterschiedlichen Zeiten und an unterschiedlichen Orten in derselben Anwendung befinden - es gibt keinen Grund, warum Sie kein RDBMS haben können, das langfristig verarbeitet Speicher und eine NoSQL-Datenbank, die die kurzfristige Zustandskontrolle handhabt). Es könnte sogar eine Reihe von Singleton-Objekten sein.

Ihre Datenstrukturen können dann auf eine etwas verwaltete Weise in einem neutralen Raum zur Verfügung gestellt werden. Dies ist der Ansatz, den wir mit LedgerSMB verfolgen (aber mit einigen semi-globalen Variablen für im Wesentlichen versteckte Singletons, aber auch diese werden verwaltet. Wir haben uns entschieden, das Objekt direkt zu verstecken, da dies die Verwaltung der Variablen ein wenig vereinfacht hat, aber dann gibt es sie alle 4 von ihnen).

Natürlich hat jeder Ansatz Kompromisse und Sie können diese Kompromisse nicht umgehen. Der Schlüssel besteht darin, die Kompromisse zu untersuchen (Management vs. Leistung vs. Sauberkeit des Codes vs. potenzielle Fallstricke bei der Codierung) und eine Entscheidung zu treffen, die darauf basiert, was für Ihre Anwendung am besten ist.

Chris Travers
quelle
Danke für die Antwort! Es scheint mir, dass Programmiersprachenforschung bei diesem Problem helfen könnte. Wenn der Code beispielsweise einige Daten aus einer globalen Datenbank oder aus versteckten Singletons liest, kann eine statische / deklarative Garantie dafür bestehen, welche Daten benötigt werden.
Vladimir Slepnev
-1

Wenn Sie die Wörter verwenden (oder zitieren)

hairy flow of control

dann gehe ich davon aus, dass Ihr Code wirklich ein Chaos ist. Sie sollten es sofort fallen lassen. Wenn Sie die Modularisierung / Trennung von Bedenken verwenden, gibt es keinen "haarigen Kontrollfluss". Ihrem Code fehlt einfach die Einfachheit, was sich auch dadurch ableiten lässt, dass Sie auf globale Variablen verwiesen haben :-).

user127749
quelle
Warum das Downvote? Dem Zitat fehlte die Einleitung, die genau meine Ansicht unterstützt: "(Es ist wahrscheinlich als" Antipattern "oder" Code Smell "klassifiziert und hat als solches einen Namen in den entsprechenden Kreisen, aber ich würde es nicht wissen, also werde ich es tun lass es namenlos) "
user127749
2
Dies ist nicht wirklich eine Antwort auf die Frage, das ist wahrscheinlich der Grund für die Ablehnung
Daniel Gratzer
Lassen Sie mich dann die Frage umformulieren: Gibt es einen Zaubertrick, um das Durcheinander von Code rückgängig zu machen, der gegen eines der grundlegendsten Prinzipien des Software-Designs verstößt: KISS (halten Sie es einfach, dumm)? Der Trick ist keine Zauberei, sondern entweder ein Programmierer, der nicht ersetzt werden kann, weil er alle nicht so offensichtlichen Details kennt (die das Unternehmen langfristig töten werden), oder die Codebasis neu zu strukturieren. Leider interessieren sich viele Unternehmen zunächst nicht für das richtige Code-Design oder verstehen die Konsequenzen nicht einmal. Dann müssen sie ihren Code mindestens einmal umschreiben, viele schreiben ihn sogar um ein Vielfaches neu ...
user127749