“Facile à raisonner” - qu'est-ce que cela signifie? [fermé]


50

J'ai souvent entendu dire que d'autres développeurs utilisent cette expression pour "annoncer" certains modèles ou développer de meilleures pratiques. La plupart du temps, cette expression est utilisée pour parler des avantages de la programmation fonctionnelle.

La phrase "Facile à raisonner à propos de" a été utilisée telle quelle, sans aucune explication ni échantillon de code. Donc, pour moi, cela devient comme le prochain mot "buzz" que les développeurs "plus expérimentés" utilisent dans leurs discussions.

Question: Pouvez-vous donner quelques exemples de "Pas facile de raisonner à propos de", donc on peut comparer avec les exemples "Facile de raisonner à propos de"?


4
@MartinMaat une phrase plus précise qui est largement utilisée est le raisonnement équationnel, je suggérerais que cela pourrait être ce que Fabio est après
jk.

3
J'aime utiliser l'expression "charge cognitive" pour ce genre de chose.
Baldrickk

16
Savez-vous ce que veut dire raisonnement sur les programmes ?
Bergi

5
Dans le sens non formel, j'utilise le terme «solution» pour comprendre une solution assez simple à comprendre (généralement) les résultats pour une entrée donnée sans la tester. Cela signifie que pour tout ensemble d'entrées, les résultats ne seront pas surprenants. Il est difficile de raisonner des solutions qui ont des cas non évidents, par exemple. J'utilise principalement ceci en référence à la robustesse.
JimmyJames

7
Je suis très coupable d'utiliser "plus facile de raisonner" fréquemment; Je note cependant que j'essaie de faire attention à dire le comparatif plus facile plutôt que l'absolu facile . Il y avait un jour dans ma vie où je pouvais raisonner à propos de l'absence de logiciel, alors ce n'était pas facile ce jour-là; cela est devenu facile seulement en passant beaucoup de temps et d'efforts. Dire que tout problème de programmation est facile revient à adopter une position péjorative à l’égard de ceux qui ne le trouvent pas (encore) facile. Dire qu'un modèle est plus facile qu'un autre revient à dire qu'il y a moins de concepts impliqués, moins de pièces mobiles, etc.
Eric Lippert

Réponses:


59

À mon sens, l'expression "facile à raisonner à propos de" se réfère à un code qui est facile à "exécuter dans votre tête".

Quand on regarde un morceau de code, s'il est court, clairement écrit, avec des noms bien et une mutation minimale de valeurs, alors travailler mentalement à travers ce que fait le code est une tâche (relativement) facile.

Un long morceau de code avec des noms médiocres, des variables qui changent constamment de valeur et de ramifications compliquées nécessiteront normalement, par exemple, un stylo et un morceau de papier pour aider à garder une trace de l’état actuel. Un tel code ne peut donc pas être facilement manipulé dans votre tête. Un tel code n’est donc pas facile à raisonner.


29
Avec une légère mise en garde qui dit que peu importe comment vous nommez vos variables, un programme qui tente de réfuter la conjecture de Goldbach est par nature difficile à "exécuter", dans votre tête ou ailleurs. Mais il peut encore être facile de raisonner, dans le sens où il est facile de se convaincre que, s'il prétend avoir trouvé un contre-exemple, il dit la vérité ;-)
Steve Jessop

4
Je ne voudrais jamais exécuter de code dans ma tête. Pour moi, ce serait le spectacle ultime de "pas facile de raisonner." Je voudrais pouvoir faire des déclarations prédictives sur ce que ferait l'ordinateur sans l' exécuter. Le code qui est "facile à raisonner" est un code qui n'a pas besoin d'être exécuté dans votre tête, il peut être raisonné à la place.
Cort Ammon

1
Comment peut-on répondre à une question sur le raisonnement à propos du code sans même mentionner la vérification formelle ? Cette réponse suggère que le raisonnement sur le code est informel et ad hoc. ce n'est pas, c'est généralement fait avec beaucoup de soin et d'approches mathématiques. Certaines propriétés mathématiques rendent le code "facile à raisonner" dans un sens objectif (fonctions pures, pour donner un exemple très simple). Les noms de variables n'ont rien à voir avec la facilité avec laquelle il est possible de "raisonner" sur le code, du moins dans un sens formel.
Polygnome

3
@ Polygnome Le raisonnement sur le code ne se fait généralement pas avec beaucoup de soin ni d'approches mathématiques. Au moment où j'écris ces lignes, les personnes qui raisonnent de manière informelle sur le code sont plus nombreuses que les approches mathématiques, au moins, ou du moins, à mon avis.
Kaz

2
@Polygnome "Code easy to reason about" almost exclusively alludes to its mathematical properties and formal verification- cela ressemble à peu près à une réponse à la question. Vous voudrez peut-être poster cela comme réponse au lieu de ne pas être en désaccord sur la nature de la réponse (subjective) dans les commentaires.
Dukeling

47

Un mécanisme ou un morceau de code est facile à déterminer quand vous devez prendre en compte peu d'éléments pour prédire ce qu'il va faire, et les éléments que vous devez prendre en compte sont facilement disponibles.

Les vraies fonctions sans effets secondaires et sans état sont faciles à raisonner car la sortie est entièrement déterminée par l'entrée, qui se trouve exactement dans les paramètres.

Inversement, il est beaucoup plus difficile de raisonner un objet avec un état, car vous devez tenir compte de l'état dans lequel l'objet se trouve quand une méthode est appelée, ce qui signifie que vous devez penser aux autres situations qui pourraient conduire à la position de l'objet dans un objet. état particulier.

Les variables globales sont encore pires: pour raisonner sur le code qui lit une variable globale, vous devez comprendre où cette variable peut être définie dans votre code et pourquoi - et il peut même ne pas être facile de trouver tous ces emplacements.

La chose la plus difficile à raisonner est la programmation multithread avec un état partagé, car non seulement vous avez un état, mais vous avez plusieurs threads qui le modifient en même temps. Il faut tenir compte de la possibilité qu’à chaque point d’exécution, un autre thread (ou plusieurs d’entre eux!) exécute à peu près n’importe quelle autre partie du code et modifie les données que vous utilisez sous vos yeux. En théorie, cela peut être géré avec des mutexes / des moniteurs / des sections critiques / tout ce que vous appelez, mais en pratique, aucun humain n'est réellement capable de le faire de manière fiable à moins de confiner radicalement l'état partagé et / ou le parallélisme. sections du code.


9
Je suis d’accord avec cette réponse, mais même avec des fonctions pures, des approches déclaratives (comme CSS, XSLT, makeou même la spécialisation de modèles C ++ et la surcharge de fonctions) peuvent vous remettre dans l’esprit de considérer l’ensemble du programme. Même lorsque vous pensez avoir trouvé la définition de quelque chose, le langage permet à une déclaration plus précise n'importe où dans le programme de la remplacer. Votre IDE pourrait aider avec ceci.
Steve Jessop

4
J'ajouterais que dans le scénario multithread, vous devez également avoir une compréhension assez approfondie des instructions de niveau inférieur de votre code: une opération qui ressemble à une source atomique dans la source peut avoir des points d'interruption inattendus dans l'exécution réelle.
Jared Smith

6
@SteveJessop: En effet, ce point est souvent négligé. Il y a une raison pour laquelle C # vous fait dire quand vous voulez qu'une méthode soit redéfinissable plutôt que de faire discrètement la paramétrabilité comme valeur par défaut; nous souhaitons agiter un drapeau disant "la correction de votre programme peut dépendre du code que vous ne pouvez pas trouver au moment de la compilation" à ce stade. (Cela dit, je souhaite aussi que "scellé" soit la valeur par défaut pour les classes de C #.)
Eric Lippert

@EricLippert Quelles étaient les dernières raisons pour sealedne pas être la valeur par défaut?
Zev Spitz

@ZevSpitz: Cette décision a été prise bien avant mon époque; Je ne sais pas.
Eric Lippert

9

Dans le cas de la programmation fonctionnelle, le sens de «Facile à raisonner» est principalement déterministe. J'entendais par là qu'une entrée donnée conduira toujours à la même sortie. Vous pouvez faire ce que vous voulez pour le programme, tant que vous ne touchez pas ce morceau de code, il ne cassera pas.

D'autre part, il est généralement plus difficile de raisonner sur OO car la "sortie" produite dépend de l'état interne de chaque objet impliqué. Cela se traduit généralement par des effets secondaires inattendus : lorsqu’une partie du code est modifiée, une pièce apparemment sans rapport se rompt.

... l'inconvénient de la programmation fonctionnelle est bien sûr qu'en pratique, une grande partie de ce que vous voulez faire est IO et la gestion de l'état.

Cependant, il y a beaucoup d'autres choses qui sont plus difficiles à raisonner, et je conviens avec @Kilian que la simultanéité est un excellent exemple. Les systèmes distribués aussi.


5

Éviter une discussion plus large et aborder la question spécifique:

Pouvez-vous donner quelques exemples de "Pas facile de raisonner à propos de", de sorte qu'il peut être comparé aux exemples "Facile à raisonner de"?

Je vous renvoie à "L'histoire de Mel, un vrai programmeur" , un morceau de folklore de programmeur qui date de 1983 et compte donc comme "légende" pour notre profession.

Il raconte l'histoire d'un programmeur écrivant du code privilégiant autant que possible les techniques obscures, y compris du code auto-référentiel et auto-modificateur, et une exploitation délibérée de bogues machine:

une boucle apparente infinie avait en fait été codée de manière à tirer parti d’une erreur de report de débordement. L'ajout de 1 à une instruction décodée en tant que "Charger à partir de l'adresse x" donnait normalement "Charger à partir de l'adresse x + 1". Mais lorsque x était déjà l'adresse la plus élevée possible, non seulement l'adresse était renvoyée à zéro, mais un 1 était également transféré dans les bits à partir desquels le code d'opération serait lu, ce qui modifiait le code d'opération de "load from" à "jump to". l'instruction complète est passée de "charger de la dernière adresse" à "passer à l'adresse zéro".

Ceci est un exemple de code qui est «difficile à raisonner».

Bien sûr, Mel serait en désaccord ...


1
+1 pour faire référence à l'histoire de Mel, l'un de mes préférés depuis toujours.
John Bollinger

3
Lisez l'histoire de Mel ici, car l'article de Wikipedia ne contient pas de lien.
TRiG

@TRiG note de bas de page 3 sur la page, non?
AakashM

@AakashM a réussi à passer à côté de ça.
TRiG

5

Je peux donner un exemple très courant.

Considérez le code C # suivant.

// items is List<Item>
var names = new List<string>();
for (var i = 0; i < items.Count; i++)
{
    var item = items[i];
    var mangled = MyMangleFunction(item.Name);
    if (mangled.StartsWith("foo"))
    {
        names.Add(mangled);
    }
}

Considérons maintenant cette alternative.

// items is List<Item>
var names = items
    .Select(item => MyMangleFunction(item.Name))
    .Where(s => s.StartsWith("foo"))
    .ToList();

Dans le deuxième exemple, je sais exactement ce que ce code fait en un coup d’œil. Quand je vois Select, je sais qu'une liste d'éléments est en train d'être convertie en une liste d'autre chose. Quand je vois Where, je sais que certains éléments sont filtrés. En un coup d'œil, je peux comprendre ce qui namesest et l'utiliser efficacement.

Quand je vois une forboucle, je n'ai aucune idée de ce qui se passe jusqu'à ce que je lise le code. Et parfois, je dois y faire un suivi pour être sûr d'avoir pris en compte tous les effets secondaires. Je dois faire un peu de travail pour arriver à comprendre ce que sont les noms (au-delà de la définition du type) et comment les utiliser efficacement. Ainsi, le premier exemple est plus difficile à raisonner que le second.

En fin de compte, être facile à raisonner ici dépend également de la compréhension des méthodes Selectet des méthodes LINQ Where. Si vous ne les connaissez pas, le second code est plus difficile à raisonner au départ. Mais vous ne payez que les coûts pour les comprendre une fois. Vous payez le coût pour comprendre une forboucle chaque fois que vous en utilisez une et chaque fois qu’elle change. Parfois, le coût en vaut la peine, mais être "plus facile à raisonner" est bien plus important.


2

Une phrase apparentée est (je paraphrase),

Il ne suffit pas que le code ait " pas de bugs évidents ": il devrait plutôt avoir " évidemment pas de bugs ".

Un exemple de relativement "facile à raisonner à propos de" pourrait être RAII .

Un autre exemple pourrait être d'éviter une étreinte mortelle : si vous pouvez garder un verrou et en acquérir un autre, et qu'il y a beaucoup de verrous, il est difficile de vous assurer qu'il n'y a pas de scénario dans lequel une étreinte mortelle pourrait se produire. L'ajout d'une règle du type "il n'y a qu'un seul verrou (global)" ou "vous n'êtes pas autorisé à acquérir un deuxième verrou tant que vous en détenez un premier" rend le système relativement facile à raisonner.


1
Hmm. Je ne suis pas sûr que RAII soit si facile à raisonner. Bien sûr, il est facile à comprendre sur le plan conceptuel , mais il est plus difficile de raisonner (c.-à-d. Prédire) le comportement du code qui utilise beaucoup de RAII. Je veux dire, ce sont essentiellement des appels de fonction invisibles au niveau de la portée. Le fait que beaucoup de gens aient du mal à raisonner à ce sujet est très clair si vous avez déjà participé à une programmation COM .
Cody Gray

Je voulais dire relativement facile (C ++ par rapport à C): par exemple, l'existence d'un constructeur pris en charge par le langage signifie que les programmeurs ne peuvent pas créer / utiliser / utiliser un objet qu'ils oublient d'initialiser, etc.
ChrisW

Cet exemple basé sur COM est problématique car il mélange des styles, c'est-à-dire un pointeur intelligent de style C ++ CComPtr<>avec une fonction de style C ( CoUninitialize()). Je trouve que c'est aussi un exemple bizarre, pour autant que je me souvienne, vous appelez CoInitialize / CoUninitialize au niveau de la portée du module et pour toute la durée de vie du module, par exemple in mainou in DllMain, et non dans une toute petite portée de fonction locale de courte durée, comme indiqué dans l'exemple. .
ChrisW

C'est un exemple trop simplifié à des fins d'illustration. Vous avez tout à fait raison de dire que COM est initialisé à la portée du module, mais imaginez l'exemple de Raymond (comme celui de Larry) comme étant la mainfonction de point d'entrée ( ) pour une application. Vous initialisez COM au démarrage, puis vous le désinitialisez juste avant de quitter. Sauf que vous avez des objets globaux, tels que les pointeurs intelligents COM, qui utilisent le paradigme RAII. Concernant les styles de mixage: un objet global qui a initialisé COM dans son ctor et non initialisé dans son dtor est réalisable, et ce que suggère Raymond, mais il est subtil et difficile à raisonner.
Cody Grey

Je dirais que, à bien des égards, la programmation COM est plus facile à raisonner en C, car tout est un appel de fonction explicite. Il n'y a rien de caché ou d'invisible derrière le dos. C'est un peu plus de travail (c.-à-d., Plus fastidieux), car vous devez écrire manuellement tous ces appels de fonction et revenir en arrière et vérifier votre travail pour voir si vous l'avez fait correctement, mais tout est mis à nu, ce qui est la clé rendre facile de raisonner . En d'autres termes, "parfois les pointeurs intelligents sont trop intelligents" .
Cody Grey

2

Le point crucial de la programmation est l'analyse de cas. Alan Perlis a fait remarquer à ce propos dans l’Épigramme 32: Les programmeurs ne doivent pas être mesurés par leur ingéniosité ni par leur logique mais par l’exhaustivité de leur analyse de cas.

Il est facile de raisonner sur une situation si l’analyse de cas est facile. Cela signifie soit qu'il y a peu de cas à prendre en compte, ou, à défaut, quelques cas particuliers : il peut y avoir de grands espaces de cas, mais qui s'effondrent à cause de certaines régularités, ou succombent à une technique de raisonnement telle que l'induction.

Une version récursive d'un algorithme, par exemple, est généralement plus facile à raisonner qu'une version impérative, car elle ne génère pas de cas superflus résultant de la mutation de variables d'état de support n'apparaissant pas dans la version récursive. De plus, la structure de la récursion est telle qu’elle s’inscrit dans un modèle mathématique preuve par induction. Nous n’avons pas à tenir compte de complexités telles que les variantes de boucle et les conditions préalables les plus faibles et rigoureuses.

Un autre aspect de ceci est la structure de l’espace. Il est plus facile de raisonner sur une situation qui présente une division à plat, ou le plus souvent à plat, par rapport à une situation de cas hiérarchique: cas avec sous-cas et sous-sous-cas, etc.

L' orthogonalité est une propriété des systèmes simplifiant le raisonnement : il s'agit de la propriété selon laquelle les cas qui régissent les sous-systèmes restent indépendants lorsque ces sous-systèmes sont combinés. Aucune combinaison ne donne lieu à des "cas spéciaux". Si un élément à quatre cas est combiné à un autre à trois cas orthogonalement, il y en a douze, mais idéalementchaque cas est une combinaison de deux cas qui restent indépendants. En un sens, il n'y a pas vraiment douze cas; les combinaisons ne sont que des "phénomènes émergents" dont nous n'avons pas à nous soucier. Cela signifie que nous avons encore quatre cas auxquels nous pouvons penser sans prendre en compte les trois autres de l'autre sous-système, et vice versa. Si certaines des combinaisons doivent être spécialement identifiées et dotées d'une logique supplémentaire, alors le raisonnement est plus difficile. Dans le pire des cas, chaque combinaison comporte un traitement spécial, puis il y a réellement douze nouveaux cas, qui s'ajoutent aux quatre et trois originaux.


0

Sûr. Prendre la concurrence:

Sections critiques imposées par les mutex: facile à comprendre car il n'y a qu'un seul principe (deux threads d'exécution ne peuvent pas entrer simultanément dans la section critique), mais sujets à l'inefficacité et à l'impasse.

Modèles alternatifs, par exemple programmation sans verrou ou acteurs: potentiellement beaucoup plus élégant et puissant, mais incroyablement difficile à comprendre, car vous ne pouvez plus vous fier (apparemment) à des concepts fondamentaux tels que "écrivez cette valeur à cet endroit".

Etre facile à raisonner est l’ un des aspects d’une méthode. Mais le choix de la méthode à utiliser nécessite de prendre en compte tous les aspects.


13
-1: vraiment, vraiment mauvais exemple qui me fait penser que vous ne comprenez pas ce que la phrase signifie vous-même. Les «sections critiques imposées par les mutex» sont en fait l’une des choses les plus difficiles à raisonner - presque tous ceux qui les utilisent présentent des conditions de concurrence ou des impasses. Je vais vous proposer une programmation sans verrouillage, mais l’essentiel du modèle de l’acteur est qu’il est beaucoup, beaucoup plus facile de raisonner.
Michael Borgwardt

1
Le problème est que la concurrence est en soi un sujet très difficile à raisonner pour les programmeurs, ce qui en fait un très bon exemple. Vous avez tout à fait raison de dire que les sections critiques imposées par les mutex sont un moyen relativement simple d'implémenter la concurrence, par rapport à la programmation sans verrouillage, mais la plupart des programmeurs sont comme Michael et leurs yeux se perdent lorsque vous commencez à parler de sections critiques et de mutex. ne semble certainement pas être une chose facile à comprendre. Sans parler de tous les bugs.
Cody Gray

0

Limitons la tâche au raisonnement formel. Parce que le raisonnement humoristique ou inventif ou poétique a des lois différentes.

Même dans ce cas, l'expression est faiblement définie et ne peut pas être définie de manière stricte. Mais cela ne signifie pas qu'il devrait rester si sombre pour nous. Imaginons qu'une structure passe un test et marque des points différents. Les bons points pour CHAQUE point signifient que la structure est pratique dans tous les aspects et donc "facile à raisonner".

La structure "Facile à raisonner" devrait donner de bonnes notes aux éléments suivants:

  • Les termes internes ont des noms raisonnables, faciles à distinguer et à définir. Si les éléments ont une hiérarchie, la différence entre les noms parent et enfant doit être différente de celle entre les noms frères.
  • Le nombre de types d'éléments structurels est faible
  • Les types d'éléments structurels utilisés sont des choses simples auxquelles nous sommes habitués.
  • Les éléments difficilement compréhensibles (récurrences, méta-étapes, géométrie à 4 dimensions ou plus ...) sont isolés - pas directement combinés les uns aux autres. (par exemple, si vous essayez de penser à une règle récursionnelle changeant pour les cubes 1, 2, 3, 4, 3, 3, 3, ce sera très compliqué. Mais si vous allez concilier chacune de ces règles avec une formule En fonction de n, vous aurez séparément une formule pour chaque n-cube et séparément une règle de récurrence pour une telle formule (et que deux structures séparées peuvent être facilement pensées).
  • Les types d'éléments structurels sont évidemment différents (par exemple, ne pas utiliser de tableaux mélangés à partir de 0 et de 1)

Le test est-il subjectif? Oui, naturellement. Mais l'expression elle-même est subjective aussi. Ce qui est facile pour une personne ne l'est pas pour une autre. Les tests doivent donc être différents pour les différents domaines.


0

L'idée des langages fonctionnels pouvant être raisonnés découle de leur histoire, en particulier ML, qui a été développé comme un langage de programmation analogue aux constructions que la Logic for Computable Functions utilisait pour le raisonnement. La plupart des langages fonctionnels sont plus proches des calculs de programmation formels que des langages impératifs, de sorte que la conversion du code en entrée d'un système de raisonnement est moins onéreuse.

Pour un exemple de système de raisonnement, dans le pi-calcul, chaque emplacement de mémoire modifiable dans un langage impératif doit être représenté sous la forme d'un processus parallèle séparé, tandis qu'une séquence d'opérations fonctionnelles est un processus unique. Quarante ans après le prouveur de théorèmes du CFL, nous travaillons avec des Go de mémoire vive. Avoir des centaines de processus est moins un problème. traite le raisonneur a épuisé l’espace d’état d’environ 3 Go et a corrigé un bogue intermittent. Cela aurait été impossible dans les années 70 ou aurait nécessité un supercalculateur au début des années 90, alors que l'espace d'état d'un programme de langage fonctionnel de taille similaire était suffisamment petit pour permettre de raisonner à l'époque.

D'après les autres réponses, la phrase devient une phrase à la mode, même si la loi de Moore a érodé une grande partie de la difficulté qui empêchait de raisonner au sujet des langues impératives.


-2

Il est facile de raisonner sur un terme spécifique à une culture. C'est pourquoi il est si difficile de trouver des exemples concrets. C'est un terme qui est ancré chez les personnes qui doivent faire le raisonnement.

"Facile à raisonner à propos de" est en fait une expression très auto-descriptive. Si on regarde le code, et veut raisonner ce qu'il fait, c'est facile =)

Ok, le décomposer. Si vous regardez du code, vous voulez généralement qu'il fasse quelque chose. Vous voulez vous assurer qu'il fait ce que vous pensez qu'il devrait faire. Vous développez donc des théories sur ce que le code devrait faire, puis vous le raisonnez pour tenter de démontrer pourquoi le code fonctionne réellement. Vous essayez de penser le code comme un humain (plutôt que comme un ordinateur) et de rationaliser les arguments sur ce que le code peut faire.

Le pire cas pour "facile à raisonner" est lorsque le seul moyen de donner une idée de ce que fait le code est de le parcourir ligne par ligne comme une machine de Turing pour toutes les entrées. Dans ce cas, le seul moyen de raisonner quoi que ce soit sur le code est de vous transformer en un ordinateur et de l'exécuter dans votre tête. Ces pires exemples sont facilement visibles dans les concours de programmation obsolètes, tels que ces 3 lignes de PERL qui déchiffrent RSA:

#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)

Quant à facile de raisonner, encore une fois, le terme est très culturel. Vous devez considérer:

  • Quelles sont les compétences du raisonneur? Combien d'expérience?
  • Quelles sortes de questions le raisonneur pourrait-il avoir à propos du code?
  • à quel point le raisonneur doit-il être certain?

Chacun de ceux-ci affecte "facile de raisonner sur" différemment. Prenons comme exemple les compétences du raisonneur. Lorsque j'ai commencé à travailler dans mon entreprise, il était recommandé de développer mes scripts sous MATLAB car il est "facile à raisonner". Pourquoi? Eh bien, tout le monde dans l'entreprise connaissait MATLAB. Si je choisissais une langue différente, il serait difficile pour quiconque de me comprendre. Peu importe que la lisibilité de MATLAB soit atroce pour certaines tâches, tout simplement parce qu’elle n’a pas été conçue pour elles. Plus tard, au fur et à mesure que ma carrière progressait, Python devenait de plus en plus populaire. Soudain, le code MATLAB est devenu "difficile à raisonner" et Python était le langage de prédilection pour écrire du code facile à raisonner.

Pensez également aux idoms que le lecteur peut avoir. Si vous pouvez compter sur votre lecteur pour reconnaître une FFT dans une syntaxe particulière, il est "plus facile de raisonner à propos de" le code si vous vous en tenez à cette syntaxe. Cela leur permet de regarder le fichier texte comme une toile sur laquelle vous avez peint une FFT, plutôt que d'avoir à entrer dans les détails les plus importants. Si vous utilisez C ++, déterminez à quel point vos lecteurs sont à l'aise avec la stdbibliothèque. Combien aiment-ils la programmation fonctionnelle? Certains des idiomes qui sortent des bibliothèques de conteneurs dépendent beaucoup du style idomatique que vous préférez.

Il est également important de comprendre à quelles sortes de questions le lecteur pourrait être intéressé à répondre. Vos lecteurs s'intéressent-ils principalement à la compréhension superficielle du code ou cherchent-ils des bugs au plus profond de leurs entrailles?

Il est intéressant de savoir à quel point le lecteur doit être sûr. Dans de nombreux cas, un raisonnement flou suffit en fait à faire sortir le produit. Dans d'autres cas, tels que le logiciel de vol de la FAA, le lecteur voudra avoir un raisonnement irréprochable. J'ai rencontré un cas dans lequel je plaidais pour l'utilisation de RAII pour une tâche particulière, parce que "vous pouvez simplement le configurer et l'oublier ... cela fera le bon choix". On m'a dit que j'avais tort à ce sujet. Ceux qui voulaient raisonner sur ce code n'étaient pas du genre à "vouloir juste oublier les détails". Pour eux, RAII ressemblait plus à un chad suspendu, les obligeant à réfléchir à tout ce qui peut se produire lorsque vous quittez la portée.


12
Le code Perl est difficile à lire . pas raison de. Si j'avais quelque intérêt à le comprendre, je supprimerais le code. Le code qui est en fait difficile à raisonner est celui qui est encore difficile à raisonner quand il est joliment formaté avec des identificateurs clairs pour tout, sans astuces de golf.
Kaz
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.