Dans le livre The Pragmatic Programmer , les auteurs mentionnent le concept de programmation par coïncidence . Il explique ce que c'est, pourquoi il est causé, quels sont les dangers que vous pouvez rencontrer et il se compare à un champ de mines terrestres en temps de guerre.
Avez-vous déjà regardé de vieux films de guerre en noir et blanc? Le soldat fatigué sort prudemment de la brosse. Il y a une clairière à venir: y a-t-il des mines terrestres ou est-il sûr de traverser? Rien n'indique qu'il s'agit d'un champ de mines - pas de panneaux, de barbelés ou de cratères. Le soldat pousse le sol devant lui avec sa baïonnette et grimace, s'attendant à une explosion. Il n'y en a pas. Il parcourt donc péniblement le champ pendant un moment, poussant et poussant au fur et à mesure. Finalement, convaincu que le terrain est sûr, il se redresse et marche fièrement en avant, pour être ensuite mis en pièces.
Les sondes initiales du soldat pour les mines n'ont rien révélé, mais ce n'était que de la chance. Il a été conduit à une fausse conclusion - avec des résultats désastreux.
En tant que développeurs, nous travaillons également dans les champs de mines. Il y a des centaines de pièges qui n'attendent que de nous attraper chaque jour. Rappelant l'histoire du soldat, nous devons nous garder de tirer de fausses conclusions. Nous devons éviter de programmer par coïncidence - en se fondant sur la chance et les succès accidentels - en faveur d'une programmation délibérée ...
Mais je ne suis pas vraiment satisfait de la façon dont ils décrivent le problème "comment le surmonter". Oui, il faut penser à l'avance avant d'écrire le code, mais comment pratiquer cela? La seule chose que je peux penser est en ajoutant des fonctionnalités aux projets Open Source existants, où vous devez avoir des connaissances à la fois sur "ce que je fais maintenant" et sur "Comment les autres morceaux de code fonctionnent", et ce n'est pas le cas lorsque vous écrivez vos propres projets.
MODIFIER:
un résumé de vos messages:
- Ne devinez pas votre prochain mouvement, prouvez qu'il est correct
- Test unitaire et refactoriser autant que possible, si nécessaire
- Ajouter des fonctionnalités - compiler - tester souvent
- Si vous ne pouvez pas expliquer le code à un noob, vous programmez probablement par hasard.
BTW, il est difficile d'accepter une réponse, c'est vraiment difficile. Toutes les réponses sont vraiment géniales :)
la source
Réponses:
Vous n'avez pas besoin de penser à l'avenir, d'être simplement très clair sur ce qui a été fait et d'être très clair sur ce que vous faites en ce moment.
Les sous-programmes doivent dire ce qu'ils font, faire ce qu'ils disent et ne pas avoir de dépendances cachées. Ensuite, quelqu'un qui les appelle peut plus facilement raisonner sur ce qu'ils vont faire.
Évitez l'état global. (Variables, singletons, etc.) Plus vous devez avoir d'états dans votre tête pour comprendre ce que font les choses, plus il est difficile de comprendre ce qui est censé se produire et de trouver les cas limites.
Écrire des tests unitaires. Les tests unitaires sont parfaits pour capturer le comportement réel du code que vous venez d'écrire, plutôt que le comportement idéal que vous espérez trouver.
Raccourcissez votre cycle d'édition / compilation / test. Lorsque vous ajoutez un gros morceau de code et testez mal, il y a de fortes chances qu'il se comporte différemment de ce que vous pensez. Ensuite, vous le "corrigez" avec des changements aléatoires, et vous avez la bonne réponse pour le moment, mais vous ne savez pas comment cela s'est réellement produit. Vous programmez maintenant par hasard. Mais lorsque vous ajoutez 5 lignes, puis testez, les chances que vous obteniez la bonne réponse, car cela fonctionne comme si vous pensiez que cela fonctionne, sont bien meilleures. Je peux dire par expérience que 5 morceaux de 10 lignes chacun, testés individuellement, est une bête très différente de 50 lignes de code testées en même temps.
Refactor impitoyablement. Plusieurs fois, j'ai repéré un refactorisateur qui rendra mon code un peu plus simple mais prendra un tas de travail que je ne voulais pas faire. Après avoir commencé à m'attaquer délibérément à ces refacteurs en tant que priorité, j'ai constaté que cela se rentabilise généralement en un mois. Mais notez la clé, les refacteurs sur lesquels je me concentre sont ceux qui rendent la vie quotidienne plus simple, et non ceux qui répondent à une esthétique arbitraire meilleure ou plus générale. Ces refactors avec lesquels j'ai appris à être beaucoup plus prudent.
Aucune de ces choses ne nécessite une planification préalable. Mais ils facilitent tous la compréhension de votre code existant et facilitent donc la mise en œuvre délibérée de votre prochain petit morceau.
la source
UNION
endroit dont j'avais besoinUNION ALL
.) Et ainsi de suite.Il se résume à peu près à ne pas deviner . Surtout les nouveaux programmeurs le font, mais j'ai vu des vétérans le faire aussi, car ils pensent que cela fait gagner du temps à la recherche. Quelque chose ne fonctionne pas, vous ajoutez donc un
+1
ou un-1
, changez untrue
en unfalse
ou vice versa, réorganisez certaines instructions, ajoutez ou modifiez des délais, modifiez les priorités des threads et d'autres petites transformations, testez essentiellement des permutations aléatoires jusqu'à ce que cela fonctionne.Cela s'applique principalement à la modification du code existant, mais est également un facteur dans le nouveau code, car personne ne part vraiment de zéro. Vous vous basez toujours sur des bibliothèques, des systèmes d'exploitation ou au moins des architectures de processeur standard.
En d'autres termes, vous n'avez pas terminé tant que vous ne savez pas pourquoi votre correctif fonctionne. Le chemin que vous empruntez pour y arriver importe peu. Même des permutations aléatoires peuvent parfois être utiles pour réduire un bogue difficile à diagnostiquer, tant que vous prenez le temps par la suite de vous demander: "D'accord, changer vrai en faux l'a corrigé, mais pourquoi?"
la source
Le commentaire le plus effrayant que j'ai jamais rencontré dans un programme était
et c'est effrayant juste parce qu'il reconnaît que le morceau de code était le résultat d'une programmation par coïncidence .
Pour éviter la programmation par coïncidence, vous devriez être en mesure d'expliquer (à un collègue, vous-même ou un canard en caoutchouc ) exactement ce que fait le code et pourquoi il fonctionne. Les puces pour la programmation délibérément aident principalement à progresser vers cet objectif de pouvoir expliquer le code.
1 Pour le contexte, ce commentaire est apparu dans le code qui gère les changements de contexte dans un système d'exploitation primitif. Le code était déjà en production depuis plusieurs années lorsque je l'ai rencontré.
la source
Pour les nouveaux programmeurs, la partie la plus importante pour surmonter cela est de vraiment comprendre ce qu'ils font.
Dans de nombreux domaines, lorsque vous ne savez pas comment faire quelque chose, vous vous contentez d'essais et d'erreurs. Essayer quelque chose; si ça marche, super, sinon, essayez autre chose.
En programmation, en particulier lorsque vous utilisez un langage qui a le concept de comportement indéfini (comme C ou C ++), cette approche ne fonctionne tout simplement pas, car le succès n'est plus une décision booléenne. Vous pouvez avoir des choses qui "fonctionnent", qui fonctionnent parfois, qui fonctionnent pour certaines entrées mais pas pour d'autres.
J'ai parfois enseigné de nouveaux programmeurs, et la tendance à essayer de taper des choses aléatoires pour voir si cela fonctionne est courante. Ils tapaient une ligne, puis se tournaient vers moi et me demandaient: "Est-ce que cela fonctionnerait de cette façon?" alors qu'il était clair qu'ils n'avaient absolument aucune idée si c'était possible.
La leçon à retenir est qu'en tant que nouveau programmeur, vous devez vraiment être en mesure d'expliquer ce que fait votre code. Vous devez apprendre à lire le code, pas seulement à l'écrire.
(Bien sûr, cela s'applique également aux programmeurs chevronnés, mais mon expérience ici a été principalement avec de nouveaux débutants complets.)
la source
Il est beaucoup trop facile de coder, tester et corriger "sur la ligne de course". Vous avez des fonctionnalités qui, étant donné X & Y, produisent Z. Mais que se passe-t-il si X est corrompu et Y n'est pas disponible? Et si vous ne parvenez pas à sortir Z? Gardez constamment à l'esprit ce qui peut mal tourner et notez-le pour le cycle de test.
Gardez vos routines courtes et descriptives - le meilleur code nécessite peu (le cas échéant) de commentaires.
Les noms de méthode, de classe et de variable significatifs contribuent grandement à la lisibilité.
Si vous rencontrez une odeur de code, arrêtez. Il est peu probable que cette odeur disparaisse et un petit effort maintenant pourrait vous faire économiser énormément de chagrin plus tard.
Incluez des tests dans votre processus de développement. Je préconiserais l'utilisation du BDD plutôt que du TDD car cela vous oblige à décrire ce que vous visez à réaliser plutôt que de vous fier aveuglément à une série de tests qui pourraient vous donner un faux sentiment de sécurité.
Résistez à l'envie d'ajouter des fonctionnalités intéressantes (sauf s'il s'agit de votre propre projet pour animaux de compagnie). Tout code supplémentaire doit être conçu, écrit, testé et maintenu. Si ce n'est pas requis par le client / l'entreprise - vous risquez de devenir un énorme drain sur vos ressources.
la source