D'abord, un peu de contextualisation. Je code une recherche à partir de Age -> Rate. Il y a 7 tranches d'âge, la table de recherche comporte donc 3 colonnes (de | à | taux) avec 7 lignes. Les valeurs changent rarement - ce sont des taux légiférés (première et troisième colonnes) qui sont restés les mêmes pendant 3 ans. J'ai pensé que le moyen le plus simple de stocker cette table sans codage en dur est dans la base de données dans une table de configuration globale, en tant que valeur de texte unique contenant un CSV (donc "65,69,0.05,70,74,0.06" est la façon dont les niveaux 65-69 et 70-74 seraient stockés). Relativement facile à analyser puis à utiliser.
Ensuite, j'ai réalisé que pour implémenter cela, je devrais créer une nouvelle table, un référentiel pour l'enrouler, des tests de couche de données pour le dépôt, des tests unitaires autour du code qui aplatit le CSV dans la table et des tests autour de la recherche elle-même. Le seul avantage de tout ce travail est d'éviter de coder en dur la table de recherche.
Lorsque vous parlez aux utilisateurs (qui utilisent actuellement la table de recherche directement - en regardant une copie papier), l'opinion est à peu près que «les taux ne changent jamais». De toute évidence, ce n'est pas vraiment correct - les taux ont été créés il y a seulement trois ans et dans le passé, les choses qui "ne changent jamais" avaient l'habitude de changer - donc pour moi de programmer de manière défensive, je ne devrais certainement pas stocker la table de recherche dans L'application.
Sauf quand je pense à YAGNI . La fonctionnalité que j'implémente ne spécifie pas que les taux vont changer. Si les taux changent, ils changeront si rarement que la maintenance n'est même pas prise en compte, et la fonctionnalité n'est en fait pas suffisamment critique pour que quoi que ce soit soit affecté s'il y avait un délai entre le changement de taux et l'application mise à jour.
J'ai à peu près décidé que rien de précieux ne serait perdu si je codais en dur la recherche, et je ne suis pas trop préoccupé par mon approche de cette fonctionnalité particulière. Ma question est la suivante: en tant que professionnel, ai-je correctement justifié cette décision? Le codage en dur des valeurs est une mauvaise conception, mais se donner la peine de supprimer les valeurs de l'application semble violer le principe YAGNI.
EDIT Pour clarifier la question, je ne suis pas préoccupé par la mise en œuvre réelle. Je crains que je ne puisse faire une mauvaise et rapide chose, et la justifier en disant YAGNI, ou que je peux adopter une approche plus défensive et exigeante, qui, même dans le meilleur des cas, a finalement de faibles avantages. En tant que programmeur professionnel, ma décision de mettre en œuvre une conception que je connais est-elle simplement défectueuse se résume-t-elle à une analyse coûts / avantages?
EDIT Bien que toutes les réponses soient très intéressantes car je pense que cela se résume aux choix de conception d'un individu, je pense que les meilleures réponses étaient @ Corbin et @EZ Hart car elles évoquent des choses que je n'avais pas considérées dans la question:
- la fausse dichotomie consistant à «supprimer correctement les valeurs codées en dur» en les déplaçant vers la base de données vs «appliquer efficacement YAGNI» en utilisant le codage en dur. Il y avait une troisième option de mettre la table de recherche dans la configuration de l'application, ce qui n'entraîne pas la surcharge de la bonne façon, et sans l'efficacité de YAGNI. Nous ne sommes généralement pas limités à l'une ou l'autre des décisions, et cela se résume alors à une décision coûts / avantages.
- la génération de code peut réduire la surcharge de déplacement des valeurs codées en dur vers la base de données, et d'une manière qui supprime également ma décision trop complexe de traiter un CSV dans la table. Cela ajoute potentiellement un problème de maintenance à long terme avec le code généré si les exigences de base changent pour la méthode de recherche. Tout cela affecte simplement l'analyse coûts / avantages, et il est probable que si j'avais eu cette automatisation disponible, je n'aurais même pas envisagé de coder en dur quelque chose comme ça.
Je marque la réponse de @ Corbin comme correcte car elle modifie mes hypothèses de coût de développement, et j'ajouterai probablement des outils de génération de code à mon arsenal dans un proche avenir.
Réponses:
Vous avez trouvé une faille dans votre processus de développement. Quand il est difficile de faire la bonne chose (créer la table, repo, repo tests, flatten tests ...), les développeurs trouveront un moyen de la contourner. Cela implique généralement de faire la mauvaise chose. Dans ce cas, cela vous tente de traiter les données d'application comme une logique d'application. Ne le fais pas. Ajoutez plutôt des automatisations utiles à votre processus de développement. Nous utilisons CodeSmith pour générer le code ennuyeux et standard que personne ne veut écrire. Après avoir créé une table, nous exécutons CodeSmith et il génère les tests unitaires DAO, DTO et stubs out pour chacun.
Selon les technologies que vous utilisez, vous devriez avoir des options similaires. De nombreux outils ORM génèrent des modèles à partir d'un schéma existant. Les migrations de rails fonctionnent dans la direction opposée - les tables des modèles. La méta-programmation dans les langages dynamiques est particulièrement efficace pour éliminer le code passe-partout. Vous devrez travailler un peu plus pour générer tout ce dont vous avez besoin si vous avez une application complexe à plusieurs niveaux, mais cela en vaut la peine. Ne laissez pas le sentiment, "wow, c'est une douleur dans le cou" vous empêcher de faire la bonne chose.
Oh, et ne stockez pas vos données dans un format qui nécessite un traitement supplémentaire (CSV). Cela ajoute simplement des étapes supplémentaires qui nécessitent votre attention et vos tests.
la source
Pour valider et étendre la réponse de @ Thorbjørn Ravn Andersen: Garder le calcul / la recherche au même endroit est un bon début.
Votre processus de pensée défensif contre YAGNI est un problème courant. Dans ce cas, je suggérerais qu'il soit informé par deux autres choses.
Premièrement - comment les besoins des utilisateurs ont-ils été présentés? Ont-ils précisé la possibilité de modification des taux? Sinon, la complexité supplémentaire fait-elle partie de quelque chose que vous pouvez facturer ou non? (ou si vous faites partie du personnel, que vous pouvez passer votre temps à faire d'autres travaux à la place?) Si c'est le cas, alors allez-y définitivement et livrez ce qui était raisonnablement demandé.
Deuxièmement, et peut-être plus important encore, la simple possibilité de modification ne remplira probablement pas une exigence réelle face à un changement législatif. Si et quand les taux changent, il y aura probablement une date limite et un certain traitement avant et après. De plus, si cette même interface doit ensuite effectuer tout type de traitement des demandes de remboursement antidatées, le taux correct devra peut-être être recherché en fonction de la date d'entrée en vigueur, plutôt que de la date réelle.
En bref, je note qu'une exigence modifiable réelle peut être assez complexe, donc à moins qu'elle ne soit étoffée, le simple est probablement meilleur.
Bonne chance
la source
Faites de la recherche réelle une fonction de bibliothèque. Vous pouvez ensuite voir tout le code à l' aide de cette recherche dans votre référentiel source, vous savez donc quels programmes doivent être mis à niveau lorsque les taux changent.
la source
PensionRateLookup
classe peut-être) qui est ensuite utilisé globalement. Je le ferais, qu'il soit stocké en dehors de l'application ou codé en dur, de cette façon seule l'implémentation de laPensionRateLookup
classe doit être maintenue. Mon problème est de savoir comment j'ai utilisé YAGNI pour conclure que le codage en dur de la table de recherche est acceptable.Laissez-moi voir si j'ai bien répondu à votre question. Vous avez 2 options pour implémenter une fonctionnalité: soit vous codez en dur une valeur et votre fonctionnalité est facile à implémenter (mais vous n'aimez pas la partie codée en dur) ou vous avez un gros effort pour "refaire" beaucoup de choses qui sont faites afin que vous puissiez développer votre fonctionnalité de manière propre. Est-ce exact?
La première chose qui me vient à l'esprit est "La chose la plus importante pour connaître les bonnes pratiques est de savoir quand il vaut mieux s'en passer".
Dans ce cas, l'effort est très élevé, vous pouvez donc le faire de manière propre, les chances d'effet collatéral de ce changement sont grandes et le rendement que vous obtiendriez est faible (comme vous l'avez expliqué, il semble probable qu'il ne le sera pas changement).
J'utiliserais l'approche du code dur (mais la préparais pour être flexible à l'avenir) et, en cas de changement de ce taux à l'avenir, j'en profiterais pour refactoriser toute cette section de mauvaise conception du code. Ainsi, le temps et le coût pourraient être estimés correctement et le coût de modification de votre valeur codée en dur serait minime.
Ce serait mon approche :)
la source
Il s'agit d'un élément qui "ne changera pas" tant qu'il ne le sera pas. Il est inévitable que cela va changer, mais ce temps peut être un peu éloigné.
Votre justification est correcte. À ce moment, le client n'a pas demandé la possibilité de modifier facilement ces tarifs. En tant que tel, YAGNI.
Cependant, ce que vous ne voulez pas, c'est le code qui accède à vos tarifs et interprète les résultats dispersés dans la base de code. Une bonne conception OO vous permettrait d'encapsuler la représentation interne de vos tarifs dans une classe et d'exposer uniquement une ou deux méthodes nécessaires pour utiliser les données.
Vous allez avoir besoin de cette encapsulation pour éviter les erreurs de copier-coller, ou devoir effectuer une refactorisation sur tout le code qui utilise les taux lorsque vous devez apporter une modification à la représentation interne. Lorsque vous prenez cette précaution initiale, l'approche la plus compliquée peut être un simple échange et remplacer pour la version plus en vedette.
En outre, appelez la limitation de la conception actuelle au client. Dites-leur que dans l'intérêt de maintenir la planification, vous avez codé en dur les valeurs - ce qui nécessite une modification de codage pour les mettre à jour. De cette façon, lorsqu'ils prennent connaissance des changements de taux en attente en raison de la nouvelle législation, ils peuvent choisir de simplement mettre à jour la table de recherche ou d'effectuer le changement le plus compliqué à ce moment-là. Mais mettez cette décision sur leurs genoux.
la source
Divisez la différence et placez les données de débit dans un paramètre de configuration. Vous pouvez utiliser le format CSV que vous avez déjà, vous évitez les frais généraux inutiles de la base de données, et si le changement est jamais nécessaire, ce sera un changement que le client devrait pouvoir effectuer sans avoir à recompiler / réinstaller et sans salir dans la base de données - ils peuvent simplement modifier le fichier de configuration.
Habituellement, lorsque vous regardez un choix entre deux extrêmes (violer YAGNI vs données dynamiques codées en dur), la meilleure réponse se situe quelque part au milieu. Méfiez-vous des fausses dichotomies.
Cela suppose que toute votre configuration est dans des fichiers; si c'est quelque part difficile comme le registre, vous devriez probablement ignorer ce conseil :)
la source
Je viens de créer une table DB. (Vous pensiez à stocker une table entière dans une seule, êtes-vous devenu fou?)
Le tableau a besoin de 2 champs PAS 3. Âge et taux. Cette ligne suivante contient la valeur supérieure! Vous dénormalisez sans même le savoir!
Voici le Sql pour obtenir le tarif pour une personne âgée de 67 ans.
Ne vous embêtez pas à faire un écran de maintenance car il est hors de portée. S'ils le demandent plus tard, émettez une demande de modification et faites-le.
EDIT: Comme d'autres l'ont dit, gardez le code obtient le taux centralisé, au cas où toute la structure de taux change.
la source
Je suis d'accord avec la plupart des réponses données. J'ajouterais également que la cohérence avec le reste de l'application est importante. Si c'est le seul endroit dans le code qui a des valeurs codées en dur, cela surprendra probablement les responsables. Cela est particulièrement vrai s'il s'agit d'une grande base de code stable. S'il s'agit d'un petit programme géré par vous, la décision est moins importante.
J'ai un souvenir lointain de la lecture d'un gars agile / OOP bien connu (comme Dave Thomas ou Kent Beck ou quelqu'un) disant que leur règle de base pour la duplication de code était deux fois et seulement deux: ne refactorisez pas la première fois que vous dupliquez quelque chose depuis vous pourriez ne l'écrire que deux fois dans votre vie. Mais la troisième fois ...
Cela ne répond pas exactement à la question, puisque vous interrogez YAGNI mais je pense que cela parle de la flexibilité générale des règles agiles. Le point de l'agilité est de s'adapter à la situation et d'avancer.
la source
Code dur dans une fonction.
la source