Gute Praxis für Visual Studio-Lösungen [geschlossen]

10

Hoffentlich eine einfache Relativitätsfrage. Ich beginne mit der Arbeit an einem neuen internen Projekt, um die Rückverfolgbarkeit reparierter Geräte in den Gebäuden zu gewährleisten.

Die Datenbank wird remote auf einem Webserver gespeichert und über die Web-API (JSON-Ausgabe) aufgerufen und mit OAuth geschützt. Die Front-End-Benutzeroberfläche wird in WPF und der Geschäftscode in C # ausgeführt.

Daraus sehe ich die verschiedenen Ebenen Präsentation / Anwendung / Datenspeicher. Es gibt Code zum Verwalten aller authentifizierten Aufrufe an die API, eine Klasse zum Darstellen von Entitäten (Geschäftsobjekte), Klassen zum Erstellen der Entitäten (Geschäftsobjekte), Teile für die WPF-GUI, Teile der WPF-Ansichtsmodelle usw.

Ist es am besten, dies in einem einzelnen Projekt zu erstellen oder in einzelne Projekte aufzuteilen?

In meinem Herzen sage ich, dass es mehrere Projekte sein sollten. Ich habe es zuvor in beide Richtungen gemacht und festgestellt, dass das Testen mit einer einzelnen Projektlösung einfacher ist. Bei mehreren Projekten können jedoch rekursive Abhängigkeiten auftreten. Besonders wenn Klassen Schnittstellen haben, um das Testen zu vereinfachen, habe ich festgestellt, dass die Dinge unangenehm werden können.

JonWillis
quelle
1
Ich würde sie in das aufteilen, was für das Projekt Sinn macht.
Ramhound
Hat jemand andere irgendwelche Gedanken, eine über das Halten der Schnittstellen, wie MattDavey vorgeschlagen hat? Ich habe diesen Ansatz bereits verwendet, um die genannten Abhängigkeiten zu vermeiden. Oder sollten sich die Schnittstellen für Klasse x im selben Projekt wie Klasse x befinden?
JonWillis
Welche Ebenen verwenden Sie alle? Ich habe einige verschiedene Varianten gesehen, obwohl die wichtigsten Varianten Präsentation / Anwendung / Infrastruktur sind. Einige teilen die Anwendung auch in zwei Teile auf: Anwendung + Service. Einige Modelle erwähnen auch eine bestimmte Ebene für die Geschäftslogik, die für mich in den Geschäftsobjekten selbst enthalten sein könnte.
JonWillis

Antworten:

8

Dies hängt von der Größe des Projekts ab

Hier sind die Richtlinien, die ich normalerweise verwende

  • Ein kleines Projekt mit einer Handvoll Seiten oder weniger, ich halte mich fast immer an ein einzelnes Projekt.

  • Wenn die Datenzugriffsebene des kleinen Projekts groß oder komplex ist, kann ich sie in eine eigene Ebene aufteilen, ansonsten befindet sie sich nur in einem eigenen Ordner.

  • Wenn das Projekt größer ist, habe ich fast immer ein separates Projekt für die DAL, und jede weitere Aufteilung hängt davon ab, wo die Grenzen zwischen den Funktionen der Anwendung liegen.

  • Wenn die Anwendung mehrere Zwecke hat, jede mit ihren eigenen Ansichten, Ansichtsmodellen usw., werde ich normalerweise jedes Teil in einen eigenen Bereich unterteilen. Wenn jeder Abschnitt klein ist, trenne ich sie durch einen Ordner. Wenn jeder Abschnitt groß ist, werde ich sie durch ein Projekt trennen.

  • Wenn ich mehrere Projekte habe, die auf denselben Objektsatz ( ViewModelBase, RelayCommandusw.) verweisen müssen, erstelle ich ein Projekt nur für die gemeinsam genutzten Infrastrukturobjekte.

  • Wenn ich eine große Anzahl freigegebener benutzerdefinierter Stile / Vorlagen / Ressourcen habe, erstelle ich ein Projekt nur für diese.

Als Randnotiz habe ich bei meinem ersten großen WPF-Projekt einen Fehler gemacht und sie getrennt, indem ich Modelle in ein Projekt, Ansichten in ein anderes und ViewModels in ein drittes eingefügt habe. Ich kann Ihnen jetzt sagen, dass dies nicht der richtige Weg ist, da die Wartung zum Albtraum wird :)

Rachel
quelle
Neugierig, welche Wartungsprobleme hatten Sie beim Trennen der Schichten?
Ian
@ Rachel, ich werde WPF verwenden. Es würde mich also interessieren, wie Sie das Projekt am Ende organisiert haben. Ich denke, ich kann mich daran erinnern, dass ein kleines MVC-Projekt beim Aufteilen von 3 Teilen in 3 DLLs schmerzhaft war. Für WPF ist Meine Ansicht die GUI, die zu ändernde Entität / das zu ändernde Geschäftsobjekt und das ViewModel die Interaktion zwischen ihnen. Das ViewModel würde sich mit der Logik befassen, ein Repository aufzurufen, um die Reparaturen zu laden / zu speichern (die wiederum Fabriken / Web-APIs usw. haben).
JonWillis
1
@Ian Das größte Problem war, dass ich bei den meisten geringfügigen Änderungen, z. B. beim Hinzufügen eines einzelnen Felds, das Modell, View, ViewModel und DAL in 4 separaten Bibliotheken suchen musste. Das Projekt, an dem ich zu der Zeit arbeitete, war ziemlich groß und ich habe mehr Zeit verschwendet, als mir wichtig ist, nach bestimmten Dateien zu suchen. Seitdem habe ich geändert, um verwandte Objekte zusammenzuhalten, z. B. alles, was mit der Suche zu tun hat, wie z. B. SearchView, SearchViewModelund SearchResultModelalle würden in einem Ordner zusammengefasst, und ich habe festgestellt, dass dies die Wartung der App erleichtert.
Rachel
@ Ian Ich erinnere mich auch daran, dass ich Abhängigkeitsprobleme hatte und auf Zirkelverweise stieß, weil trotz meiner besten Bemühungen einige Ebenen auf andere verweisen mussten, diese Ebene jedoch auf sie verwies, sodass ich einige hässliche Problemumgehungen hatte, bis ich sie umgestaltete
Rachel
1
@ JonWillis Die meisten meiner WPF-Projekte werden anhand der in meiner Antwort angegebenen Punkte aufgeschlüsselt. Normalerweise ist die DAL eine eigene Ebene, und jedes Modul oder jeder Abschnitt des Projekts ist zusammen gruppiert (entweder in einem eigenen Ordner, Namespace oder Projekt, abhängig von der Größe des Projekts). So wären beispielsweise alle Suchobjekte zusammen, einschließlich der Interfacefür die Datenschicht, aber die eigentliche Datenzugriffsschicht für die Suche befindet sich in der DAL-Bibliothek. Sehr oft habe ich eine Infrastructureoder eine CommonBibliothek, die allgemeine Basisklassen, Schnittstellen und Hilfsklassen enthält.
Rachel
14

Ich habe die besten Ergebnisse mit einem Projekt pro Ebene und einem Testprojekt pro Ebene gesehen. Ich habe nur wenige Anwendungen gesehen, die in 10 oder weniger Projekten in der Lösung nicht ausgeführt werden können, wobei die Lösung alles umfasst .

Fallen Sie nicht in die Falle, Projekte zu verwenden, bei denen Sie wirklich einen Namespace wünschen. Tonnenweise Projekte verursachen nichts als Overhead ohne Gewinn.

Bryan Boettcher
quelle
9

IMHO getrennt ist fast immer besser. Ich trenne meine Datenschicht fast immer ab, es sei denn, das Projekt ist zu 100% trivial. Der Grund dafür ist, dass die Datenschicht am häufigsten herumgereicht wird. In seltenen Fällen schließen Sie eine GUI an mehrere Datenschichten an und erwarten, dass sie gut funktioniert. Das weitaus häufigere Szenario besteht darin, dass Sie über eine einzelne Datenschicht verfügen und diese auf mehrere GUIs (z. B. ASP.Net, WPF und eine Silverlight-App) verteilen möchten. Es ist fantastisch, wenn Sie einfach das Datenschichtprojekt erstellen und diese DLL als Referenz in die nächste von Ihnen erstellte GUI einfügen können.

Morgan Herlocker
quelle
+1 Wenn ich neue Projekte starte, baue ich ziemlich oft eine simulierte Datenschicht, die die Daten im Speicher hält. Ermöglicht es mir, zuerst den Rest der App zu erstellen. Dann kann ich es später gegen eine "echte" Datenzugriffsschicht
austauschen
Würden Sie Entitäten (DTO), Faktoren und Klassen, die für die Kommunikation mit dem Webserver verwendet werden, als Teil der Datenschicht betrachten?
JonWillis
@ JonWillis - Nein, wahrscheinlich nicht alle. Ich würde die Fabriken und Klassen für den Webserver in einen Namespace eines Klassenbibliotheksprojekts stellen. Meine typische Datenschicht enthält nur die erforderlichen DBML- und / oder EDMX-Dateien. In der Regel gebe ich jedoch "Bibliothek / Framework" Sachen ihr eigenes Projekt. Sie müssen definitiv nicht in das GUI-Projekt eingebunden werden, obwohl ich sehe, dass die Leute das die ganze Zeit tun.
Morgan Herlocker
Realistisch gesehen, wie lange würden Sie brauchen, um einige Namespaces in ein neues Projekt zu verzweigen. Ich denke, es ist ein ziemlich einfacher Refactoring-Job.
Didier A.
4

Für mich ist 4 * die magische Zahl. Ein Projekt für jede Ebene und ein Projekt, das alle Schnittstellen / DTOs definiert, die für die Kommunikation zwischen ihnen erforderlich sind.

* 7, wenn Sie Unit-Tests zählen

MattDavey
quelle
2

Ich habe immer eine einzige Lösung verwendet, wenn ich an diesen verschiedenen Schichten arbeite oder wenn eine enge Kopplung mit ihnen besteht. Ich möchte F5 drücken und alle Projekte bei Bedarf neu erstellen lassen. Ich glaube nicht, dass es einen "richtigen" Weg gibt, dies zu tun.

Jeremy
quelle
2

Sein persönlicher Geschmack, das Wichtigste ist, konsequent zu sein . Ich persönlich habe für jede Schicht der Anwendung ein eigenes Projekt, sodass die Trennung offensichtlich ist.

Tom Squires
quelle
Auf welche Ebenen trennen Sie sich? Haben Sie separate Anwendungs- / Dienstebenen und wenn ja, wie unterscheiden sie sich tatsächlich? Ist Ihre Geschäftslogik in der Anwendung / im Service enthalten oder handelt es sich um Methoden für die tatsächlichen Geschäftsobjekte?
JonWillis
1

Die Zunahme der Anzahl der Projekte hat damit zu tun, dass Unit-Tests aktiviert und das Abhängigkeitsdiagramm so weit vereinfacht werden, dass die Dinge nicht mehr so ​​komplex sind, dass Änderungen in einem Teil der App Dinge in scheinbar nicht verwandten Teilen der App beschädigen.

Es funktioniert, wenn ich eine Art Abhängigkeitsinversion durchführe, um alle "Verträge", Schnittstellen, abstrakten Klassen und Datenübertragungsobjekte in einer Assembly zusammenzufassen. In einer anderen Assembly habe ich alles, was mit der Datenbank spricht, abgelegt. Unit-Tests erhalten eine eigene Baugruppe. Wenn die Benutzeroberfläche grundsätzlich nicht testbar ist (z. B. ASP.NET-Winforms), bietet die Aufteilung der Benutzeroberfläche in testbaren Code und nicht testbaren Code - jeweils eine Assembly - einen erheblichen Vorteil. Manchmal taucht Code auf, der nichts mit der Datenbank, der Benutzeroberfläche oder irgendetwas zu tun hat, was ich bisher erwähnt habe - es ist Code, den ich mir im .NET Framework gewünscht habe. Diesen Code werde ich in eine Utilities-Assembly einfügen oder zumindest in die Root-Assembly (wahrscheinlich die mit den Schnittstellen).

Wenn alle Baugruppen auf alle Baugruppen verweisen oder fast alle, sollten sie wieder zu einer einzigen Baugruppe zusammengeführt werden. Wenn Ihnen oder den Mitarbeitern Ihres Teams die Disziplin fehlt, um zu verhindern, dass Code auf Datenebene in die Benutzeroberfläche und Benutzeroberfläche in die Datenebene eingefügt wird, vereinfachen Sie die Dinge, indem Sie alles wieder in einer einzigen Ebene zusammenführen.

Bei einigen Editionen von Visual Studio treten bei etwa 15 Assemblys Leistungsprobleme auf. Manchmal hängt dies davon ab, welche Art von Projekt vorhanden ist. Das strategische Entladen von Projektdateien kann jedoch manchmal hilfreich sein.

MatthewMartin
quelle
Im Moment bin ich der einzige Entwickler im Unternehmen. Und auch frisch von der Universität, um so schnell wie möglich gute Praktiken für die größeren Projekte zu vermitteln. Ich bin daran interessiert, es wartbar zu machen, weil sich die Systemspezifikation so sehr geändert hat, bevor ich überhaupt anfing, sie zu dokumentieren, gegen die Aufforderung, das System so schnell wie möglich zu wollen. Wäre eine Baugruppe, die nur Schnittstellen enthält, Ihrer Meinung nach eine geeignete Lösung? Auf diese Weise sollte die Abhängigkeit nur von den Schnittstellen und Factory-Klassen bestehen.
JonWillis
1
Ja. Es ist besser, die Motivation der Aufteilung von Baugruppen zu verstehen, aber wenn Sie (oder Ihre Teammitglieder) es nicht verstehen, ist es immer noch ein kostengünstiges Manöver. Selbst wenn Sie am Ende alle Assemblys haben, die von allen Assemblys abhängig sind und keine Hoffnung auf Unit-Tests haben, ist es ein Schritt in die richtige Richtung, Dinge, die sich wie Verträge verhalten (Schnittstellen, abstrakte Klassen), in ihre eigene Assembly zu verschieben, und hat nur wenige Nachteile.
Matthew
-2

Der einzige gute Grund, mehr als ein Projekt zu haben, besteht darin, dass Sie eine Reihe von Klassen und Dateien für mehrere Anwendungen freigeben müssen.

Wenn Projekte nur von einer Anwendung verwendet werden, sollten sie gar nicht erst erstellt worden sein. Verwenden Sie stattdessen Namespaces. Sparen Sie sich die Mühe von Zirkelverweisen, DLL-Overhead und Projektverwirrung bei der Suche nach Dateien.

Lesen Sie diesen Artikel, um eine ausführlichere Erklärung zu erhalten, warum dies so ist: http://lostechies.com/chadmyers/2008/07/16/project-anti-pattern-many-projects-in-a-visual-studio- Lösungsdatei /

Und wie der Artikel besagt, würde ich jeden begrüßen, der einen triftigen Grund hat, mehrere Projekte außer Code-Sharing in der gesamten Anwendung zu haben, um mir zu sagen, was es ist, weil ich bezweifle, dass es eines gibt.

Didier A.
quelle
Gegenargumente zur Ablehnung wären willkommen.
Didier A.