Bonnes pratiques pour les solutions volumineuses dans Visual Studio (2008) [fermé]

87

Nous avons une solution avec plus de 100 projets, la plupart en C #. Naturellement, il faut beaucoup de temps à la fois pour ouvrir et construire, donc je recherche les meilleures pratiques pour ces bêtes. Les questions auxquelles j'espère obtenir des réponses sont les suivantes:

  • comment gérer au mieux les références entre les projets
    • "Copier local" doit-il être activé ou désactivé?
  • chaque projet doit-il être construit dans son propre dossier, ou doit-il tous construire dans le même dossier de sortie (ils font tous partie de la même application)

  • Les dossiers de solutions sont-ils un bon moyen d'organiser les choses?

Je sais que diviser la solution en plusieurs solutions plus petites est une option, mais cela vient avec son propre ensemble de refactoring et de création de maux de tête, alors peut-être pouvons-nous l'enregistrer pour un thread séparé :-)

Eyvind
la source
2
Puis-je demander pourquoi une seule solution nécessite plus de 100 projets? Créent-ils chacun leur propre assemblage?
Neil N
1
Oui, ils le sont, et chacun d'eux représente une fonctionnalité logiquement distincte.
Eyvind
2
@Eyvind - N'est-ce pas à cela que servent les classes et les espaces de noms? Quel avantage les assemblages séparés vous apportent-ils? Je peux penser à certains, comme des mises à niveau potentiellement plus petites et une utilisation de la mémoire (si certaines ne sont pas chargées), mais il y a certainement un coût à avoir plus de 100 assemblages à compiler et à gérer.
si618
1
@Mark Je ressens ta douleur. Nous sommes à 94 projets ici. Je ne peux pas faire grand-chose à ce sujet maintenant, car nous devrions arrêter le développement de plusieurs équipes pour se restructurer. Nous avons 3 projets EXE qui font référence aux 91 autres. J'expérimente avec un dossier de sortie commun, jusqu'à présent, les gains sont très impressionnants.
Kevin
2
Homme, plus de 100 ans? Ce n'est rien pour ce que nous avons ... en poussant près de 600 ici maintenant ...
C Johnson

Réponses:

41

Vous pourriez être intéressé par ces deux articles MSBuild que j'ai écrits.

MSBuild: Meilleures pratiques pour créer des builds fiables, partie 1

MSBuild: Meilleures pratiques pour la création de builds fiables, partie 2

Spécifiquement dans la partie 2, il y a une section Construire de grandes arborescences de sources que vous voudrez peut-être jeter un coup d'œil.

Pour répondre brièvement à vos questions ici:

  • CopyLocal? Pour sûr désactiver ceci
  • Construire dans un ou plusieurs dossiers de sortie? Construire dans un dossier de sortie
  • Dossiers de solution? C'est une question de goût.

Sayed Ibrahim Hashimi

Mon livre: dans le moteur de construction Microsoft: utilisation de MSBuild et Team Foundation Build

Sayed Ibrahim Hashimi
la source
Merci mec, je ne manquerai pas de les vérifier!
Eyvind
1
Je dirai que j'ai ce livre et c'est génial. Cela m'a aidé à automatiser mes builds TFS et les builds de développement local très largement. Je travaille maintenant sur des builds incrémentaux, et le livre va très loin dans le sujet. Vaut le prix. Merci Sayed. Continuez ce bon travail.
irperez
Merci irperez pour les commentaires
Sayed Ibrahim Hashimi
2
-1 pour la recommandation INCONDITIONNELLE de désactiver CopyLocal. Set CopyLocal = false peut entraîner différents problèmes pendant le déploiement. Voir mon article de blog "Ne pas modifier les références de projet" Copier local "à false, sauf si vous comprenez les sous-séquences." ( Geekswithblogs.net/mnf/archive/2012/12/09/… )
Michael Freidgeim
Est-ce que "construire dans un dossier de sortie" peut causer des problèmes lors de la compilation avec plusieurs threads?
BrunoLM
9

+1 pour une utilisation économe des dossiers de solutions pour aider à organiser les choses.

+1 pour la construction du projet dans son propre dossier. Nous avons d'abord essayé un dossier de sortie commun et cela peut conduire à des références subtiles et pénibles à trouver.

FWIW, nous utilisons des références de projet pour les solutions, et bien que nuget soit probablement un meilleur choix de nos jours, nous avons trouvé que svn: externals fonctionne bien pour les assemblys internes tiers et (de type framework). Prenez simplement l'habitude d'utiliser un numéro de révision spécifique au lieu de HEAD lorsque vous faites référence à svn: externals (coupable comme chargé :)

si618
la source
2
+1 J'ai également des problèmes avec la solution de dossier de sortie commune. Je n'ai pas compris ce que signifie «références de projet pour les solutions», veuillez expliquer un peu plus ...
Mauricio Scheffer
Comme dans nous utilisons VS-> Ajouter une référence-> Projets, au lieu de VS-> Ajouter une référence-> Parcourir. Petit point que je sais mais certaines personnes le font différemment (et je pense que cela cause plus de maux de tête). Si vous regardez le texte MSBuild csproj, vous verrez la propriété ProjectReference au lieu de Reference.
si618
Réponse intéressante! Je pense que nous avons zigzagué là où vous zagiez. Nous n'avons aucun dossier de solution et nous nous appuyons sur la dénomination des projets (les projets sont nommés de la même manière que l'espace de noms). Tous nos résultats vont dans un seul dossier, ce qui rend la configuration du développeur beaucoup plus proche de celle du déploiement. Si les dépendances sont définies correctement, nous n'avons pas de références obsolètes.
Thomas Bratt
oui, le répertoire de sortie commun conduit à beaucoup de douleur, en particulier lors de l'utilisation de resharper. Références périmées en effet.
Florian Doyon
1
@Kevin, cela fait plusieurs années maintenant, mais de mémoire un exemple est deux projets référençant le même assembly, disons une bibliothèque externe qui n'est pas référencée par projet. Tout va bien quand ils sont sur la même version, mais une nouvelle version de cette bibliothèque sort, mais un seul projet met à jour sa référence, quelle version est utilisée dans le dossier de sortie commun?
si618
8

Déchargez les projets que vous n'utilisez pas souvent et achetez un SSD. Un SSD n'améliore pas le temps de compilation, mais Visual Studio devient deux fois plus rapide à ouvrir / fermer / construire.

Nicolas Dorier
la source
3
Il convient de noter que le déchargement d'un projet est un paramètre par utilisateur, de sorte que les développeurs de votre équipe ne peuvent charger que les projets qui les intéressent. Cela a vraiment aidé notre équipe.
Page
Vous pouvez utiliser l'extension de Solution Load Manager visualstudiogallery.msdn.microsoft.com/ ... pour définir ce qu'il ne faut pas charger par défaut
Michael Freidgeim
6

Nous avons un problème similaire car nous avons 109 projets distincts à traiter. Pour répondre aux questions originales en fonction de nos expériences:

1. Comment gérer au mieux les références entre les projets

Nous utilisons l'option de menu contextuel «ajouter une référence». Si «projet» est sélectionné, la dépendance est ajoutée par défaut à notre fichier de solution global unique.

2. La "copie locale" doit-elle être activée ou désactivée?

Off dans notre expérience. La copie supplémentaire ne fait qu'ajouter aux temps de construction.

3. Chaque projet doit-il être généré dans son propre dossier ou doit-il tous être généré dans le même dossier de sortie (ils font tous partie de la même application)

Toutes nos sorties sont placées dans un seul dossier appelé «bin». L'idée étant que ce dossier est le même que lorsque le logiciel est déployé. Cela permet d'éviter les problèmes qui se produisent lorsque la configuration du développeur est différente de la configuration du déploiement.

4. Les dossiers de solutions sont-ils un bon moyen d'organiser les choses?

Non dans notre expérience. La structure des dossiers d'une personne est le cauchemar d'une autre. Les dossiers profondément imbriqués augmentent simplement le temps nécessaire pour trouver quoi que ce soit. Nous avons une structure complètement plate mais nommons nos fichiers de projet, nos assemblages et nos espaces de noms de la même manière.


Notre façon de structurer les projets repose sur un seul fichier solution. Construire cela prend beaucoup de temps, même si les projets eux-mêmes n'ont pas changé. Pour vous aider, nous créons généralement un autre fichier de solution «ensemble de travail actuel». Tous les projets sur lesquels nous travaillons sont ajoutés à cela. Les temps de construction sont considérablement améliorés, bien qu'un problème que nous ayons vu est qu'Intellisense échoue pour les types définis dans les projets qui ne sont pas dans l'ensemble actuel.

Un exemple partiel de notre disposition de solution:

\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
la source
Est-ce que "construire dans un dossier de sortie" peut causer des problèmes lors de la compilation avec plusieurs threads?
BrunoLM
4

Nous travaillons ici sur un grand projet similaire. Les dossiers de solutions se sont avérés être un bon moyen d'organiser les choses, et nous avons tendance à laisser la copie locale sur true. Chaque projet se construit dans son propre dossier, puis nous savons que pour chaque projet déployable, nous avons le sous-ensemble correct des binaires en place.

En ce qui concerne l'ouverture du temps et la construction du temps, cela va être difficile à résoudre sans se casser en solutions plus petites. Vous pouvez étudier la mise en parallèle de la construction (google "Parallel MS Build" pour un moyen de le faire et de l'intégrer dans l'interface utilisateur) pour améliorer la vitesse ici. En outre, regardez la conception et voyez si la refactorisation de certains de vos projets pour en réduire globalement peut aider.

David M
la source
3

En termes de facilité de construction, vous pouvez utiliser l'option "Configuration Manager ..." pour les builds afin d'activer ou de désactiver la construction de projets spécifiques. Vous pouvez avoir un "Projet [n] Build" qui pourrait exclure certains projets et l'utiliser lorsque vous ciblez des projets spécifiques.

En ce qui concerne les plus de 100 projets, je sais que vous ne voulez pas être martelé dans cette question sur les avantages de réduire la taille de votre solution, mais je pense que vous n'avez pas d'autre option pour accélérer le temps de chargement (et utilisation de la mémoire) de devenv.

Michael Meadows
la source
Hm, a-t-il été critiqué pour avoir tort ou simplement pour être en désaccord? Je peux vivre avec le premier si vous pouvez me dire pourquoi.
Michael Meadows
D'accord, je n'aime pas voter contre le vote sans commentaire, alors Michael vous obtenez mon +1 pour équilibrer l'équation ;-)
si618
2
btw, personnellement, je n'aime pas me débrouiller avec la gestion de la configuration pour ce genre de chose. Pourquoi? car si vous validez accidentellement votre configuration modifiée, votre serveur de build ou d'autres développeurs seront affectés.
si618
D'accord. En fait, le même problème s'applique aux solutions comportant trop de projets. :)
Michael Meadows
3

Ce que je fais généralement avec cela dépend un peu de la façon dont le processus de "débogage" se déroule réellement. En règle générale, je ne règle PAS la copie locale sur true. J'ai configuré le répertoire de construction pour chaque projet pour tout afficher au point final souhaité.

Par conséquent, après chaque build, j'ai un dossier rempli avec toutes les DLL et toutes les applications Windows / Web et tous les éléments sont au bon endroit. La copie locale n'était pas nécessaire puisque la DLL finit par se retrouver au bon endroit.

Remarque

Ce qui précède fonctionne pour mes solutions, qui sont généralement des applications Web et je n'ai rencontré aucun problème avec les références, mais cela pourrait être possible!

Vendeurs Mitchel
la source
3

Nous avons un problème similaire. Nous le résolvons en utilisant des solutions plus petites. Nous avons une solution principale qui ouvre tout. Mais perf. là-dessus est mauvais. Nous segmentons donc les solutions plus petites par type de développeur. Ainsi, les développeurs de bases de données ont une solution qui charge les projets qui les intéressent, les développeurs de services et les développeurs d'interface utilisateur la même chose. Il est rare que quelqu'un doive ouvrir toute la solution pour faire ce dont il a besoin au jour le jour. Ce n'est pas une panacée - il a ses avantages et ses inconvénients. Voir "modèle multi-solution" dans cet article (ignorez la partie sur l'utilisation de VSS :)

JP Alioto
la source
2

Je pense qu'avec des solutions de cette envergure, la meilleure pratique devrait être de les briser. Vous pouvez penser à la «solution» comme un lieu pour rassembler les projets nécessaires et peut-être d'autres pièces pour travailler sur une solution à un problème. En divisant les plus de 100 projets en plusieurs solutions spécialisées dans le développement de solutions pour une partie seulement du problème global, vous pouvez en traiter moins à un moment donné en accélérant vos interactions avec les projets requis et en simplifiant le domaine du problème.

Chaque solution produirait le résultat dont elle est responsable. Cette sortie doit avoir des informations de version qui peuvent être définies dans un processus automatisé. Lorsque la sortie est stable, vous pouvez mettre à jour les références dans les projets et solutions dépendants avec la dernière distribution interne. Si vous souhaitez toujours entrer dans le code et accéder à la source, vous pouvez le faire avec le serveur de symboles Microsoft que Visual Studio peut utiliser pour vous permettre d'accéder aux assemblys référencés et même d'extraire le code source.

Le développement simultané peut être effectué en spécifiant les interfaces à l'avance et en se moquant des assemblys en cours de développement pendant que vous attendez des dépendances qui ne sont pas complètes mais que vous souhaitez développer.

Je trouve que c'est une bonne pratique car il n'y a pas de limite à la complexité de l'effort global lorsque vous le décomposez physiquement de cette manière. Mettre tous les projets dans une seule solution atteindra finalement une limite supérieure.

J'espère que cette information vous aidera.

Blake Taylor
la source
2

Nous avons environ 60 projets et nous n'utilisons pas de fichiers de solution. Nous avons un mélange de projets C # et VB.Net. La performance était toujours un problème. Nous ne travaillons pas sur tous les projets en même temps. Chaque développeur crée ses propres fichiers de solution en fonction des projets sur lesquels il travaille. Les fichiers de solution ne sont pas archivés dans notre contrôle de source.

Tous les projets de bibliothèque de classes seraient générés dans un dossier CommonBin à la racine du répertoire source. Les projets exécutables / Web sont créés dans leur dossier individuel.

Nous n'utilisons pas de références de projet, mais plutôt une référence basée sur un fichier du dossier CommonBin. J'ai écrit une tâche MSBuild personnalisée qui inspecterait les projets et déterminerait l'ordre de construction.

Nous l'utilisons depuis quelques années maintenant et nous n'avons rien à redire.

Vasu Balakrishnan
la source
3
Voulez-vous partager votre tâche msbuild personnalisée?
andreapier
0

Tout est lié à votre définition et à votre vision de ce que sont une solution et un projet. Dans mon esprit, une solution n'est que cela, un regroupement logique de projets qui résolvent une exigence très spécifique. Nous développons une grande application Intranet. Chaque application de cet intranet a sa propre solution, qui peut également contenir des projets pour les services exes ou Windows. Et puis nous avons un framework centralisé avec des choses comme les classes de base et les helpers et httphandlers / httpmodules. Le framework de base est assez volumineux et est utilisé par toutes les applications. En répartissant ainsi les nombreuses solutions, vous réduisez le nombre de projets requis par une solution, car la plupart d'entre eux n'ont rien à voir les uns avec les autres.

Avoir autant de projets dans une solution est tout simplement une mauvaise conception. Il ne devrait y avoir aucune raison d'avoir autant de projets sous une solution. L'autre problème que je vois est avec les références de projet, elles peuvent vraiment vous foutre en l'air, surtout si vous souhaitez diviser votre solution en plus petites.

Mon conseil est de le faire et de développer un cadre centralisé (votre propre implémentation d'Enterprise Library si vous voulez). Vous pouvez soit le partager en GAC, soit référencer directement l'emplacement du fichier afin d'avoir un magasin central. Vous pouvez également utiliser la même tactique pour les objets métier centralisés.

Si vous souhaitez référencer directement la DLL, vous voudrez la référencer dans votre projet avec une copie locale false (quelque part comme c: \ mycompany \ bin \ mycompany.dll). Un environnement d'exécution, vous devrez ajouter des paramètres à votre app.config ou web.config pour qu'il fasse référence à un fichier qui ne se trouve pas dans le GAC ou le bac d'exécution. En réalité, peu importe si c'est une copie locale ou non, ou si la dll se retrouve dans la corbeille ou est même dans le GAC, car la configuration remplacera les deux. Je pense que c'est une mauvaise pratique de copier localement et d'avoir un système en désordre. Vous devrez probablement copier localement temporairement si vous avez besoin de déboguer dans l'un de ces assemblys.

Vous pouvez lire mon article sur la façon d'utiliser une DLL globalement sans le GAC. Je n'aime vraiment pas le GAC principalement parce qu'il empêche le déploiement de xcopy et ne déclenche pas de redémarrage automatique sur les applications.

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

utilisateur306031
la source
0

Définir CopyLocal = false réduira le temps de génération, mais peut entraîner différents problèmes pendant le déploiement.

Il existe de nombreux scénarios, lorsque vous avez besoin de laisser Copy Local 'sur True, par exemple les projets de niveau supérieur, les dépendances de second niveau, les DLL appelées par réflexion.

Mon expérience avec la définition de CopyLocal = false n'a pas réussi. Voir le résumé des avantages et des inconvénients dans mon article de blog "Ne pas modifier les références de projet" Copier local "en false, à moins de comprendre les sous-séquences.

Michael Freidgeim
la source