J'ai écrit mes pensées sur les classes statiques dans un fil précédent :
J'aimais les classes utilitaires remplies de méthodes statiques. Ils ont procédé à une excellente consolidation des méthodes d'assistance qui, autrement, auraient été générées, entraînant redondance et maintenance. Ils sont très faciles à utiliser, aucune instanciation, aucune élimination, rien que du feu. J'imagine que c'était ma première tentative involontaire de créer une architecture orientée service - de nombreux services sans état qui faisaient simplement leur travail et rien d'autre. Cependant, à mesure que le système se développe, les dragons arrivent.
Polymorphisme
Disons que nous avons la méthode UtilityClass.SomeMethod qui bourdonne joyeusement. Tout à coup, nous devons modifier légèrement les fonctionnalités. La plupart des fonctionnalités sont les mêmes, mais nous devons néanmoins modifier quelques éléments. Si cela n’avait pas été une méthode statique, nous pourrions créer une classe de dérivés et modifier le contenu de la méthode selon les besoins. Comme c'est une méthode statique, nous ne pouvons pas. Bien sûr, si nous devons simplement ajouter des fonctionnalités avant ou après l’ancienne méthode, nous pouvons créer une nouvelle classe et appeler l’ancienne à l’intérieur de celle-ci - mais c’est tout simplement dégoûtant.
Malheurs d'interface
Les méthodes statiques ne peuvent pas être définies via des interfaces pour des raisons logiques. Et comme nous ne pouvons pas redéfinir les méthodes statiques, les classes statiques sont inutiles lorsque nous devons les transmettre par leur interface. Cela nous rend incapables d'utiliser des classes statiques dans le cadre d'un modèle de stratégie. Nous pourrions corriger certains problèmes en passant des délégués à la place des interfaces.
Essai
Cela va fondamentalement de pair avec les problèmes d’interface mentionnés ci-dessus. Notre capacité d'interchanger les implémentations étant très limitée, nous aurons également du mal à remplacer le code de production par le code de test. Encore une fois, nous pouvons les envelopper mais cela nous demandera de modifier de grandes parties de notre code simplement pour pouvoir accepter des wrappers à la place des objets réels.
Favorise les blobs
Comme les méthodes statiques sont généralement utilisées en tant qu'utilitaires et que leurs méthodes ont des objectifs différents, nous allons rapidement nous retrouver avec une classe volumineuse remplie de fonctionnalités non cohérentes. Idéalement, chaque classe doit avoir un objectif unique au sein du système. Je préférerais de beaucoup avoir cinq fois les classes tant que leurs objectifs sont bien définis.
Paramètre fluage
Pour commencer, cette petite méthode statique mignonne et innocente peut prendre un seul paramètre. À mesure que la fonctionnalité augmente, deux nouveaux paramètres sont ajoutés. Bientôt d'autres paramètres, facultatifs, sont ajoutés. Nous créons donc des surcharges de la méthode (ou ajoutons simplement des valeurs par défaut, dans les langues qui les prennent en charge). D'ici peu, nous avons une méthode qui prend 10 paramètres. Seuls les trois premiers sont vraiment nécessaires, les paramètres 4 à 7 sont facultatifs. Mais si le paramètre 6 est spécifié, vous devez également renseigner 7-9 ... Si nous avions créé une classe dans le seul but de faire ce que cette méthode statique a fait, nous pourrions résoudre ce problème en prenant les paramètres requis dans le fichier. constructeur, et en permettant à l'utilisateur de définir des valeurs facultatives via des propriétés ou des méthodes permettant de définir plusieurs valeurs interdépendantes en même temps. Aussi,
Demander aux consommateurs de créer une instance de classes sans raison
Un des arguments les plus courants est, pourquoi demander aux consommateurs de notre classe de créer une instance pour invoquer cette méthode unique, sans utiliser l’instance par la suite? Créer une instance d'une classe est une opération très très économique dans la plupart des langues, la rapidité n'est donc pas un problème. L'ajout d'une ligne de code supplémentaire au consommateur représente un faible coût pour poser les bases d'une solution beaucoup plus facile à gérer dans le futur. Enfin, si vous souhaitez éviter de créer des instances, créez simplement un wrapper singleton de votre classe qui permette une réutilisation facile - bien que cela rende l'exigence que votre classe soit sans état. Si ce n'est pas sans état, vous pouvez toujours créer des méthodes de wrapper statiques qui gèrent tout, tout en vous offrant tous les avantages à long terme. Finalement,
Seul un Sith traite en absolus
Bien sûr, il y a des exceptions à mon aversion pour les méthodes statiques. Les vraies classes d'utilitaires qui ne posent aucun risque de gonflement constituent d'excellents cas pour les méthodes statiques - System.Convert par exemple. Si votre projet est unique et ne nécessite aucune maintenance future, l'architecture globale n'est pas très importante - statique ou non statique, peu importe - la vitesse de développement l'est toutefois.
Normes, normes, normes!
L'utilisation de méthodes d'instance ne vous empêche pas d'utiliser également des méthodes statiques, et inversement. Tant que la différenciation est raisonnée et normalisée. Il n'y a rien de pire que de regarder une couche métier contenant différentes méthodes d'implémentation.