J'ai vu ce fil
Si une classe "Utilitaires" est mauvaise, où dois-je mettre mon code générique?
et pensé pourquoi les classes d'utilité sont-elles mauvaises?
Disons que j'ai un modèle de domaine qui comprend des dizaines de classes. Je dois être capable de xml-ify instances. Est-ce que je crée une méthode toXml sur le parent? Dois-je créer une classe d'assistance MyDomainXmlUtility.toXml? C'est un cas où le besoin de l'entreprise couvre tout le modèle de domaine - appartient-il vraiment en tant que méthode d'instance? Qu'en est-il s'il existe un tas de méthodes auxiliaires sur la fonctionnalité xml de l'application?
design-patterns
software-design
hvgotcodes
la source
la source
Réponses:
Les classes utilitaires ne sont pas vraiment mauvaises, mais elles peuvent enfreindre les principes qui composent une bonne conception orientée objet. Dans une bonne conception orientée objet, la plupart des classes doivent représenter une seule chose et tous ses attributs et opérations. Si vous opérez sur une chose, cette méthode devrait probablement en faire partie.
Cependant, il y a des moments où vous pouvez utiliser des classes d'utilitaires pour regrouper un certain nombre de méthodes - un exemple étant la
java.util.Collections
classe qui fournit un certain nombre d'utilitaires pouvant être utilisés sur n'importe quelle collection Java. Ceux-ci ne sont pas spécifiques à un type particulier de collection, mais implémentent à la place des algorithmes qui peuvent être utilisés sur n'importe quelle collection.En réalité, ce que vous devez faire est de réfléchir à votre conception et de déterminer où il est le plus logique de placer les méthodes. Habituellement, il s'agit d'opérations à l'intérieur d'une classe. Cependant, parfois, il s'agit bien d'une classe d'utilité. Cependant, lorsque vous utilisez une classe utilitaire, ne vous contentez pas d'y lancer des méthodes aléatoires, organisez plutôt les méthodes par objectif et fonctionnalité.
la source
Je pense que le consensus général est que les classes d'utilité ne sont pas mauvaises en soi . Il vous suffit de les utiliser judicieusement:
Concevez les méthodes d'utilité statique pour qu'elles soient générales et réutilisables. Assurez-vous qu'ils sont apatrides; c'est-à-dire pas de variables statiques.
Si vous avez beaucoup de méthodes utilitaires, partitionnez-les en classes de manière à ce que les développeurs puissent les trouver facilement.
N'utilisez pas de classes utilitaires où les méthodes statiques ou d'instance dans une classe de domaine seraient une meilleure solution. Par exemple, considérez si les méthodes d'une classe de base abstraite ou d'une classe d'assistance instanciable seraient une meilleure solution.
À partir de Java 8, les «méthodes par défaut» dans une interface peuvent être une meilleure option que les classes utilitaires. (Voir Interface avec les méthodes par défaut vs classe abstraite dans Java 8 par exemple.)
L'autre façon de regarder cette Question est d'observer que dans la Question citée, "Si les classes d'utilité sont" mauvaises "" est un argument d'homme de paille. C'est comme si je demandais:
Dans la question ci-dessus, je ne dis pas en fait que les porcs peuvent voler ... ou que je suis d'accord avec la proposition selon laquelle ils pourraient voler.
Les déclarations typiques «xyz is evil» sont des artifices rhétoriques destinés à vous faire réfléchir en posant un point de vue extrême. Ils sont rarement (voire jamais) conçus comme des déclarations de fait littéral.
la source
Les classes d'utilité sont problématiques car elles ne regroupent pas les responsabilités avec les données qui les prennent en charge.
Ils sont cependant extrêmement utiles et je les construis tout le temps en tant que structures permanentes ou en tant que tremplins lors d'un refactor plus approfondi.
Du point de vue du code propre , les classes d'utilitaires enfreignent la responsabilité unique et le principe ouvert-fermé. Ils ont de nombreuses raisons de changer et ne sont pas extensibles par conception. Ils ne devraient vraiment exister que lors du refactoring en tant que cruft intermédiaire.
la source
class
mot-clé est utilisé. Il caracole comme un espace de noms, il marche comme un espace de noms - c'est un ...x.equals(y)
parce que 1) le fait que cela ne devrait vraiment modifier aucun état n'est pas véhiculé (et je ne peux pas m'y fier sans connaître l'implémentation) 2) Je n'ai jamais eu l'intention de mettrex
un " position favorisée "ou" agi sur "par rapport ày
3) Je ne veux pas considérer les" identités "dex
ouy
mais je m'intéresse simplement à leurs valeurs.Je suppose que ça commence à devenir mauvais quand
1) Cela devient trop gros (regroupez-les simplement en catégories significatives dans ce cas).
2) Des méthodes qui ne devraient pas être des méthodes statiques sont présentes
Mais tant que ces conditions ne sont pas remplies, je pense qu'elles sont très utiles.
la source
Widget.compareTo(Widget widget)
par rapport au statiqueWidgetUtils.compare(Widget widgetOne, Widget widgetTwo)
. La comparaison est un exemple de quelque chose qui ne devrait pas être fait de manière statique.Règle de base
Vous pouvez examiner ce problème sous deux angles:
*Util
méthodes générales suggèrent souvent une mauvaise conception de code ou une convention de dénomination paresseuse.Exemple 1. Utilisation correcte des
util
classes / modules. Exemple de bibliothèque externeSupposons que vous rédigiez une application qui gère les prêts et les cartes de crédit. Les données de ces modules sont exposées via des services Web au
json
format. En théorie, vous pouvez convertir manuellement des objets en chaînes qui y figurerontjson
, mais cela réinventerait la roue. La bonne solution serait d'inclure dans les deux modules la bibliothèque externe utilisée pour convertir les objets java au format souhaité. (dans l'image d'exemple, j'ai montré gson )Exemple 2. Utilisation correcte des
util
classes / modules. Écrire le vôtreutil
sans excuses aux autres membres de l'équipeEn tant que cas d'utilisation, supposons que nous devons effectuer certains calculs dans deux modules d'application, mais tous deux doivent savoir quand il y a des jours fériés en Pologne. En théorie, vous pouvez effectuer ces calculs à l'intérieur des modules, mais il serait préférable d'extraire cette fonctionnalité pour séparer le module.
Voici un petit détail, mais important. La classe / module que vous avez écrit n'est pas appelée
HolidayUtil
, maisPolishHolidayCalculator
. Fonctionnellement, c'est uneutil
classe, mais nous avons réussi à éviter les mots génériques.la source
Les classes utilitaires sont mauvaises car elles signifient que vous étiez trop paresseux pour trouver un meilleur nom pour la classe :)
Cela étant dit, je suis paresseux. Parfois, vous avez juste besoin de faire le travail et votre esprit est vide ... c'est alors que les classes "Utilitaires" commencent à s'infiltrer.
la source
En repensant à cette question maintenant, je dirais que les méthodes d'extension C # détruisent complètement le besoin de classes utilitaires. Mais toutes les langues n'ont pas une telle construction dans le génie.
Vous avez également JavaScript, où vous pouvez simplement ajouter une nouvelle fonction directement à l'objet existant.
Mais je ne suis pas sûr qu'il existe vraiment une manière élégante de résoudre ce problème dans un langage plus ancien comme C ++ ...
Un bon code OO est un peu difficile à écrire, et il est difficile à trouver car l'écriture de Good OO nécessite beaucoup plus de temps / de connaissances que d'écrire un code fonctionnel décent.
Et quand vous avez un budget limité, votre patron n'est pas toujours content de voir que vous avez passé toute la journée à écrire un tas de cours ...
la source
Je ne suis pas entièrement d'accord pour dire que les classes d'utilité sont mauvaises.
Bien qu'une classe utilitaire puisse violer les principes OO de certaines manières, ils ne sont pas toujours mauvais.
Par exemple, imaginez que vous vouliez une fonction qui nettoiera une chaîne de toutes les sous-chaînes correspondant à la valeur
x
.stl c ++ (à partir de maintenant) ne prend pas directement en charge cela.
Vous pouvez créer une extension polymorphe de
std::string
.Mais le problème est, voulez-vous vraiment que CHAQUE chaîne que vous utilisez dans votre projet soit votre classe de chaînes étendue?
Il y a des moments où OO n'a pas vraiment de sens, et c'est l'un d'entre eux. Nous voulons que notre programme soit compatible avec d'autres programmes, nous allons donc nous en tenir à
std::string
et créer une classeStringUtil_
(ou quelque chose).Je dirais que c'est mieux si vous vous en tenez à un utilitaire par classe. Je dirais que c'est idiot d'avoir un utilitaire pour toutes les classes ou plusieurs utilitaires pour une classe.
la source
Il est très facile de marquer quelque chose comme un utilitaire simplement parce que le concepteur ne pouvait pas penser à un endroit approprié pour mettre le code. Il existe souvent peu de véritables «utilitaires».
En règle générale, je garde généralement le code dans le paquet où il est utilisé pour la première fois, puis je ne le refactore à un endroit plus générique que si je trouve que plus tard, il est vraiment nécessaire ailleurs. La seule exception est si j'ai déjà un package qui exécute des fonctionnalités similaires / connexes et que le code y correspond le mieux.
la source
Les classes utilitaires contenant des méthodes statiques sans état peuvent être utiles. Ces tests sont souvent très faciles à tester.
la source
Avec Java 8, vous pouvez utiliser des méthodes statiques dans les interfaces ... problème résolu.
la source
La plupart des classes Util sont mauvaises parce que:
Il existe quelques analogies entre les bibliothèques statiques et dynamiques.
la source
Lorsque je ne peux pas ajouter une méthode à une classe (par exemple,
Account
est verrouillée contre les modifications par les développeurs Jr.), j'ajoute simplement quelques méthodes statiques à ma classe Utilities comme ceci:la source
Account
fichier. Ou mieux, optez pour des systèmes de contrôle de source non verrouillables.Account
fichier était verrouillé de sorte que les développeurs Jr. ne peuvent pas y apporter de modifications. En tant que développeur junior, pour contourner cela, il a fait comme ci-dessus. Cela dit, mieux vaut simplement obtenir un accès en écriture au fichier et le faire correctement.Les classes d'utilité ne sont pas toujours mauvaises. Mais ils ne doivent contenir que les méthodes communes à un large éventail de fonctionnalités. S'il y a des méthodes qui ne sont utilisables que parmi un nombre limité de classes, envisagez de créer une classe abstraite en tant que parent commun et mettez-y les méthodes.
la source