Ich hatte heute eine hitzige Diskussion über unsere MVC-Anwendung. Wir haben eine in MVC ( ASP.NET ) geschriebene Website, die normalerweise dem Muster folgt, in der Ansicht etwas zu tun -> Controller antippen -> Controller erstellt ein Modell (ruft einen Manager auf, der die Daten abruft, erstellt das Modell in der Controller-Methode selbst) -> Modell geht zur Ansicht -> Spülen & Wiederholen.
Er sagte, unser Code sei zu eng miteinander verbunden. Wenn wir beispielsweise auch eine Desktop-Anwendung benötigen, können wir unseren vorhandenen Code nicht verwenden.
Die Lösung und die beste Vorgehensweise, die er sagte, besteht darin, eine API zu erstellen und dann Ihre Website über Ihre API zu erstellen und dann eine Desktop-Anwendung, eine mobile App usw. zu erstellen. Dies ist sehr einfach.
Dies scheint mir aus verschiedenen Gründen eine schlechte Idee zu sein.
Wie auch immer, ich kann anscheinend nichts durch googeln finden, was über diese Praxis sprechen könnte. Hat jemand irgendwelche Informationen über Vor- und Nachteile, warum sollten Sie, warum sollten Sie nicht oder weiterlesen?
Einige Gründe, die ich für eine schlechte Idee halte:
Es ist viel zu abstrakt, um Ihr Backend über eine API auszuführen. Du versuchst es zu flexibel zu machen, was es zu einem unüberschaubaren Durcheinander macht.
Alles, was in MVC eingebaut ist, scheint nutzlos zu sein, wie Rollen und Authentifizierung. Zum Beispiel [Autorisieren] Attribute und Sicherheit; Sie müssen Ihre eigenen rollen.
Für alle Ihre API-Aufrufe sind angehängte Sicherheitsinformationen erforderlich, und Sie müssen ein Tokensystem entwickeln und so weiter.
Sie müssen vollständige API-Aufrufe für jede einzelne Funktion schreiben, die Ihr Programm jemals ausführen wird. Nahezu jede Methode, die Sie implementieren möchten, muss über eine API ausgeführt werden. Ein Get / Update / Delete für jeden Benutzer sowie eine Variante für jede andere Operation, z. B. das Aktualisieren des Benutzernamens, das Hinzufügen eines Benutzers zu einer Gruppe usw. usw., und jeder einzelne wäre ein eigener API-Aufruf.
Sie verlieren alle Arten von Werkzeugen wie Schnittstellen und abstrakte Klassen, wenn es um APIs geht. Sachen wie WCF unterstützen Schnittstellen nur sehr spärlich.
Sie haben eine Methode, die einen Benutzer erstellt oder eine Aufgabe ausführt. Wenn Sie 50 Benutzer erstellen möchten, können Sie es einfach 50 Mal aufrufen. Wenn Sie sich für diese Methode als API entscheiden, kann Ihr lokaler Webserver Named-Pipes-Verbindungen herstellen, und das ist kein Problem - Ihr Desktop-Client kann auch darauf zugreifen, aber bei der Erstellung eines Massenbenutzers wird die API plötzlich 50-mal über das Internet gehämmert, was nicht der Fall ist nicht gut Sie müssen also eine Massenmethode erstellen, aber eigentlich erstellen Sie sie nur für Desktop-Clients. Auf diese Weise müssen Sie am Ende a) Ihre API basierend auf der Integration ändern und können nicht einfach direkt in sie integrieren. B) Sie müssen viel mehr Arbeit leisten, um eine zusätzliche Funktion zu erstellen.
YAGNI . Wenn Sie nicht speziell vorhaben, zwei identisch funktionierende Anwendungen, beispielsweise eine Web- und eine Windows-Anwendung, zu schreiben, ist dies eine enorme Menge zusätzlicher Entwicklungsarbeit.
Das Debuggen ist viel schwieriger, wenn Sie nicht durchgängig arbeiten können.
Viele unabhängige Vorgänge, die viel Hin und Her erfordern, z. B. Code, der möglicherweise den aktuellen Benutzer abruft, überprüft, ob der Benutzer die Administratorrolle innehat, die Firma abruft, der der Benutzer angehört, eine Liste anderer Mitglieder abruft und alle sendet eine E-Mail. Das würde eine Menge API-Aufrufe erfordern oder das Schreiben einer maßgeschneiderten Methode für die gewünschte Aufgabe, wobei der einzige Vorteil dieser maßgeschneiderten Methode die Geschwindigkeit und der Nachteil wäre, dass sie unflexibel wäre.
Wahrscheinlich noch ein paar Gründe, die mir auf den Kopf gefallen sind.
Mir kommt es nur so vor, als würde es sich nicht lohnen, wenn Sie wirklich zwei identische Anwendungen benötigen. Ich habe noch nie eine ASP.NET-Anwendung gesehen, die so erstellt wurde. Sie müssten zwei separate Anwendungen (die API und Ihren Code) schreiben und beide auch versionieren (wenn Ihre Benutzerseite ein neues Feld erhält, müssen Sie d müssen die API und Ihren konsumierenden Code gleichzeitig aktualisieren, um keine negativen Auswirkungen zu haben, oder viel zusätzliche Arbeit in die Aufrechterhaltung der Robustheit investieren).
Edit: Einige großartige Antworten, die wirklich anfangen, eine gute Vorstellung davon zu bekommen, was dies alles jetzt bedeutet. Um meine Frage zu erweitern: Wie würden Sie eine MVC-App strukturieren, um dieser API-Struktur zu folgen?
Sie haben beispielsweise eine Website, auf der Informationen zu einem Benutzer angezeigt werden. Unter MVC haben Sie:
View - (CS) HTML-Seite, auf der ein UserViewModel-Controller angezeigt wird - Ruft GetUser () auf und erstellt ein UserViewModel, das an die View Manager-Klasse (Art Ihrer API) mit einer GetUser-Methode übergeben wird.
Der Controller führt GetUser () aus, aber Sie möchten auch eine Desktop-App. Dies bedeutet, dass Ihr GetUser über eine API verfügbar gemacht werden muss. Möglicherweise möchten Sie eine TCP-Verbindung, entweder WCF oder Remoting. Sie möchten auch eine mobile App, die RESTful ist, da dauerhafte Verbindungen schuppig sind.
Würden Sie dann für jeden eine API schreiben, einen WCF-Webdienst, der über eine Methode GetUser () verfügt und der nur den Code enthält return new UserManager().GetUser()
? Und eine MVC 4 Web-API-Methode, die das Gleiche tut? Rufen Sie GetUser weiterhin direkt in Ihrer MVC-Controller-Methode auf?
Oder würden Sie die Lösung auswählen, die für alle drei geeignet ist (Web-API-REST-Service) und alles darauf aufbauen, sodass alle drei Apps API-Aufrufe (die MVC-Aufrufe, an den lokalen Computer) ausführen.
Und ist das nur ein theoretisch perfektes Szenario? Ich sehe große Gemeinkosten bei der Entwicklung auf diese Weise, insbesondere wenn Sie sich auf eine Weise entwickeln müssen, die es Ihnen ermöglicht, Operationen auf eine REST-artige Weise durchzuführen. Ich denke, ein Teil davon wurde in den Antworten behandelt.
Edit 2: Nachdem ich mehr gelesen habe, habe ich unten einen Kommentar eingefügt, der meiner Meinung nach das erklären könnte. Die Frage ist ein Trick, denke ich. Wenn Sie Ihr Back-End als API schreiben, war ich verwirrt, dass es einen einzigen Webservice geben sollte, den alle Aufrufe (MVC-App, Desktop-App, mobile App) erledigen.
Ich bin zu dem Schluss gekommen, dass Sie wirklich sicherstellen sollten, dass Ihre Geschäftslogikschicht korrekt entkoppelt ist. Wenn ich mir meinen Code anschaue, mache ich das bereits - der Controller ruft GetUser()
einen Manager auf und erstellt daraus ein Ansichtsmodell, um es mit einer Ansicht zu rendern. Die Geschäftslogikschicht ist also eine API. Wenn Sie es jedoch von einer Desktop-App aus aufrufen möchten, müssen Sie so etwas wie einen WCF-Dienst schreiben, um das Aufrufen zu erleichtern. Es reicht schon aus, eine WCF-Methode aufzurufen GetUser()
, die den Code enthält return MyBusinessLayer.GetUser()
. Die API ist also die Geschäftslogik, und WCF- / Web-APIs usw. sind nur ein bisschen Code, damit externe Anwendungen sie aufrufen können.
Es ist also mit einem gewissen Aufwand verbunden, dass Sie Ihre Geschäftslogikschicht je nach Bedarf in verschiedene APIs einbinden müssen und für jeden Vorgang, den Ihre anderen Apps ausführen sollen, eine API-Methode schreiben müssen Suchen Sie nach einer Möglichkeit zur Authentifizierung, aber im Großen und Ganzen ist es das Gleiche. Stecken Sie Ihre Geschäftslogik in ein separates Projekt (Klassenbibliothek), und Sie werden wahrscheinlich kein Problem haben!
Hoffentlich ist diese Interpretation richtig. Vielen Dank für alle Diskussionen / Kommentare, die es generiert hat.
quelle
Antworten:
Ja du solltest.
Dies macht Ihr Back-End nicht nur wiederverwendbar, sondern sorgt auch für mehr Sicherheit und besseres Design. Wenn Sie Ihr Backend als Teil eines einzelnen Systems schreiben, erstellen Sie ein monolithisches Design, das sich nie leicht erweitern, ersetzen oder verbessern lässt.
Ein Bereich, in dem dies derzeit beliebt ist, ist Microservices . Wo das Backend in viele kleine (oder sogar große) Dienste aufgeteilt ist, die jeweils eine API bereitstellen, die das Client-System verwendet. Wenn Sie sich vorstellen, viele Datenquellen von Drittanbietern in Ihrer Anwendung zu verwenden, stellen Sie fest, dass Sie dies möglicherweise bereits tun.
Ein weiterer Vorteil ist, dass der Aufbau und die Wartung jedes Dienstes an ein anderes Team übergeben werden können. Sie können Funktionen hinzufügen, die kein anderes Team betreffen, das Produkte herstellt. Erst wenn sie fertig sind und ihren Service freigeben, können sie Ihrem Produkt Funktionen hinzufügen, um sie zu nutzen. Dies kann die Entwicklung viel reibungsloser gestalten (obwohl insgesamt möglicherweise langsamer, würden Sie tendenziell eine bessere Qualität und Verständlichkeit erzielen).
Bearbeiten: OK, ich sehe dein Problem. Sie betrachten die API als eine Remote-Bibliothek. Es ist nicht. Stellen Sie sich den Dienst eher als Datenbereitstellungsdienst vor. Sie rufen den Service auf, um Daten abzurufen und dann Vorgänge für diese Daten lokal auszuführen. Um festzustellen, ob ein Benutzer angemeldet ist, rufen Sie "
GetUser
" auf und sehen sich beispielsweise den'logged on'
Wert an. ( YMMV mit diesem Beispiel natürlich).Ihr Beispiel für die Erstellung von Massenbenutzern ist nur eine Entschuldigung - hier gibt es keinen Unterschied, was Sie in einem monolithischen System hätten tun können, kann immer noch in einer Dienstarchitektur erfolgen (z. B. hätten Sie eine Reihe von Benutzern an die Massenerstellung übergeben oder ein einziges zu erstellen. Sie können immer noch genau das gleiche mit Diensten tun).
MVC basiert bereits auf dem Konzept der isolierten Dienste, nur die MVC-Frameworks bündeln sie in einem einzigen Projekt. Das bedeutet nicht, dass Sie nur die gebündelten Helfer verlieren, die Ihnen Ihr Framework bietet. Verwenden Sie ein anderes Framework und Sie müssen andere Helfer verwenden. Oder rollen Sie in diesem Fall Ihre eigenen (oder fügen Sie sie direkt über eine Bibliothek hinzu).
Das Debuggen ist ebenfalls einfach - Sie können die API isoliert gründlich testen, sodass Sie kein Debugging durchführen müssen (und Sie können End-to-End-Debugging durchführen, Visual Studio kann eine Verbindung zu mehreren Prozessen gleichzeitig herstellen).
Dinge wie zusätzliche Arbeit beim Implementieren von Sicherheit sind eine gute Sache. Wenn Sie derzeit den gesamten Code in Ihre Website bündeln und ein Hacker Zugriff darauf erhält, erhält er auch Zugriff auf alles, einschließlich der Datenbank. Wenn Sie es in eine API aufteilen, kann der Hacker sehr wenig mit Ihrem Code anfangen, es sei denn, er hackt auch die API-Ebene - was für ihn unglaublich schwierig sein wird Sie haben das Betriebssystem oder den Webserver gehackt und er hatte eine direkte Verbindung zur Datenbank, "
select * from users
" wo sie problemlos laufen konnten .Ich werde sagen, dass ich viele Websites (und Client-Server-Anwendungen) gesehen habe, die so geschrieben wurden. Als ich in der Finanzdienstleistungsbranche gearbeitet habe, hat noch nie jemand eine Website als All-in-One-Lösung geschrieben, zum Teil, weil dies ein zu großes Sicherheitsrisiko darstellt, und zum Teil, weil die Entwicklung bei der Verarbeitung stabiler (dh älterer) Back-End-Daten auf GUIs beruht systeme. Es ist einfach, das DP-System als Website mit einer Architektur im Servicestil verfügbar zu machen.
2. Änderung: Einige Links zum Thema (für das OP):
Beachten Sie, dass der Webserver im Kontext einer Website als Präsentationsebene betrachtet werden sollte, da der Client die anderen Ebenen aufruft und auch die Benutzeroberflächenansichten erstellt, die zum Rendern an den Browser gesendet werden. Es ist ein großes Thema, und es gibt viele Möglichkeiten, Ihre Anwendung zu entwerfen - datenzentriert oder domänenzentriert (ich halte domänenzentriert normalerweise für "reiner", aber für YMMV ), aber alles hängt davon ab, dass eine logische Ebene dazwischen festgelegt wird Ihr Kunde und Ihre DB. Es ist ein wenig wie MVC, wenn Sie die mittlere, API, Ebene als äquivalent zu Ihrem Modell ansehen. Nur das Modell ist kein einfacher Wrapper für die Datenbank, es ist umfangreicher und kann viel mehr (z. B. Aggregieren von Daten aus 2 Datenquellen, Posten) -Verarbeiten Sie die Daten, um sie an die API anzupassen, zwischenspeichern Sie die Daten usw.):
quelle
Sie können unmöglich vermeiden, eine API zu erstellen . Selbst wenn Sie "nur eine Website" erstellen, müssen die Daten dennoch irgendwie von Ihrem Backend abgerufen werden. Wie auch immer Sie sich dafür entscheiden, das ist Ihre De-facto- API.
Wenn man das weiß, ist die eigentliche Frage nicht, ob man eine API erstellt, sondern wie man sie erstellt . Sie können es on-the-fly als tun Ad - hoc - Sache -und tatsächlich sind viele Websites gebaut genau diese Weg- oder Sie können es entwerfen sorgfältig in anderen Kontexten nutzbar zu sein. In diesem Zusammenhang wird ziemlich deutlich, dass Ihr Kollege Recht hat: Sie sollten zuerst die API ausführen und dann Ihre Site darauf aufbauen.
Dennoch bringt dies einige Bedenken mit sich, wie Sie darauf hinweisen. Um sie anzusprechen:
Das hängt davon ab, wie Sie es tun. Wie George Pólya in seinem ausgezeichneten Text " How to Solve It " ( Wie man es löst) ausführt , ist das allgemeinere Problem häufig leichter zu lösen. Dies nennt man das Paradoxon des Erfinders . Bei der Programmierung funktioniert dies häufig durch Trennung von Interessen: Ihr Backend muss sich nicht mehr mit dem Format der Daten befassen, die es ein- und auslagert, und daher kann sein Code viel einfacher sein. Ihre Datenparser und -renderer müssen sich nicht mehr darum kümmern, was mit den von ihnen erstellten Daten geschieht, und können daher auch einfacher sein. Alles funktioniert, indem der Code in besser verwaltbare Teile zerlegt wird.
Ich gebe zu, dass es mir extrem schwer fällt, mit Leuten zu sympathisieren, die sich weigern, ihre Werkzeuge zu lernen. Nur weil Sie ihre Verwendung nicht verstehen, bedeutet dies nicht, dass sie unbrauchbar sind, und es bedeutet sicherlich nicht, dass Sie Ihre eigenen würfeln sollten . Ganz im Gegenteil; Sie sollten Ihre eigenen Werkzeuge erst rollen, wenn Sie die Alternativen verstanden haben, damit Sie sicher sein können, dass Sie dieselben Probleme wie bei ihnen angehen (auch wenn dies nur auf Ihre eigene Art und Weise geschieht).
Denken Sie an Linus Torvalds , der am bekanntesten für das Schreiben von Linux ist , aber auch Git geschrieben hat : Jetzt eines der beliebtesten Versionskontrollsysteme der Welt. Einer der treibenden Faktoren in seinem Design war eine tiefe Opposition gegen Subversion (ein weiteres äußerst populäres VCS , das zu der Zeit, als Git geschrieben wurde, wohl das populärste); Er beschloss, alles zu nehmen, was Subversion konnte, und in welchem Umfang es möglich war, diese Probleme anders zu lösen. Dazu musste er selbst Experte für Subversion werden, um dieselben Problembereiche zu verstehen und einen anderen Ansatz zu verfolgen.
Beim Erlernen Ihrer Werkzeuge stellen Sie möglicherweise fest, dass diese so sind, wie sie sind, und nicht ersetzt werden müssen.
Ja. So soll es sein.
Nicht unbedingt. Hier kommen Architekturen wie REST ins Spiel. Sie identifizieren die Ressourcen, mit denen Ihre Anwendung arbeitet, und die Vorgänge, die für diese Ressourcen sinnvoll sind, und implementieren diese dann, ohne sich um die anderen Sorgen zu machen .
Im Gegenteil, Schnittstellen werden bei der Verwendung einer API viel wichtiger, nicht weniger . Sie kommen in den Darstellungen heraus, in denen Sie sie rendern. Die meisten Leute geben heutzutage ein JSON- basiertes Format dafür an, aber Sie können jedes gewünschte Format verwenden, solange Sie es gut spezifizieren. Sie rendern die Ausgabe Ihrer Aufrufe in diesem Format auf dem Backend und analysieren sie auf dem Frontend nach Belieben (wahrscheinlich dieselbe Art von Objekt). Der Aufwand ist gering und der Flexibilitätsgewinn enorm.
Das Erstellen einer Massenversion einer vorhandenen Methode würde ich kaum als "viel mehr Arbeit" bezeichnen. Wenn Sie sich nicht um Dinge wie Atomizität sorgen, kann die Bulk-Methode nicht viel mehr als ein sehr dünnes Frontend für das Original sein.
Nein, YANI (Du brauchst es schon). Ich habe das wie oben umrissen. Die Frage ist nur, wie viel Designarbeit in sie gesteckt werden muss.
Warum würden Sie nicht in der Lage sein, durch End-to-End zu gehen?
Um es auf den Punkt zu bringen: Wenn Sie die Daten in einem leicht zu erkennenden Format untersuchen können, bei dem die gesamte Bildschirmgröße herausgeschnitten wird, wird das Debuggen in der Regel einfacher und nicht schwieriger.
REST löst dieses Problem, indem es an vollständigen Objekten ( Ressourcen , um die Begriffe der REST-Theorie zu verwenden) und nicht an den einzelnen Eigenschaften von Objekten arbeitet . Um den Namen eines Benutzers zu aktualisieren, erhalten Sie das Benutzerobjekt, ändern seinen Namen und setzen den Benutzer zurück. Sie können andere Änderungen gleichzeitig mit der Änderung des Benutzernamens vornehmen. Das allgemeinere Problem lässt sich leichter lösen, da Sie alle diese Einzelaufrufe für die Aktualisierung einzelner Eigenschaften eines Objekts eliminieren können: Laden Sie es einfach und speichern Sie es.
In gewisser Hinsicht ist dies nicht anders als RISC- Architekturen auf der Hardwareseite. Einer der Hauptunterschiede zwischen RISC und CISC (seinem Vorgänger) besteht darin, dass CISC-Architekturen in der Regel viele Befehle enthalten, die direkt auf den Speicher angewendet werden, während RISC-Architekturen in der Regel hauptsächlich in Registern ausgeführt werden: In einer reinen RISC-Architektur sind die einzigen Operationen auf den Speicher LOAD (etwas aus dem Speicher in ein Register kopieren) und STORE (einen Wert aus einem Register nehmen und in den Speicher stellen).
Sie würden denken, dass dies bedeuten würde, dass viel mehr Fahrten von den Registern in den Speicher ausgeführt werden, was die Maschine verlangsamen würde. In der Praxis passiert jedoch oft das Gegenteil: Der Prozessor (Client) erledigt mehr Arbeit zwischen den Speicherausflügen (Server) , und hier kommt die Beschleunigung her.
Lange Rede kurzer Sinn: Ihr Kollege hat Recht. Dies ist der richtige Weg. Im Gegenzug für ein wenig Vorarbeit wird der Code für Ihre Website dramatisch vereinfacht und eine bessere Integration mit anderen Websites und Apps ermöglicht. Das ist einen Preis wert.
Weitere Lektüre:
quelle
Ich weiß, dass Microservices derzeit im Trend liegen, aber sie sind es nicht immer wert. Ja, lose gekoppelter Code ist das Ziel. Aber es sollte nicht zu Lasten eines schmerzhafteren Entwicklungszyklus gehen.
Ein guter Mittelweg wäre, ein separates Datenprojekt in Ihrer Lösung zu erstellen. Das Datenprojekt wäre eine .NET-Klassenbibliothek. Ihr ASP.NET MVC-Projekt fügt dann einen Verweis auf die Datenbibliothek hinzu, und alle Modelle werden aus dem Datenprojekt abgerufen. Dann, als die Zeit gekommen war, eine Desktop- oder mobile App zu erstellen, konnten Sie auf denselben Code verweisen. Es handelt sich also möglicherweise nicht um eine offizielle API, sondern um eine solche. Wenn Sie es als API zugänglich machen möchten, können Sie ein einfaches Webprojekt erstellen, das als Wrapper für das Datenprojekt fungiert.
Microsoft hat dieses Konzept beworben, das als Portable Class Libraries bezeichnet wird .
quelle
Nein, solltest du nicht . Wenn Sie nicht sofort vorhaben, alternative Frontends (wie mobile oder Desktop-Apps oder separate Webanwendungen) zu erstellen, die auf dasselbe Backend zugreifen, sollten Sie keine Webserviceschicht einführen. YAGNI .
Eine lose Kopplung ist immer wünschenswert (zusammen mit einer hohen Kohäsion), aber es ist ein Konstruktionsprinzip und bedeutet nicht, dass Sie Objekte auf verschiedenen Servern physisch trennen müssen! Und eine schlecht gestaltete Service-API kann eine enge Kopplung über Servergrenzen hinweg herstellen, sodass eine API keine lose Kopplung garantiert.
Sollte in Zukunft ein Bedarf an einer Service-API bestehen, können Sie diese jederzeit an dieser Stelle einführen. Solange Sie Ihren Code gut strukturiert halten (Datenzugriff und Geschäftslogik sind sauber von der Benutzeroberflächenlogik getrennt), wird es nicht schwieriger sein, ihn später als jetzt einzuführen. Und das resultierende Design wird viel besser sein, wenn es den tatsächlichen Anforderungen entspricht.
Hinweis: Ich gehe davon aus, dass die Frage lautet, ob Sie eine Webdienst- API erstellen sollen oder nicht. Die Frage lautet nur API, aber API kann auch nur die Schnittstelle einer Bibliothek bedeuten, und dann hat natürlich jeder Layer per Definition eine API. Das Fazit ist, dass Ihre Geschäftslogik und Datenzugriffsschichten auf Entwurfsebene sauber von der Benutzeroberflächenlogik getrennt sein sollten. Sie sollten jedoch keine Webserviceschicht einführen, wenn Sie diese nicht benötigen.
quelle
Meine Firma hat eine Anwendung, die so aufgebaut ist. Zunächst wurden wir beauftragt, ein Back-End mit API für ein Front-End zu erstellen, das von einem anderen Entwickler erstellt wurde. Als der andere Entwickler dieses Frontend nicht entwickeln konnte, wurden wir beauftragt, auch das Frontend zu erstellen. Obwohl dieser Ansatz definitiv Vorteile bietet, gibt es einen großen Nachteil: Kosten. Der anfängliche Build wird erheblich teurer und die laufende Wartung wird teurer, da mehr Code zu warten ist und auch zwei separate Systeme bereitgestellt werden. Aufgrund der zusätzlichen Kosten sollte dies immer eine Geschäftsentscheidung sein, die von den Entwicklern nicht aus einer Laune heraus getroffen wird.
Um es auf den Punkt zu bringen, ich würde schätzen, dass das oben erwähnte Projekt aufgrund dieses Ansatzes 20% mehr gekostet hat. Sie beschreiben nicht, für welche Art von Projekt Sie arbeiten, für welche Art von Unternehmen Sie arbeiten. Wenn Sie jedoch ein Start-up-Unternehmen sind, das ein Produkt aufbaut, können diese zusätzlichen Kosten den Unterschied zwischen dem Versand einiger zusätzlicher Funktionen ausmachen, die Ihr Produkt ausmachen ein Erfolg.
Ein weiterer Grund dafür, zumindest nicht allgemein, ist, dass es bei der Erstellung dieser zweiten Schnittstelle nur selten eine Eins-zu-eins-Zuordnung der Funktionalität gibt. Wenn Sie zum Beispiel eine mobile App erstellen, haben diese in der Regel weniger Funktionen. Dies bedeutet, dass einige Ihrer API-Methoden niemals wiederverwendet werden. Daher könnte ein Kompromiss mit Ihrem Kollegen darin bestehen, zwischen Ihnen die wichtigsten / kritischsten Aufrufe zu entscheiden, diese einer API hinzuzufügen und für alles andere traditionellere Methoden zu verwenden.
Ein weiterer zu berücksichtigender Punkt ist, dass Ihr Kollege angibt, dass Sie Ihren vorhandenen Code nicht wiederverwenden können. Dies ist jedoch nicht der Fall, wenn Sie eine gewisse Trennung Ihrer Geschäftslogik haben. Sie müssen lediglich einen dünnen Webdienst-Wrapper um Ihre internen APIs erstellen, was keine besonders große Aufgabe ist. Es wäre naiv zu glauben, Sie könnten eine Webserviceschicht ohnehin ohne Änderungen für ein anderes Front-End wiederverwenden.
quelle
Dies hängt von der Art der Anwendung und der Art des Marktes ab, in dem Sie tätig sind.
Es gibt Kompromisse und Vorteile, wenn Sie diesen Weg gehen. Es ist keine eindeutige Antwort, dass der eine Weg besser ist als der andere.
Ich werde aus eigener Erfahrung sprechen. Ich war derjenige, der sich 2007 für die Codebasis entschieden hat, an der ich in dieser Richtung arbeite. Diese Codebasis liegt derzeit in der Größenordnung von einer Million Codezeilen, von denen die Hälfte Server-Code ist, der sich hinter einer riesigen Menge von Web-Diensten verbirgt APIs, die andere Hälfte ist eine Flottille von Clients, Desktop-Native, Desktop-Web, Mobile, Back-End-Integrationen usw. Diese Entscheidung war nicht ohne Nachteile, aber im Nachhinein kann ich sagen, dass ich es wieder tun würde . Lassen Sie mich einige Kompromisse nennen.
Leistungen
Flexibilität. Ganz gleich, ob Sie eine mobile App erstellen müssen, um das Desktop-Erlebnis zu verbessern, oder eine Integration in das SAP-Back-End wünschen, es wird einfacher, wenn Sie bereits eine API aufrufen können. Wenn Sie genug von diesen Anforderungen erhalten, werden Sie sich organisch zu einer API weiterentwickeln. Die einzige Frage ist, ob ein Standard-Webdienst vorhanden ist oder ob es sich um eine interne API handelt, bei der die Webdienste maßgeschneidert sind.
Skalierbarkeit (des Teams). In unserem Fall haben wir viele verschiedene Gruppen von Entwicklern, die alle auf dieser API aufbauen. Wir haben sogar spezielle API-Teams, die mit den verschiedenen Gruppen sprechen, die Anforderungen zusammenfassen und daraus eine Allzweck-API erstellen. Es ist zu einem Punkt gekommen, an dem uns nicht einmal mehr gesagt wird, dass Leute Dinge auf der API aufbauen, und nicht jeder, der das tut, arbeitet für unser Unternehmen.
Sicherheit. Eine klare Trennung zwischen den unsicheren und den sicheren Teilen Ihrer Codebasis ist hilfreich, um die Sicherheit zu überdenken. Das Durcheinander von Benutzeroberfläche und Back-End-Code kann zu Verwirrung führen.
Kompromisse
Flexibilität. Sie müssen die Arbeit erledigen, um etwas "richtig" in die API zu integrieren. Es ist nicht möglich, eine DB-Abfrage schnell über den UI-Code auszuführen, um ein bestimmtes Problem zu lösen. Außerdem müssen APIs, die tatsächlich wiederverwendbar sind, so viele Anwendungsfälle berücksichtigen, dass die schnelle Lösung normalerweise die falsche Lösung ist. Die API lässt sich weniger flexibel weiterentwickeln, zumal es bereits so viel Client-Code gibt (aus diesem Grund stellen wir auf eine versionierte API um).
Anfängliche Entwicklungsgeschwindigkeit. Es ist ohne Zweifel langsamer, API-first zu entwickeln. Sie können es nur dann zurückgewinnen, wenn Sie über genügend Clients verfügen, die auf der API aufbauen. Dann stellen Sie jedoch fest, dass Sie drei verschiedene Client-Implementierungen benötigen, bevor sich Ihre API generisch genug entwickelt hat. Wir haben festgestellt, dass die meisten unserer anfänglichen API-Entwürfe falsch waren und unsere Richtlinien zum Erstellen von Webdiensten stark überarbeitet werden mussten.
rote Heringe
Sie haben einige davon erwähnt. Sie spielen in der Praxis eigentlich keine Rolle.
Abstraktion. Ihre API wird abstrakt genug, um alle Anwendungsfälle abzudecken, die Ihr Produkt bedienen muss, und nicht mehr. Auch ohne Webservices verfügen Sie entweder über eine interne API, die dies ausführt, oder über viel doppelten Code. Ich bevorzuge die Abstraktion gegenüber der Vervielfältigung.
Verlassen des serverseitigen MVC-Stacks. Heutzutage wird fast jedes System nach einer Weile eine mobile App benötigen. Wenn Sie dann Webdienste für diese mobile App erstellen, müssen Sie ohnehin herausfinden, wie Authentifizierung und Autorisierung in einem API-Kontext erfolgen. Es ist tatsächlich weniger Arbeit, wenn Sie nur eine Möglichkeit haben, dies zu tun, wie Sie es in Ihren Webdiensten tun.
Bulk-Operationen. Wird in der Regel durch Erstellen einer Bulk-API gelöst, die einen Back-End-Job startet und eine Job-ID zur Statusabfrage zurückgibt. Es ist keine so große Sache.
Debuggen. Ich stellte fest, dass es insgesamt etwas einfacher wurde, Fehler im System zu beheben. Sie können weiterhin sowohl im Front-End- als auch im Back-End-Code Haltepunkte setzen. In der Praxis ist es also nicht so schwierig, diese zu durchlaufen, und Sie erhalten die Möglichkeit, automatisierte API-Tests zu erstellen und die API für die Überwachung von Produktionssystemen zu instrumentieren.
Viele unabhängige Operationen. Das hängt davon ab, wie Sie Dinge gestalten. Wenn Sie darauf bestehen, eine reine CRUD-API zu haben, dann werden Sie unter diesem Problem leiden. Es ist jedoch eine gute Idee, einige CQRS-APIs zu erweitern, und wenn Sie sichergestellt haben, dass Sie eine interne API haben, für die die Dienste ein Front-End sind, können Sie diese interne API problemlos wiederverwenden, um Dienste für diese spezifischen zu erstellen Szenarios.
In Summe
In einem System, das in ausreichend unterschiedlichen Kontexten verwendet wird, entwickelt sich natürlich eine API, da dies der einfachste Weg ist, alle Anforderungen zu erfüllen. Aber es gibt definitiv einen Fall von YAGNI. Es gibt Kompromisse und es macht keinen Sinn, bis es Sinn macht. Der entscheidende Punkt ist, nicht dogmatisch zu sein und offen für verschiedene Ansätze in der Architektur zu sein, um den sich entwickelnden Anforderungen des Produkts gerecht zu werden.
quelle
Was Ihr Kollege beschreibt, ist eine serviceorientierte Architektur. Dies kann ein enorm skalierbarer, testbarer und vernünftiger Weg sein, Code zu schreiben, aber es hängt wirklich davon ab, was Sie machen.
SOA bietet einige bedeutende Vorteile, die ich zu nennen versuchen werde:
Skalierbarkeit
Da Ihr Back-End entkoppelt ist, wird Ihr Front-End nur zu einer Reihe von Vorlagen, sogar zu Flatfiles. Flatfiles sind enorm schnell und günstig von jedem CDN zu bedienen. Sie können minimiert und in statisches HTML vorkompiliert und dann clientseitig mit Daten gefüllt werden.
Ihre API muss konsistent bleiben, kann jedoch gegen eine schnellere Technologie ausgetauscht werden, ohne den Stack zu beschädigen, wenn Sie aus Ihrer vorhandenen Technologie herauswachsen. Sie könnten es zum Beispiel in Go neu erstellen. Sie könnten es stückweise neu erstellen und die Last auf die Server verteilen. Solange die Schnittstelle gleich bleibt, wird die Technologie abstrahiert.
Testbarkeit
MVC fängt normalerweise sauber an, aber in der Praxis konzentrieren sich Controller selten auf eine einzelne Ressource. Je mehr Dinge Ihre Controller-Methoden tun, desto weniger überprüfbar werden sie.
Eine API umgeht dieses Problem. Bei jedem API-Aufruf wird eine Ressource abgerufen und bereitgestellt. Sauber und überprüfbar.
Garantierte Trennung von Anliegen
Ihr Frontend und Backend sind vollständig geschieden. Sie können das Frontend einem anderen Entwickler oder Designer übergeben. Dies ist MVC auf eine andere Ebene gebracht. Ich bin sicher, dass Sie MVC nicht aufgeben möchten. SOA ist MVC, aber mehr noch.
Nachteile
Es gibt natürlich einige Nachteile. Ein Monolith ist oft schneller in Fahrt. Es kann sein, was Sie gewohnt sind. Es passt möglicherweise besser in Ihren Stapel. Ihre Werkzeuge sind möglicherweise für die Erstellung von Monolithen optimiert.
Keiner dieser Gründe ist meiner Meinung nach besonders gut, und Sie können eine Umrüstung in Betracht ziehen, wenn sie auf Sie zutrifft.
quelle
Hier gibt es viele gute Antworten. Ich füge nur meine Implementierungserfahrung hinzu.
So mache ich Dinge:
interface
(virtual class
), das die von mir benötigten API-Funktionen verfügbar macht / erzwingt. Bei der Implementierung werden sie die hochspezialisierten DBAL-Funktionen verwenden, um die Ergebnisse zu erzielen. Es hilft mir auch, die API auf Compilerebene zu erzwingen, sodass ich sicherstellen kann, dass in der Server + API-Implementierung alle Funktionen integriert sind.Technisch gesehen ist die API also die zweite Schicht. Sie verwenden es direkt mit der Website und setzen es über einen Server Remoteclients aus. Code wird wiederverwendet und kein wiederverwendbarer Codeabschnitt ist jemals inline. (Lebe und sterbe nach dieser Regel und alles ist großartig) Hilft bei der Wartbarkeit, beim Testen ... alles.
Sie verbinden die Website niemals mit dem Desktop / Mobile-API-Server (es sei denn, Ihre Website ist AJAX und wird unter JSON ausgeführt) . Wenn die Site jedoch dynamischen Inhalt im Markup rendert, können Sie durch Durchlaufen einer Zwischen-API Ihre Leistung steigern. Die Website muss schnell sein! Der Remoteclientzugriff kann etwas langsamer sein.
PS : Ja, die Wartung ist etwas komplexer, da mehr Räder zusammenarbeiten, aber auf lange Sicht ist es einfacher. Also, wenn Ihr Projekt für eine Weile leben soll und etwas komplex ist, haben Sie immer eine API. Es ist auch viel einfacher, jede Schicht für sich zu testen.
quelle
Der Streitpunkt ist nicht, ob Sie eine API verwenden sollten, sondern was eine "API" eigentlich ist. Die einzige Alternative zur Verwendung einer entworfenen API besteht in der Verwendung einer API, bei der es sich um eine zufällige Codeverwirrung handelt. Sie schreiben, dass eine API die Dinge "zu flexibel" macht, was wiederum die Dinge unhandlich macht. Dies deutet auf ein vollständiges und gründliches Missverständnis der API hin. Wenn dieses Missverständnis nicht zwischen Ihnen und Ihrem Kollegen geteilt wird, haben Sie viel Zeit verschwendet, indem Sie sich über ganz andere Dinge gestritten haben.
Wenn Sie keine genau definierte API verwenden, können Sie tun, was Sie wollen. Per Definition ist dies die flexibelste Option. Auch per Definition ist "Mach was du willst" immer noch eine API. Die einzige Aufgabe einer API besteht darin, die Flexibilität zu beseitigen. Durch das Entfernen der Flexibilität ermutigt eine gute API einen Benutzer, ähnliche Dinge auf ähnliche Weise zu tun.
Natürlich kann eine schlechte API entweder zu viel oder zu wenig Flexibilität bieten oder sogar beides gleichzeitig. Eine wirklich schlecht gestaltete API kann ein Projekt sogar noch schneller beenden als der Ansatz "Alles geht". Es empfiehlt sich jedoch, nur kompetente Programmierer zu haben, die die API zusammen mit Ihrer Anwendung entwickeln und weiterentwickeln.
Beispiel
Die Anzahl der API-Aufrufe, die dies für eine anständige API erfordern würde, wäre wahrscheinlich 1. Ja, es ist unflexibel, aber warum sollte es flexibel sein?
quelle
Nun, tust du? Wenn nicht, dann ist das eine ziemlich irrelevante Aussage.
Ich würde sagen, wenn Sie 2015 eine neue Anwendung erstellen möchten, sollten Sie sich ernsthaft mit einer Benutzeroberfläche befassen, die eine API und keine vom Server generierten HTML-Seiten umfasst. Es gibt klare Kosten, aber auch klare Vorteile.
Wenn Sie jedoch über eine vorhandene Site verfügen, für die keine konkreten Pläne vorliegen (soweit ich das beurteilen kann), sind seine Kommentare nur irrelevant.
quelle
Kurzversion: Ihr Controller ist effektiv eine API, egal was passiert; obwohl ASP.NET das möglicherweise verdeckt.
Längere Version:
Stellen Sie sich eine einfache MVC-Web-App vor, die Informationen zu Bier bietet und Ihnen optional eine verkauft. Wie sehen die Routen aus?
In einer normalen Web-App gibt es wahrscheinlich einige Nebenrouten wie:
In einer Web-API sind diese nicht erforderlich, da sie von der HTTP-Methode abgeleitet werden.
Angesichts der obigen Symmetrie halte ich es für einen überzeugenden Fall, dass Ihre API und Ihr Controller so nahe beieinander liegen, dass sie möglicherweise dasselbe sind.
Nachdem einige graben tun, habe ich festgestellt , dass dies könnte der Stand der Dinge für Sie , je nachdem , welche Version von ASP.NET Sie verwenden. Der älteren MVC 5 und früheren Versionen fehlen die Konventionen und die Schnittstelle, um die beiden Implementierungen solide zu vereinen. In früheren Versionen wird von Web App-Rückgaben eine Ansicht aufgefüllt, während die API eine HttpResponse ausgibt. In beiden Fällen generieren sie jedoch semantisch genau dieselbe Antwort .
Wenn Sie MVC 6 verwenden, erhalten Sie beides in einer einheitlichen Controller-Klasse, die genau weiß, was zurückgegeben wird. Ich habe keinen guten ASP-Beispielcode für dieses Modell gefunden, aber ich habe einen Rails-Code mit demselben Muster gefunden. Betrachten Sie diesen Controller als "Gefällt mir" aus dem Diaspora-Projekt . Jeder Controller Methode hat Routen durch ein „einfalls convention“ definiert hier die Menge an den LCRUD in einer API.
Wenn Sie die Implementierungen lesen, kann jede möglicherweise auf HTML, Mobile HTML oder JSON reagieren. In Kombination mit einer Konvention zum Auffinden der Ansichten werden die Web-App und die Web-API vollständig vereinheitlicht. Sie werden auch feststellen, dass nicht alle Methoden tatsächlich jede Antwort bereitstellen (was sinnvoll ist, da die Benutzeroberfläche möglicherweise Methoden erfordert, die von der API nicht unterstützt werden, und umgekehrt).
Dies ist eine Impedanz-Fehlanpassung, da ASP.NET dies alles erst spät herausgefunden hat, während Rails die Symmetrie seit einiger Zeit akzeptiert und dies sehr deutlich macht.
Spekulation:
Ihr Mitarbeiter hat wahrscheinlich sowohl Recht als auch Unrecht, je nachdem, welche ASP-Version Sie verwenden. In der alten MVC-Version war es wahrscheinlich aufgrund des Unterschieds zwischen der API und der App eine "Best Practice", die API im Voraus zu erstellen, da das ASP.NET-Modell dort keine gute Wiederverwendung von Code ermöglichte.
In neueren Versionen ist es sinnvoller, einheitlichen Code zu verwenden, da die Wiederverwendung von Code mit der einheitlichen Controller-Basisklasse vereinfacht wurde.
In beiden Fällen ist der Controller jedoch die API.
quelle
Als ich meine Karriere 2006 begann, war diese Art von Architektur in der .NET-Welt der letzte Schrei. Ich habe an drei verschiedenen Projekten gearbeitet, die Mitte der 2000er Jahre mit einem Web-Service zwischen der Business-Logik-Schicht und dem Web-Frontend konzipiert wurden. Natürlich waren die Webservices heutzutage SOAP, aber es ist immer noch dieselbe Architektur. Die vermeintlichen Vorteile waren die Möglichkeit, entweder das Frontend oder das Backend zu wechseln und sogar ein Desktop-Programm zu entwickeln. Letztendlich hat sich YAGNI als wahr erwiesen. Ich habe noch nie etwas davon gesehen. Die ganze Zeit sah ich nur die Kosten für die Aufteilung des Projekts auf diese Weise. Am Ende habe ich sogar den Webdienst aus einem der Projekte herausgerissen (es dauerte ein halbes Jahr, um ihn Schritt für Schritt zu entfernen, während ich andere Dinge tat), und das gesamte Team war glücklich. Ich habe diesen Ansatz seitdem nie ausprobiert und werde es auch nicht tun, es sei denn, ich habe einen ganz bestimmten Grund angegeben. 5 Jahre Erfahrung in der Erprobung dieser Architektur haben mich gelehrt, dass ich sie nicht brauchen werde, und keine Menge Experten, die mir das Gegenteil sagen, werden mich davon überzeugen, dass ich es tun werde. Nur ein Projekt, wo ich es brauche, kann das tun.
Nun, da dies gesagt ist, bemühe ich mich sehr, eine Ebene zwischen der Geschäftslogik und den Controllern / Präsentatoren zu entwickeln. Zum Beispiel habe ich eine Serviceschicht, ich mache keine abfragbaren Daten verfügbar, verwende Schnittstellen für alle meine Services und injiziere sie in Steuerungen mit IoC. Wenn ich jemals einen Webdienst in meiner Architektur benötige, kann ich ihn zu angemessenen Kosten einführen. Ich möchte diese Kosten einfach nicht im Voraus bezahlen.
Ich mag auch die Idee der Mikrodienste, aber ich verstehe, dass Mikrodienste eher vertikale Module als horizontale Schichten bedeuten. Wenn Sie beispielsweise Facebook erstellen, ist die Chat-Funktion ein separater Dienst, der separat auf eigenen Servern usw. bereitgestellt wird. Dies ist die Art von unabhängigen Diensten, die ich fördern würde.
quelle
Dritte werden es nutzen? Ja, das solltest du .
Sie haben vor, es in nicht allzu ferner Zukunft wiederzuverwenden? Ja du solltest.
Sie sind Ihr Drittanbieter , und eine dokumentierte oder dokumentierbare API oder eine API, die von Drittanbietern verwendet werden kann, bietet Ihnen eine solide Wiederverwendbarkeit und Modularität.
Du bist in Eile? Nein, das solltest du nicht.
Die spätere Umgestaltung ist einfacher und schneller als die meisten Methoden und Lehrer vorhersagen und sagen. Es ist wichtiger, etwas zu haben, das funktioniert (auch mit einem schlechten internen Design, da es überarbeitet werden kann und wird), als überhaupt nichts zu haben. (aber mit einem unglaublichen internen Design, wohoo)
Das Front-End wird vielleicht aus Gründen nie das Licht der Welt erblicken? Ja, das solltest du .
Ich habe diesen Grund hinzugefügt, weil mir das oft passiert ist.
Zumindest muss ich meine Komponenten wiederverwenden und weitergeben usw.
quelle
Hier gibt es gute Antworten. Ich poste dies als Teilantwort; es wäre vielleicht besser als kommentar. Es ist jedoch nicht gut, auf mehreren Posts den gleichen Kommentar zu hinterlassen.
Man kann nicht behaupten, dass YAGNI ein Grund dafür ist, keine API zu erstellen.
Die API ist ein natürlicher und logischer Testendpunkt. Daher gibt es ab Tag 0 zwei Anwendungen, die die API verwenden: die Benutzeroberfläche und die Testsuite. Einer ist für Menschen gedacht, der andere für Maschinen. Sie sind notwendigerweise unterschiedlich. Das Testen des Front-End-Verhaltens ist eine ganz andere Aufgabe als das Testen des Back-End-Verhaltens. Daher sind die Techniken und wahrscheinlich auch die Werkzeuge völlig unterschiedlich. Mit der API kann das beste Tool für den Job verwendet werden. Darüber hinaus müssen die Front-End-Tester aufgrund der durch die API gebotenen Trennung die Back-End-Funktionalität nicht testen.
Die API hilft auch dabei, die Front-End-Codierer von den Bedenken des Back-End-Codierers fernzuhalten und umgekehrt. Dies sind sehr unterschiedliche Fähigkeiten in unserem Unternehmen; Mit der API können wir uns darauf konzentrieren, wo wir am stärksten sind.
quelle