Ich genieße seit 20 Jahren die Vielfalt der Architektur und möchte meine Gedanken teilen





Zuerst wollte ich einen Kommentar zu dem Artikel " Ich habe zehn Jahre lang unter schrecklichen Architekturen in C # gelitten ... " schreiben , aber ich erkannte zwei Dinge:



  1. Es gibt zu viele Gedanken, um sie zu teilen.
  2. Für einen solchen Band ist das Kommentarformat entweder zum Schreiben oder zum Lesen unpraktisch.
  3. Ich habe Habr schon lange gelesen, manchmal kommentiere ich, aber ich habe nie Artikel geschrieben.
  4. Ich bin nicht gut in nummerierten Listen.


Haftungsausschluss: Ich kritisiere @ pnovikov oder seine Idee im Allgemeinen nicht. Der Text ist von hoher Qualität (ich fühle mich wie ein erfahrener Redakteur), ich teile einige meiner Gedanken. Es gibt viele Architekturen, aber das ist in Ordnung (ja, es klingt wie der Titel eines koreanischen Films). 



Lassen Sie uns jedoch in Ordnung gehen. Zuerst meine Meinung darüber, was Architektur beeinflusst, dann über die kontroversen Punkte im Artikel über "Architekturen reparieren". Ich werde Ihnen auch sagen, was für uns gut funktioniert - vielleicht ist es für jemanden nützlich.



Und natürlich ist alles, was hier gesagt wird, eine persönliche Meinung, die auf meinen Erfahrungen und kognitiven Vorurteilen basiert.



Über meine Meinung



Ich treffe oft architektonische Entscheidungen. Einmal groß, einmal klein. Gelegentlich habe ich mir Architektur von Grund auf neu ausgedacht. Nun, wie von Grund auf neu - sicher wurde alles vor uns erfunden, aber wir wissen nichts über etwas, also müssen wir erfinden. Und nicht aus Liebe zum Fahrradbau (sagen wir nicht nur aus Liebe zum Fahrradbau), sondern weil es für einige Aufgaben keine vorgefertigte Lösung gab, die allen Parametern entspricht.



Warum glaube ich, dass völlig unterschiedliche Architekturen das Recht haben zu existieren? Man könnte spekulieren, dass Programmieren eine Kunst ist, kein Handwerk, aber ich werde es nicht tun. Meine Meinung: einmal eine Kunst, einmal ein Handwerk. Darum geht es nicht. Hauptsache, die Aufgaben sind unterschiedlich. Und Leute. Zur Verdeutlichung sind Aufgaben Geschäftsanforderungen.



Wenn meine Aufgaben eines Tages vom selben Typ werden, werde ich jemanden schreiben oder bitten, ein neuronales Netzwerk zu schreiben (oder vielleicht reicht ein Skript), das mich ersetzt. Und ich selbst werde etwas weniger trostloses tun. Bis meine und, wie ich hoffe, Ihre persönliche Apokalypse nicht gekommen ist, lassen Sie uns darüber nachdenken, wie sich Aufgaben und andere Bedingungen auf die Vielfalt der Architekturen auswirken. TL & DR; - abwechslungsreich .



Leistung versus Skalierbarkeit



Dies ist vielleicht der richtigste Grund, die Architektur zu ändern. Es sei denn natürlich, es ist einfacher, die alte Architektur an die neuen Anforderungen anzupassen. Aber hier ist es schwierig, kurz etwas Nützliches zu erzählen.



Zeitliche Koordinierung



Nehmen wir an, die Begriffe (ich habe zweimal sichergestellt, dass ich mit einem "o" geschrieben habe) sind sehr eng. Dann haben wir keine Zeit zu wählen, geschweige denn Architektur zu entwickeln - nehmen Sie vertraute Werkzeuge und graben Sie. Aber es gibt eine Nuance - manchmal können komplexe Projekte nur dann pünktlich durchgeführt werden, wenn etwas grundlegend Neues angewendet (und vielleicht erfunden) wird. Jemand könnte sagen, dass das Einladen eines Kunden in ein Badehaus eine alte Technik ist, aber ich spreche jetzt von Architektur ...



Wenn das Timing angenehm ist - es stellt sich oft als paradox heraus -, scheint es, als könnten Sie sich etwas Neues einfallen lassen, aber warum? Zwar erliegen viele erfolgreich der Versuchung, ein weiteres brennenderes Projekt anzunehmen und die Situation auf das vorherige zu reduzieren.



In meiner Praxis führt das Timing selten zu Revolutionen in der Architektur, aber es passiert. Und das ist großartig.



Entwicklungsgeschwindigkeit und -qualität



Es passiert so - das Team (oder jemand aus dem Management) bemerkt, dass sich die Entwicklungsgeschwindigkeit verlangsamt hat oder viele Fehler über die Iteration gelaufen sind. Oft wird die "falsche Architektur" dafür verantwortlich gemacht. Manchmal - zu Recht. Häufiger - genau wie der bequemste Angeklagte (besonders wenn das Team keinen „Elternteil“ hat).



Im Prinzip kommt es in einigen Fällen auf den Zeitfaktor an. Und in anderen - zur Wartbarkeit, dazu später mehr.



Wartbarkeit



Ein mehrdeutiges Thema. Weil alles sehr subjektiv ist und viel davon abhängt, was. Zum Beispiel - aus dem Team, der Programmiersprache, den Prozessen im Unternehmen, der Anzahl der Anpassungen für verschiedene Kunden. Lassen Sie uns über den letzten Faktor sprechen, er scheint mir der interessanteste zu sein.



Jetzt haben Sie ein benutzerdefiniertes Projekt erstellt. Erfolgreich, pünktlich und im Rahmen des Budgets ist der Kunde mit allem zufrieden. Ich hatte das auch. Jetzt schaust du dir an, was du benutzt hast und denkst - also hier ist es - eine Goldmine! Wir nutzen jetzt all diese Entwicklungen, wir werden schnell ein B2B-Produkt erstellen und ... Zunächst ist alles in Ordnung. Das Produkt wurde hergestellt, ein paar Mal verkauft. Stellte mehr Anbieter und Entwickler ein ("mehr Gold benötigt"). Kunden sind zufrieden, sie bezahlen für Support, neue Verkäufe entstehen ...



Und dann sagt einer der Kunden mit menschlicher Stimme: "Ich hätte das ganz anders gemacht - wie viel kann es kosten?" Nun, denken Sie nur - kleben Sie ein paar if'chiks mit anderem Code (sagen wir, es war keine Zeit, DI zu schrauben), was kann passieren?



Und beim ersten Mal wird wirklich nichts Schlimmes passieren. Ich würde in einer solchen Situation nicht einmal raten, etwas Besonderes einzäunen. Eine vorzeitige Komplikation der Architektur entspricht einer vorzeitigen Optimierung. Aber wenn es das zweite und dritte Mal passiert, ist dies ein Grund, sich an Dinge wie DI, das "Strategie" -Muster, Feature Toggle und andere wie diese zu erinnern. Und für eine Weile wird es helfen.



Und dann kommt der Tag, an dem Sie sich die Projekteinstellungen (nur einige hundert Optionen) für einen bestimmten Prüfstand ansehen ... Denken Sie daran, wie Sie die Anzahl der Kombinationen zählen und überlegen, wie dies, Ihre Mutter, getestet werden kann. Es ist klar, dass dies in einer idealen Welt einfach ist - schließlich ist jedes Feature so konzipiert und implementiert, dass es das andere in keiner Weise beeinflusst, und wenn dies der Fall ist, ist dies alles vorgesehen, und unsere Entwickler haben sich im Allgemeinen nie geirrt.



Natürlich habe ich die Farben verdickt - Sie können einige Funktionen hervorheben, die von echten Kunden verwendet werden, mehr Tests schreiben (wie und welche sind ein Thema für ein anderes Gespräch) und die Aufgabe ein wenig vereinfachen. Aber denken Sie darüber nach - jede Hauptversion muss für alle Kunden getestet werden. Ich möchte Sie daran erinnern, dass dies kein B2C ist, bei dem Sie sagen können, dass Sie eine Funktion für 5% der Benutzer einführen und Feedback sammeln möchten. Für B2B können Sie Feedback von Gerichten sammeln ...



Lösungen? Teilen Sie das Produkt beispielsweise in Module mit einem separaten Lebenszyklus ein (nicht zu vergessen, ihre Interaktion zu testen). Dies reduziert die Komplexität der Wartung, erschwert jedoch die Entwicklung. Und jetzt spreche ich nicht über das fruchtbare Thema für Holivars „Monolith vs. microservices "- in einem monolithen kann man auch ähnliche arrangieren (obwohl meiner meinung nach komplizierter).



Und wohlgemerkt, aus pragmatischer Sicht hatten wir in jeder Phase eine gute Architektur.



Und wofür ist das alles?



Ich möchte Sie (und mich) nicht ermüden, indem ich andere Gründe für Änderungen in der Architektur aufführe. Lassen Sie uns nun zustimmen, dass sich Architekturen im Laufe der Zeit abhängig von vielen Faktoren ändern. Das heißt: Die ideale Architektur, die "gut, alle Probleme" löst, existiert nicht.



Wenn ich Sie noch nicht davon überzeugt habe, schauen Sie sich die verschiedenen Programmiersprachen und Frameworks an (nur nicht im Frontend - öffnen Sie dieses Thema nicht). Wenn jemand sagt, dass dies schlecht ist, schlage ich vor, ein Gedankenexperiment durchzuführen - stellen Sie sich eine Welt vor, in der es eine bestimmte Programmiersprache gibt. Mit einer wichtigen Bedingung - Sie mögen es nicht. Zum Beispiel, weil Sie es nie benutzt haben und nie beabsichtigt haben.



Und ich gestehe, es gibt noch einen weiteren guten Grund - sich etwas Neues auszudenken, einige Parameter zu optimieren, mit Kompromissen zu spielen - es ist verdammt aufregend. Jetzt, da wir uns alle einig sind (richtig?), Sind wir uns einig, dass Vielfalt in der Architektur in Ordnung ist ...



Diskussion des Artikels über "Fixing Architectures"



Was ist mit IoC?



Über IoC stimme ich zu, dass Fußtücher einen Platz in der Armee haben und Module universell gut sind. Aber hier ist der Rest ...



Wenn Sie natürlich einigen Apologeten zuhören, um "sauberen Code" zu erhalten, können Sie einen Berg von Diensten codieren, von denen jeder durchschnittlich eineinhalb Methoden und eine Methode - zweieinhalb Zeilen - enthält. Aber warum? Ehrlich gesagt, möchten Sie auf jeden Fall den Prinzipien folgen, die Ihnen helfen, mit unwahrscheinlichen Problemen in ferner Zukunft fertig zu werden, aber selbst einfache Logik über Dutzende von Dateien verteilen? Oder reicht es Ihnen, jetzt anständig funktionierenden Code zu schreiben? 



Übrigens arbeite ich jetzt an einem Modul, das definitiv in verschiedenen Produkten verwendet wird und höchstwahrscheinlich aktiv "abstimmt". Also versuche ich dort nicht "flach" zu sein. Zahlt sich nicht aus. Obwohl ich darin die einzige Implementierung von Schnittstellen öfter als gewöhnlich verwende.



Wenn wir also Module haben und nicht "kleinlich" sind, woher kommen dann IoC-Leistungsprobleme oder nicht unterstützte "IoC-Konfigurationsfußstoffe"? Ich bin nicht rübergekommen. 



Ich werde jedoch unsere Arbeitsbedingungen klarstellen:



  • Unsere Module sind nicht diejenigen, die "von fast jedem IoC-Framework bereitgestellt werden", sondern "direkte Module", die über die API remote miteinander kommunizieren (manchmal können Sie sie aus Leistungsgründen in einem Prozess zusammenfassen, aber das Arbeitsschema ändert sich nicht).

  • IoC wird so einfach wie möglich und so einfach wie möglich verwendet - Abhängigkeiten bleiben in den Parametern des Konstruktors stecken.

  • Ja, wir haben jetzt eine Microservice-Architektur, aber hier versuchen wir, nicht zu klein zu sein. 



Tipp: Schnittstellen können in derselben Datei wie die Klasse gespeichert werden - dies ist praktisch (wenn Sie natürlich eine normale IDE und keinen Editor verwenden). Ich mache Ausnahmen, wenn Schnittstellen (oder Kommentare zu ihnen) wachsen. Aber das ist natürlich alles Geschmack.



Was ist los mit dem ORM und warum direkter Datenbankzugriff? 



Ja, ich selbst werde sagen, was falsch ist - viele von ihnen sind zu weit von SQL entfernt. Aber nicht alles. Suchen Sie also eines, das zu Ihnen passt, anstatt „O / RM zu ertragen, 3000 Objekte zu löschen“ oder ein anderes zu finden.



Tipp: Versuchen Sie es mit LINQ to DB . Es ist gut ausbalanciert, es gibt Update / Delete-Methoden für mehrere Zeilen. Sei einfach vorsichtig - süchtig. Ja, es gibt keine EF-Funktionen und ein etwas anderes Konzept, aber ich mochte EF viel mehr.



Übrigens ist es schön, dass dies eine Entwicklung unserer Landsleute ist. Igor Tkachev - Respekt (ich habe ihn bei Habré nicht gefunden).



UPD: RouRIn den Kommentaren wurde darauf hingewiesen, dass es eine Erweiterung für EF Core gibt , die Massenoperationen ermöglicht. Ich werde LINQ sowieso nicht an DB abgeben, weil es gut ist .



Was ist los mit den Datenbanktests?



Ja, sie sind langsamer als Daten im Speicher. Ist es tödlich? Nein natürlich nicht. Wie kann man dieses Problem lösen? Hier sind zwei Rezepte, die am besten gleichzeitig verwendet werden.



Rezept Nummer 1. Sie nehmen einen coolen Entwickler, der es liebt, alle möglichen coolen Dinge zu tun, und besprechen mit ihm, wie Sie dieses Problem wunderbar lösen können. Ich habe Glück, weilMachtlöste das Problem schneller als es schien (ich erinnere mich nicht einmal, ob wir darüber gesprochen haben oder nicht). Wie? Es wurde (anscheinend an einem Tag) eine Testfabrik für ORM erstellt, die die Hauptuntergruppe von Vorgängen durch den Zugriff auf Arrays ersetzt.



Perfekt für einfache Unit-Tests. Eine alternative Option ist die Verwendung von SQLite oder ähnlichem anstelle von "großen" Datenbanken.

Kommentar von Macht: . -, , ORM, , SQL . -, , , , , .. . .



Rezept Nummer 2. Ich bevorzuge es, Geschäftsszenarien in realen Datenbanken zu testen. Wenn das Projekt die Unterstützung mehrerer DBMS deklariert, werden Tests für mehrere DBMS durchgeführt. Warum? Es ist einfach. In der Anweisung "Ich möchte den Datenbankserver nicht testen" werden leider Konzepte ersetzt. Ich teste nicht, ob Join funktioniert oder von bestellt.



Ich teste meinen Code mit DB. Und da ich weiß, dass selbst verschiedene Versionen desselben DBMS bei denselben Abfragen unterschiedliche Ergebnisse liefern können ( Beweis ), möchte ich die Hauptszenarien genau auf den Datenbanken überprüfen, mit denen dieser Code funktioniert.



Normalerweise sehen solche Tests für mich so aus:



  • Für eine Gruppe von Tests (Fixture) wird sie mithilfe der Datenbankmetadaten von Grund auf neu generiert. Bei Bedarf werden die erforderlichen Nachschlagewerke ausgefüllt.

  • Jedes Skript fügt die erforderlichen Daten während der Passage selbst hinzu (Benutzer tun dies auch). Nicht so bei Leistungstests, aber das ist eine ganz andere Geschichte ...

  • Nach jedem Test werden überschüssige Daten (außer Nachschlagewerke) gelöscht.



Hinweis: Wenn solche Tests für längere Zeit objektiv für Sie durchgeführt werden (und nicht, weil es Zeit ist, Abfragen an die Datenbank zu optimieren), erstellen Sie einen Build, der sie seltener ausführt (Testkategorien oder ein separates Projekt, um zu helfen). Andernfalls möchten Entwickler den Rest nicht selbst ausführen - schnelle Tests.



Transaktion und E-Mail



Ich werde nur der Geschichte hinzufügen, dass "die Transaktion in der Datenbank aus irgendeinem Grund gefallen ist und die E-Mail weg war". Und was für ein Spaß es sein wird, wenn eine Transaktion auf einen nicht verfügbaren Mailserver wartet, das gesamte System aufgrund einer Benachrichtigung absteckt, die der Benutzer dann ohne Lesen an den Warenkorb sendet ...



Richtig, ich habe immer geglaubt, dass nur Juni in freier Wildbahn Briefe in einer Transaktion sendet in Ermangelung einer Überprüfung. In unserem Team haben sie für einen solchen Kandelaber geschlagen (bisher virtuell).



Ergebnis



Wenn @ pnovikov keine Pläne hat, die Welt mit Hilfe der einzig wahren Ideologie der Architektur zu übernehmen, habe ich im Allgemeinen keine anderen erwähnenswerten Unterschiede gefunden. Für einige Aufgaben sind natürlich die von ihm geäußerten Grundsätze geeignet. Ich werde gerne die folgenden Artikel und Kommentare lesen, vielleicht finde ich einige nützliche Ideen für mich.



Ich werde den vorgeschlagenen Rahmen kaum nutzen. Der Grund ist einfach - wir haben bereits eine ideale Architektur ...



PS Wenn Sie etwas in den Kommentaren besprechen möchten, werde ich gerne daran teilnehmen.



All Articles