web-dev-qa-db-fra.com

La frappe statique vaut-elle les compromis?

J'ai commencé à coder en Python principalement là où il n'y a pas de sécurité de type, puis je suis passé à C # et Java là où il y en a. J'ai trouvé que je pouvais travailler un peu plus rapidement et avec moins de maux de tête en Python, mais là encore, mes applications C # et Java sont à un niveau de complexité beaucoup plus élevé, donc je n'ai jamais donné Python a vrai test de stress, je suppose.

Les camps Java et C # donnent l'impression que sans le type de sécurité en place, la plupart des gens rencontreraient toutes sortes d'horribles bugs à gauche et ce serait plus difficile que sa valeur.

Ce n'est pas une comparaison de langue, veuillez donc ne pas aborder les problèmes tels que compilés vs interprétés. La sécurité des types vaut-elle le coup pour la vitesse de développement et la flexibilité? POURQUOI?

aux personnes qui voulaient un exemple de l'opinion selon laquelle la frappe dynamique est plus rapide:

"Utilisez un langage typé dynamiquement pendant le développement. Il vous donne un retour plus rapide, un temps de traitement et une vitesse de développement." - http://blog.jayway.com/2010/04/14/static-typing-is-the-root-of-all-evil/

110
Morgan Herlocker

C'est une sorte de mythe selon lequel les programmeurs n'ont pas à se soucier des types dans les langages typés dynamiquement.

Dans les langues typées dynamiquement:

  • Vous devez toujours savoir si vous travaillez avec un tableau, un entier, une chaîne, une table de hachage, une référence de fonction, un dictionnaire, un objet ou autre.

  • S'il s'agit d'un objet, vous devez savoir à quelle classe il appartient.

  • L'affectation d'un de ces types à une variable ou à un paramètre de fonction censé être un autre type est presque toujours une erreur.

  • À un niveau inférieur, des éléments comme le nombre de bits ou fréquemment signé ou non signé doivent toujours être pris en compte si vous remplissez un paquet TCP, par exemple).

  • Vous pouvez rencontrer des problèmes où vous obtenez un zéro où vous vouliez vraiment une chaîne vide. En d'autres termes, vous déboguez toujours des bogues de non-concordance de type. La seule vraie différence est que le compilateur n'attrape pas les erreurs.

  • Je dirais que vous n'économisez même pas beaucoup de frappe -, parce que vous avez tendance à vouloir documenter dans les commentaires le type de vos paramètres de fonction au lieu de le documenter dans votre code. C'est pourquoi les blocs de commentaires de style doxygen sont beaucoup plus populaires dans la pratique dans le code typé dynamiquement, où dans les langages typés statiquement, vous ne les voyez principalement que pour les bibliothèques.

Cela ne veut pas dire que la programmation dans des langages typés dynamiquement n'est pas plus agréable car le compilateur n'est pas toujours sur votre dos, et les programmeurs expérimentés ne le font pas ' t ont tendance à avoir de la difficulté à trouver et à corriger le type de bogues que le typage statique attraperait de toute façon, mais c'est un problème complètement distinct d'une augmentation présumée de l'efficacité ou d'une réduction du taux de bogues, pour lequel le typage dynamique est au mieux même avec le typage statique.

164
Karl Bielefeldt

Au fur et à mesure que les types deviennent plus forts, ils peuvent vous aider davantage - si vous les utilisez correctement au lieu de les combattre. Concevez vos types pour refléter votre espace de problème et les erreurs logiques sont plus susceptibles de devenir des incompatibilités de type au moment de la compilation plutôt que des plantages à l'exécution ou des résultats absurdes.

124
geekosaur

Avis de non-responsabilité: je suis un amoureux des caractères;)

Il est difficile de répondre à votre question: Quels sont ces compromis?

Je prendrai un exemple extrême: Haskell , il est typé statiquement. Peut-être l'une des langues les plus fortement typées qui existent, en fait.

Cependant, Haskell prend en charge Programmation générique, dans le sens où vous écrivez des méthodes qui fonctionnent avec tout type conforme à un certain concept (ou interface).

De plus, Haskell utilise Type Inference, pour que vous n'ayez jamais à déclarer le type de vos variables. Ils sont calculés statiquement pendant la compilation, tout comme un interprète Python les calculerait en exécutant le programme.

J'ai constaté que la plupart des gens se moquant de la frappe statique se plaignaient en fait d'autre chose (verbosité, peine de changer de type en faveur d'un autre), mais Haskell ne présente aucun de ces problèmes, tout en étant typé statiquement ...


Exemple de brièveté:

-- type
factorial :: Integer -> Integer

-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)

Mis à part le support intégré, il est difficile d'être plus bref.

Exemple de programmation générique:

> reverse "hell­o" -- Strings are list of Char in Haskell
=> "olleh"
> reverse [1, 2, 3, 4, 5]
=> [5,4,3,2,1]

Exemple d'inférence de type:

> :t rever­se "hell­o"
:: [Char]

qui peut être calculé simplement:

  • "hello" est une liste de Char (exprimée en [Char])
  • reverse appliqué à un type [A] renvoie un type [A]

Essayez-le dans votre navigateur

78
Matthieu M.

J'aime les langages à la fois statiques et dynamiques. Les deux plus grands avantages de la sécurité de type sont pour moi:

1) Vous pouvez souvent déduire ce qu'une fonction fait uniquement à partir de sa signature de type (cela est particulièrement vrai dans les langages fonctionnels comme Haskell).

2) Lorsque vous effectuez une refonte importante, le compilateur vous dit automatiquement tout ce que vous avez à faire pour que tout fonctionne. Quand je refactorise quelque chose en C++, ma procédure est souvent simplement a) changer la partie que je sais que je veux changer, puis b) corriger chaque erreur de compilation.

37
dfan

Personnellement, je trouve que la sécurité des types m'aide à me développer plus rapidement dans mon travail actuel. Le compilateur effectue une grande partie de la vérification de ma santé mentale presque au fur et à mesure que je tape, ce qui me permet de me concentrer davantage sur la logique métier que j'implémente.

En fin de compte, pour moi, même si je perds une certaine flexibilité, je gagne du temps qui serait autrement consacré à la recherche de problèmes de type.

29
Michael K

Il y a beaucoup d'opinions fortes autour du débat mais évidemment ce n'est pas vraiment une question d'opinion, c'est une question de faits. Donc nous devrions regarder la recherche empirique. Et les preuves en sont claires:

Oui , la frappe statique vaut les compromis - et pas seulement un peu, mais en fait substantiellement. En fait, des preuves solides montrent que le typage statique peut réduire le nombre de bogues dans le code d'au moins 15% (et il s'agit d'une estimation basse, la valeur réelle pourcentage est certainement plus élevé). C'est un nombre scandaleusement élevé: Je pense que même la plupart des partisans de la frappe statique n'auraient pas pensé que cela faisait une différence aussi radicale.

Considérez ceci: si quelqu'un vous a dit qu'il y avait un moyen simple de réduire les bugs de votre projet de 15% du jour au lendemain, cela devrait être une évidence.1  C'est presque la balle d'argent proverbiale.

Les preuves sont présentées dans l'article Taper ou ne pas taper: quantifier les bogues détectables en JavaScript par Zheng Gao, Christian Bird et Earl T. Barr. J'encourage tout le monde à le lire, c'est un article bien écrit qui présente des recherches exemplaires.

Il est difficile de résumer succinctement la rigueur avec laquelle les auteurs ont effectué leur analyse, mais voici un aperçu (très approximatif):

TypeScript et Flow sont deux langages de programmation basés sur JavaScript qui, tout en restant par ailleurs compatibles, ajoutent une indication de type et une vérification de type statique. Cela permet d'augmenter le code existant par types, puis de taper check it.

Les chercheurs ont collecté des projets Open Source écrits en JavaScript depuis GitHub, examiné les rapports de bogues résolus et tenté de réduire chacun des bogues signalés en un morceau de code qui serait détecté par le vérificateur de type statique de TypeScript ou Flow. Cela leur a permis d'estimer une limite inférieure du pourcentage de bogues pouvant être corrigés en utilisant une saisie statique.

Les chercheurs ont pris des précautions strictes pour s'assurer que leur analyse ne considérerait pas un bogue non lié à un type comme étant lié à des types.2

Par rapport aux études antérieures, cette nouvelle étude présente des atouts particuliers:

  • Il y a une comparaison directe de la frappe dynamique vs dynamique, avec peu (le cas échéant) de facteurs de confusion, car la seule différence entre JavaScript et TypeScript/Flow est la dactylographie.
  • Ils effectuent la réplication sur plusieurs dimensions en vérifiant à la fois TypeScript et Flow (c'est-à-dire des systèmes de types différents), et en faisant en sorte que différentes personnes reproduisent l'annotation de type (manuelle) pour corriger les bogues. Et ils effectuent cela sur un grand nombre de bases de code de différents projets.
  • Le papier mesure l'impact direct de la frappe statique sur bugs corrigibles (plutôt que sur une qualité plus vague).
  • Les auteurs définissent dès le départ un modèle rigoureux de ce qu'il faut mesurer et comment. De plus, leur description est incroyablement claire et facilite l'analyse des défauts (c'est toujours bien quand un document de recherche s'ouvre aux attaques: si aucune attaque ne parvient à ébranler ses arguments, il en ressort encore plus fort).3
  • Ils effectuent correctement analyse de puissance de sorte que leur taille d'échantillon soit suffisante et que leur analyse statistique ultérieure soit étanche à l'air.
  • Ils sont trop conservateurs pour exclure les explications de confusion et ne mesurent qu'une seule partie mobile. De plus, ils limitent leur analyse aux bogues qui peuvent être immédiatement corrigés en incluant des types, et excluent tout ce qui pourrait nécessiter une refactorisation plus avancée pour s'adapter à la saisie. Donc en réalité, l'effet est plausiblement beaucoup plus grand, mais certainement pas plus petit que ce qu'ils ont rapporté.
  • Et enfin, ils ne trouvent pas un léger effet mais une différence stupéfiante . Malgré leur procédure trop conservatrice, même au bas de l'intervalle de confiance à 95%, ils constatent qu'il y a au moins 10% de bogues qui disparaîtraient simplement avec un minimum de vérifications de type supplémentaires.

À moins qu'il n'y ait une faille fondamentale dans le papier que personne n'a encore découvert, le papier montre de manière concluante un grand avantage du typage statique, presque gratuitement.4


Sur une note historique, la recherche sur les disciplines de dactylographie dans la programmation a connu un début difficile car, pendant longtemps, les preuves n'étaient pas claires du tout. La raison en est que faire des expériences systématiques pour examiner l'effet du typage statique vs dynamique n'est pas facile: une expérience systématique doit isoler l'effet que nous étudions. Et malheureusement, nous ne pouvons pas isoler l'effet de la discipline de frappe, car elle est liée aux langages de programmation.

Il existe en fait existait langages de programmation qui permettaient à la fois la saisie statique et dynamique dans différents dialectes (par exemple VB avec Option StrictOn ou Off, ou LISP typé statiquement). Cependant, ceux-ci n'étaient pas bien adaptés à une comparaison directe, surtout parce qu'il n'existait pas de bases de code suffisamment grandes pour permettre une comparaison directe. Au mieux, nous pourrions les comparer dans des "environnements de laboratoire", où les sujets testés résolvent au hasard une tâche dans la variante typée de façon statique ou dynamique de la langue.

Malheureusement, ces affectations de programmation artificielles ne modélisent pas bien l'utilisation réelle. En particulier, beaucoup d'entre eux sont de petite envergure et résolvent un problème bien défini qui peut être résumé sur une demi-page de texte.

Heureusement, c'était dans le passé, car TypeScript, Flow et JavaScript sont en effet les mêmes langages, à l'exception du typage statique, et parce qu'il existe un vaste ensemble de données réelles de code et de bogues à échantillonner.


1 Inspiré d'une citation du papier original.

2 Je ne suis pas entièrement satisfait de cela: l'une des principales forces des langages à typage statique est que les problèmes ostensiblement sans rapport avec le type peuvent être formulés de manière à pouvoir être vérifiés statiquement. Cela transforme de nombreuses erreurs logiques en erreurs de type, ce qui considérablement augmente le taux de bogues pouvant être détectés par la saisie statique. En fait, l'article classe grossièrement les bogues sans rapport avec le type et je soutiens qu'un grand pourcentage de ceux-ci pourraient en fait être détectés par une frappe statique.

3 J'invite tout le monde, en particulier les partisans de la frappe dynamique, à essayer de trouver des failles non corrigées dans l'analyse. Je ne pense pas qu'il y en ait beaucoup (le cas échéant), et je suis convaincu qu'aucune faille potentielle ne modifierait sensiblement le résultat.

4 Je soupçonne que le coût réel du typage statique dans les projets réels à grande échelle est inexistant, car il devient alors une partie naturelle de l'architecture et pourrait même simplifier la planification. La correction des erreurs de type statique prend du temps, mais beaucoup moins que les erreurs découvertes plus tard. Cela a été largement étudié empiriquement et est connu depuis des décennies (voir par exemple Code complet).

14
Konrad Rudolph

La sécurité des types vaut-elle le coup pour la vitesse de développement et la flexibilité?

Donc, cela dépend vraiment de ce que vous faites. Si vous programmez, par exemple, les systèmes de sauvegarde pour les avions, la sécurité de type est probablement la voie à suivre.

Langage dynamique vs programmation en langage statique sont vraiment deux animaux différents. Ils nécessitent tous deux une approche fondamentalement différente les uns des autres. Vous pouvez principalement porter une méthode d'approche entre statique et dynamique, mais vous perdrez les avantages de l'autre.

C'est vraiment un état d'esprit. Est-ce que l'un est meilleur que l'autre? Cela dépend vraiment de qui vous êtes et de votre façon de penser. La plupart des gens avec qui je travaille ne toucheraient jamais un langage dynamique s'ils n'y étaient pas obligés, car ils estiment qu'il y a trop de place à l'erreur. Ont-ils tort de penser cela? Non, bien sûr que non, mais cela signifie qu'ils ont réalisé que leur approche de l'application de leur style de codage ne fonctionnera pas dans un environnement dynamique. Les autres personnes avec lesquelles je vais dans des groupes d'utilisateurs sont exactement le contraire. Ils trouvent le typage statique trop lourd, car cela limite leur approche pour résoudre certains types de problèmes.

Je peux honnêtement dire que je saute beaucoup entre JavaScript et C #. Maintenant, la connaissance et le travail dans les deux langues influencent l'autre dans une certaine mesure, mais en vérité, le code que j'écris dans chacun semble complètement différent de l'autre. Ils nécessitent une approche différente, car ils sont fondamentalement différents. Ce que j'ai trouvé, c'est que si vous vous trouvez en train de penser, "Mec c'est tellement plus difficile de faire ça en langage X", votre approche est probablement un peu décalée. Voici un exemple, les gens parlent de la façon "Pythonique" de faire les choses. Cela signifie qu'il existe un moyen pour que le langage Python fonctionne pour rendre un problème plus facile. Le faire d'une autre manière est généralement plus difficile et plus lourd. Vous devez surmonter la difficulté de savoir comment un langage fonctionne vraiment pour vous. C'est exactement la même chose avec les langages dynamiques vs statiques.

12
kemiller2002

Il y avait une question similaire qui vient d'être posée récemment: langues dynamiques vs langues typées statiquement pour les sites Web

Pour reformuler le cœur de ma réponse:

À mesure que les systèmes grossissent, les langages typés statiquement garantissent la robustesse au niveau des composants et donc la flexibilité au niveau du système.

Oui, Java est strictement typé et oui, Java suce (pas d'infraction. C'est horrible. Grande plate-forme et écosystème, mais l'une des pires langues jamais (en fait utilisé)).
Mais en déduisant que cette frappe stricte n'est qu'une erreur. C'est comme pointer vers PHP et inférer la frappe dynamique est nul (encore une fois, pas d'offense. Ça s'améliore lentement, je vous le donne)).

Personnellement, je fais l'essentiel de mon développement en haXe , qui a un système de type statique. Non seulement il est significativement plus expressif que celui de Java et nécessite-t-il beaucoup moins d'efforts en raison de l'inférence de type, mais il est également facultatif. Si jamais cela vous gênait, vous le contourniez simplement .

La sécurité de type est une fonctionnalité (c'est quelque chose que beaucoup de langues supposément de haut niveau ne réussissent pas) pour vous aider évitez de vous tirer une balle dans le pied .
Et à propos de n'importe quel langage réussi typé dynamiquement serait tout simplement mieux, si vous aviez la possibilité de faire vérifier votre type de code à volonté.
Par exemple, j'ai certainement aimé expérimenter Ruby, mais c'était principalement parce que Ruby est entièrement orienté objet, ce qui est entièrement orthogonal à la présence d'un système de type de temps de compilation.

Je pense que l'affirmation selon laquelle les systèmes de type statique sont gênants est simplement basée sur le manque de connaissance des bons systèmes de type statique. Il existe un certain nombre de langues qui le font correctement, haXe étant l'un d'entre eux, et sans doute même pas le meilleur à cet égard.

Exemple de code haXe:

class Car {
    public function new();
    public function wroom() trace('wroooooooom!')
}
class Duck {
    public function new();
    public function quack(at) trace('quackquack, ' + at + '!')
}

function letQuack(o) o.quack();
letQuack(new Car());
letQuack(new Duck());

Cela produira une erreur de temps de compilation:

Car should be { quack : Void -> Unknown<0> }
Car has no field quack
For function argument 'o'
Duck should be { quack : Void -> Unknown<0> }
Invalid type for field quack :
to : String -> Void should be Void -> Unknown<0>
For function argument 'o'

Vous ne pouvez pas vraiment prétendre que j'ai dû consacrer beaucoup d'efforts à la sécurité des caractères.

Dire que vous n'avez pas besoin de sécurité de type, parce que vous avez des tests, c'est encore plus idiot. La rédaction des tests est ennuyeuse et répétitive. Et je ne veux vraiment pas écrire un test, juste pour savoir, qu'une instance de Car ne charlatera pas et qu'un canard a besoin de quelqu'un pour charlatan.

À la fin de la journée, vous trouverez, quel que soit le coût de la sécurité de type frais généraux, il est finalement amorti (même en Java - mais peut-être pas si tôt).

7
back2dos

Ça dépend.

Les modes de défaillance humaine sont souvent statistiques. Une vérification de type stricte réduit la probabilité de certains types de défaillances humaines (provoquant un code bogué). Mais ce n'est pas parce que vous pouvez échouer que vous le ferez (Murphy ne résiste pas).

Que cette réduction des probabilités de défaillances en vaille la peine dépend du coût.

Si vous écrivez du code pour une centrale nucléaire ou un système ATC, toute réduction du mode de défaillance humaine peut être extrêmement importante. Si vous prototypez rapidement une idée de site Web sans spécification et avec des conséquences de défaillance presque nulles, la réduction des modes ou des probabilités de défaillance peut ou non vous acheter quoi que ce soit, mais peut vous coûter du temps de développement (plus de frappes, etc.), et dans les cellules cérébrales distraites en mémorisant le ou les types actuels requis.

5
hotpaw2

Pour une raison quelconque, je ne fais plus souvent d'erreurs liées au type d'objet. Dans des langages comme C #, je suis plus susceptible de faire des erreurs liées aux transformations d'exécution que je ne suis susceptible de faire une erreur de sécurité de type détectable par le compilateur, ce qui, je le concède, est généralement causé par le besoin occasionnel de contourner la statique d'un statique langue dactylographiée. Lorsque j'écris Ruby, le code a tendance à indiquer assez fortement le type d'un objet et la disponibilité d'un REPL signifie que j'ai déjà vérifié expérimentalement que la méthode/les attributs souhaités existent, ou J'aurai un test unitaire qui fait essentiellement la même chose, donc je rencontre aussi rarement des problèmes de sécurité de type dans Ruby.

Mais cela ne veut pas dire que les systèmes typés statiquement ne peuvent pas être meilleurs qu'ils ne le sont.

Dans les langages typés statiquement, le type système est également très important. Par exemple, avec quelque chose comme la monade Some dans les langages fonctionnels (type <Some>: = yes x | no), vous obtenez des vérifications au moment de la compilation qui empêchent essentiellement la redoutée NullReferenceException commune dans la plupart des systèmes de types; lorsque le code de correspondance de modèle s'exécute, vous obtenez des erreurs de temps de compilation vous indiquant que vous n'avez pas réussi à gérer la condition nulle (si vous utilisez ce mécanisme pour déclarer le type). Vous réduisez également les types d'erreurs similaires lorsque vous utilisez des éléments tels que l'opérateur de pipeline |> en F #.

Dans la tradition Hindley – Milner du typage statique, vous pouvez créer des choses qui vous donnent bien plus qu'une garantie qu'un type prétend prendre en charge l'interface X, et une fois que vous avez ces choses, je dirais que le système typé statiquement devient beaucoup plus précieux.

Lorsque ce n'est pas une option, les extensions Design By Contract à C # peuvent ajouter un autre ensemble de mécanismes qui augmentent la valeur du système de type statique, mais ils nécessitent toujours plus de discipline que certains de ces paradigmes fonctionnels.

5
JasonTrue

Les types sont des contraintes sur les interfaces, ils sont donc un sous-ensemble de ce que vous voudrez peut-être tester avec des tests unitaires, et donc de nombreux compromis sont similaires:

  • Les types statiques permettent de savoir plus tôt si le code répond ou non aux exigences qui peuvent être exprimées par le système de type, en échange de retarder le retour d'informations de la construction de quelque chose de peu fonctionnel (comme les commentaires des clients ou les tests de niveau supérieur).
  • Le fait de savoir que le code répond à certaines exigences peut faciliter la refactorisation et le débogage, mais il ajoute également des frais généraux aux interfaces changeantes et aux exigences changeantes.
  • En particulier, si un langage typé statistiquement manque de coercition, il offre une sécurité supplémentaire contre l'utilisation de code sur des données qui provoqueraient des bogues (réduisant le besoin de conditions et d'assertions), mais des contraintes trop restrictives obligent l'utilisateur à écrire plus de code pour masser ses données dans un forme acceptable (telle que la conversion de type explicite).
  • Les annotations de type explicites peuvent aider à la compréhension lors de la lecture du code, ou elles peuvent encombrer le code avec des informations redondantes ou inutiles.
  • Selon la mise en œuvre, cela peut nuire à la lourdeur. Cela dépend notamment de la nécessité ou de la déduction des annotations de types, de la capacité du système de types à exprimer les types/interfaces génériques, de la syntaxe et de la volonté de tester les contraintes pouvant être exprimées par le système de types (c.-à-d. le même test est probablement plus concis en tant que fonctionnalité de langue qu'en tant que test unitaire, mais vous n'avez peut-être pas eu l'intention de le tester).
  • De plus (mais sans rapport avec TDD), les types statiques peuvent aider à l'optimisation du temps de compilation, au détriment d'exiger que les types vérifient (et prennent le temps de les vérifier et d'effectuer les optimisations), et une meilleure optimisation peut être effectuée si les données sont limitées aux types qui correspondent bien au matériel. Cela facilite le développement sur le code avec des exigences de performances, mais peut causer des problèmes pour le code qui ne correspond pas bien à ces contraintes (conformément au point 3).

Pour résumer, je dirais que les langages dynamiques sont particulièrement utiles pour le prototypage, alors que si vous devez être sûr que votre code est correct, vous devriez privilégier un système de type fort.

4
T.R.

Oui définitivement. Une chose que vous constaterez en utilisant à la fois des langages fortement typés et Python (Python est fortement typé) est que la plupart du code bien écrit dans les langages dynamiques a tendance à suivre beaucoup des mêmes conventions que le code fortement typé de toute façon. La frappe dynamique est très utile pour la sérialisation et la désérialisation, mais pour la plupart des autres choses, elle ne contribue pas vraiment à un grand avantage. Et à moins que la majeure partie de votre code ne soit liée à la sérialisation, pourquoi supprimer la vérification gratuite des erreurs?

3
Mason Wheeler

Morgan, j'ai une idée intéressante à essayer: la frappe statique + dynamique. Vous avez mentionné Python, C # et Java. Saviez-vous qu'il existe de très bons ports de Python pour .NET et Java? Dans les deux cas, les ports vous permettent d'utiliser les bibliothèques de ces plates-formes et/ou d'interagir avec le code existant. Cela vous donne plusieurs possibilités:

  1. Conservez le code hérité dans un langage statique et rigide. Utilisez Python pour de nouvelles choses.
  2. Utilisez Python pour prototyper de nouvelles choses sur des plates-formes matures. Recodez les composants que vous souhaitez conserver dans le langage le plus mature.
  3. Utilisez le langage dynamique pour les portions que vous changez souvent.
  4. Utilisez éventuellement le langage dynamique pour jouer avec des idées comme la modification du code en cours d'exécution.
  5. Faites tout dans le langage dynamique, sauf pour les parties critiques où vous utilisez le langage fortement typé.

J'ai utilisé ces approches dès la fin des années 90 pour contourner la douleur du développement en C/C++. J'avais besoin des bibliothèques natives et parfois des performances. Pourtant, je voulais la meilleure syntaxe, flexibilité, sécurité, etc. Donc, l'astuce consistait à les combiner soigneusement pour obtenir les bons compromis. C'était souvent mieux dans la pratique que de jeter la langue entière et le code hérité vers une autre langue/plate-forme.

(Remarque: une réponse l'a déjà dit, mais je tiens également à souligner à nouveau que la frappe dynamique! = Pas de frappe/faible. De nombreux systèmes de type dynamique utilisent une frappe forte à l'intérieur. La façon dont je pense à ce qui fait la dynamique d'un type est que un type de variable est déterminé lors de l'exécution, n'a pas besoin d'annotation de type et/ou peut changer lors de l'exécution.

3
Nick P

Il y a eu beaucoup de systèmes très compliqués écrits en LISP, et je n'ai entendu aucun Lisper se plaindre qu'ils voulaient du typage statique. Lorsque j'ai travaillé avec, je ne me souviens d'aucun problème qui m'ait ralenti beaucoup qu'un système de type statique (et vous pouvez spécifier des types statiquement dans Common LISP) aurait intercepté.

De plus, les langages traditionnels typés statiquement ne semblent pas bien adaptés pour détecter les erreurs. Lors de la conception d'une mise en page, l'important est qu'un certain nombre soit une mesure verticale sur la page, et non qu'il s'agisse de int, unsigned, float ou double. Le compilateur, d'autre part, signalera souvent les conversions de type qu'il juge dangereuses, et me laissera volontiers ajouter une mesure verticale et le nombre de caractères dans une chaîne. Cette faiblesse du système de type statique était l'idée originale derrière la notation hongroise de Simonyi, avant qu'elle ne soit bâtie dans une laideur inutile.

3
David Thornley

Je vois cette question se poser beaucoup, et je pense que la qualité de votre logiciel (et le manque de bogues) a plus à voir avec votre processus de développement, la façon dont votre système est architecturé et l'engagement de vous et de vos pairs à la qualité du code.

Mon dernier emploi était principalement python développement. J'ai travaillé pour une grande société d'hébergement Web internationale et nous avions des équipes de développement aux États-Unis, au Canada et en Corée du Sud. Custom python framework web pour l'application cliente front end qui a permis aux utilisateurs de gérer leurs noms de domaine et comptes d'hébergement web. Backend: all python aussi. Python web service pour parler à des serveurs individuels pour faire des choses comme fournir un nouveau site d'hébergement Web, créer un nouveau blog, créer des entrées DNS dans notre système de service de noms; etc., etc. Dans mon travail actuel, les applications clientes sont toutes en Java; notre produit principal est un mélange de Java et flash. Custom Java framework web pour nos anciennes applications, guichet pour nos nouveaux outils internes).

Ayant travaillé dans les deux, je dois dire que cette question me dérange chaque fois que je la vois. Si vous utilisez un langage typé dynamiquement et testez réellement votre code, tout ira bien. Si le système est bien conçu et que vous respectez les normes, tout ira bien. Il n'y a jamais eu beaucoup de bogues qui sont survenus en raison du manque de compilateur vérifiant les types. La plupart des bogues étaient des erreurs logiques, tout comme mon travail Java aujourd'hui.

2
LGriffel

La sécurité des types vaut-elle le coup pour la vitesse de développement et la flexibilité? POURQUOI?

La frappe statique est un net augmentation de la vitesse et de la flexibilité du développement tout au long du cycle de vie du logiciel. Il réduit l'effort total et les inconvénients, mais déplace beaucoup d'efforts et d'inconvénients à l'avant, où il est plus visible. La barrière d'entrée pour avoir du code de travail est plus élevée, mais une fois que vous avez dépassé cette barrière (en satisfaisant le vérificateur de type), étendre et maintenir ce code prend beaucoup moins de travail.

Il y aura toujours des maux de tête dans le développement de logiciels en raison de:

  • La complexité inhérente à ce que vous essayez d'accomplir

  • La faillibilité inhérente aux humains, d'autant plus que nous faisons plus d'erreurs lorsque nous essayons de faire quelque chose de plus complexe

Tôt ou tard, vous devrez prendre un certain temps pour relever ces défis. Il n'y a pas moyen de contourner cela. La saisie statique résout simplement ces défis le plus tôt possible. Plus tôt vaut mieux que plus tard, car plus tard vous découvrirez une erreur (pas une question de si, mais quand), plus cela coûte de corriger cette erreur.

Corriger une erreur signalée par un vérificateur de type coûte beaucoup moins cher que de déboguer une exception liée au type déclenchée lors de l'exécution. Le report de la vérification de type à l'exécution ne fait que balayer le problème sous le tapis.

2
Jordan

Vous n'obtiendrez pas de réponse vraiment objective à cela, mais mon expérience est que la sécurité de type est inestimable jusqu'à vous maîtrisez TDD. Une fois que vous avez une large couverture de tests unitaires, où les tests ont été écrits avant le code, la vérification du compilateur devient pénible et commence réellement à vous gêner.

2
pdr

OUI.

J'ai travaillé dans les applications PHP, où les types ne sont pas aussi "forts" que dans Java ou C #. Habituellement, j'ai fini de "simuler les types", car, dans afin d'éviter les mauvaises conversions automatiques ou la validation des données.

Les langages de types dynamiques sont bons pour O.S. des scripts et des petites applications rapides. Pas des applications complexes.

Résumé: Si je dois choisir entre un langage de programmation "Type faible" ou "Type dynamique" ou un langage de programmation "Type fort" pour une application commerciale complexe, je choisis le Langage de programmation "Type fort".

0
umlcat

Je pense que cela vaut la peine de prendre du recul et de se demander quand le typage dynamique pose problème.

Un cas est celui où une branche de code n'est pas testée du tout, mais franchement, le code qui n'est jamais testé risque d'être bogué, que la frappe dynamique soit utilisée ou non.

Un autre problème plus subtil est cependant la substituabilité imparfaite.

Si un type est complètement faux, à moins qu'un chemin de code particulier ne soit jamais utilisé et susceptible d'être détecté rapidement.

D'un autre côté, si un type est un substitut imparfait, le code peut surtout fonctionner mais se casser de manière subtile qui ne sera détectée que beaucoup plus tard.

Les nombres et les chaînes sont deux des types de programmation les plus courants. Dans de nombreux langages dynamiques, ils se succèdent imparfaitement. Par exemple, javascript ou php si vous fournissez un nombre où une chaîne est attendue ou vice-versa, votre programme s'exécute sans générer d'erreur, mais peut se comporter de manière plutôt subtile.

Python a évité ce problème particulier, les nombres et les chaînes ne se substituent en aucun cas les uns aux autres et essayer d'en utiliser un là où l'autre est attendu entraînera normalement une défaillance rapide.

Cependant, cela n'a pas complètement évité le problème imparfait de susbstituibilité. Différents types de nombres peuvent être des substituts imparfaits les uns des autres, tout comme différents types de séquences.


Ce que je veux en venir, c'est que je ne pense pas qu'il soit possible de comparer les avantages et les coûts du typage statique et dynamique de manière générique, car je pense que les avantages et les coûts dépendent de la variation particulière du typage statique ou dynamique d'une langue les usages.

0
Peter Green

Ce n'est que ma propre opinion, mais non, je ne pense pas que la sécurité des types en vaille la peine. Pas même une seconde.

Je suis développeur depuis longtemps. Commençant par c ++, c #, puis déplacé vers javascript (frontend et backend via node.js). Depuis que je développe en javascript, ma productivité a explosé, au point que je m'aggrave en utilisant des langages basés sur les types. Je suis également contre la compilation, je veux que tout soit en exécution maintenant. Les langages interprétés sont vraiment où j'ai trouvé mon amour pour la programmation.

En ce qui concerne les types, je ne vois tout simplement aucun avantage. Je vois maintenant les types de la même manière que je vois la gestion de la mémoire. Complètement inutile. Les langages de demain devraient complètement empêcher le développeur de savoir quoi que ce soit sur les types. L'ordinateur doit comprendre les types et laisser le développeur en dehors.

Voici un exemple. J'utilisais juste Swift (la nouvelle langue d'Apple) en espérant qu'il serait à la hauteur de son nom il y a un jour et j'ai essayé de faire: var n = 1/2 ne fonctionnait pas. J'étais comme, ce qui se passe ici. et puis malheureusement réalisé que je devais faire var n: Float = 1/2. Cela m'a rappelé à quel point je déteste les systèmes de type et à quel point ils sont une aggravation inutile.

J'irais même plus loin pour dire que je ne veux même pas de types définis par l'utilisateur (tels que les classes). Je ne veux pas du tout de types. Tout ce que je veux, c'est var et des objets. Où n'importe quel objet peut être utilisé comme n'importe quel objet. Et les objets sont dynamiques et en constante évolution. Où cela devient un problème d'exécution quant à ce qui fonctionne et ce qui ne fonctionne pas.

Les développeurs adorent dire à quel point les langages mal typés ne sont pas bons pour les grands projets. Mais je dirais que c'est le contraire. Les langages fortement typés sont horribles pour les grands projets. Et si vous dites que javascript ne fonctionne pas pour les grands projets, demandez à Uber une entreprise de 40 milliards + + qui exécute tout son backend sur node.js/javascript, ou Facebook qui a commencé avec PHP.

En ce qui concerne les langues typées statiquement, ce n'est pas bon pour les itérations rapides d'aujourd'hui. voici un exemple simple, vous avez 10 développeurs travaillant sur un projet .net avec un serveur d'intégration continue, un développeur soumet une erreur et la construction entière est cassée, même si les 10 développeurs travaillent sur des choses différentes, ils sont maintenant tous arrêtés et attendent pour que le développeur incriminé corrige son erreur. Tu parles d'efficacité hein? Les langages système/statiques sont interdépendants de cette façon et rendent votre code interdépendant. Cependant, les fichiers de script ne sont jamais interdépendants. S'il y a un problème avec l'un des scripts, il n'arrête pas la production, tous les problèmes que vous voyez sont laissés à l'exécution. Et le runtime ne s'arrête jamais. Ça ne casse jamais. Cela peut produire une sortie erronée, mais il ne fait pas qu'arrêter tout le processus comme le font les systèmes de type.

0
user19718