web-dev-qa-db-fra.com

Les classes partielles de C # sont-elles de mauvais design?

Je me demande pourquoi le concept de «classe partielle» existe même en C #/VB.NET. Je travaille sur une application et nous lisons un livre (en fait très bon) lié à la plate-forme de développement que nous mettons en œuvre au travail. Dans le livre, l'auteur fournit une grande base de code/wrapper autour de l'API de la plate-forme et explique comment il l'a développée alors qu'il enseigne différents sujets sur le développement de la plate-forme.

Bref, il utilise des classes partielles partout pour simuler un héritage multiple en C # (IMO). Pourquoi il ne s'est pas contenté de diviser les classes en plusieurs classes et d'utiliser la composition me dépasse. Il aura 3 fichiers de «classe partielle» pour constituer sa classe de base, chacun avec 3-500 lignes de code ... Et cela plusieurs fois dans son API.

Trouvez-vous cela justifiable?Si c'était moi, j'aurais suivi le S.R.P. et créé plusieurs classes pour gérer différents comportements requis, puis créé une classe de base qui possède des instances de ces classes en tant que membres (par exemple, une composition). Pourquoi MS a-t-il même mis une classe partielle dans le framework? Ils ont supprimé la possibilité de développer/réduire tout le code à chaque niveau de la portée en C # (cela était autorisé en C++) car il ne permettait évidemment que de mauvaises habitudes - la classe partielle est, IMO, la même chose.Je suppose que ma question est la suivante: pouvez-vous m'expliquer quand il y aurait une raison légitime d'utiliser un cours partiel? 

EDIT: Je sais que pour Web/WinForm, il n’ya pas d’autre choix. Mais en dehors de ça? Pourquoi MS n’a-t-il pas mis un mot-clé différent pour coller des classes gérées par code? Ou existe-t-il vraiment un scénario de conception légitime qui le mérite?

Je ne veux pas dire que ce soit un fil de guerre. Je cherche honnêtement à apprendre quelque chose ici. Quand faut-il utiliser des classes partielles dans la conception de code? Question simple, pas besoin de fermer

Merci

68
dferraro

Pouvez-vous m'expliquer quand il y aurait une raison légitime d'utiliser un cours partiel?

L'une des raisons les plus légitimes et les plus utiles est d'encourager la séparation du code généré automatiquement et de ses propres extensions personnalisées. Par exemple, il est courant d'avoir un code de formulaire généré automatiquement par un concepteur quelconque, mais vous souhaitez généralement y ajouter votre propre comportement spécifique. Ainsi, si vous régénérez la partie de code automatique, vous ne touchez pas la partie qui a vos extensions spécifiques.

Cela dit, il est tout à fait possible d'avoir trop d'une bonne chose. Quelques conseils:

  • Ne faites pas vos classes partial pour être partial.

  • Ne mettez pas de classes partielles nulle part sauf les unes les autres. Si vous devez passer à une section du projet totalement indépendante pour voir l'autre moitié de la classe, vous le faites probablement mal.

  • N'utilisez pas partial comme technique pour masquer la taille de la classe. Si vous interrompez vos classes avec partial parce qu'elles sont trop grandes, vous devriez revenir au principe de la responsabilité unique .

  • Si vous avez trois fragments partial ou plus pour la même classe, c'est presque une garantie que vous abusez de partiels. La limite supérieure typique du caractère raisonnable est deux et elle est généralement utilisée pour segmenter le code généré automatiquement du code manuscrit.

Bref, il utilise des classes partielles partout pour simuler un héritage multiple en C # (IMO). Pourquoi il ne s'est pas contenté de diviser les classes en plusieurs et d'utiliser la composition me dépasse Il aura 3 fichiers de «classe partielle» pour constituer sa classe de base, chacun avec 3-500 lignes de code ... Et cela plusieurs fois dans son API.

Oui, c'est clairement un abus de partial!

97
John Feminella

Il y a deux raisons pour lesquelles j'utiliserais (et ferais) des classes partielles.

  1. Pour séparer des parties du code générées automatiquement (telles que le code du concepteur WinForms ou la sortie T4).
  2. Pour autoriser les types imbriqués à disposer de leur propre fichier tout en réalisant l'encapsulation requise par votre conception.

Mettre à jour
Je vois que certains ne sont pas convaincus de mon deuxième point, alors laissez-moi vous donner un exemple; la ListViewItemCollection dans le cadre. Il est à juste titre imbriqué sous ListView car il est réservé à ListView, mais pour faciliter la maintenance, je lui donnerais son propre fichier en utilisant des classes partielles. Je ne vois pas cela comme une mauvaise conception ou une utilisation abusive du mot clé partial.

Pour plus de discussion, consultez la question que celle-ci duplique: Classes partielles en C #

12
Jeff Yates

Une autre utilisation légitime des classes partielles consiste à aider à réduire l'encombrement du "service Web monolithique" dans WCF. Vous souhaitez le diviser en groupes logiques de fonctionnalités, mais vous ne voulez pas avoir à créer une rame d'instances de service/points de terminaison individuels (probablement parce qu'ils partagent l'état, les ressources, etc.).

La solution? Demandez au service d'implémenter plusieurs interfaces et implémentez chaque interface dans sa propre classe partielle. Mappez ensuite différents points de terminaison de la configuration sur la même implémentation physique. Cela rend le projet beaucoup plus facile à gérer, mais vous n'avez toujours qu'un seul point de terminaison physique.

Dans certains cas, je qualifierais ce type d’approche de mauvaise pratique en raison du PÉR, mais lorsque vous travaillez avec des services de la WCF ou des services Web en général, ce n’est pas si simple. Vous devez équilibrer les exigences de conception internes et les exigences de consommation externes.

11
Aaronaught

Une utilisation moins courante pourrait être de diviser une énorme classe en fichiers physiques distincts pour faciliter la vie du point de vue du contrôle de source. Je viens de rejoindre un projet contenant des classes de services Web extrêmement lourdes, qui fonctionnent avec des milliers de lignes de code et des méthodes associées à plusieurs fonctions commerciales. 

La fusion de diverses branches de fonctionnalités est un cauchemar en raison des différentes équipes qui apportent simultanément des modifications non liées dans le même fichier. Je ne peux pas scinder le service Web sans apporter des modifications sérieuses, mais la diviser en classes partielles préserve le comportement de manière exacte et supprime toute une série de problèmes de fusion. 

Je n'encourage certainement pas ce qui précède en tant que choix de conception, mais c'était une belle victoire rapide pour nous, et cela montre que les partiels ne sont pas mauvais tous le temps ...

7
Jon M

J'ai utilisé des classes partielles de différentes manières dans le passé. En apprenant plus sur la programmation et en particulier sur le concept de "composition préférentielle sur héritage", je peux facilement voir que le besoin diminuait à la fois pour l'héritage vertical et la surutilisation de classes partielles. 

À part le code généré automatiquement, je ne peux pas penser à un bon usage des classes partielles. Même si vous utilisez EF et avez besoin de métadonnées différentes, ils ne recommandent même pas l'utilisation de partiels pour les métadonnées. En fait, si vous essayez de dupliquer des propriétés dans un autre partiel (juste pour ajouter des métadonnées), vous obtiendrez une erreur du compilateur.

Plus nous en apprenons sur la refactorisation et le SOC (séparation des préoccupations), plus nos classes deviennent petites et ciblées. Ils sont par défaut réutilisés, ce qui les rend à la longue pareils et faciles à tester. Il suffit de dire NON aux programmes gargantuesques. Henry Ford a appris ce concept au début des années 1900. Les programmeurs ont commencé à l'apprendre cent ans plus tard.

Utilisez la composition quand vous le pouvez ...

4
John Peters

Pouvez-vous m'expliquer quand il y aurait une raison légitime d'utiliser un cours partiel?

Les versions récentes de Visual Studio utilisent des classes partielles pour séparer le code de concepteur généré automatiquement de votre propre code.

Un exemple ASP.NET:

  • Page.aspx
  • Page.aspx.cs <- Votre code
  • Page.aspx.Designer.cs <- Classe partielle contenant du code généré automatiquement.

Un exemple WinForms:

  • Form1.resx
  • Form1.cs <- Votre code
  • Form1.Designer.cs <- Classe partielle contenant du code généré automatiquement
2
Simon Bartlett

Je suis entièrement d'accord avec la réponse de John . Mais je voudrais aller un peu plus loin.

  • Ne faites pas vos cours partiels.

La seule utilisation de classes partielles que je puisse penser que je considérerais comme "bonne conception" est avec du code généré automatiquement. Toute autre utilisation est presque certainement une division inutile de votre classe. (En fait, je peux voir que le second point de Jeff sur les classes imbriquées est peut-être une utilisation valide)

Personnellement, je pense que ce livre que vous lisez semble de mauvaise qualité, mais considérez qu’il utilise peut-être simplement des classes partielles pour qu’il puisse simplement faire la démonstration d’une partie du code à la fois plutôt que de présenter la classe entière en une fois.

2
Simon P Stevens

J'ai utilisé des classes partielles pour séparer "physiquement" les méthodes d'accès aux données statiques des propriétés et des méthodes de classe métier dans une architecture d'enregistrement active. Par exemple, nous avions côte à côte des classes partielles Company et CompanyData. L'avantage était qu'un fichier était le fichier POCO et que l'autre ne contenait que des méthodes d'accès aux données. Cela a été un tremplin pour supprimer l'accès aux données des classes de référentiel dans une application héritée. Je pense que c'était un usage légitime, cela a certainement rendu le processus de re-factorisation plus sain.

2
Jamie Ide

Je suis tombé par hasard sur ce fil tout en recherchant les avantages de la classe partielle . Je suis en train de convertir une application Java EE en une application .NET basée sur Silverlight .

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.225
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

...

 public partial class Wwcusts04d : System.Windows.Controls.Page {

Maintenant, si la page partielle elle-même est générée automatiquement, à quoi sert-elle de la conserver? De plus, le code à l'intérieur ne fait que relier divers contrôles à leurs noms. Je ne confesse pas avoir la connaissance de silverlight, mais cette chose ne convient-elle pas mieux au xaml?

2
sumit bisht

Une autre utilisation intéressante pour les classes partielles serait lors de l’implémentation du modèle de fabrique abstraite . Rendez l’objet fabrique racine partiel, puis placez les méthodes fabrique réelles dans le même fichier que la classe instanciée par la fabrique. 

EDIT: Les classes partielles fonctionnent également bien pour les classes qui interagissent avec un fichier de configuration. Placez le code contenant les paramètres de configuration à proximité du code qui utilise réellement le paramètre de configuration.

2
Robert Davis

Pour ajouter aux réponses précédentes qui mentionnaient la séparation du code généré du code personnalisé, j'ai trouvé des classes partielles utiles pour l'extension de jeux de données fortement typés.

1
Scott Lawrence

Une classe partielle existe dans le cadre .Net only pour permettre aux concepteurs de Visual Studio (concepteurs Asp.Net et Windows Forms) de générer du code/désordre avec vos classes tout en conservant ce code généré dans un fichier séparé.

(Voir Classes partielles .NET vs héritage )

Si vous faites quelque chose de similaire (générer du code devant coexister avec du code écrit par l'utilisateur), vous trouverez peut-être également des classes partielles utiles, mais je ne pense pas que Microsoft ait jamais prévu que les classes partielles en tant que concept de langage soient utiles à quiconque. autre que l'équipe Visual Studio.

Ce n'est pas tellement que l'utilisation de classes partielles est mauvaise conception - c'est juste que vous ne trouverez probablement pas d'utilisation pour elles.

1
Justin

Il y a beaucoup de discussions sur ce sujet, et beaucoup de gens disent que 1) il est mal conçu d'utiliser des classes partielles, 2) qu'il est utilisé pour du code généré automatiquement et 3) qu'il ne devrait pas remplacer l'héritage.

J'ai toutefois une situation dans laquelle les classes partielles semblent très utiles: je construis une série d'applications qui seront éventuellement intégrées à une suite. Ils auront tous un formulaire principal qui fournira des fonctionnalités et plusieurs composants partagés (par exemple, un formulaire pour afficher des rapports). Alors que je pourrait définir une classe de base et en hériter, cela signifierait beaucoup de travail lorsque le moment sera venu de combiner toutes les applications dans la version "entreprise" du produit.

Ainsi, les classes partielles sont très utiles, car je peux tout simplement inclure les différentes classes partielles dans la version combinée, tout en me permettant de construire les versions individuelles et autonomes du produit. Si j'essayais d'accomplir cela en utilisant l'héritage, chaque composant appellerait sa propre version des composants communs (par exemple, InvoiceReportViewer, PurchasingReportsViewer, etc.) plutôt que d'appeler ReportsViewer, sachant que Visual Studio aurait intégré tous les bits pour moi.

1
David T. Macknet

J'ai utilisé une classe partielle à deux reprises dans VB.Net et les deux fois étaient pour la rare occasion où j'avais besoin d'une liaison tardive. Créez simplement une classe partielle et désactivez Option Strict en haut.

1
Jules

Une autre chose à considérer, les classes partial vous oblige à créer différents noms de fichiers contenant le même nom de classe. Par exemple, vous avez FactoryClass et vous en créez des versions partielles comme: Factory.designer.cs, Factory.data.cs et tous ces fichiers ont une classe nommée FactoryClass.

Si vous naviguez vers this question; il existe une meilleure pratique définie comme:

La meilleure pratique consiste toutefois à définir une classe par fichier et à lui attribuer le même nom que la classe (ou la structure, etc.) définie.

0
Teoman shipahi