Je me retrouve souvent à embrasser "c'est mieux que jamais" quand je fais progresser la SECHÉITÉ d'un design. En règle générale, je trouve que j'ai besoin de cultiver une compréhension de l'emplacement unique faisant autorité pour un élément de connaissance dans le contexte d'un système d'autres éléments de connaissance. Ainsi, j'ai tendance à concevoir le système «maintenant».
À l'inverse, cette pratique me fait construire assez longtemps à l'avance, malgré une chance raisonnable que je n'en ai pas besoin.
Comment ces deux modèles s'accordent-ils?
Quelles pratiques utilisez-vous pour vous assurer qu'ils jouent bien?
Comment les enseignez-vous ensemble sans créer de confusion?
design-patterns
language-agnostic
philosophy
Justin Myles Holmes
la source
la source
Réponses:
J'essaie aussi de penser loin, mais généralement pas en code. Je réfléchis et prends des notes, j'espère bien organiser les choses pour que je puisse y revenir.
Je penche davantage vers "vous n'en aurez pas besoin" en ce qui concerne le code, mais "c'est mieux que jamais" avec le design.
Lorsque vous commencez à construire un nouveau système, il est tentant de vouloir tout construire maintenant, mais cela peut également saper votre élan et votre moral. J'ai tendance à penser à la conception globale et à essayer de tracer une ligne directe à travers elle - à trouver une architecture squelettique de bout en bout et à la construire d'abord, en appliquant des principes de conception saine afin de pouvoir ensuite évoluer et refactoriser pour apporter dans de nouvelles fonctionnalités.
Construire la représentation de bout en bout la plus simple du système qui puisse fonctionner; faites-le d'abord, puis vous avez quelque chose à réfléchir. Cela a tendance à cristalliser toutes ces vagues questions «et si» et à vous aider à définir ce que vous devez construire ensuite.
la source
YAGNI signifie que les choses se font quand elles doivent être faites et pas avant. Cela ne signifie pas qu'ils ne sont jamais faits, sauf s'ils ne sont jamais nécessaires. Cela signifie que vous ne faites que ce qui donne au client une valeur commerciale immédiate . Ce que signifie la valeur commerciale immédiate est subjectif pour chaque client et chaque projet.
Dans les deux cas, vous ne pouvez rien perdre avec YAGNI.
Dans l'autre cas, vous perdez du temps à écrire du code qui ne sera jamais utilisé, à écrire des tests pour du code qui ne sera jamais utilisé, et à écrire de la documentation pour du code qui ne sera jamais utilisé, et de la maintenance sur du code qui ne sera jamais utilisé, les gens se demandant ce que fait ce code , et si jamais il est utilisé, ad nauseum.
Exemple
Si je travaille sur un prototype / preuve de concept ou une version 1.0 d'une application, je n'ai pas besoin d'une conception à l'échelle du niveau de Facebook. L' enfer , je ne ai pas besoin d' une conception à l' échelle au niveau de Facebook, jusqu'à ce que je commence à voir que j'ai ce genre de trafic.
Pensez-vous que Zuckerberg a conçu la toute première version de Facebook pour s'adapter à 500 millions d'utilisateurs? Non, il l'a conçu et construit pour faire ce qu'il voulait et pas plus. S'il avait essayé de créer un design en cascade pour 500 millions d'utilisateurs dès le premier jour, Facebook n'aurait probablement jamais été publié.
La façon pratique de faire les choses est de savoir comment il l'a fait. Il a commencé avec PHP et MySQL, et le remaniement et la réécriture selon les besoins en fonction de la valeur commerciale , l'adaptation à des millions d'utilisateurs était d'une valeur commerciale énorme, mais pas au jour 0. Au jour 0, le lancement de quelque chose était la valeur commerciale énorme.
Il avait prévu de repenser et de réécrire. Ce qui est un état d'esprit différent de celui de planifier l'évier de la cuisine et de ne jamais réellement développer ou fournir quoi que ce soit d'utile qui soit complet.
La planification de la fin de vie d'une base de code et d'une réécriture est agile et à l'épreuve du temps. Essayer de trouver un objectif indéfini de "flexibilité" se termine à chaque fois par un échec. Vous concevez sans aucun besoin et perdez du temps, vous pourriez développer ce qui a une valeur commerciale au lieu de rêver de fonctionnalités qui ne seront jamais utilisées.
la source
La façon Zen de Python dit:
L'idée est que ce n'est pas parce que vous pouvez définir quelque chose maintenant que vous devriez. En avez-vous besoin maintenant?
Les cas où cela est moins évident sont les cas de refactorisation. Dois-je appliquer SEC chaque fois que je le peux? La réponse n'est pas claire car il y a des moments où appliquer DRY coûte plus (en temps passé) que la duplication. Cependant, à long terme, appliquer DRY jusqu'à ce que vous ayez des raisons techniques / de performance est toujours bon.
Donc, YAGNI jusqu'à ce que vous le fassiez, alors FAITES-LE MAINTENANT. N'attendez pas!
la source
Je ne pense pas qu'ils jouent ensemble du tout. Je pense que vous vous penchez dans un sens ou dans l'autre. Et je me penche vers YAGNI.
Mais pour ce que ça vaut, je ne suis pas d'accord avec la deuxième proposition, que "Maintenant, c'est mieux que jamais". Si une exigence est importante, elle devra être accomplie. "Jamais" n'est donc pas une possibilité. Si ce n'est pas important, "maintenant" n'est pas mieux - "jamais" n'est mieux.
Juste mes deux cents.
la source
Ils sont orthogonaux et n'ont rien à voir les uns avec les autres.
Hum. Les deux? Que peut-il y avoir de plus?
YAGNI décrit les fonctionnalités vues par les utilisateurs. Vous n'avez pas besoin de fantaisie.
Maintenant, c'est mieux que jamais décrit le processus. Écrivez des tests maintenant. Écrivez le code maintenant. Ne passez pas les heures à envisager des alternatives de conception. Construisez quelque chose plutôt que de parler de construire quelque chose.
la source
Si "jamais" est l'implication de "pas maintenant", alors votre conception est défectueuse.
Les décisions locales que vous prenez doivent être transparentes pour le reste d'un système.
Par exemple, si vous avez un composant
CookieSource
, qui nécessite unCookieFactory
pour transformer leCookieRecipes
il saitCookies
, en fonction de certains de vos paramètres d'entrée, ilCookieSource
n'est pas nécessaire et ne doit donc pas dépendre de la façon dont ilCookieFactory
est implémenté et comment ilCookieRecipes
est représenté.Si
CookieFactory
c'est en fait unBakery
, cela peut prendreRecipe
en fonctionPastry
ne devrait pas importer. Et à moins que vous n'ayez besoin de cette fonctionnalité, il n'est pas nécessaire de l'implémenter. Et il n'y a aucune raison au monde pour que vous ne puissiez pas l'ajouter par la suite, sauf s'il n'y a pas de barrière d'abstraction claire entreCookieSource
et les services qu'il utilise.Lorsque vous créez un logiciel, ajoutez des fonctionnalités selon vos besoins et essayez de ne pas vous enfermer dans les décisions que vous prenez. Au lieu de cela, enfermez la décision dans une abstraction appropriée .
la source
La solution la plus simple que j'ai trouvée est de s'attendre à des changements lors de l'écriture de code à l'avance. Lorsque je passe un booléen à une fonction, je le change généralement dès que possible en indicateur / enums, c'est donc a) plus lisible et b) facile à étendre. De même, si je remarque que je passe un tas de paramètres là où ça sent comme j'en aurai besoin d'un de plus, je crée généralement une structure spéciale. L'espoir est que YAGNI le fasse, mais si vous le faites à un moment donné, cela ne cassera pas horriblement tous les utilisateurs tout de suite et le "travail de grognement" est déjà fait. Souvent, vous pouvez également ajouter quelques commentaires comme / * les futurs ajouts vont ici * / ou alors il est clair que ce n'est pas encore implémenté, mais voici l'endroit pour l'ajouter. Cela aide généralement le plus, car j'ai trouvé que le refactoring d'interface plus tard était le plus long.
la source
Concevez en pensant aux futures extensions, mais n'implémentez pas ces extensions avant d'en avoir besoin.
L'exemple qui me vient à l'esprit est qu'au début de Netflix, vous ne pouviez avoir qu'une seule file d'attente associée à chaque compte. Ils ont ensuite piraté la prise en charge de plusieurs files d'attente. Parce qu'il n'était pas conçu de cette façon depuis le début, il est devenu de plus en plus difficile à entretenir, alors ils ont décidé de mettre fin à cette fonctionnalité. Après un tollé de clients, ils ont mordu la balle et ont repensé pour intégrer correctement plusieurs files d'attente.
Si quelqu'un au début avait permis la possibilité qu'il pourrait vouloir plusieurs files d'attente plus tard, il aurait pu se sauver beaucoup de chagrin à long terme pour très peu d'efforts supplémentaires à court terme. Ils n'ont pas eu à mettre en œuvre plusieurs files d'attente immédiatement, assurez-vous que s'ils l'ont fait, cela ne nécessiterait pas une réécriture massive ou un piratage incontrôlable.
En surface, il semble que cela nécessiterait une capacité semblable à une diseuse de bonne aventure pour prédire les besoins futurs, mais dans la pratique, des choses comme ça ont tendance à ressortir à un bon programmeur lorsqu'il remarque qu'il code en dur quelque chose, ou qu'une table de base de données collecte un grand nombre de colonnes uniquement vaguement liées.
la source