La possibilité de découverte pour les développeurs est-elle un problème lors de l'utilisation des principes SOLID?

10

Je fais des applications métier où tous les autres développeurs sont habitués à faire des applications CRUD de base ou se concentrent uniquement sur la création d'interfaces jolies / fonctionnelles et j'obtiens beaucoup les éléments suivants.

"Avec la façon dont nous le faisons, l'employé aurait tout ce que vous pourriez faire avec un employé." Et c'était vrai. Cette «classe» avait des milliers de lignes de code et tout ce que vous pouviez faire avec un employé était là. Ou, pire encore, il y avait un tableau de données sur les employés et chaque développeur a compris comment faire ce qu'il voulait faire dans le gestionnaire d'événements.

Toutes les mauvaises choses de cette approche étaient vraies, mais au moins le développeur utilisant l'employé pouvait, sans aller vers d'autres documents, trouver comment inscrire l'employé dans un plan de santé, donner une augmentation de salaire, licencier, embaucher, transférer, etc. pour Manager et toutes les autres grandes idées. Ou, s'ils utilisaient l'employé d'autres tableaux de données nécessaires, ils pouvaient simplement faire ce qu'ils voulaient.

Oui, il y avait beaucoup de code en double. Oui, c'était un code très fragile. Oui, c'était beaucoup plus difficile que nécessaire. Oui, le changement de fonctionnalité était une source de peur et le copier-coller était naturel en raison de l'approche.

Mais ils pouvaient au moins découvrir ce qui était disponible en créant une classe ou ils pouvaient faire ce qu'ils devaient faire sans avoir à comprendre la différence entre les interfaces, les classes abstraites, les classes concrètes, etc. Et ils n'avaient pas à chercher autre chose que les méthodes renvoyées par intellisense ou connaître les tables où résident les données.

J'ai googlé / bingé et même yahoo! D mais je n'ai trouvé aucune reconnaissance de ce problème.

Alors peut-être qu'il n'y a pas de problème et qu'il me manque juste quelque chose. J'ai creusé la tête en essayant de trouver une solution où le (s) développeur (s) qui ne fonctionnent pas le comportement / la conception réelle peuvent facilement découvrir comment faire quelque chose sans avoir à référencer des documents externes ou à scanner les noms de classe dans les différents composants / projets pour trouver celui qui semble fonctionner.

La seule chose que j'ai pu trouver est de les avoir, faute d'un meilleur nom, "Table of Content Class" qui ne fait rien de plus que renvoyer les classes réelles (et vraiment la plupart d'entre elles sont des interfaces mais elles ne le font pas connaître la différence ou même le soin) que d'autres développeurs peuvent utiliser pour effectuer les tâches souhaitées. On se retrouve toujours avec de très grosses classes mais il n'y a presque aucun comportement en elles.

Existe-t-il un meilleur moyen qui ne nécessite pas une connaissance approfondie du niveau intermédiaire où la mise en œuvre réelle de SOLID a lieu?

Fondamentalement, ce que je demande, c'est qu'il existe un moyen de permettre aux développeurs de type CRUD de continuer à être des développeurs CRUD dans un système très complexe

ElGringoGrande
la source
8
Peut-être que vos développeurs ne dépendent pas entièrement d'IntelliSense (ou équivalent) pour la découverte. Nommez bien les choses. Documentez bien les choses. Il s'agit d'un problème de communication, pas d'un problème technique.
Rein Henrichs
Hmmm. Un peu. Plus j'y pense, plus je crois qu'il y a une opportunité d'affaires qui se cache.
ElGringoGrande
2
@ReinHenrichs: Si le développeur a besoin de lire la documentation, cela leur prendra du temps et la productivité en souffrira. Il est donc important qu'ils découvrent rapidement ce dont ils ont besoin pour une tâche donnée. Il n'a pas besoin de s'appuyer sur intellisense, mais il vaut mieux être facile. Le rendre facile est certainement un problème technique.
Jan Hudec
@JanHudec: Non, ce n'est pas un problème technique mais organisationnel d'utiliser des conventions appropriées pour la dénomination, la mise en page et les espaces. Sans conventions de dénomination, vous ne sauriez pas quoi rechercher. Sans une dénomination cohérente, vous ne trouverez pas tout et / ou vous aurez beaucoup plus de mal à tout retracer. Sans mise en page cohérente et utilisation d'espaces (en particulier dans les déclarations de type), vous ne trouveriez pas la moitié des instances dont vous avez besoin. Oui, une meilleure expression rationnelle pourrait aider, mais je ne veux pas apprendre l'expression rationnelle juste pour trouver où une classe est utilisée.
Marjan Venema
@JanHudec Ce n'est pas un "si" mais un "quand". Les développeurs devront lire la documentation. Si vous voulez qu'ils "découvrent rapidement ce dont ils ont besoin pour une tâche donnée", le mieux est de vous concentrer sur l'efficacité de la documentation. N'essayez pas de résoudre un problème de personnes (comme la communication) avec une solution technique. Il. Est-ce que. Ne pas. Travail.
Rein Henrichs

Réponses:

4

Il semble que ce que vous avez décrit (c.-à-d. La classe Employé ayant TOUT le code possible que vous pourriez faire avec un employé) est un modèle extrêmement courant que j'ai personnellement vu beaucoup. J'ai écrit moi-même une partie de ce code avant d'en savoir plus.

Ce qui commence comme une classe qui est censée représenter une seule entité avec un ensemble de méthodes gérables, se transforme en quelque chose qui est un cauchemar à maintenir car chaque fonctionnalité et chaque version ajoutent de plus en plus à la même classe. Cela va à l'encontre des principes SOLIDES qui disent que vous devez écrire une classe une fois et résister à l'envie de la modifier encore et encore.

Il y a quelque temps (avant de découvrir des modèles de conception ou SOLID promus par d'autres), j'ai décidé pour mon prochain projet de renverser un peu les choses. Je travaillais sur un serveur qui servait d'interface entre deux très grandes plateformes. Au début, seule la synchronisation de la configuration était requise, mais j'ai pu voir que ce serait un endroit logique pour de nombreuses autres fonctionnalités.

Donc, au lieu d'écrire une classe qui expose des méthodes, j'ai écrit des classes qui représentaient des méthodes (se sont avérées être un modèle "Command" de GoF). Au lieu de faire le travail pour le client, toutes mes principales classes d'application sont devenues des détenteurs d'état persistants et elles sont devenues beaucoup plus courtes. Chaque fois que je devais ajouter une nouvelle méthode d'interface au service lui-même, je créais simplement une nouvelle classe qui avait la méthode Execute () qui commençait tout. Si plusieurs commandes avaient quelque chose en commun, elles dérivaient de la classe de base commune. Finalement, la chose avait plus de 70 classes de commande différentes et l'ensemble du projet était encore très gérable et était en fait un plaisir de travailler.

Votre "classe TOC" n'est pas trop loin de ce que j'ai fait. J'avais une usine abstraite (GoF) chargée d'instancier les commandes. Dans la classe d'usine, j'ai caché la plupart des détails derrière la classe de base et les macros de style ATL, donc quand un programmeur devait ajouter ou rechercher une demande, il y allait et tout ce qu'il voyait était:

BEGIN_COMMAND_MAP()
    COMMAND_ENTRY( CChangeDeviceState )
    COMMAND_ENTRY( CSetConfiguration )
    ....
END_COMMAND_MAP()

Alternativement (ou en plus), vous pouvez placer toutes vos classes de commandes réelles dans un espace de noms séparé.Par conséquent, lorsque les gens codent et doivent exécuter quelque chose, ils tapent simplement le nom de l'espace de noms et Intellisense répertorie toutes les commandes que vous avez définies. Ensuite, chaque commande comprend toutes les méthodes get / set qui déterminent exactement quels paramètres d'entrée et de sortie.

Vous pouvez également explorer l'utilisation du modèle de façade (GoF). Au lieu d'exposer plus de 1000 classes à vos ingénieurs CRUD. Cachez-les tous derrière une seule classe qui expose uniquement ce qui est nécessaire. Je m'en tiendrai toujours à ce que chaque "action" soit sa propre classe, mais votre classe Facade peut avoir des méthodes qui instancieraient chacune de vos actions et avec Intellisense, elles verraient immédiatement ce qui est disponible. Ou demandez à Facade d'avoir des méthodes réelles, mais faites-leur en interne instancier des commandes, mettez-les en file d'attente et attendez les réponses. Retournez ensuite comme si un appel de méthode normal avait été effectué.

(*) Je ne voulais pas entrer dans trop de détails, mais j'avais en fait un ensemble de classes "Command" et "CommandHandler". Cela séparait la responsabilité de la gestion / de la mise en file d'attente / de la sérialisation des paramètres d'entrée / sortie des classes qui "géraient" réellement ces commandes.

DXM
la source
Oui. J'ai réalisé aujourd'hui que nous nous sommes retrouvés avec un modèle de façade mal mis en œuvre. Je ne pense pas qu'il y ait autre chose à faire que de casser la grande façade en plus petites. J'aime bien votre idée d'incorporer certaines classes de commande dans les coulisses.
ElGringoGrande
0

Ça peut être un problème. Surtout si vous nommez mal les choses. Mais il existe un certain nombre de solutions sans recourir à des classes complexes. Heck, une classe avec trop de méthodes peut être tout aussi difficile à naviguer avec Intellisense.

Essayez d'utiliser des espaces de noms (C #) ou des packages (Java), ou tout autre concept similaire de votre langage (je les appellerai tous des espaces de noms), pour simplifier le problème.

Commencez par le nom de votre entreprise. Cela limite Intellisense aux seuls espaces de noms écrits par vous-mêmes. Ensuite, si vous avez plusieurs applications, utilisez la deuxième partie de l'espace de noms pour les diviser. Inclure un espace de noms Core, pour les éléments qui existent dans les applications. Décomposez ensuite les choses en types de fonctionnalités. Etc.

Si vous faites cela correctement, vous vous retrouverez avec des objets très découvrables.

Pour prendre votre exemple, si je veux la validation de l'utilisateur, je tape "MyCo". et cela me donne une liste des espaces de noms d'application. Je sais que la base de données des utilisateurs est utilisée dans toutes nos applications, alors je tape "Core". puis j'obtiens une liste de types de fonctionnalités. L'un d'eux est "Validation", ce qui semble être un choix évident. Et là, dans Validation, il y a "UserValidator" avec toutes ses fonctionnalités.

En l'occurrence, pour les choses que j'utilise beaucoup, je me souviendrai rapidement des noms, ou du moins des conventions. Parce que j'apporte de nombreuses modifications aux règles de validation, je saurai que toutes mes classes de validation s'appellent FooValidator, où Foo est le nom de la table. Je n'ai donc pas besoin de parcourir les espaces de noms. Je vais simplement taper UserValidator et laisser l'IDE faire le reste du travail.

Mais pour des choses dont je ne me souviens pas, il est toujours assez facile de les trouver. Et quand je le fais, je peux supprimer le préfixe d'espace de noms.

pdr
la source
C'est en partie une mauvaise dénomination de ma part. Les noms ne sont pas horribles mais je pense souvent à un meilleur mois après coup. Mais même avec de bons noms, si vous avez des milliers de classes, les noms ne sont pas toujours faciles à découvrir. J'essaie de surmonter cela. J'ai juste pensé qu'il pourrait y avoir un moyen connu.
ElGringoGrande
0

Puisque vous les référez en gros à des développeurs "CRUD", nous supposerons que vous pensez qu'ils ne sont pas très bons. Nous ne savons pas si cela signifie qu'ils ne comprennent pas non plus votre domaine d'activité. S'ils comprennent le domaine, les classes devraient avoir du sens pour eux. Sachant que plusieurs classes ont été construites, elles devraient d'abord jeter un coup d'œil, demander ensuite, envisager de construire à partir de zéro comme troisième option.

Pour ce qui est de savoir comment savoir automatiquement comment utiliser / réutiliser une classe rien qu'en la regardant, il ne faut pas s'attendre la première fois. Vous devrez documenter et éventuellement fournir des explications supplémentaires, soit par le biais de la formation, soit lors de la révision du code.

De nombreux API et projets open source fournissent de la documentation, des exemples de code et d'autres explications. Le vôtre n'a peut-être pas besoin d'être aussi convivial, mais il est impossible de le contourner. Enseignez-leur bien.

JeffO
la source
Non. CRUD ne veut pas dire qu'ils ne sont pas bons. Ce sont des développeurs qui ont toujours traité des applications de données de base. CRUD = créer, lire, mettre à jour et supprimer. Je ne vois pas comment cela fait d'eux de mauvais programmeurs.
ElGringoGrande
En argot anglais britannique, "crud" == "shit".
Michael Shaw