Trägt die Aufteilung einer potenziell monolithischen Anwendung in mehrere kleinere zur Vermeidung von Fehlern bei? [geschlossen]

48

Eine andere Art, dies zu fragen, ist: Warum sind Programme in der Regel monolithisch?

Ich denke an so etwas wie ein Animationspaket wie Maya, das die Leute für verschiedene Workflows verwenden.

Wären die Animations- und Modellierungsfunktionen nicht einfacher zu warten, wenn sie in eine separate Anwendung aufgeteilt und separat entwickelt würden, wobei Dateien zwischen ihnen ausgetauscht würden?

dnv
quelle
9
If the animation and modelling capabilities were split into their own separate application and developed separately, with files being passed between them, would they not be easier to maintain?Mischen Sie nicht einfachere Erweiterungsmöglichkeiten mit einfacheren Wartungsmöglichkeiten, da dies nicht frei von Komplikationen oder zweifelhaften Designs ist. Maya kann die Hölle auf Erden sein, während seine Plugins es nicht sind. Oder umgekehrt.
12.
37
Ich füge hinzu, dass ein einzelnes monolithisches Programm in der Regel einfacher zu verkaufen und für die meisten Benutzer einfacher zu verwenden ist .
DarthFennec
2
@DarthFennec Die besten Apps sehen für den Benutzer wie eine App aus, nutzen jedoch alles, was unter der Haube benötigt wird. Wie viele Microservices versorgen die verschiedenen Websites, die Sie besuchen? Fast keiner von ihnen ist mehr ein Monolith!
corsiKa
23
@corsiKa Es gibt normalerweise nichts zu gewinnen, wenn Sie eine Desktop-Anwendung als mehrere Programme schreiben, die unter der Haube kommunizieren, und nicht nur, wenn Sie mehrere Module / Bibliotheken schreiben und sie zu einer monolithischen Binärdatei verknüpfen. Microservices erfüllen einen völlig anderen Zweck, da eine einzelne Anwendung auf mehreren physischen Servern ausgeführt werden kann und die Leistung mit der Last skaliert werden kann.
DarthFennec
5
@corsiKa - Ich würde vermuten, dass die überwiegende Anzahl der von mir verwendeten Websites immer noch Monolithen sind. Immerhin läuft der größte Teil des Internets auf Wordpress.
Davor Ždralo

Antworten:

94

Ja. Im Allgemeinen sind zwei kleinere, weniger komplexe Anwendungen viel einfacher zu warten als eine einzige große.

Es tritt jedoch eine neue Art von Fehler auf, wenn alle Anwendungen zusammenarbeiten, um ein Ziel zu erreichen. Damit sie zusammenarbeiten können, müssen sie Nachrichten austauschen, und diese Orchestrierung kann auf verschiedene Weise schief gehen, auch wenn jede Anwendung möglicherweise einwandfrei funktioniert. Eine Million winziger Anwendungen zu haben, hat seine eigenen speziellen Probleme.

Eine monolithische Anwendung ist die Standardoption, mit der Sie am Ende immer mehr Funktionen zu einer einzelnen Anwendung hinzufügen. Dies ist der einfachste Ansatz, wenn Sie jede Funktion für sich betrachten. Erst wenn es groß geworden ist, können Sie sich das Ganze ansehen und sagen: "Weißt du was? Das würde besser funktionieren, wenn wir X und Y trennen."

Ewan
quelle
6
Ja, und es gibt auch Leistungsaspekte, z. B. die Kosten für die Weitergabe eines Zeigers im Vergleich zur Serialisierung von Daten.
JimmyJames
65
"Im Allgemeinen sind zwei kleinere, weniger komplexe Anwendungen viel einfacher zu warten als eine einzige große." - das ist wahr, außer wenn es nicht ist. Hängt stark davon ab, wo und wie diese beiden Anwendungen miteinander kommunizieren müssen.
Doc Brown
10
"Im Allgemeinen sind zwei kleinere, weniger komplexe Anwendungen viel einfacher zu warten als eine einzige große." Ich denke, ich möchte mehr Erklärungen dafür. Warum genau würde der Prozess des Erzeugens von zwei statt einer ausführbaren Datei aus einer Codebasis den Code auf magische Weise vereinfachen? Was entscheidet, wie einfach Code zu überlegen ist, ist, wie eng er gekoppelt ist und ähnliche Dinge. Aber das ist eine logische Trennung und hat nichts mit der physischen zu tun .
Voo
11
@Ew Die physikalische Trennung erzwingt keine logische Trennung, das ist das Problem. Ich kann problemlos ein System entwerfen, bei dem zwei separate Anwendungen eng miteinander verbunden sind. Sicher, es besteht eine gewisse Korrelation , da Personen, die Zeit für die Trennung einer Anwendung aufwenden, höchstwahrscheinlich kompetent genug sind, diese Dinge zu berücksichtigen, aber es gibt wenig Grund, eine Ursache anzunehmen . Nach der gleichen Logik kann ich behaupten, dass die Verwendung der neuesten C # -Version die Pflege des Codes erheblich vereinfacht, da sich die Art von Team, das mit seinen Tools auf dem neuesten Stand ist, wahrscheinlich auch um die Pflege des Codes kümmern wird.
Voo
9
Ich denke , die hier Diskussion kann mit 2 Aussagen zusammenfassen: 1) Splitting einer App nicht selbst eine App macht mehr wartbar - im Gegenteil, bietet es eine weiteren möglichen Fehlerpunkt 2) Splitting einer App Kräfte Sie darüber nachdenken , wo man Split Dies ist ein Vorteil gegenüber einem Monolithen, bei dem dies noch nie geschehen ist.
R. Schmitz
51

Wenn Sie eine potenziell monolithische Anwendung in mehrere kleinere Anwendungen aufteilen, können Sie Fehler vermeiden

In der Realität sind die Dinge selten so einfach.

Das Aufteilen hilft definitiv nicht, diese Fehler an erster Stelle zu verhindern. Es kann manchmal helfen, Fehler schneller zu finden. Eine Anwendung, die aus kleinen, isolierten Komponenten besteht, kann mehr individuelle (Art von "Einheit" -) Tests für diese Komponenten ermöglichen, wodurch es manchmal einfacher ist, die Ursache bestimmter Fehler zu lokalisieren und sie so schneller zu beheben.

Jedoch,

  • Sogar eine Anwendung, die von außen monolithisch zu sein scheint, kann aus einer Menge von Komponenten bestehen, die innerhalb der Einheit getestet werden können. Daher ist das Testen von Einheiten für eine monolithische Anwendung nicht unbedingt schwieriger

  • Wie Ewan bereits erwähnte, bringt das Zusammenspiel mehrerer Komponenten zusätzliche Risiken und Fehler mit sich. Das Debuggen eines Anwendungssystems mit komplexer Interprozesskommunikation kann erheblich schwieriger sein als das Debuggen einer Einzelprozessanwendung

Dies hängt auch stark davon ab, wie gut sich eine größere App in Komponenten aufteilen lässt, wie breit die Schnittstellen zwischen den Komponenten sind und wie diese Schnittstellen verwendet werden.

Kurz gesagt, dies ist oft ein Kompromiss und nichts, wo eine "Ja" - oder "Nein" -Antwort im Allgemeinen richtig ist.

Warum sind Programme in der Regel monolithisch?

Tun sie? Schauen Sie sich um, es gibt Millionen von Web-Apps auf der Welt, die für mich nicht sehr monolithisch aussehen, ganz im Gegenteil. Es gibt auch viele Programme, die ein Plugin-Modell bereitstellen (AFAIK sogar die von Ihnen erwähnte Maya-Software).

Wären sie nicht einfacher zu warten

Eine "einfachere Wartung" ergibt sich hier häufig aus der Tatsache, dass verschiedene Teile einer Anwendung von verschiedenen Teams einfacher entwickelt werden können, wodurch die Arbeitslast besser verteilt wird und spezialisierte Teams klarer fokussiert sind.

Doc Brown
quelle
4
In Ihrem letzten Satz besagt Conways Gesetz , dass die Systemstruktur dazu neigt, org zu imitieren. Struktur: Entwickler / Teams kennen sich mit einigen Teilen besser aus als andere. Obwohl Korrekturen / Verbesserungen an den relevantesten Stellen vorgenommen werden sollten , kann es für Entwickler einfacher sein, sie in "ihre" Teile zu hacken, als (a) zu lernen, wie dies geschieht anderer Teil funktioniert oder (b) mit jemandem zusammenarbeiten, der mit diesem Teil besser vertraut ist. Dies hängt mit den "Nähten" zusammen, die @TKK erwähnt, und wie schwierig es sein kann, "richtige" / einfache zu finden und durchzusetzen.
Warbo
38

Ich muss mit der Mehrheit in dieser Frage nicht einverstanden sein. Das Aufteilen einer Anwendung in zwei separate macht den Code an sich nicht einfacher zu pflegen oder zu begründen.

Das Trennen von Code in zwei ausführbare Dateien ändert lediglich die physische Struktur des Codes, aber das ist nicht wichtig. Entscheidend für die Komplexität einer Anwendung ist, wie eng die einzelnen Komponenten miteinander verbunden sind. Dies ist keine physikalische Eigenschaft, sondern eine logische .

Sie können eine monolithische Anwendung haben, bei der verschiedene Anliegen und einfache Schnittstellen klar voneinander getrennt sind. Sie können über eine Microservice-Architektur verfügen, die sich auf Implementierungsdetails anderer Microservices stützt und eng mit allen anderen gekoppelt ist.

Die Aufteilung einer großen Anwendung in kleinere Anwendungen ist sehr hilfreich, wenn klare Schnittstellen und Anforderungen für jedes Teil festgelegt werden sollen. In DDD speak käme das auf Ihre begrenzten Kontexte. Ob Sie dann viele kleine Anwendungen oder eine große mit derselben logischen Struktur erstellen, ist eher eine technische Entscheidung.

Voo
quelle
Was aber, wenn man eine Desktop-Anwendung mit mehreren Bearbeitungsmodi verwendet und stattdessen nur eine Desktop-Anwendung für jeden Modus erstellt, den ein Benutzer einzeln öffnen würde, anstatt eine Schnittstelle zu haben? Würde das nicht eine nicht unbedeutende Menge an Code eliminieren, der für die Erzeugung des "Merkmals" "Benutzer kann zwischen Bearbeitungsmodi wechseln" vorgesehen ist?
The Great Duck
3
@TheGreatDuck Das klingt so, als würde es auch eine nicht unbedeutende Menge von Benutzern eliminieren, die nicht gerne zwischen verschiedenen Anwendungen wechseln müssen. ;) Aber ja, das Eliminieren von Features führt im Allgemeinen zu einfacherem Code. Beseitigen Sie die Rechtschreibprüfung, und Sie werden die Möglichkeit von Fehlern bei der Rechtschreibprüfung beseitigen. Es wird nur selten gemacht, weil das Feature hinzugefügt wurde, weil jemand es wollte.
Odalrick
1
@TheGreatDuck Sicherlich sollte das Design der UX vor allen architektonischen Entscheidungen stehen. Es hat keinen Sinn, die am besten entworfene Architektur zu haben, wenn niemand Ihr Programm verwendet. Entscheiden Sie zuerst, was Sie bauen möchten, und legen Sie dann die technischen Details fest. Wenn zwei separate Anwendungen bevorzugt werden, wählen Sie diese aus. Sie können jedoch weiterhin viel Code über gemeinsam genutzte Bibliotheken freigeben.
Voo
Stimmt es, dass die Komplexität des Systems auf die enge Kopplung der Teile zurückzuführen ist? Ich möchte sagen, dass die Gesamtkomplexität zunimmt, wenn Sie Ihr System partitionieren, während Sie Indirektion und Kommunikation einführen, obwohl die Komplexität der einzelnen Komponenten in einem begrenzten Zustand geringerer Komplexität isoliert ist.
Alex
1
@TheGreatDuck Die zugrunde liegende Annahme dabei war, dass die Systeme etwas gemeinsam haben und tatsächlich auf die eine oder andere Weise miteinander kommunizieren müssen. Ich glaube nicht, dass das OP gefragt hat, ob zwei völlig unterschiedliche Anwendungen, die aus seltsamen Gründen zusammengebündelt sind, einfacher zu warten sind, wenn sie getrennt werden. Scheint ein seltsamer Fall zu sein, der in der Praxis nicht oft auftaucht (obwohl ich mir sicher bin, dass irgendwo jemand das getan hat).
Voo
15

Einfacher zu pflegen, wenn Sie fertig sind, ja. Aber sie aufzuteilen ist nicht immer einfach. Der Versuch, einen Teil eines Programms in eine wiederverwendbare Bibliothek aufzuteilen, zeigt, wo die ursprünglichen Entwickler nicht darüber nachgedacht haben, wo die Nähte sein sollten. Wenn ein Teil der Anwendung tief in einen anderen Teil der Anwendung hineinreicht, kann es schwierig sein, dies zu beheben. Durch das Rippen der Nähte müssen Sie die internen APIs klarer definieren. Dies erleichtert letztendlich die Wartung der Codebasis. Wiederverwendbarkeit und Wartbarkeit sind beide Produkte mit genau definierten Nähten.

Nein U
quelle
guter Eintrag. Ich denke, ein klassisches / kanonisches Beispiel für das, worüber Sie sprechen, ist eine GUI-Anwendung. Oft ist eine GUI-Anwendung ein Programm und das Backend / Frontend ist eng miteinander verbunden. Im Laufe der Zeit treten Probleme auf ... wie wenn jemand anderes das Backend verwenden muss, dies jedoch nicht kann, da es an das Frontend gebunden ist. oder die Backend-Verarbeitung dauert zu lange und blockiert das Frontend. oft ist die eine große GUI-Anwendung in zwei Programme aufgeteilt: eines ist die Frontend-GUI und eines ist ein Backend.
Trevor Boyd Smith
13

Es ist wichtig, sich daran zu erinnern, dass Korrelation keine Kausalität ist.

Der Bau eines großen Monolithen und dessen Aufteilung in mehrere kleine Teile kann zu einem guten Design führen oder auch nicht. (Es kann das Design verbessern, aber es wird nicht garantiert.)

Ein gutes Design führt jedoch häufig dazu, dass ein System aus mehreren kleinen Teilen und nicht aus einem großen Monolithen besteht. (Ein Monolith kann das beste Design sein, es ist nur viel weniger wahrscheinlich.)

Warum sind Kleinteile besser? Weil es einfacher ist, über sie nachzudenken. Und wenn es einfach ist, über die Richtigkeit zu urteilen, erhalten Sie mit größerer Wahrscheinlichkeit ein korrektes Ergebnis.

Um CAR Hoare zu zitieren:

Es gibt zwei Möglichkeiten, ein Software-Design zu erstellen: Eine Möglichkeit besteht darin, es so einfach zu gestalten, dass es offensichtlich keine Mängel gibt, und die andere darin, es so kompliziert zu gestalten, dass es keine offensichtlichen Mängel gibt.

Wenn dies der Fall ist, warum sollte jemand eine unnötig komplizierte oder monolithische Lösung entwickeln? Hoare liefert die Antwort im nächsten Satz:

Die erste Methode ist weitaus schwieriger.

Und später in derselben Quelle (der 1980er Turing Award Lecture):

Der Preis für Zuverlässigkeit ist das Streben nach äußerster Einfachheit. Es ist ein Preis, den die Reichen am schwersten zu bezahlen finden.

Daniel Pryden
quelle
6

Dies ist keine Frage mit einer Ja- oder Nein-Antwort. Die Frage ist nicht nur die Wartungsfreundlichkeit, sondern auch die effiziente Nutzung von Fähigkeiten.

Im Allgemeinen ist eine gut geschriebene monolithische Anwendung effizient. Die Kommunikation zwischen Prozessen und Geräten ist nicht billig. Das Aufbrechen eines einzelnen Prozesses verringert die Effizienz. Wenn Sie jedoch alles auf einem einzelnen Prozessor ausführen, kann dies den Prozessor überlasten und die Leistung beeinträchtigen. Dies ist das grundlegende Problem der Skalierbarkeit. Wenn das Netzwerk ins Bild kommt, wird das Problem noch komplizierter.

Eine gut geschriebene monolithische Anwendung, die effizient als ein einzelner Prozess auf einem einzelnen Server ausgeführt werden kann, kann einfach zu warten und fehlerfrei sein, aber dennoch keine effiziente Verwendung von Codierungs- und Architekturfähigkeiten darstellen. Der erste Schritt besteht darin, den Prozess in Bibliotheken zu unterteilen, die immer noch als derselbe Prozess ausgeführt werden, jedoch unabhängig voneinander codiert werden, wobei den Disziplinen Kohäsion und lose Kopplung gefolgt wird. Ein guter Job auf diesem Niveau verbessert die Wartbarkeit und beeinträchtigt selten die Leistung.

Die nächste Stufe besteht darin, den Monolithen in getrennte Prozesse zu unterteilen. Dies ist schwieriger, weil Sie in schwieriges Gebiet eintreten. Es ist einfach, Fehler bei den Rennbedingungen einzuführen. Der Kommunikationsaufwand steigt und Sie müssen auf "gesprächige Schnittstellen" achten. Die Belohnungen sind großartig, weil Sie eine Skalierbarkeitsbarriere durchbrechen, aber auch das Fehlerpotential steigt. Mehrprozessanwendungen sind auf Modulebene einfacher zu warten, das Gesamtsystem ist jedoch komplizierter und schwieriger zu beheben. Fixes können teuflisch kompliziert sein.

Wenn die Prozesse auf separate Server oder auf eine Implementierung im Cloud-Stil verteilt werden, werden die Probleme schwieriger und die Belohnungen größer. Skalierbarkeit steigt. (Wenn Sie über eine Cloud-Implementierung nachdenken, die keine Skalierbarkeit bietet, sollten Sie überlegen.) Die Probleme, die in dieser Phase auftreten, können jedoch unglaublich schwer zu identifizieren und zu überdenken sein.

MarvW
quelle
4

Nein . Die Wartung wird dadurch nicht einfacher. Wenn irgendetwas zu mehr Problemen willkommen ist.

Warum?

  • Die Programme sind nicht orthogonal, sondern müssen sich gegenseitig schützen, sofern dies zumutbar ist, was ein gemeinsames Verständnis voraussetzt.
  • Viel Code beider Programme ist identisch. Führen Sie eine gemeinsame Bibliothek oder zwei separate Kopien?
  • Sie haben jetzt zwei Entwicklungsteams. Wie kommunizieren sie?
  • Sie haben jetzt zwei Produkte, die benötigt werden:

    • Ein allgemeiner Benutzeroberflächenstil, Interaktionsmechanismen usw. Sie haben also jetzt Designprobleme. (Wie kommunizieren die Entwicklerteams wieder?)
    • Abwärtskompatibilität (Kann Modellierer v1 in Animator v3 importiert werden?)
    • Die Cloud- / Netzwerkintegration (falls vorhanden) muss jetzt für doppelt so viele Produkte aktualisiert werden.
  • Sie haben jetzt drei Verbrauchermärkte: Modellierer, Animatoren und Modellierer-Animatoren

    • Sie werden widersprüchliche Prioritäten haben
    • Sie werden widersprüchliche Unterstützungsbedürfnisse haben
    • Sie haben widersprüchliche Nutzungsstile
  • Müssen die Modeller-Animatoren zwei separate Anwendungen öffnen, um an derselben Datei zu arbeiten? Gibt es eine dritte Anwendung mit beiden Funktionen, lädt eine Anwendung die Funktionen der anderen?
  • usw...

Obwohl kleinere Codebasen auf Anwendungsebene einfacher zu warten sind, erhalten Sie kein kostenloses Mittagessen. Dies ist das gleiche Problem im Herzen von Micro-Service / Any-Modular-Architecture. Es ist kein Allheilmittel, Wartungsschwierigkeiten auf Anwendungsebene werden gegen Wartungsschwierigkeiten auf Orchestrierungsebene eingetauscht. Bei diesen Problemen handelt es sich immer noch um Probleme. Sie befinden sich nicht mehr in der Codebasis. Sie müssen entweder vermieden oder behoben werden.

Wenn das Lösen des Problems auf Orchestrierungsebene einfacher ist als das Lösen auf jeder Anwendungsebene, ist es sinnvoll, es in zwei Codebasen aufzuteilen und die Orchestrierungsprobleme zu behandeln.

Andernfalls, nein, tun Sie es einfach nicht. Sie werden besser bedient, wenn Sie die interne Modularität der Anwendung selbst verbessern. Verschieben Sie Codeabschnitte in zusammenhängende und leichter zu verwaltende Bibliotheken, für die die Anwendung als Plugin fungiert. Ein Monolith ist schließlich nur die Orchestrierungsschicht einer Bibliothekslandschaft.

Kain0_0
quelle
3

Es gab viele gute Antworten, aber da es fast einen toten Spalt gibt, werfe ich auch meinen Hut in den Ring.

Aufgrund meiner Erfahrung als Softwareentwickler habe ich festgestellt, dass dies kein einfaches Problem ist. Es hängt wirklich von der Größe , dem Maßstab und dem Zweck der Anwendung ab. Ältere Anwendungen sind aufgrund der zum Ändern erforderlichen Trägheit im Allgemeinen monolithisch, da dies lange Zeit üblich war (Maya würde sich in dieser Kategorie qualifizieren). Ich gehe davon aus, dass Sie im Allgemeinen über neuere Anwendungen sprechen.

Bei Anwendungen, bei denen es sich mehr oder weniger um Einzelanwendungen handelt, übersteigt der Aufwand, der erforderlich ist, um viele separate Teile zu warten, im Allgemeinen die Nützlichkeit der Trennung. Wenn es von einer Person gewartet werden kann, kann es wahrscheinlich monolithisch gemacht werden, ohne zu viele Probleme zu verursachen. Die Ausnahme von dieser Regel ist, wenn Sie viele verschiedene Teile (ein Frontend, ein Backend, möglicherweise einige Datenebenen dazwischen) haben, die bequem (logisch) voneinander getrennt sind.

In sehr großen Einzelanwendungen macht es meiner Erfahrung nach Sinn, dies aufzuteilen. Sie haben den Vorteil, dass Sie eine Teilmenge der Fehlerklasse reduzieren, die im Austausch gegen andere (manchmal leichter zu lösende) Fehler möglich ist. Im Allgemeinen können auch Teams von Personen isoliert arbeiten, um die Produktivität zu verbessern. Viele Anwendungen sind heutzutage jedoch ziemlich fein aufgeteilt, manchmal zu ihrem eigenen Nachteil. Ich war auch in Teams, in denen die Anwendung unnötigerweise auf so viele Microservices aufgeteilt war, dass sie viel Overhead verursachte, wenn die Dinge aufhörten, miteinander zu reden. Darüber hinaus wird es mit jeder Aufteilung schwieriger, alle Kenntnisse darüber zu haben, wie jedes Teil mit den anderen Teilen spricht. Es gibt ein Gleichgewicht, und wie Sie anhand der Antworten hier sehen können, ist die Vorgehensweise nicht sehr klar.

CL40
quelle
2
Mein erster Job als Programmierer war ein Jahrtausendwanzenprogrammierer. Die Software, an der ich arbeitete, war in Hunderte kleiner Programme aufgeteilt, die alle einen kleinen Teil der Arbeit erledigten, mit Batch-Dateien verknüpft waren und Dateien für die Kommunikation verwendeten. Es war ein großes Durcheinander, erfunden in einer Zeit, in der Computer langsam waren, wenig Speicher und Speicher teuer waren. Als ich damit arbeitete, war der Code bereits 10-15 Jahre alt. Als wir fertig waren, fragten sie mich nach meinem Rat und mein Rat war, alles auf eine neue monolithische Anwendung umzustellen. Sie taten es und ein Jahr später erhielt ich ein großes Dankeschön.
Pieter B
@PieterB Ich habe eine ähnliche Erfahrung gemacht. "Cutting Edge" -Tech ist leider in vielerlei Hinsicht ein sehr großer Frachtkult. Anstatt die beste Methode für den Job zu wählen, folgen viele Unternehmen ohne Frage dem, was ein FAANG gerade tut.
13.
und auch: Was als monolithische Anwendung herauskommt, wenn es einmal kompiliert ist, kann eine sehr modulare Anwendung sein, was den Code betrifft.
Pieter B
1

Für UI-Apps ist es unwahrscheinlich, dass die Gesamtzahl der Fehler sinkt, aber das Gleichgewicht der Fehlermischung verschiebt sich zu Problemen, die durch die Kommunikation verursacht werden.

Apropos benutzerorientierte UI-Anwendungen / Sites - Benutzer sind äußerst unpatientiert und benötigen nur eine geringe Antwortzeit. Dies führt zu Kommunikationsverzögerungen bei Fehlern. Als Ergebnis wird man die potenzielle Abnahme von Fehlern aufgrund der verringerten Komplexität einer einzelnen Komponente mit sehr schweren Fehlern und Zeitanforderungen für die prozess- / maschinenübergreifende Kommunikation handeln.

Wenn die Dateneinheiten, mit denen sich das Programm befasst, groß sind (dh Bilder), sind prozessübergreifende Verzögerungen länger und schwerer zu beseitigen - so etwas wie "Transformation auf 10-MB-Bild anwenden" bringt sofort zusätzlich + 20 MB an Festplatten- / Netzwerk-E / A ein zu 2 Konvertierung von In-Memory-Format in Serializabe-Format und zurück. Sie können wirklich nicht viel tun, um die dafür benötigte Zeit vor dem Benutzer zu verbergen.

Darüber hinaus wird jede Kommunikation und insbesondere Festplatten-E / A-Vorgänge einer Viren- / Firewall-Überprüfung unterzogen. Dies führt zwangsläufig zu einer weiteren Schicht schwer reproduzierbarer Fehler und zu noch mehr Verzögerungen.

Das Aufteilen eines monolithischen "Programms" scheint dort, wo Kommunikationsverzögerungen nicht kritisch oder bereits unvermeidbar sind

  • Parallelisierbare Massenverarbeitung von Informationen, bei der Sie kleine zusätzliche Verzögerungen eintauschen können, um die einzelnen Schritte erheblich zu verbessern (manchmal müssen Sie keine benutzerdefinierten Komponenten mehr verwenden, wenn Sie sie einmal von der Stange verwenden). Durch die geringe Stellfläche für einzelne Schritte können Sie beispielsweise mehrere billigere Maschinen anstelle einer einzigen teuren Maschine verwenden.
  • Das Aufteilen monolithischer Dienste in weniger gekoppelte Mikrodienste - das gleichzeitige Aufrufen mehrerer Dienste anstelle von einem führt höchstwahrscheinlich nicht zu zusätzlichen Verzögerungen (kann sogar die Gesamtzeit verkürzen, wenn jeder einzelne schneller ist und keine Abhängigkeiten bestehen).
  • Verschieben von Vorgängen, von denen Benutzer erwarten, dass sie lange dauern - Rendern komplizierter 3D-Szenen / -Filme, Berechnen komplexer Datenmetriken, ...
  • Alle Arten von "automatischen Vervollständigungen", "Rechtschreibprüfungen" und anderen optionalen Hilfsmitteln können und werden häufig als externe Vorschläge verwendet. Das offensichtlichste Beispiel sind die automatischen URL-Vorschläge des Browsers, bei denen Ihre Eingaben ständig an externe Dienste (Suchmaschinen) gesendet werden .

Beachten Sie, dass dies sowohl für Desktop-Apps als auch für Websites gilt. Der dem Benutzer zugewandte Teil des Programms ist in der Regel "monolithisch". Der gesamte Benutzerinteraktionscode, der an einzelne Daten gebunden ist, wird normalerweise in einem einzigen Prozess ausgeführt (das Aufteilen ist nicht ungewöhnlich) Prozesse auf Datenbasis wie eine HTML-Seite oder ein Bild, aber es ist orthogonal zu dieser Frage). Selbst für die meisten Basiswebsites mit Benutzereingaben wird auf der Clientseite eine Überprüfungslogik ausgeführt, auch wenn die Serverseite modularer wäre und die Komplexität / Codeduplizierung verringert.

Alexei Levenkov
quelle
0

Hilft [es] , Fehler zu verhindern ?

Verhindern? Nun, nein, nicht wirklich.

  • Es hilft , Fehler zu erkennen .
    Und zwar all die Fehler, von denen Sie nicht einmal wussten, dass Sie sie hatten, und die Sie erst entdeckten, als Sie versuchten, das ganze Durcheinander in kleinere Teile aufzuteilen. In gewisser Weise verhinderte dies, dass diese Bugs in der Produktion auftauchten - aber die Bugs waren bereits da.
  • Es hilft , die Auswirkungen von Fehlern zu reduzieren .
    Fehler in monolithischen Anwendungen können das gesamte System zum Absturz bringen und den Benutzer davon abhalten, überhaupt mit Ihrer Anwendung zu interagieren. Wenn Sie diese Anwendung in Komponenten aufteilen, wirken sich die meisten Fehler - von Natur aus - nur auf eine der Komponenten aus.
  • Es wird ein Szenario für neue Fehler erstellt .
    Wenn Sie die Benutzererfahrung beibehalten möchten, müssen Sie eine neue Logik für die Kommunikation all dieser Komponenten einbinden (über REST-Dienste, über Betriebssystemaufrufe, wie Sie möchten ), damit sie nahtlos vom POV des Benutzers aus interagieren können.
    Ein einfaches Beispiel: Mit Ihrer monolithischen App können Benutzer ein Modell erstellen und es animieren, ohne die App zu verlassen. Sie teilen die App in zwei Komponenten auf: Modellierung und Animation. Jetzt müssen Ihre Benutzer das Modell der Modellierungs-App in eine Datei exportieren, die Datei suchen und sie dann mit der Animations-App öffnen Modellierungs-App zum Exportieren der Datei undStarte automatisch die Animations-App und öffne die Datei. Und diese neue Logik, so einfach sie auch sein mag, kann eine Reihe von Fehlern in Bezug auf Datenserialisierung, Dateizugriff und Berechtigungen, Benutzer, die den Installationspfad der Apps ändern, usw. aufweisen.
  • Es ist die perfekte Ausrede, um dringend benötigtes Refactoring anzuwenden .
    Wenn Sie sich dazu entschließen, eine monolithische App in kleinere Komponenten aufzuteilen, verfügen Sie (hoffentlich) über viel mehr Wissen und Erfahrung über das System als beim ersten Entwurf, und dank dessen können Sie eine Reihe von Refaktoren anwenden, um den Code zu erstellen Sauberer, einfacher, effizienter, belastbarer, sicherer. Und dieses Refactoring kann in gewisser Weise dazu beitragen, Fehler zu vermeiden. Natürlich können Sie das gleiche Refactoring auch auf die monolithische App anwenden, um die gleichen Fehler zu vermeiden, aber nicht, weil es so monolithisch ist, dass Sie Angst haben, etwas in der Benutzeroberfläche zu berühren und die Geschäftslogik zu brechen. ¯ \ _ (ツ) _ / ¯

Ich würde also nicht sagen, dass Sie Fehler verhindern, indem Sie eine monolithische App in kleinere Komponenten aufteilen, aber Sie machen es in der Tat einfacher, einen Punkt zu erreichen, an dem Fehler leichter verhindert werden können.

walen
quelle