Question

Existe-t-il de bonnes utilisations des classes partielles en dehors des scénarios de code générés par webforms / winforms? Ou est-ce que cette fonctionnalité est essentiellement pour supporter ça?

Était-ce utile?

La solution

Il est en partie nécessaire de prendre en charge des scénarios (WebForms, WinForms, LINQ-to-SQL, etc.) mélangeant du code généré avec du code de programmeur.

Il y a plus de raisons de l'utiliser. Par exemple, si vous avez des classes volumineuses dans des fichiers volumineux et encombrants, mais que les classes ont des groupes de méthodes liées logiquement, des classes partielles peuvent être une option pour rendre vos tailles de fichiers plus gérables.

Autres conseils

La génération de code était la force motrice derrière les classes partielles. Le besoin vient du fait que la classe générée par le code change constamment, mais permet aux développeurs de fournir du code personnalisé en tant que partie de la classe qui ne sera pas remplacée à chaque fois que des modifications sont effectuées qui forcent la classe à être régénérée.

Prenez WinForms ou Typed-DataSets par exemple (ou n’importe quel concepteur, par exemple). Chaque fois que vous modifiez le concepteur, il sérialise le code correspondant dans un fichier. Supposons que vous deviez fournir quelques méthodes supplémentaires que le générateur ne sait pas. Si vous l’ajoutiez au fichier généré, vos modifications seraient perdues lors de la prochaine génération.

Un projet sur lequel je travaille actuellement utilise la génération de code pour toutes les entités DAL, BLL et commerciales. Cependant, le générateur ne nous envoie que 75% des informations. La partie restante doit être codée à la main (logique métier personnalisée, par exemple). Je peux supposer que chaque classe BLL a une méthode SelectAll, ce qui facilite sa génération. Cependant, mon client BLL doit également disposer d'une méthode SelectAllByLocation. Je ne peux pas mettre cela dans mon générateur car ce n'est pas générique pour toutes les classes de BLL. Par conséquent, je génère toutes mes classes en tant que classes partielles, puis, dans un fichier séparé, je définis mes méthodes personnalisées. Désormais, lorsque ma structure changera ou que je devrai régénérer ma BLL pour une raison quelconque, mon code personnalisé ne sera pas effacé.

J'utilise des classes partielles pour séparer les différents sous-éléments des contrôles personnalisés que j'écris. En outre, lorsqu'il est utilisé avec un logiciel de création d'entités, il permet à des produits tels que LLBLGen de créer des versions générées de classes, ainsi qu'une version personnalisée modifiée par l'utilisateur, qui ne sera pas remplacée si les entités doivent être régénérées.

J'utilise souvent des classes partielles pour donner à chaque classe imbriquée son propre fichier. J'ai travaillé sur certaines architectures dans lesquelles la plupart des implémentations n'étaient requises que par une classe. Nous avons donc imbriqué ces classes dans cette classe. Il était logique de garder les fichiers plus faciles à gérer en utilisant la capacité de classe partielle et en scindant chacun dans son propre fichier.

Nous les avons également utilisées pour regrouper des substitutions de stock ou pour masquer un ensemble de propriétés stock. Des choses comme ça. C'est un moyen pratique de mélanger une modification de stock (il suffit de copier le fichier et de changer le nom de la classe partielle en classe cible - tant que la classe cible est également partielle, bien sûr).

Une autre utilisation possible des classes partielles serait de tirer parti des méthodes partielles pour faire disparaître les méthodes de manière sélective à l'aide de la compilation conditionnelle - ce qui serait très utile pour le code de diagnostic en mode débogage ou les scénarios de tests unitaires spécialisés.

Vous pouvez déclarer une méthode partielle un peu comme une méthode abstraite, puis dans l’autre classe partielle, lorsque vous tapez le mot clé "quot-partial". vous pouvez tirer parti d'Intellisense pour créer l'implémentation de cette méthode.

Si vous entourez une partie avec des instructions de construction conditionnelles, vous pouvez facilement couper le code de débogage ou de test. Dans l'exemple ci-dessous, en mode DEBUG, la méthode LogSomethingDebugOnly est appelée, mais dans la version de publication, c'est comme si la méthode n'existait pas du tout. C'est un bon moyen d'éloigner le code de diagnostic du code de production sans créer de branche ou plusieurs blocs de compilation conditionnels.

// Main Part
public partial class Class1
{
    private partial void LogSomethingDebugOnly();

    public void SomeMethod()
    {
        LogSomethingDebugOnly();
        // do the real work
    }
}

// Debug Part - probably in a different file
public partial class Class1
{

    #if DEBUG

    private partial void LogSomethingDebugOnly()
    {
        // Do the logging or diagnostic work
    }

    #endif
}

LINQ to SQL utilise bien les classes partielles pour étendre le code généré par le concepteur. Je pense que vous trouverez généralement ce modèle de classes partielles utilisé par le code créé par le concepteur.

Je trouve les cours partiels extrêmement utiles. Ils sont généralement utilisés pour pouvoir étendre les classes générées automatiquement. Je les ai utilisés dans un projet avec des tests unitaires lourds. Mes classes UT avaient des dépendances complexes et il n'était pas très pratique de séparer le code entre plusieurs classes. Bien sûr, il est préférable d'utiliser l'héritage \ composition, mais dans certains cas, des classes partielles peuvent s'avérer utiles.

Comme mentionné précédemment, je pense moi aussi qu'il s'agit d'une odeur de code.

Si une classe est si grande qu'elle doit être divisée en davantage de fichiers, cela signifie qu'elle enfreint le principe de responsabilité unique et fait trop de choses. La grande classe pourrait être divisée en petites classes qui coopèrent ensemble.

Si vous devez utiliser des classes ou des régions partielles pour organiser le code, demandez-vous si elles doivent figurer dans leurs propres classes. Cela améliore la lisibilité et permet une meilleure réutilisation du code.

peut-être que c'est trop tard, mais laissez-moi ajouter mes 2 centimes aussi:

*. Lorsque vous travaillez sur de gros projets, la répartition d'une classe sur des fichiers distincts permet à plusieurs programmeurs de travailler simultanément.

*. Vous pouvez facilement écrire votre code (pour des fonctionnalités étendues) pour une classe générée par VS.NET. Cela vous permettra d’écrire le code de vos propres besoins sans jouer avec le code généré par le système

Où je suis, nous avons un programme qui gère les fichiers entrants provenant de clients. Il est configuré pour que le code de chaque client se trouve dans son propre projet de bibliothèque de classes, qui sait gérer le format choisi par le client.

Le code principal utilise les bibliothèques en définissant une interface assez étendue qu'une classe de la bibliothèque doit implémenter (probablement quelques interfaces distinctes, mais il est trop tard pour la changer maintenant). Parfois, cela implique beaucoup plus de code dans la même classe que ce que nous pensons normalement prudent. Les classes partielles nous permettent de les séparer un peu.

Sur UserControls, qui sont relativement compliqués, je mets le traitement des événements dans un fichier et la peinture et les propriétés dans un autre fichier. Les classes partielles fonctionnent très bien pour cela. Généralement, ces parties de la classe sont relativement indépendantes et il est agréable de pouvoir modifier la peinture et la gestion des événements côte à côte.

J'ai travaillé sur un projet il y a quelques années dans lequel nous avions une classe DataSet typée contenant une tonne de code: Méthodes dans les DataTables, méthodes dans les TableAdapters, déclarations d'instances TableAdapter, nommez-les. C’était un point central du projet sur lequel tout le monde devait travailler souvent, et le fichier de code de classe partiel était sujet à de nombreux conflits de contrôle de la source.

J'ai donc divisé le fichier de code en six fichiers de classe fixes ou partiels, regroupés par fonction, afin que nous puissions travailler sur des éléments plus petits sans avoir à verrouiller l'ensemble du fichier à chaque fois que nous devions modifier quelque chose.

(Bien entendu, nous aurions également pu résoudre le problème en n'utilisant pas un système de contrôle de source à verrouillage exclusif, mais c'est un autre problème.)

En général, je considère cela comme une odeur de code.

Si votre classe est aussi compliquée, elle peut probablement être divisée en composants réutilisables plus petits.

Ou cela signifie qu'il n'y a pas de hiérarchie d'héritage où il devrait y en avoir une.

Pour les scénarios de génération de code, c'est bon, mais je pense que la génération de code est une autre odeur de code.

Je suis en retard dans le jeu ... mais seulement mes 2 centimes ...

Une utilisation possible pourrait être de refactoriser une classe divine existante dans une base de code existante en plusieurs classes partielles. Cela pourrait améliorer la possibilité de découverte du code - si la convention de dénomination appropriée est suivie pour les noms de fichier contenant les classes partielles. Cela pourrait également réduire le référentiel de code source: résolution et fusion dans une certaine mesure.

Idéalement, une classe de divinités devrait être divisée en plusieurs petites classes, chacune ayant une responsabilité unique. Parfois, il est perturbant de procéder à des refactorisations moyennes à grandes. Dans de tels cas, des classes partielles pourraient fournir un soulagement temporaire.

Correction, comme Matt l'a souligné, les deux côtés de la partie doivent être dans le même assemblage. mon mauvais.

Je l'utilise dans une couche d'accès aux données. Les classes générées comme le mappeur et interrogent un partiel. Si j’ai besoin d’ajouter une méthode de mappage, par exemple pour effectuer un chargement de fantaisie non généré, je l’ajoute à la classe personnalisée.

À la fin, le programmeur qui utilise la couche de données de la couche de gestion ne voit qu’une classe avec toutes les fonctionnalités dont il a besoin. Et si la source de données change, les pièces génériques peuvent facilement être générées sans écraser les éléments personnalisés.

Je viens de trouver un usage pour les classes partielles. J'ai une classe [DataContract] que j'utilise pour transmettre des données au client. Je voulais que le client puisse afficher la classe d'une manière spécifique (sortie texte). J'ai donc créé une classe partielle et substitué la méthode ToString.

Parfois, vous pouvez trouver un code terriblement vieux au travail qui peut rendre presque impossible la refactorisation en éléments distincts sans détruire le code existant.

Lorsque vous n'avez pas le choix ni le temps de créer une architecture plus authentique, les classes partielles facilitent incroyablement la séparation de la logique lorsque cela est nécessaire. Cela permet au code existant de continuer à utiliser la même architecture tout en vous rapprochant d’une architecture plus concrète.

Partout où vous auriez utilisé des sections #region , cela serait probablement plus logique en tant que fichiers séparés dans des classes partielles.

Personnellement, j'utilise des classes partielles pour les grandes classes où les membres statiques vont dans un fichier et les membres d'instance dans l'autre.

EDIT: les outils DSL pour Visual Studio utilisent des classes partielles.

C’est donc une fonctionnalité utilisée par de nombreux codes générés automatiquement. Au lieu d'utiliser #region, le code généré automatiquement va dans un fichier et le code utilisateur (aussi appelé code personnalisé) dans un autre et même dans des répertoires différents, afin que le développeur ne soit pas confondu avec autant de fichiers sans signification.

C’est bien d’avoir ce choix que vous pouvez combiner - mais pas obligé d’utiliser - avec un héritage

De plus, il peut être utile de séparer la logique de certaines classes entre plusieurs répertoires. Bien sûr, pour les machines, c'est la même chose, mais cela améliore l'expérience de lisibilité de l'utilisateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top