Best Practices für große Lösungen in Visual Studio (2008) [geschlossen]

87

Wir haben eine Lösung mit über 100 Projekten, die meisten davon C #. Natürlich dauert das Öffnen und Bauen sehr lange, daher suche ich nach Best Practices für solche Bestien. In Bezug auf die Fragen, auf die ich Antworten erhoffe, sind:

  • Wie gehen Sie am besten mit Referenzen zwischen Projekten um?
    • sollte "copy local" ein- oder ausgeschaltet sein?
  • sollte jedes Projekt in einem eigenen Ordner erstellt werden oder sollten alle in demselben Ausgabeordner erstellt werden (sie sind alle Teil derselben Anwendung)

  • Sind die Ordner von Lösungen eine gute Möglichkeit, Dinge zu organisieren?

Ich weiß, dass es eine Option ist, die Lösung in mehrere kleinere Lösungen aufzuteilen, aber das bringt eine Reihe von Umgestaltungen und Kopfschmerzen mit sich. Vielleicht können wir das für einen separaten Thread speichern :-)

Eyvind
quelle
2
Darf ich fragen, warum eine einzelne Lösung mehr als 100 Projekte benötigt? Schaffen sie jeweils ihre eigene Versammlung?
Neil N
1
Ja, das sind sie, und jede von ihnen repräsentiert eine logisch separate Funktionalität.
Eyvind
2
@Eyvind - Sind das nicht Klassen und Namespaces? Welchen Nutzen bringen Ihnen separate Baugruppen? Ich kann mir einige vorstellen, wie beispielsweise potenziell kleinere Upgrades und die Speichernutzung (wenn einige nicht geladen sind), aber das Kompilieren und Verwalten von mehr als 100 Assemblies ist mit Sicherheit mit Kosten verbunden.
Si618
1
@ Mark Ich fühle deinen Schmerz. Wir haben bis zu 94 Projekte hier. Ich kann jetzt nicht viel dagegen tun, da wir die Entwicklung in mehreren Teams stoppen müssten, um eine Umstrukturierung vorzunehmen. Wir haben 3 EXE-Projekte, die auf die anderen 91 verweisen. Ich experimentiere mit einem gemeinsamen Ausgabeordner, bis jetzt sind die Gewinne sehr beeindruckend.
Kevin
2
Mann, 100+? Das ist nichts für das, was wir haben ... jetzt fast 600 hier drängen ...
C Johnson

Antworten:

41

Diese beiden MSBuild-Artikel, die ich geschrieben habe, könnten Sie interessieren.

MSBuild: Best Practices zum Erstellen zuverlässiger Builds, Teil 1

MSBuild: Best Practices zum Erstellen zuverlässiger Builds, Teil 2

Insbesondere in Teil 2 gibt es einen Abschnitt Erstellen großer Quellbäume , den Sie sich ansehen möchten.

Um Ihre Fragen hier kurz zu beantworten:

  • CopyLocal? Schalten Sie dies auf jeden Fall aus
  • In einen oder mehrere Ausgabeordner erstellen? In einen Ausgabeordner erstellen
  • Lösungsordner? Das ist Geschmackssache.

Sagte Ibrahim Hashimi

Mein Buch: In der Microsoft Build Engine: Verwenden von MSBuild und Team Foundation Build

Sagte Ibrahim Hashimi
quelle
Danke Mann, ich werde das auf jeden Fall überprüfen!
Eyvind
1
Ich werde sagen, dass ich dieses Buch habe und es ist großartig. Es hat mir geholfen, meine TFS-Builds zu automatisieren, und die lokalen Entwickler-Builds sind sehr umfangreich. Ich arbeite jetzt an inkrementellen Builds, und das Buch geht sehr tief in das Thema ein. Den Preis wert. Danke, sagte. Mach weiter so.
Irperez
Vielen Dank irperez für die Kommentare
Ibrahim Hashimi
2
-1 für UNBEDINGTE Empfehlung zum Deaktivieren von CopyLocal. Das Setzen von CopyLocal = false kann während der Bereitstellungszeit unterschiedliche Probleme verursachen. Siehe meinen Blog-Beitrag "NICHT ändern" Lokale Projektreferenzen kopieren auf "Falsch", es sei denn, Sie verstehen Teilsequenzen . "( Geekswithblogs.net/mnf/archive/2012/12/09/… )
Michael Freidgeim
Könnte "In einen Ausgabeordner erstellen" beim Kompilieren mit mehreren Threads Probleme verursachen?
BrunoLM
9

+1 für die sparsame Verwendung von Lösungsordnern zur Organisation von Aufgaben.

+1 für die Projekterstellung in einem eigenen Ordner. Wir haben zunächst einen gemeinsamen Ausgabeordner ausprobiert. Dies kann dazu führen, dass subtile und schmerzhafte veraltete Referenzen gefunden werden.

FWIW, wir verwenden Projektreferenzen für Lösungen, und obwohl Nuget heutzutage wahrscheinlich die bessere Wahl ist, haben wir festgestellt, dass svn: externals sowohl für interne Assemblys von Drittanbietern als auch für (Assembly-Typ-) interne Assemblys gut funktioniert. Gewöhnen Sie sich einfach an, eine bestimmte Revisionsnummer anstelle von HEAD zu verwenden, wenn Sie auf svn: externals verweisen (schuldig wie angeklagt :)

si618
quelle
2
+1 Ich habe auch Probleme mit der allgemeinen Ausgabeordnerlösung. Ich habe nicht verstanden, was "Projektreferenzen für Lösungen" bedeuten, bitte erklären Sie ein bisschen mehr ...
Mauricio Scheffer
Wie in verwenden wir VS-> Referenz hinzufügen-> Projekte anstelle von VS-> Referenz hinzufügen-> Durchsuchen. Kleiner Punkt, den ich kenne, aber einige Leute machen es anders (und ich denke, das verursacht mehr Kopfschmerzen). Wenn Sie sich den MSBuild csproj-Text ansehen, wird anstelle der Referenz die ProjectReference-Eigenschaft angezeigt.
Si618
Interessante Antwort! Ich denke, wir haben gezackt, wo Sie gezackt haben. Wir haben überhaupt keine Lösungsordner und verlassen uns auf die Projektbenennung (Projekte haben den gleichen Namen wie der Namespace). Alle unsere Ausgaben werden in einem einzigen Ordner gespeichert, wodurch das Entwickler-Setup dem Bereitstellungs-Ordner viel näher kommt. Wenn Abhängigkeiten richtig eingestellt sind, haben wir keine veralteten Referenzen.
Thomas Bratt
Ja, das gemeinsame Ausgabeverzeichnis führt zu großen Schmerzen, insbesondere bei Verwendung von Resharper. Veraltete Referenzen in der Tat.
Florian Doyon
1
@ Kevin, es ist schon einige Jahre her, aber aus dem Speicher sind ein Beispiel zwei Projekte, die auf dieselbe Assembly verweisen, beispielsweise eine externe Bibliothek, auf die nicht projektbezogen verwiesen wird. Alles in Ordnung, wenn sie dieselbe Version haben, aber dann eine neue Version dieser Bibliothek herauskommt, aber nur ein Projekt ihre Referenz aktualisiert. Welche Version wird im gemeinsamen Ausgabeordner verwendet?
Si618
8

Entladen Sie Projekte, die Sie nicht oft verwenden, und kaufen Sie eine SSD. Eine SSD verbessert die Kompilierungszeit nicht, aber Visual Studio lässt sich zweimal schneller öffnen / schließen / erstellen.

Nicolas Dorier
quelle
3
Es ist erwähnenswert, dass das Entladen eines Projekts eine Einstellung pro Benutzer ist, sodass Entwickler in Ihrem Team nur die Projekte laden können, die ihnen wichtig sind. Dies hat unserem Team wirklich geholfen.
Seite
Sie können die Solution Load Manager-Erweiterung visualstudiogallery.msdn.microsoft.com/… verwenden , um zu definieren, was standardmäßig nicht geladen werden soll
Michael Freidgeim
6

Wir haben ein ähnliches Problem wie 109 separate Projekte. Um die ursprünglichen Fragen zu beantworten, die auf unseren Erfahrungen basieren:

1. Wie gehen Sie am besten mit Referenzen zwischen Projekten um?

Wir verwenden die Kontextmenüoption 'Referenz hinzufügen'. Wenn 'Projekt' ausgewählt ist, wird die Abhängigkeit standardmäßig zu unserer einzelnen globalen Lösungsdatei hinzugefügt.

2. Sollte "copy local" ein- oder ausgeschaltet sein?

Aus unserer Erfahrung. Das zusätzliche Kopieren verlängert nur die Erstellungszeiten.

3. Sollte jedes Projekt in einem eigenen Ordner erstellt werden oder sollten alle in demselben Ausgabeordner erstellt werden (sie sind alle Teil derselben Anwendung)?

Alle unsere Ausgaben werden in einem einzigen Ordner namens 'bin' abgelegt. Die Idee ist, dass dieser Ordner derselbe ist wie bei der Bereitstellung der Software. Dies hilft, Probleme zu vermeiden, die auftreten, wenn sich das Entwickler-Setup vom Bereitstellungs-Setup unterscheidet.

4. Sind Lösungsordner eine gute Möglichkeit, Dinge zu organisieren?

Nein nach unserer Erfahrung. Die Ordnerstruktur einer Person ist der Albtraum einer anderen Person. Tief verschachtelte Ordner verlängern nur die Zeit, die benötigt wird, um etwas zu finden. Wir haben eine völlig flache Struktur, aber benennen unsere Projektdateien, Assemblys und Namespaces gleich.


Unsere Art, Projekte zu strukturieren, basiert auf einer einzigen Lösungsdatei. Der Aufbau dauert lange, auch wenn sich die Projekte selbst nicht geändert haben. Um dies zu unterstützen, erstellen wir normalerweise eine andere Lösungsdatei für den aktuellen Arbeitssatz. Alle Projekte, an denen wir arbeiten, werden hinzugefügt. Die Erstellungszeiten werden erheblich verbessert, obwohl ein Problem darin besteht, dass Intellisense für Typen fehlschlägt, die in Projekten definiert sind, die nicht im aktuellen Satz enthalten sind.

Ein Teilbeispiel unseres Lösungslayouts:

\bin

OurStuff.SLN

OurStuff.App.Administrator
OurStuff.App.Common
OurStuff.App.Installer.Database
OurStuff.App.MediaPlayer
OurStuff.App.Operator
OurStuff.App.Service.Gateway
OurStuff.App.Service.CollectionStation
OurStuff.App.ServiceLocalLauncher
OurStuff.App.StackTester
OurStuff.Auditing
OurStuff.Data
OurStuff.Database
OurStuff.Database.Constants
OurStuff.Database.ObjectModel
OurStuff.Device
OurStuff.Device.Messaging
OurStuff.Diagnostics
...
[etc]
Thomas Bratt
quelle
Könnte "In einen Ausgabeordner erstellen" beim Kompilieren mit mehreren Threads Probleme verursachen?
BrunoLM
4

Wir arbeiten hier an einem ähnlich großen Projekt. Lösungsordner haben sich als eine gute Möglichkeit zum Organisieren von Dingen erwiesen, und wir neigen dazu, die lokale Kopie einfach auf true zu setzen. Jedes Projekt wird in einem eigenen Ordner erstellt, und dann wissen wir, dass für jedes bereitstellbare Projekt dort die richtige Teilmenge der Binärdateien vorhanden ist.

Die Zeiteröffnung und der Zeitaufbau werden schwer zu beheben sein, ohne in kleinere Lösungen einzudringen. Sie können die Parallelisierung des Builds untersuchen (Google "Parallel MS Build", um dies zu tun und in die Benutzeroberfläche zu integrieren), um hier die Geschwindigkeit zu verbessern. Sehen Sie sich auch das Design an und prüfen Sie, ob eine Umgestaltung einiger Ihrer Projekte, die insgesamt zu weniger führt, hilfreich sein kann.

David M.
quelle
3

Um die Schmerzen beim Erstellen zu lindern, können Sie die Option "Configuration Manager ..." für Builds verwenden, um das Erstellen bestimmter Projekte zu aktivieren oder zu deaktivieren. Sie können ein "Project [n] Build" erstellen, das bestimmte Projekte ausschließen und dieses verwenden kann, wenn Sie auf bestimmte Projekte abzielen.

Was die über 100 Projekte angeht, weiß ich, dass Sie sich nicht mit dieser Frage über die Vorteile einer Reduzierung Ihrer Lösungsgröße beschäftigen möchten, aber ich denke, Sie haben keine andere Möglichkeit, die Ladezeit zu beschleunigen (und Speichernutzung) von devenv.

Michael Meadows
quelle
Hm, wurde dies wegen Unrecht oder nur wegen Nichtübereinstimmung abgelehnt? Ich kann mit dem ersteren leben, wenn Sie mir sagen können, warum.
Michael Meadows
Einverstanden, ich mag es nicht, ohne Kommentar abzustimmen, also Michael, du bekommst meine +1, um die Gleichung
auszugleichen ;-)
2
Übrigens mag ich es persönlich nicht, mit Konfigurationsmanagement für solche Dinge herumzuspielen. Warum? Wenn Sie versehentlich Ihre geänderte Konfiguration festschreiben, sind Ihr Build-Server oder andere Entwickler betroffen.
Si618
Einverstanden. Tatsächlich gilt das gleiche Problem für Lösungen mit zu vielen Projekten. :)
Michael Meadows
3

Was ich normalerweise damit mache, hängt ein wenig davon ab, wie der "Debug" -Prozess tatsächlich abläuft. Normalerweise setze ich die lokale Kopie jedoch NICHT auf true. Ich habe das Build-Verzeichnis für jedes Projekt so eingerichtet, dass alles an den gewünschten Endpunkt ausgegeben wird.

Daher habe ich nach jedem Build einen Ordner mit allen DLLs und allen Windows- / Webanwendungen, und alle Elemente befinden sich am richtigen Speicherort. Lokale Kopie wurde nicht benötigt, da die DLL am Ende an der richtigen Stelle landet.

Hinweis

Das Obige funktioniert für meine Lösungen, bei denen es sich normalerweise um Webanwendungen handelt, und ich habe keine Probleme mit Referenzen festgestellt, aber es ist möglicherweise möglich!

Mitchel Sellers
quelle
3

Wir haben ein ähnliches Problem. Wir lösen es mit kleineren Lösungen. Wir haben eine Master-Lösung, die alles öffnet. Aber perf. darauf ist schlecht. Daher segmentieren wir kleinere Lösungen nach Entwicklertyp. DB-Entwickler haben also eine Lösung, die die Projekte lädt, die sie interessieren, Service-Entwickler und UI-Entwickler das Gleiche. Es kommt selten vor, dass jemand die gesamte Lösung öffnen muss, um täglich das zu erledigen, was er benötigt. Es ist kein Allheilmittel - es hat seine Vor- und Nachteile. Siehe "Multi-Solution-Modell" in diesem Artikel (ignorieren Sie den Teil über die Verwendung von VSS :)

JP Alioto
quelle
2

Ich denke, bei so großen Lösungen sollte die beste Vorgehensweise darin bestehen, sie aufzubrechen. Sie können sich die "Lösung" als einen Ort vorstellen, an dem Sie die erforderlichen Projekte und möglicherweise andere Teile zusammenführen können, um an einer Lösung für ein Problem zu arbeiten. Indem Sie die über 100 Projekte in mehrere Lösungen aufteilen, die darauf spezialisiert sind, Lösungen für nur einen Teil des Gesamtproblems zu entwickeln, können Sie dort zu einem bestimmten Zeitpunkt weniger Probleme lösen, indem Sie Ihre Interaktionen mit den erforderlichen Projekten beschleunigen und die Problemdomäne vereinfachen.

Jede Lösung würde die Ausgabe erzeugen, für die sie verantwortlich ist. Diese Ausgabe sollte Versionsinformationen enthalten, die in einem automatisierten Prozess festgelegt werden können. Wenn die Ausgabe stabil ist, können Sie die Referenzen in abhängigen Projekten und Lösungen mit der neuesten internen Verteilung aktualisieren. Wenn Sie dennoch in den Code eintreten und auf die Quelle zugreifen möchten, können Sie dies tatsächlich mit dem Microsoft-Symbolserver tun, mit dem Visual Studio in referenzierte Assemblys zugreifen und sogar den Quellcode abrufen kann.

Die gleichzeitige Entwicklung kann erfolgen, indem Schnittstellen im Voraus angegeben und die in der Entwicklung befindlichen Assemblys verspottet werden, während Sie auf Abhängigkeiten warten, die nicht vollständig sind, gegen die Sie jedoch entwickeln möchten.

Ich halte dies für eine bewährte Methode, da die Komplexität des Gesamtaufwands unbegrenzt ist, wenn Sie ihn auf diese Weise physisch aufteilen. Wenn Sie alle Projekte in einer einzigen Lösung zusammenfassen, wird dies letztendlich eine Obergrenze erreichen.

Hoffe, diese Informationen helfen.

Blake Taylor
quelle
2

Wir haben über 60 Projekte und verwenden keine Lösungsdateien. Wir haben eine Mischung aus C # - und VB.Net-Projekten. Die Leistung war immer ein Thema. Wir arbeiten nicht an allen Projekten gleichzeitig. Jeder Entwickler erstellt seine eigenen Lösungsdateien basierend auf den Projekten, an denen er arbeitet. Die Lösungsdateien werden nicht in unsere Quellcodeverwaltung eingecheckt.

Alle Klassenbibliotheksprojekte werden in einem CommonBin-Ordner im Stammverzeichnis des Quellverzeichnisses erstellt. Ausführbare / Web-Projekte werden in ihren jeweiligen Ordner erstellt.

Wir verwenden keine Projektreferenzen, sondern dateibasierte Referenzen aus dem CommonBin-Ordner. Ich habe eine benutzerdefinierte MSBuild-Aufgabe geschrieben, die die Projekte überprüft und die Erstellungsreihenfolge bestimmt.

Wir verwenden dies seit einigen Jahren und haben keine Beschwerden.

Vasu Balakrishnan
quelle
3
Würde es Ihnen etwas ausmachen, Ihre benutzerdefinierte msbuild-Aufgabe zu teilen?
Andreapier
0

Alles hängt mit Ihrer Definition und Ihrer Sicht auf eine Lösung und ein Projekt zusammen. In meinen Augen ist eine Lösung genau das, eine logische Gruppierung von Projekten, die eine ganz bestimmte Anforderung lösen. Wir entwickeln eine große Intranet-Anwendung. Jede Anwendung in diesem Intranet verfügt über eine eigene Lösung, die auch Projekte für Exes oder Windows-Dienste enthalten kann. Und dann haben wir ein zentrales Framework mit Dingen wie Basisklassen und Helfern und httphandlers / httpmodules. Das Basisframework ist ziemlich groß und wird von allen Anwendungen verwendet. Indem Sie die vielen Lösungen auf diese Weise aufteilen, reduzieren Sie die Anzahl der Projekte, die für eine Lösung erforderlich sind, da die meisten von ihnen nichts miteinander zu tun haben.

So viele Projekte in einer Lösung zu haben, ist einfach schlechtes Design. Es sollte keinen Grund geben, so viele Projekte unter einer Lösung zu haben. Das andere Problem, das ich sehe, sind Projektreferenzen, die Sie letztendlich wirklich vermasseln können, insbesondere wenn Sie Ihre Lösung jemals in kleinere aufteilen möchten.

Mein Rat ist, dies zu tun und ein zentrales Framework zu entwickeln (Ihre eigene Implementierung der Enterprise Library, wenn Sie so wollen). Sie können entweder GAC für die Freigabe verwenden oder direkt auf den Speicherort der Datei verweisen, sodass Sie über einen zentralen Speicher verfügen. Sie können dieselbe Taktik auch für zentralisierte Geschäftsobjekte verwenden.

Wenn Sie direkt auf die DLL verweisen möchten, möchten Sie sie in Ihrem Projekt mit copy local false referenzieren (z. B. c: \ mycompany \ bin \ mycompany.dll). Zur Laufzeit müssen Sie Ihrer app.config oder web.config einige Einstellungen hinzufügen, damit sie auf eine Datei verweist, die sich nicht im GAC oder im Laufzeitbereich befindet. Tatsächlich spielt es keine Rolle, ob es sich um eine lokale Kopie handelt oder nicht oder ob die DLL im Bin oder sogar im GAC landet, da die Konfiguration beide überschreibt. Ich denke, es ist eine schlechte Praxis, lokal zu kopieren und ein chaotisches System zu haben. Sie müssen höchstwahrscheinlich vorübergehend lokal kopieren, wenn Sie in einer dieser Assemblys debuggen müssen.

Sie können meinen Artikel über die globale Verwendung einer DLL ohne GAC lesen. Ich mag den GAC wirklich nicht, vor allem, weil er die Bereitstellung von xcopy verhindert und keinen Autorestart für Anwendungen auslöst.

http://nbaked.wordpress.com/2010/03/28/gac-alternative/

user306031
quelle
0

Wenn Sie CopyLocal = false festlegen, wird die Erstellungszeit verkürzt, es können jedoch während der Bereitstellungszeit unterschiedliche Probleme auftreten.

Es gibt viele Szenarien, in denen Copy Local auf True gesetzt werden muss, z. B. Projekte der obersten Ebene, Abhängigkeiten der zweiten Ebene und DLLs, die durch Reflektion aufgerufen werden.

Meine Erfahrung mit dem Setzen von CopyLocal = false war nicht erfolgreich. Siehe Zusammenfassung der Vor- und Nachteile in meinem Blog-Beitrag "Ändern Sie NICHT" Lokale Projektreferenzen kopieren auf falsch, es sei denn, Sie verstehen Teilfolgen. "

Michael Freidgeim
quelle