Je n'écris pas vraiment de grands projets. Je ne maintiens pas une base de données volumineuse ni des millions de lignes de code.
Mon code est principalement du type "script" - des éléments pour tester des fonctions mathématiques ou pour simuler quelque chose - de "programmation scientifique". Les programmes les plus longs sur lesquels j'ai travaillé jusqu'ici comptent quelques centaines de lignes de code et la plupart des programmes sur lesquels je travaille tournent autour de 150.
Mon code est aussi la merde. J'ai réalisé cela l'autre jour alors que j'essayais de trouver un fichier que j'ai écrit il y a quelque temps, mais que j'ai probablement écrasé et que je n'utilise pas le contrôle de version, ce qui fait que beaucoup d'entre vous sont affolés de stupidité.
Le style de mon code est compliqué et est rempli de commentaires obsolètes indiquant des manières alternatives de faire quelque chose ou de lignes de code copiées. Bien que les noms de variables soient toujours très descriptifs au début, au fur et à mesure que j'ajoute ou modifie des éléments, par exemple, quelque chose de nouveau que quelqu'un souhaite tester, le code se superpose et est écrasé. avoir un cadre, je commence à utiliser des noms de variables de merde et le fichier va au pot.
Dans le projet sur lequel je travaille actuellement, je suis dans la phase où tout cela revient à me mordre fort. Mais le problème est (mis à part le contrôle de version, la création d'un nouveau fichier pour chaque nouvelle itération et son enregistrement quelque part dans un fichier texte, ce qui aidera probablement considérablement la situation). Je ne sais pas vraiment comment procéder pour améliorer mon style de codage actuel.
Des tests unitaires sont-ils nécessaires pour écrire de plus petits morceaux de code? Qu'en est-il de la POO? Quelles sortes d'approches sont bonnes pour écrire du code bon et propre rapidement lors de la "programmation scientifique" par opposition au travail sur des projets plus importants?
Je pose ces questions parce que souvent, la programmation elle-même n'est pas très complexe. C'est plus sur les mathématiques ou les sciences que je teste ou que je fais de la recherche avec la programmation. Par exemple, une classe est-elle nécessaire lorsque deux variables et une fonction pourraient probablement s'en occuper? (Pensez que ce sont généralement des situations dans lesquelles la vitesse du programme est préférable pour être plus rapide - lorsque vous exécutez plus de 25 000 000 pas de temps d'une simulation, vous voulez plutôt que ce soit le cas.)
C'est peut-être trop large, et si oui, je m'excuse, mais en regardant les livres de programmation, ils semblent souvent être adressés à des projets plus importants. Mon code n'a pas besoin de la POO, et il est déjà sacrément court, donc ce n'est pas comme "oh, mais le fichier sera réduit de mille lignes si nous faisons cela!" Je veux savoir comment "recommencer" et programmer proprement sur ces projets plus petits et plus rapides.
Je serais heureux de fournir des détails plus spécifiques, mais plus les conseils sont généraux, plus ils me seront utiles. Je programme en Python 3.
Quelqu'un a suggéré un duplicata. Permettez-moi de préciser que je ne parle pas d'ignorer les normes de programmation standard. De toute évidence, il existe une raison pour que ces normes existent. Mais d’autre part, est-il vraiment judicieux d’écrire du code dit OO alors que des tâches standard auraient pu être faites, auraient été beaucoup plus rapides à écrire et auraient eu un niveau de lisibilité similaire en raison de la brièveté de la programme?
Il y a des exceptions. De plus, il existe probablement des normes pour la programmation scientifique qui vont au-delà des simples normes. Je parle de ceux-là aussi. Il ne s’agit pas de savoir si les normes de codage normales doivent être ignorées lors de l’écriture de code scientifique, mais bien d’écrire du code scientifique propre!
Mise à jour
Je pensais juste que j'ajouterais une sorte de mise à jour "pas tout à fait une semaine plus tard". Tous vos conseils ont été extrêmement utiles. J'utilise maintenant le contrôle de version - git, avec git kraken pour une interface graphique. Il est très facile à utiliser et a considérablement nettoyé mes fichiers - plus besoin d’anciens fichiers collés, ni d’anciennes versions de code commentées "au cas où".
J'ai également installé pylint et l'ai exécuté sur tout mon code. Un fichier a obtenu un score négatif au départ; Je ne sais même pas comment cela a été possible. Mon fichier principal a démarré à un score de ~ 1,83 / 10 et se situe maintenant à ~ 9,1 / 10. Tout le code est maintenant assez bien conforme aux normes. Je l'ai aussi parcouru de mes propres yeux en mettant à jour les noms de variables qui avaient disparu ... euh ... de travers, et en cherchant des sections à refactoriser.
En particulier, sur ce site, j’ai posé une question récente sur la refactorisation d’une de mes fonctions principales. C’est maintenant beaucoup plus propre et beaucoup plus court: au lieu d’une fonction longue et gonflée, si remplie, elle est maintenant inférieure à la moitié. la taille et beaucoup plus facile à comprendre ce qui se passe.
Ma prochaine étape est la mise en œuvre de "tests unitaires". J'entends par fichier un fichier que je peux exécuter sur mon fichier principal et qui examine toutes les fonctions qu'il contient avec des instructions assert et try / excepts, ce qui n'est probablement pas la meilleure façon de le faire et qui génère beaucoup de code en double, mais je vais continuer à lire et essayer de trouver comment mieux le faire.
J'ai également considérablement mis à jour la documentation que j'avais déjà écrite et ajouté des fichiers supplémentaires, tels qu'un tableur Excel, la documentation et un document associé dans le référentiel github. Cela ressemble un peu à un vrai projet de programmation maintenant.
Donc ... je suppose que tout cela est pour dire: merci .
la source
Réponses:
C'est un problème assez commun pour les scientifiques. Je l'ai souvent vu, et cela tient toujours au fait que la programmation est un outil que vous choisissez sur le côté comme outil pour faire votre travail.
Donc, vos scripts sont un désordre. Je vais aller à l'encontre du bon sens et dire que, si vous programmez seul, ce n'est pas si grave! Vous n'allez plus jamais toucher la majeure partie de ce que vous écrivez, aussi consacrez-vous trop de temps à écrire un joli code au lieu de produire de la «valeur» (le résultat de votre script) ne vous fera donc pas grand chose.
Cependant, il y aura un moment où vous devrez revenir à quelque chose que vous avez fait et voir exactement comment quelque chose fonctionnait. De plus, si d'autres scientifiques doivent revoir votre code, il est primordial qu'il soit aussi clair et concis que possible, afin que tout le monde puisse le comprendre.
Votre problème principal va être la lisibilité, alors voici quelques conseils pour améliorer:
Noms de variables:
Les scientifiques aiment utiliser des notations concises. Toutes les équations mathématiques utilisent généralement des lettres simples comme variables et je ne serais pas surpris de voir de nombreuses variables très courtes dans votre code. Cela nuit beaucoup à la lisibilité. Quand vous reviendrez à votre code, vous ne vous souviendrez plus de ce que représentent y, i et x2, et vous passerez beaucoup de temps à essayer de le comprendre. Essayez plutôt de nommer explicitement vos variables, en utilisant des noms qui représentent exactement ce qu’elles sont.
Divisez votre code en fonctions:
Maintenant que vous avez renommé toutes vos variables, vos équations semblent terribles et comportent plusieurs lignes.
Au lieu de la laisser dans votre programme principal, déplacez cette équation vers une autre fonction et nommez-la en conséquence. Maintenant, au lieu d’avoir une ligne de code énorme et foirée, vous aurez une brève instruction vous indiquant exactement ce qui se passe et quelle équation vous avez utilisée. Cela améliore à la fois votre programme principal, puisque vous n’aurez même pas à regarder l’équation réelle pour savoir ce que vous avez fait, et le code de l’équation lui-même, comme dans une fonction séparée, vous pouvez nommer vos variables comme vous le souhaitez, et revenir à les lettres simples plus familiers.
Dans cet ordre d'idées, essayez de trouver tous les éléments de code qui représentent quelque chose, en particulier si vous devez le faire plusieurs fois dans votre code, et les diviser en fonctions. Vous découvrirez que votre code deviendra rapidement plus facile à lire et que vous pourrez utiliser les mêmes fonctions sans écrire plus de code.
Cerise sur le gâteau, si ces fonctions sont nécessaires dans plusieurs de vos programmes, vous pouvez simplement créer une bibliothèque pour elles, et vous les aurez toujours disponibles.
Variables globales:
Quand j'étais débutant, je pensais que c'était un excellent moyen de transmettre les données dont j'avais besoin à de nombreux moments de mon programme. Il s'avère qu'il y a beaucoup d'autres façons de faire circuler des choses, et la seule chose que les variables globales font est de donner des maux de tête aux gens, car si vous passez à un point aléatoire de votre programme, vous ne saurez jamais quand cette valeur a été utilisée ou modifiée pour la dernière fois. le traquer sera une douleur. Essayez de les éviter autant que possible.
Si vos fonctions doivent renvoyer ou modifier plusieurs valeurs, créez une classe avec ces valeurs et transmettez-les en tant que paramètre ou faites en sorte que la fonction renvoie plusieurs valeurs (avec des n-uplets nommés) et affectez ces valeurs dans le code de l'appelant.
Contrôle de version
Cela n'améliore pas directement la lisibilité, mais vous aide à faire tout ce qui précède. Chaque fois que vous apportez des modifications, engagez-vous dans le contrôle de version (un référentiel Git local suffira), et si quelque chose ne fonctionne pas, regardez ce que vous avez modifié ou annulez! Cela facilitera la refactorisation de votre code et constituera un filet de sécurité si vous cassez accidentellement des choses.
Garder tout cela à l’esprit vous permettra d’écrire du code plus clair et plus efficace, mais vous aidera également à trouver les erreurs possibles plus rapidement, car vous n’aurez pas à parcourir des fonctions gigantesques et des variables compliquées.
la source
Physicien ici. Été là.
Je dirais que votre problème ne concerne pas le choix des outils ni les paradigmes de programmation (tests unitaires, POO, peu importe). C'est à propos de l' attitude , de la mentalité. Le fait que vos noms de variables soient bien choisis au début et finissent par être de la merde est assez révélateur. Si vous pensez que votre code est «exécuté une fois, puis jeté», alors ce sera inévitablement un gâchis. Si vous le considérez comme le produit de l'artisanat et de l'amour, ce sera magnifique.
Je crois qu'il n'y a qu'une seule recette pour écrire du code propre: écrivez-le pour l'être humain qui va le lire, pas pour l'interprète qui va le faire fonctionner. L'interprète ne se soucie pas si votre code est un gâchis, mais le lecteur humain ne garde.
Vous êtes un scientifique. Vous pouvez probablement passer beaucoup de temps à peaufiner un article scientifique. Si votre premier brouillon semble compliqué, vous le refactoriserez jusqu'à ce que la logique coule de la manière la plus naturelle qui soit. Vous voulez que vos collègues le lisent et trouvent les arguments parfaitement clairs. Vous voulez que vos étudiants soient en mesure d'apprendre de cela.
L'écriture de code propre est exactement la même chose. Pensez à votre code comme une explication détaillée d'un algorithme qui ne se trouve qu'incidemment être lisible par machine. Imaginez que vous allez le publier sous forme d'article que les gens liront. Vous allez même le montrer lors d'une conférence et guider le public ligne par ligne. Maintenant, répétez votre présentation . Oui, ligne par ligne ! Embarrassant, n'est-ce pas? Alors nettoyez vos diapositives (euh ... je veux dire, votre code), et répétez à nouveau. Répétez jusqu'à ce que vous soyez satisfait du résultat.
Ce serait encore mieux si, après les répétitions, vous pouviez montrer votre code à de vraies personnes plutôt qu'à de simples personnes imaginaires et à votre futur. Le parcourir ligne par ligne s'appelle une «promenade de code», et ce n'est pas une pratique idiote.
Bien sûr, tout cela a un coût. L'écriture de code propre prend beaucoup plus de temps que l'écriture de code jetable. Vous seul pouvez évaluer si les avantages dépassent les coûts pour votre cas d'utilisation particulier.
En ce qui concerne les outils, j'ai déjà dit qu'ils n'étaient pas si importants. Cependant, si je devais en choisir un, je dirais que le contrôle de version est le plus utile.
la source
Le contrôle de version vous donnera probablement le maximum pour votre argent. Ce n'est pas seulement pour le stockage à long terme, c'est idéal pour suivre vos expériences à court terme et revenir à la dernière version qui a fonctionné, en gardant des notes tout au long.
Viennent ensuite les tests unitaires. La chose à propos des tests unitaires est que même les bases de code avec des millions de lignes de code sont testées un par une. Les tests unitaires sont effectués dans le plus petit, au plus bas niveau d'abstraction. Cela signifie qu'il n'y a fondamentalement aucune différence entre les tests unitaires écrits pour les bases de code de petite taille et ceux utilisés pour les grandes. Il y en a juste plus.
Les tests unitaires sont le meilleur moyen d'éviter de casser quelque chose qui fonctionnait déjà lorsque vous corrigez quelque chose, ou au moins de vous dire rapidement lorsque vous corrigez. Ils sont en réalité plus utiles lorsque vous êtes aussi peu habile en tant que programmeur, ou que vous ne savez pas ou ne voulez pas écrire du code plus détaillé qui est structuré pour rendre les erreurs moins probables ou plus évidentes.
Entre le contrôle de version et l'écriture de tests unitaires au fur et à mesure, votre code deviendra naturellement beaucoup plus propre. D'autres techniques de codage plus propre peuvent être apprises lorsque vous atteignez un plateau.
la source
Vous auriez probablement compris cela vous-même, mais si vous devez " enregistrer tout cela dans un fichier texte quelque part ", vous n'utilisez pas tout le potentiel du système de contrôle de version. Utilisez quelque chose comme Subversion, git ou Mercurial et écrivez un bon message de commit avec chaque commit et vous aurez un journal qui sert à la fonction du fichier texte mais ne peut pas être séparé du référentiel.
Cela dit, utiliser le contrôle de version est la chose la plus importante que vous puissiez faire pour une raison qu’aucune des réponses existantes ne mentionne: la reproductibilité des résultats . Si vous pouvez soit utiliser vos messages de journal, soit ajouter une note aux résultats avec le numéro de révision, vous pouvez être sûr de pouvoir régénérer les résultats et vous serez mieux placé pour publier le code avec le document.
Les tests unitaires ne sont jamais nécessaires, mais ils sont utiles si (a) le code est suffisamment modulaire pour que vous puissiez tester les unités plutôt que le tout; (b) vous pouvez créer des tests. Idéalement, vous seriez capable d'écrire manuellement le résultat attendu plutôt que de le générer avec le code, bien que le générer à l'aide de code puisse au moins vous donner des tests de régression vous indiquant si quelque chose a changé son comportement. Déterminez simplement si les tests sont plus susceptibles d’être bogués que le code qu’ils testent.
OOP est un outil. Utilisez-le si cela vous aide, mais ce n'est pas le seul paradigme. Je suppose que vous ne connaissez vraiment que la programmation procédurale: si tel est le cas, dans le contexte décrit, il serait plus avantageux d'étudier la programmation fonctionnelle que la programmation orientée objet, et en particulier la nécessité d'éviter les effets secondaires autant que possible. Python peut être écrit dans un style très fonctionnel.
la source
En troisième cycle, j’ai moi-même écrit un code exigeant beaucoup d’algorithmes. C'est un peu difficile à casser. Pour le dire grossièrement, de nombreuses conventions de programmation sont construites autour de l'idée de placer des informations dans une base de données, de les récupérer au bon moment, puis de masser ces données pour les présenter à un utilisateur, en utilisant généralement une bibliothèque pour tous les calculs. algorithmes lourds parties de ce processus. Pour ces programmes, tout ce que vous avez entendu sur la programmation orientée objet, diviser le code en petites fonctions et tout rendre compréhensible en un coup d'œil, si possible, constitue un excellent conseil. Mais cela ne fonctionne pas tout à fait pour un code exigeant beaucoup d’algorithmes, ou un code qui implémente des calculs mathématiques complexes et peu d’autres choses.
Si vous écrivez des scripts pour effectuer des calculs scientifiques, vous avez probablement des papiers avec les équations ou les algorithmes que vous utilisez écrits. Si vous utilisez vous-même de nouvelles idées que vous avez découvertes, nous espérons les publier dans vos propres journaux. Dans ce cas, la règle est la suivante: vous voulez que votre code se lit autant que possible comme les équations publiées. Voici une réponse sur Software Engineering.SE avec plus de 200 votes positifs préconisant cette approche et expliquant à quoi elle ressemble: Existe - t-il une excuse pour les noms de variable courts?
Autre exemple, Simbody , un outil de simulation de physique utilisé pour la recherche et l’ingénierie en physique , contient d’ excellents extraits de code . Ces extraits contiennent un commentaire indiquant une équation utilisée pour un calcul, suivi d'un code aussi proche que possible des équations implémentées.
ContactGeometry.cpp
:ContactGeometry_Sphere.cpp
:la source
λ
ou auφ
lieu du laidlambda_
ouphy
...Mon travail consiste donc à publier et à préserver des données de recherche pour le système de l'Université de Californie. Quelques personnes ont parlé de reproductibilité, et je pense que c'est là le problème fondamental: documenter votre code de la même manière que tout ce qui est nécessaire pour reproduire votre expérience et, idéalement, écrire un code qui le rendrait simple pour quelqu'un d'autre pour reproduire votre expérience et pour vérifier vos résultats pour les sources d'erreur.
Mais quelque chose que je n'ai pas vu mentionné, et que j'estime important, est que les agences de financement considèrent de plus en plus la publication de logiciels comme une partie de la publication de données et considèrent la publication de logiciel comme une exigence de la science ouverte.
À cette fin, si vous voulez quelque chose de spécifique, qui cible les chercheurs plutôt que les développeurs de logiciels en général, je ne saurais trop recommander l’ organisation Software Carpentry . Si vous pouvez assister à l'un de leurs ateliers , c'est parfait. si tout ce que vous avez le temps / l'accès à faire est de lire certains de leurs articles sur les meilleures pratiques en informatique scientifique , c'est bien aussi. De ce dernier:
Un aperçu de haut niveau des pratiques qu'ils recommandent:
Le document donne des détails considérables sur chacun de ces points.
la source
Réponse personnelle:
je fais aussi beaucoup de scripts à des fins scientifiques. Pour les scripts plus petits, j'essaie simplement de suivre les bonnes pratiques de programmation générales (c'est-à-dire utiliser le contrôle de version, pratiquer l'auto-contrôle avec des noms de variable). Si je suis en train d'écrire quelque chose pour ouvrir ou visualiser rapidement un jeu de données, je ne me soucie pas de la programmation orientée objet.
Réponse générale:
"Cela dépend." Mais si vous avez du mal à déterminer quand utiliser un concept de programmation ou des paradigmes, voici quelques points à prendre en compte:
N ° 1: Familiarisez-vous avec ce qui existe:
Même si vous "ne" créez qu'un script (et que vous vous souciez vraiment de la composante scientifique), vous devriez prendre le temps de vous familiariser avec différents concepts et paradigmes de programmation. De cette façon, vous pouvez avoir une meilleure idée de ce que vous ne devriez pas ou ne voulez pas utiliser et quand. Cela peut sembler un peu intimidant. Et vous pouvez toujours avoir la question, "Où dois-je commencer / qu'est-ce que je commence à regarder?" J'essaie d'expliquer un bon point de départ dans les deux points suivants.
N ° 2: Commencez à réparer ce que vous savez être faux:
Personnellement, je commencerais par les choses que je sais être mauvaises. Obtenez un certain contrôle de version et commencez à vous discipliner pour vous améliorer avec ces noms de variables (c'est un combat sérieux). Réparer ce que vous savez être faux peut sembler évident. Cependant, d'après mon expérience, j'ai constaté que régler un problème m'amène à autre chose, et ainsi de suite. Avant que je ne le sache, j’ai dévoilé 10 choses que j’avais mal faites et compris comment les réparer ou les mettre en œuvre de manière propre.
N ° 3: Trouvez un partenaire de programmation:
si vous ne souhaitez pas recommencer à zéro, pensez à faire équipe avec un développeur et demandez-lui de revoir votre code. Même s'ils ne comprennent pas la partie scientifique de ce que vous faites, ils pourraient peut-être vous dire ce que vous auriez pu faire pour rendre votre code plus élégant.
No 4: Recherchez des consortiums:
je ne sais pas dans quel domaine scientifique vous êtes. Mais, en fonction de ce que vous faites dans le monde scientifique, essayez de rechercher des consortiums, des groupes de travail ou des participants à une conférence. Ensuite, voyez s’il existe des normes sur lesquelles ils travaillent. Cela peut vous conduire à certaines normes de codage. Par exemple, je fais beaucoup de travail géospatial. L'examen des documents de la conférence et des groupes de travail m'a conduit au Open Geospatial Consortium . Ils travaillent notamment sur les normes de développement géospatial.
J'espère que ça aide!
Note latérale: Je sais que vous venez d'utiliser la programmation orientée objet comme exemple. Je ne voulais pas que vous pensiez que je me suis retrouvé coincé sur la façon de gérer l'écriture de code en utilisant la POO. Il était simplement plus facile d'écrire une réponse en continuant avec cet exemple.
la source
Je recommanderais de s'en tenir au principe d'Unix: Keep It Simple, Stupid! (BAISER)
Autrement dit: faites une chose à la fois et faites-le bien.
Qu'est-ce que ça veut dire? Tout d’abord, cela signifie que vos fonctions doivent être courtes. Toute fonction dont le but, l’utilisation et la mise en œuvre ne peuvent pas être entièrement compris en quelques secondes est définitivement trop longue. Il est probable que vous fassiez plusieurs choses à la fois, chacune d’elles devant être une fonction qui leur est propre. Alors divisez-le.
En termes de lignes de code, mon heuristique est que 10 lignes sont une bonne fonction et que toute valeur supérieure à 20 est probablement une merde. D'autres personnes ont d'autres heuristiques. L'important est de limiter la durée à quelque chose que vous pouvez saisir en un instant.
Comment divisez-vous une longue fonction? Eh bien, vous devez d’abord rechercher des modèles de code répétés. Ensuite, vous factorisez ces modèles de code, leur attribuez un nom descriptif et observez votre code se rétrécir . En réalité, le meilleur refactoring est le refactoring qui réduit la taille du code.
Cela est particulièrement vrai lorsque la fonction en question a été programmée avec copier-coller. Chaque fois que vous voyez un tel motif répété, vous savez immédiatement que cela devrait probablement être transformé en une fonction qui lui est propre. C'est le principe de ne pas se répéter (DRY) . Chaque fois que vous frappez un copier-coller, vous faites quelque chose de mal! Créez une fonction à la place.
Certaines fonctions peuvent être longues car elles effectuent plusieurs choses distinctes les unes après les autres. Ce ne sont pas des violations DRY, mais ils peuvent également être divisés. Le résultat est souvent une fonction de haut niveau qui appelle une multitude de fonctions qui implémentent les étapes individuelles des fonctions d'origine. Cela augmentera généralement la taille du code, mais les noms de fonction ajoutés fonctionneront à merveille pour rendre le code plus lisible. Parce que maintenant vous avez une fonction de niveau supérieur avec toutes ses étapes explicitement nommées. De plus, après cette scission, il est clairement indiqué quelle étape agit sur quelles données. (Arguments de fonction. Vous n'utilisez pas de variables globales, n'est-ce pas?)
Une bonne heuristique pour ce type de division de fonction de section est à chaque fois que vous êtes tenté d'écrire un commentaire de section ou lorsque vous trouvez un commentaire de section dans votre code. C’est très probablement l’un des points où votre fonction devrait être scindée. Le commentaire de section peut également servir à donner un nom à la nouvelle fonction.
Les principes KISS et DRY peuvent vous mener loin. Vous n'avez pas besoin de commencer immédiatement avec la programmation orientée objet, etc., vous pouvez souvent réaliser de grandes simplifications en appliquant simplement ces deux méthodes. Cependant, il est rentable à long terme de connaître la POO et d’autres paradigmes, car ils vous fournissent des outils supplémentaires que vous pouvez utiliser pour rendre votre code de programme plus clair.
Enfin, enregistrez chaque action avec un commit. Vous intégrez quelque chose dans une nouvelle fonction, c'est un commit . Vous fusionnez deux fonctions en une seule, car elles font vraiment la même chose, c’est un commit . Si vous renommez une variable, c'est un commit . S'engager fréquemment. Si un jour se passe et que vous ne vous êtes pas engagé, vous avez probablement commis une erreur.
la source
Je suis d'accord avec les autres pour dire que le contrôle de version résoudra immédiatement bon nombre de vos problèmes. Plus précisément:
Je dirais qu'il ne faut pas trop y penser: utilisez simplement git. Tenez-vous en à des commandes simples (par exemple, une seule
master
branche), utilisez peut-être une interface graphique, et tout devrait bien se passer. En bonus, vous pouvez utiliser gitlab, github, etc. pour des publications et des sauvegardes gratuites;)La raison pour laquelle j'ai écrit cette réponse était pour aborder deux choses que vous pourriez essayer et que je n'ai pas vues mentionnées ci-dessus. La première consiste à utiliser les assertions comme une alternative légère au test unitaire. Les tests unitaires ont tendance à rester "en dehors" de la fonction / du module / quel que soit le test: ils envoient généralement des données à une fonction, reçoivent un résultat, puis vérifient certaines propriétés de ce résultat. Ceci est généralement une bonne idée, mais pourrait être gênant (surtout pour le code "jetable") pour plusieurs raisons:
Les assertions ne présentent pas ces inconvénients, car elles sont vérifiées lors de l'exécution normale d'un programme. En particulier:
Vous mentionnez la vitesse en tant que facteur, auquel cas la vérification d'assertion peut être indésirable dans cette boucle (mais reste utile pour vérifier la configuration et le traitement ultérieur). Cependant, presque toutes les implémentations d'assertions fournissent un moyen de les désactiver; Par exemple, en Python, ils peuvent apparemment être désactivés en utilisant l'
-O
option (je ne le savais pas, car je n'avais jamais ressenti le besoin de désactiver aucune de mes assertions auparavant). Je vous recommande de les laisser surpar défaut; Si votre cycle de codage / débogage / test ralentit, il vaudrait peut-être mieux tester avec un sous-ensemble plus petit de vos données ou effectuer moins d'itérations d'une simulation lors des tests ou autre. Si vous ne finissent par désactiver les assertions dans les essais non-tests pour des raisons de performance, la première chose que je vous recommande de faire est la mesure si elles sont en fait la source du ralentissement! (Il est très facile de se leurrer en ce qui concerne les goulots d'étranglement des performances)Mon dernier conseil serait d'utiliser un système de compilation qui gère vos dépendances. Personnellement, j'utilise Nix pour cela, mais j'ai également entendu de bonnes choses sur Guix . Il existe également des alternatives telles que Docker, qui sont beaucoup moins utiles d'un point de vue scientifique mais peut-être un peu plus familières.
Des systèmes tels que Nix ne sont que récemment (un peu) devenus populaires, et certains pourraient penser qu’ils sont excessifs pour du code "jetable" comme vous le décrivez, mais leur avantage pour la reproductibilité du calcul scientifique est énorme. Considérons un script shell pour exécuter un test, comme ceci (par exemple
run.sh
):Nous pouvons le réécrire dans une "dérivation" Nix à la place, comme ceci (par exemple
run.nix
):La substance entre
''...''
est le code bash, identique à celui que nous avions auparavant, sauf que vous${...}
pouvez l'utiliser pour "épisser" le contenu d'autres chaînes (dans ce cas./.
, le chemin sera étendu au chemin du répertoire qui le contientrun.nix
). Lawith import ...
ligne importe la bibliothèque standard de Nix , qui permetrunCommand
d’exécuter du code bash. Nous pouvons exécuter notre expérience en utilisantnix-build run.nix
, ce qui donnera un chemin comme/nix/store/1wv437qdjg6j171gjanj5fvg5kxc828p-output.csv
.Alors qu'est-ce que cela nous achète? Nix établira automatiquement un environnement «propre», qui n’a accès qu’à ce que nous avons explicitement demandé. En particulier, il n’a pas accès aux variables telles
$HOME
que les logiciels système que nous avons installés. Cela rend le résultat indépendant des détails de notre machine actuelle, comme le contenu~/.config
ou les versions des programmes que nous avons installés; AKA, ce qui empêche d'autres personnes de reproduire nos résultats! C'est pourquoi j'ai ajouté quecp
commande, car le projet ne sera pas accessible par défaut. Cela peut paraître ennuyeux que le logiciel du système ne soit pas disponible pour un script Nix, mais il en va tout autrement: nous n'avons besoin de rien installé sur notre système (autre que Nix) pour l'utiliser dans un script; nous le demandons simplement et Nix ira chercher / compiler / ce qui est nécessaire (la plupart des choses seront téléchargées sous forme de fichiers binaires; la bibliothèque standard est également énorme!). Par exemple, si nous voulons un ensemble de paquets Python et Haskell particuliers, pour certaines versions de ces langues, ainsi que d'autres objets indésirables (car pourquoi pas?):Le même
nix-build run.nix
exécutera ceci, récupérant tout ce que nous avons demandé en premier (et le mettant en cache au cas où nous le voudrions plus tard). La sortie (tout fichier / répertoire appelé$out
) sera stockée par Nix, qui est le chemin qu’elle crache. Elle est identifiée par le hachage cryptographique de toutes les entrées demandées (contenu du script, autres packages, noms, indicateurs de compilation, etc.); ces autres paquets sont identifiés par des hachages de leurs entrées, et ainsi de suite, de telle sorte que nous ayons une chaîne complète de provinence pour tout, depuis la version de GCC qui compilait la version de GCC qui compilait bash, et ainsi de suite!J'espère que j'ai montré que cela nous achetait beaucoup pour du code scientifique et qu'il était relativement facile de commencer avec. Il commence également à être pris très au sérieux par les scientifiques, par exemple (top hit Google) https://dl.acm.org/citation.cfm?id=2830172 pourrait donc être une compétence précieuse à cultiver (tout comme la programmation)
la source
Sans passer à l'état d'esprit total de contrôle de version + packaging + tests unitaires (qui sont de bonnes pratiques de programmation que vous devriez essayer de mettre en place à un moment donné), une solution intermédiaire qui conviendrait à mon avis est d'utiliser Jupiter Notebook . Cela semble mieux s'intégrer au calcul scientifique.
Il a l’avantage de pouvoir mélanger vos pensées avec le code; expliquer pourquoi une approche est meilleure qu'une autre et laisser l'ancien code tel quel dans une section ad-hoc. De plus, bien utiliser les cellules vous mènera naturellement à fragmenter votre code et à l’organiser en fonctions qui peuvent aider à sa compréhension.
la source
Les principales réponses sont déjà bonnes, mais je voulais aborder certaines de vos questions directement.
La taille du code n'est pas directement liée à la nécessité de tests unitaires. Cela est lié indirectement: les tests unitaires ont plus de valeur dans les bases de code complexes , et les petites bases de code ne sont généralement pas aussi complexes que les plus grandes.
Les tests unitaires brillent pour le code où il est facile de faire des erreurs, ou lorsque vous allez avoir plusieurs implémentations de ce code. Les tests unitaires ne vous aident pas beaucoup avec le développement actuel , mais ils vous empêchent également de faire des erreurs qui pourraient causer un mauvais comportement du code existant (même si vous n'avez pas touché à cela).
Supposons que vous avez une application dans laquelle la bibliothèque A effectue la mise en carré des nombres et la bibliothèque B applique le théorème de Pythagore. De toute évidence, B dépend de A. Vous devez corriger quelque chose dans la bibliothèque A et imaginons que vous introduisez un bogue qui divise les nombres en cubes au lieu de les redimensionner.
La bibliothèque B commencera soudainement à se comporter de manière incorrecte, générant éventuellement des exceptions ou donnant simplement une sortie erronée. Et quand vous regardez l'historique des versions de la bibliothèque B, vous voyez qu'il n'est pas touché. Le résultat final problématique est que vous n'avez aucune indication de ce qui pourrait mal se passer et que vous allez devoir déboguer le comportement de B avant de réaliser que le problème est en A. C'est un effort inutile.
Entrez les tests unitaires. Ces tests confirment que la bibliothèque A fonctionne comme prévu. Si vous introduisez un bogue dans la bibliothèque A qui lui renvoie des résultats erronés, vos tests unitaires le détecteront. Par conséquent, vous ne serez pas obligé d'essayer de déboguer la bibliothèque B.
Cela dépasse votre portée, mais dans un développement en intégration continue, des tests unitaires sont exécutés chaque fois que quelqu'un valide du code, ce qui signifie que vous saurez que vous avez cassé quelque chose dès que possible.
Les tests unitaires peuvent être une bénédiction, en particulier pour les opérations mathématiques complexes. Vous effectuez quelques exemples de calculs, puis vous écrivez des tests unitaires qui comparent votre sortie calculée et votre sortie réelle (sur la base des mêmes paramètres d'entrée).
Cependant, notez que les tests unitaires ne vous aideront pas à créer un bon code, mais le maintiendront . Si vous écrivez habituellement du code une fois et ne le revisitez jamais, les tests unitaires seront moins bénéfiques.
La POO est une façon de penser à des entités distinctes, par exemple:
Comparez cela à la façon dont un programmeur fonctionnel réfléchit:
Pommes et oranges. Ni l'un ni l'autre n'est objectivement meilleur que l'autre. Une chose intéressante à noter est que pour la programmation orientée objet, il
Vendor
est mentionné deux fois, mais il fait référence à la même chose. Cependant, pour la programmation fonctionnelle,talktoVendor()
etpayVendor()
sont deux choses distinctes.Cela montre la différence entre les approches. S'il y a beaucoup de logique partagée spécifique au fournisseur entre ces deux actions, alors la POO aide à réduire la duplication de code. Cependant, s'il n'y a pas de logique partagée entre les deux, alors les fusionner en un seul
Vendor
est un travail inutile (et par conséquent, une programmation fonctionnelle est plus efficace).Plus souvent qu'autrement, les calculs mathématiques et scientifiques sont des opérations distinctes qui ne reposent pas sur une logique / formule partagée implicite. Pour cette raison, la programmation fonctionnelle est plus souvent utilisée que la POO.
Votre question implique que la définition de "code propre et bon" change si vous effectuez une programmation scientifique ou travaillez sur des projets plus importants (je suppose que vous voulez dire d'entreprise).
La définition du bon code ne change pas. La nécessité d'éviter la complexité (ce qui peut être fait en écrivant du code propre) change toutefois.
Le même argument revient ici.
Je comprends la distinction que vous faites ici, mais quand vous regardez en arrière le code existant, vous regardez à la fois le calcul et la programmation. Si l' un ou l' autre est artificiel ou complexe, vous aurez du mal à le lire.
Mis à part les principes de la programmation orientée objet, la principale raison pour laquelle j'écris des classes pour héberger quelques valeurs de données est qu'elle simplifie la déclaration des paramètres de méthode et des valeurs renvoyées. Par exemple, si de nombreuses méthodes utilisent un emplacement (paire lat / lon), je me lasserai vite de devoir taper
float latitude, float longitude
et préférerai de beaucoup écrireLocation loc
.Cela est d'autant plus complexe si vous considérez que les méthodes renvoient généralement une valeur (à moins que des fonctionnalités spécifiques au langage ne renvoient plus de valeurs), et qu'un emplacement, par exemple, voudrait que vous renvoyiez deux valeurs (lat + lon). Cela vous incite à créer une
Location
classe pour simplifier votre code.Une autre chose intéressante à noter est que vous pouvez utiliser la POO sans mélanger les valeurs de données et les méthodes. Tous les développeurs ne sont pas d’accord ici (certains l’appellent un antipattern), mais vous pouvez avoir des modèles de données anémiques dans lesquels vous avez des classes de données distinctes (champs de valeur stockés) et des classes logiques (méthodes de stockage).
Ceci est, bien sûr, sur un spectre. Vous n'avez pas besoin d'être parfaitement anémique, vous pouvez l'utiliser quand vous le jugez à propos.
Par exemple, une méthode qui concatène simplement le prénom et le nom d'une personne peut toujours être hébergée dans la
Person
classe elle-même, car il ne s'agit pas vraiment de "logique", mais plutôt d'une valeur calculée.Une classe est toujours aussi grande que la somme de ses champs. Reprenons l’exemple de
Location
, qui consiste en deuxfloat
valeurs, il est important de noter ici qu’un seulLocation
objet occupe autant de mémoire que deuxfloat
valeurs distinctes .En ce sens, peu importe que vous utilisiez la POO ou non. L'empreinte mémoire est la même.
La performance en elle-même n’est pas un gros obstacle à franchir. La différence entre, par exemple, l'utilisation d'une méthode globale ou d'une méthode de classe n'a rien à voir avec les performances d'exécution, elle a tout à voir avec la génération de bytecode au moment de la compilation.
Pensez-y de cette façon: que j'écrive ma recette de gâteau en anglais ou en espagnol, cela ne change rien au fait qu'il faudra 30 minutes pour que le gâteau soit cuit (= performance d'exécution). La seule chose que la langue de la recette change est la façon dont le cuisinier mélange les ingrédients (= compilation du code binaire).
Pour Python en particulier, il n'est pas nécessaire de pré-compiler explicitement le code avant de l'appeler. Cependant, lorsque vous ne pré-compilez pas, la compilation aura lieu lors de la tentative d'exécution du code. Quand je dis "runtime", je parle de l'exécution elle-même, pas de la compilation qui pourrait précéder l'exécution.
la source
Avantages du code scientifique propre
Il peut être utile d’examiner votre code du point de vue d’un futur codeur.
Selon mon expérience,
Un code propre devrait faciliter la vérification de vos résultats
Vous voudrez peut-être diviser votre programme afin que chaque algorithme puisse être analysé séparément.
Évitez d’écrire des fonctions avec des effets secondaires contre-intuitifs dans lesquels une opération non liée entraîne le comportement d’une autre opération. Si vous ne pouvez pas l'éviter, documentez ce dont votre code a besoin et comment le configurer.
Un code propre peut servir d'exemple de code pour les futurs codeurs
Des commentaires clairs (y compris ceux qui montrent comment les fonctions doivent être appelées) et des fonctions bien séparées peuvent faire une différence énorme en ce qui concerne le temps qu'il faut à quelqu'un qui commence (ou qui vous suit) pour tirer quelque chose de votre travail utile.
De plus, créer une véritable "API" pour votre algorithme peut vous aider à mieux vous préparer si vous décidez de transformer vos scripts en une véritable bibliothèque pouvant être utilisée par quelqu'un d'autre.
Recommandations
"Cite" les formules mathématiques en utilisant des commentaires.
John Smith Method from Some Book 1st Ed. Section 1.2.3 Pg 180
, si vous avez trouvé la formule sur un site Web ou dans un document, citez-la également.Utilisez les commentaires à bon escient
Si vous pouvez améliorer la lisibilité de votre code en utilisant de bons noms de variables / noms de fonctions, faites-le d'abord. N'oubliez pas que les commentaires resteront indéfiniment jusqu'à ce que vous les supprimiez. Essayez donc de faire des commentaires qui ne seront pas périmés.
Utilisez des noms de variables descriptives
xBar_AverageVelocity
Ecrivez du code pour exécuter votre programme contre les bonnes et les mauvaises données connues.
Je pense que les tests unitaires peuvent être utiles. Je pense que la meilleure forme de test unitaire pour le code scientifique est une série de tests qui fonctionnent sur des données connues ou négatives.
Ecrivez du code pour exécuter votre algorithme et vérifiez si le résultat diffère de ce que vous attendiez. Cela vous aidera à trouver des problèmes (potentiellement très difficiles et difficiles à trouver) dans lesquels vous codez accidentellement quelque chose qui cause un résultat faux positif ou faites une erreur qui fait que la fonction renvoie toujours la même valeur.
Notez que cela peut être fait à n'importe quel niveau d'abstraction. Par exemple, vous pouvez tester un algorithme de correspondance de motif complet ou une fonction qui calcule simplement la distance entre deux résultats dans votre processus d'optimisation. Commencez par les zones les plus cruciales pour vos résultats, et / ou les parties du code qui vous préoccupent le plus.
Ajoutez facilement de nouveaux cas de test, envisagez d’ajouter des fonctions "auxiliaires" et structurez efficacement vos données d’entrée. Cela peut signifier éventuellement la sauvegarde des données d'entrée dans un fichier afin que vous puissiez facilement réexécuter des tests, tout en étant très prudent pour éviter les faux positifs ou les cas de test biaisés / résolus de manière triviale.
Pensez à utiliser quelque chose comme la validation croisée , voir cet article sur la validation croisée pour plus d'informations.
Utiliser le contrôle de version
Je recommanderais d'utiliser le contrôle de version et d'héberger votre référentiel sur un site externe. Il existe des sites qui hébergeront des dépôts gratuitement.
Avantages:
Soyez prudent lorsque vous copiez / collez du code
Copier / coller du code peut vous faire gagner du temps, mais c'est l'une des choses les plus dangereuses que vous puissiez faire, surtout si c'est du code que vous n'avez pas écrit vous-même (par exemple, s'il s'agit du code d'un collègue).
Dès que le code est fonctionnel et testé, je vous recommande de le lire très attentivement pour renommer les variables ou commenter tout ce que vous ne comprenez pas.
la source
Les outils du métier sont généralement inventés pour répondre à un besoin. Si vous avez le besoin d'utiliser l'outil, sinon, vous n'êtes probablement pas obligé de le faire.
Plus précisément, les programmes scientifiques ne sont pas la cible finale, mais le moyen. Vous écrivez le programme pour résoudre un problème que vous avez maintenant - vous ne vous attendez pas à ce que ce programme soit utilisé par d'autres (et qu'il soit maintenu) dans dix ans. Cela seul signifie que vous n'avez pas besoin de penser aux outils qui permettent au développeur actuel d'enregistrer l'historique d'autres utilisateurs tels que le contrôle de version, ou de capturer des fonctionnalités dans du code comme des tests unitaires.
Qu'est-ce qui vous profiterait alors?
la source
En plus des bons conseils déjà donnés, vous voudrez peut-être examiner le but de votre programmation et, par conséquent, ce qui est important pour vous.
"Ce sont les mathématiques ou les sciences que je teste ou que je recherche avec la programmation."
Si le but est d'expérimenter et de tester quelque chose pour votre propre compréhension et que vous sachiez quels devraient être les résultats, votre code est à la base un jeton rapide et votre approche actuelle peut suffire, bien qu'elle puisse être améliorée. Si les résultats ne sont pas conformes aux attentes, vous pouvez revenir en arrière et passer en revue.
Toutefois, si les résultats de votre codage informent l’orientation de votre recherche et que vous ne savez pas ce qu’ils devraient être, l’exactitude devient alors particulièrement importante. Une erreur dans votre code pourrait vous amener à tirer des conclusions erronées de votre expérience, avec diverses conséquences néfastes pour votre recherche globale.
Dans ce cas, diviser votre code en fonctions faciles à comprendre et à vérifier avec des tests unitaires vous donnera des briques de construction plus solides, ce qui vous donnera plus de confiance en vos résultats et vous épargnera beaucoup de frustration par la suite.
la source
Si le contrôle de version et les tests unitaires permettent de garder votre code global organisé et fonctionnel, ils ne vous aident pas non plus à écrire du code plus propre.
Si vous voulez vous empêcher d'écrire du code en désordre, vous avez besoin d'un outil qui fonctionne là où les dégâts se produisent: lorsque vous écrivez le code. Un type d'outil populaire qui s'appelle linter. Je ne suis pas un développeur Python, mais il semble que Pylint pourrait être une bonne option.
Un linter examine le code que vous avez écrit et le compare à un ensemble configurable de meilleures pratiques. Si le linter a une règle que les variables doivent être
camelCase
et que vous en écrivez unesnake_case
, il le signalera comme une erreur. Les bons linters ont des règles allant de "les variables déclarées doivent être utilisées" à "La complexité cyclomatique des fonctions doit être inférieure à 3".La plupart des éditeurs de code peuvent être configurés pour exécuter un linter chaque fois que vous enregistrez, ou simplement en général lors de la frappe, et indiquer les problèmes en ligne. Si vous tapez quelque chose comme
x = 7
, lex
sera mis en surbrillance, avec l’instruction d’utiliser un nom plus long et meilleur (si c’est ce que vous avez configuré). Cela fonctionne comme une vérification orthographique dans la plupart des traitements de texte, ce qui rend difficile l’ignorance et permet de créer de meilleures habitudes.la source
Tout ce que vous avez énuméré est un outil de la boîte à outils métaphorique. Comme n'importe quoi dans la vie, différents outils sont appropriés pour différentes tâches.
Comparé à d’autres domaines de l’ingénierie, le logiciel fonctionne avec un tas de pièces individuelles qui, en elles-mêmes, sont assez simples. Une déclaration de mission n'évalue pas différemment en fonction des fluctuations de température de la pièce. Une
if
déclaration ne se corrode pas à la place et retourne la même chose après un certain temps. Mais comme les éléments individuels sont très simples et que les logiciels sont conçus par des humains, ces éléments sont combinés en éléments de plus en plus grands jusqu'à ce que le résultat devienne si grand et complexe qu'il atteigne les limites de ce que les gens peuvent gérer mentalement.Au fur et à mesure que les projets logiciels ont pris de l'ampleur, les gens les ont étudiés et ont créé des outils pour tenter de gérer cette complexité. OOP est un exemple. De plus en plus de langages de programmation abstraits sont un autre moyen. Parce qu'une grande partie de l'argent des logiciels en fait de plus en plus , les outils pour y parvenir sont ce que vous allez voir et lire. Mais il semble que ces situations ne vous concernent pas.
Alors, ne se sentent pas comme vous devez être faire tout cela. En fin de compte, le code n'est qu'un moyen de parvenir à une fin. Malheureusement, ce qui vous donnera le meilleur aperçu de ce qui est approprié ou non, est de travailler sur des projets plus importants, car il est beaucoup plus difficile de savoir ce qui manque lorsque vous pensez à la boîte à outils.
Dans tous les cas, je ne voudrais pas m'inquiéter de ne pas utiliser la POO ou d'autres techniques tant que vos scripts sont petits. La plupart des problèmes que vous avez décrits ne sont que des compétences organisationnelles professionnelles générales, c'est-à-dire que ne pas perdre un ancien fichier est un problème auquel tous les domaines doivent faire face.
la source
En plus de toutes les bonnes suggestions fournies jusqu'à présent, une pratique que j'ai apprise au fil du temps et que je trouve essentielle consiste à ajouter très généreusement des commentaires détaillés à votre code. C'est la chose la plus importante pour moi quand je reviens à quelque chose après un long laps de temps. Explique-toi ce que tu penses. Cela prend un peu de temps à faire mais c'est relativement facile et surtout sans douleur.
J'ai parfois deux ou trois fois plus de lignes de commentaires que de code, en particulier lorsque les concepts ou les techniques sont nouveaux pour moi et doivent être expliqués par moi-même.
Faites le contrôle de version, améliorez vos pratiques, etc .... tout ce qui précède. Mais expliquez-vous les choses au fur et à mesure. Ça marche vraiment bien.
la source
Quelles sont les qualités importantes pour ce type de programme?
Peu importe qu'il soit facile à maintenir ou à faire évoluer, il est fort probable que cela ne se produira pas.
Peu importe son efficacité, peu importe.
Peu importe qu'il ait une excellente interface utilisateur ou qu'il soit sécurisé contre des attaquants malveillants.
Il peut être important que ce soit lisible: quiconque lisant votre code puisse facilement se convaincre qu'il fait ce qu’il prétend faire.
Il est certainement important que ce soit correct. Si le programme donne des résultats incorrects, ce sont vos conclusions scientifiques qui sortent de la fenêtre. Mais il ne faut que traiter correctement l'entrée que vous lui demandez réellement de traiter; Peu importe vraiment si cela tombe si on donne des valeurs de données d'entrée négatives, si toutes vos valeurs de données sont positives.
Il importe également que vous mainteniez un certain niveau de contrôle du changement. Vos résultats scientifiques doivent être reproductibles, ce qui signifie que vous devez savoir quelle version du programme a produit les résultats que vous souhaitez publier. Comme il n'y a qu'un seul développeur, le contrôle de modification n'a pas besoin d'être très élaboré, mais vous devez vous assurer que vous pouvez revenir à un moment donné et reproduire vos résultats.
Donc, ne vous inquiétez pas des paradigmes de programmation, de l'orientation des objets, de l'élégance algorithmique. Ne vous souciez que de la clarté et de la lisibilité et de la traçabilité de vos modifications dans le temps. Ne vous inquiétez pas pour l'interface utilisateur. Ne vous inquiétez pas pour tester toutes les combinaisons possibles de paramètres d'entrée, mais faites suffisamment d'essais pour vous assurer (et pour donner confiance aux autres) que vos résultats et conclusions sont valides.
la source
J'ai travaillé dans un environnement similaire avec des universitaires qui écrivent beaucoup de code (mathématiques / sciences), mais leur progression est lente pour les mêmes raisons que celles que vous avez décrites. Cependant, j’ai remarqué une chose qui s’est bien déroulée et qui, à mon avis, peut également vous aider: constituer et maintenir une collection de bibliothèques spécialisées pouvant être utilisées dans plusieurs projets. Ces bibliothèques devraient fournir des fonctions utilitaires et vous aideront donc à garder votre projet actuel spécifique au domaine problématique.
Par exemple, vous devrez peut-être gérer de nombreuses transformations de coordonnées dans votre domaine (ECEF, NED, lat / lon, WGS84, etc.), de sorte qu'une fonction similaire
convert_ecef_to_ned()
devrait être insérée dans un nouveau projet appeléCoordinateTransformations
. Placez le projet sous contrôle de version et hébergez-le sur les serveurs de votre service afin que d'autres personnes puissent l'utiliser (et éventuellement l'améliorer). Ensuite, après quelques années, vous devriez avoir une collection solide de bibliothèques avec vos projets ne contenant que du code spécifique à un problème / domaine de recherche particulier.Quelques conseils plus généraux:
la source
Ce qui suit sont mes opinions et très influencés par mon propre chemin.
Le codage engendre souvent des perspectives dogmatiques sur la manière de faire les choses. Au lieu de techniques et d’outils, je pense que vous devez examiner les valeurs et les coûts cumulés pour décider d’une stratégie appropriée.
Écrire un code solide, lisible, débogable et solide demande beaucoup de temps et d’efforts. Dans de nombreux cas, étant donné un horizon de planification limité, cela n’est pas rentable (paralysie de l’analyse).
Un collègue avait une règle de base; si vous faites essentiellement le même genre de chose pour la troisième fois, investissez des efforts, sinon un travail rapide et sale est approprié.
Des tests de quelque sorte sont essentiels, mais pour des projets ponctuels, une simple observation peut suffire. Pour tout ce qui est substantiel, des tests et une infrastructure de test sont essentiels. La valeur est que cela vous libère lors du codage, le coût est que si le test est axé sur une implémentation particulière, les tests ont également besoin de maintenance. Les tests vous rappellent également comment les choses sont supposées fonctionner.
Pour mes propres scripts uniques (souvent pour des tâches telles que la validation d'une estimation d'une probabilité, ou similaire), j'ai trouvé deux petites choses très utiles: 1. Incluez un commentaire indiquant comment le code est utilisé. 2. Incluez une brève description des raisons pour lesquelles vous avez écrit le code. Ces choses-là sont terriblement évidentes quand vous écrivez le code, mais l'évidence perd de son temps :-).
La POO concerne la réutilisation de code, l'abstraction, l'encapsulation, la factorisation, etc. Très utile, mais il est facile de s'y perdre si la production de code et de design de qualité n'est pas votre objectif final. Il faut du temps et des efforts pour produire des choses de qualité.
la source
Bien que je pense que les tests unitaires ont leurs mérites, ils ont une valeur douteuse pour le développement scientifique - ils sont souvent trop petits pour offrir beaucoup de valeur.
Mais j'aime beaucoup les tests d'intégration de code scientifique:
Isolez une petite partie de votre code qui pourrait fonctionner seul, par exemple le pipeline ETL. Ecrivez ensuite un test fournissant les données, exécutez le pipeline etl (ou simplement une étape), puis vérifiez que le résultat correspond à vos attentes. Bien que le bloc testé puisse contenir beaucoup de code, le test fournit toujours une valeur:
J'utilise souvent cette technique et aboutis souvent à une fonction principale relativement lisible, mais les sous-fonctions sont souvent assez longues et laides, mais peuvent être modifiées et réorganisées rapidement en raison de la robustesse des limites d'E / S.
la source
Je travaille normalement sur une très grande base source. Nous utilisons tous les outils que vous mentionnez. Récemment, j'ai commencé à travailler sur des scripts python pour un projet parallèle. Ils sont quelques dizaines à quelques centaines de lignes au plus. Par habitude, j'ai engagé mes scripts dans le contrôle de code source. Cela a été utile car je peux créer des branches pour expérimenter des expériences qui pourraient ne pas fonctionner. Je peux créer un fork si j'ai besoin de dupliquer le code et de le modifier dans un autre but. Cela laisse l'original intacte au cas où je devrais le sortir à nouveau.
Pour les "tests unitaires", je n'ai que quelques fichiers d'entrée destinés à produire des sorties connues que je vérifie à la main. Je pourrais probablement l'automatiser, mais il me semble que cela prendrait plus de temps que je n'en économiserais. Cela dépend probablement de la fréquence à laquelle je dois modifier et exécuter les scripts. De toute façon, si cela fonctionne, faites-le. Si le problème ne vous en vaut pas la peine, ne perdez pas votre temps.
la source
Avec l'écriture de code - comme avec l'écriture en général - la question principale est:
Des règles telles que les directives de codage officielles n’ont aucun sens lorsque vous êtes votre seul public.
Cela étant dit, par contre, il serait utile de rédiger le code de manière à ce que votre avenir puisse le comprendre tout de suite.
Donc, un "bon style" serait celui qui vous aiderait le plus. À quoi ce style devrait ressembler est une réponse que je ne peux pas donner.
Je pense que vous n'avez pas besoin de tests de programmation orientée objet ni de tests unitaires pour des fichiers de 150 LOC. Un VCS dédié serait intéressant si vous avez un code en évolution. Sinon, un
.bak
fait le tour. Ces outils sont un remède à une maladie, vous pourriez même pas avoir.Vous devriez peut-être écrire votre code de telle manière que, même si vous le lisez en état d'ébriété, vous puissiez le lire, le comprendre et le modifier.
la source