Comment «You Ain't Gonna Need It» et «Now is better than never» jouent-ils ensemble?

17

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?

Justin Myles Holmes
la source
2
Réfléchir avant d'agir. Mais celui qui hésite est perdu.
mmyers

Réponses:

26

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.

échantillon de biais
la source
3
+1 laissant une place à quelque chose dans la conception ne signifie pas que vous devez en construire une grande partie au départ. Beaucoup trop de gens prennent un coup de pied absolutiste que rien ne devrait être considéré avant la demande et se laissent dans une situation bien pire que s'ils avaient construit le tout sans aucune intervention du client.
Bill
9

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
2
Si votre design est mauvais (par exemple inflexible), vous pouvez perdre beaucoup avec YAGNI.
EricSchaefer
1
@EricSchaefer - pas s'il atteint les objectifs et apporte de la valeur à l'entreprise et que vous n'avez pas beaucoup de temps investi, vous le jetez simplement moins est perdu que jamais en livrant votre système magique infiniment flexible qui ne sera jamais complet et expédié et si c'est le cas, ce sera un cauchemar de configuration.
6

La façon Zen de Python dit:

C'est mieux que jamais. Bien que jamais ne soit souvent meilleur qu'en ce moment.

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?

  • Oui: faites-le maintenant!
  • Non: ne le fais pas! Attendez le besoin! YAGNI!

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!

Klaim
la source
3

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.

MJB
la source
Et maintenant, la question à un million de dollars: que signifie «important»?
Aaronaught
1
"Important" signifie qu'il s'agit d'un test d'acceptation.
kindall
important signifie que le client hurle quand il n'est pas là.
Paul Nathan
2
Important signifie que le client ne paie pas s'il n'est pas là.
Christopher Mahan
@Christopher, cela pourrait être interprété comme encourageant le manque de professionnalisme. Par exemple, la protection contre l'injection SQL est importante même si le client ne sait pas ce que c'est et ne le testera certainement pas avant de payer.
Peter Taylor
2

Comment ces deux modèles s'accordent-ils?

Ils sont orthogonaux et n'ont rien à voir les uns avec les autres.

Quelles pratiques utilisez-vous pour vous assurer qu'ils jouent bien?

Hum. Les deux? Que peut-il y avoir de plus?

Comment les enseignez-vous ensemble sans créer de confusion?

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.

S.Lott
la source
2

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 un CookieFactorypour transformer le CookieRecipesil sait Cookies, en fonction de certains de vos paramètres d'entrée, il CookieSourcen'est pas nécessaire et ne doit donc pas dépendre de la façon dont il CookieFactoryest implémenté et comment il CookieRecipesest représenté.
Si CookieFactoryc'est en fait un Bakery, cela peut prendreRecipe en fonction Pastryne 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 entre CookieSourceet 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 .

back2dos
la source
1

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.

Anteru
la source
J'aime cette philosophie en principe, mais en pratique, je trouve que les migrations sont suffisamment douloureuses pour me faire réfléchir à deux fois. Avez-vous déjà constaté que la migration de vos modèles empêchait des changements?
Justin Myles Holmes le
La bonne chose à propos de cette approche est que les changements sont moins douloureux; il y a encore beaucoup de travail impliqué. Je ne sais pas ce que vous voulez dire avec les modèles en migration - je suis définitivement du côté de YAGNI, mais je me prépare au pire :)
Anteru
0

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.

Karl Bielefeldt
la source