Existe-t-il une corrélation entre l'ampleur du projet et la rigueur de la langue?

72

En expliquant la différence entre la rigueur des langues et les paradigmes à un de mes collègues, j'ai fini par affirmer que:

  • Les langages tolérants, tels que les langages dynamiques et interprétés, sont mieux utilisés pour les prototypes et les petits projets ou les applications Web de taille moyenne. Lorsque vous choisissez des langages dynamiques élégants tels que Python ou JavaScript avec Node.js, les avantages sont les suivants:

    1. Développement rapide,

    2. Code passe-partout réduit,

    3. Capacité à attirer de jeunes programmeurs créatifs qui fuient des «langages d'entreprise»   comme Java.

  • Les langages statiquement typés / compilés conviennent mieux aux applications nécessitant une plus grande rigueur, telles que les applications stratégiques ou les applications professionnelles de taille moyenne à grande.

    1. Paradigmes et modèles bien connus développés depuis des décennies,

    2. Facilité de vérification statique,

    3. Capacité à trouver de nombreux développeurs professionnels avec des décennies d'expérience.

  • Des langages stricts tels que Haskell, Ada ou des techniques telles que les contrats Code en C # conviennent mieux aux systèmes qui privilégient la sécurité à la flexibilité (même si Haskell peut être extrêmement flexible), tels que les systèmes essentiels à la vie et ceux qui devraient être extrêmement stables. Les avantages sont:

    1. Capacité à attraper autant de bugs que possible au moment de la compilation,

    2. Facilité de vérification statique,

    3. Facilité des preuves formelles.

Cependant, en regardant les langages et les technologies utilisés pour les projets à grande échelle par les grandes entreprises, il semble que mon affirmation soit fausse . Par exemple, Python est utilisé avec succès pour des systèmes volumineux tels que YouTube ou d’autres applications Google qui exigent une grande rigueur.

Existe-t-il encore une corrélation entre l’ampleur du projet et la rigueur du langage / paradigme à utiliser?

Y a-t-il un troisième facteur que j'ai oublié de prendre en compte?

Où est-ce que je me trompe?

Arseni Mourzenko
la source
12
Vérification de type stricte et vérification de type statique ne sont pas la même chose. Python est typé de manière dynamique, mais il est plus strict que le C. L'avantage de la vérification de type statique n'est pas la rigueur, mais que les types sont vérifiés au moment de la construction, pas au moment de l'exécution. Au cours de ma carrière, je me suis occupé de nombreux problèmes liés au C / C ++ à cause du casting implicite.
Gort le robot
5
Il y a probablement quelque chose à dire sur le cycle de vie: les logiciels qui commencent dans votre première catégorie peuvent évoluer vers les autres, en "entraînant" la langue avec elle.
Mat
11
La seule chose élégante à propos de javascript, c'est qu'il fonctionne dans la plupart des navigateurs.
JeffO
1
@StevenBurnap: Je suis tout à fait d'accord sur la différence entre statique et strict. Java est un autre point du spectre, statique et trop strict. Les développeurs décrient souvent le typage statique en utilisant Java comme exemple, mais la plupart de ces critiques devraient en réalité viser le compilateur trop strict de Java , et non le typage statique en général. Il suffit de regarder Scala sur la même machine virtuelle Java, qui est typée statiquement, mais qui contient beaucoup moins de code commenté en raison des capacités de déduction de types du compilateur.
Cornel Masson
2
"Python est utilisé avec succès pour les grands systèmes" - quelle est la définition de "succès" ici? Qu'il tourne et produit un résultat? La quantité de tests et la main-d'œuvre requise sont-ils inclus? Qu'en est-il de la maintenabilité?
Den

Réponses:

39

Vous trouverez une étude de cas intéressante sur les projets de dimensionnement utilisant un langage interprété et dynamique dans Beginning Scala de David Pollak.

J'ai commencé à chercher un moyen d'exprimer le code dans mon cerveau d'une manière plus simple et plus directe. J'ai trouvé Ruby and Rails. Je me suis senti libéré. Ruby m'a permis d'exprimer des concepts dans beaucoup moins de lignes de code. Rails était tellement plus facile à utiliser que Spring MVC, Hibernate et les autres frameworks Web Java «rationalisés». Avec Ruby et Rails, j'ai pu exprimer beaucoup plus de ce que j'avais dans la tête en moins de temps. C'était semblable à la libération que j'ai ressentie lorsque je suis passée de C ++ à Java ...

Alors que mes projets Ruby and Rails s'étendaient au-delà de quelques milliers de lignes de code et que j'ajoutais des membres à mon équipe , les défis posés par les langages dynamiques devenaient évidents.

Nous passions plus de la moitié de notre temps à coder pour écrire des tests, et une grande partie des gains de productivité constatés ont été perdus lors de la rédaction de tests . La plupart des tests auraient été inutiles en Java car la plupart d'entre eux visaient à s'assurer que nous avions mis à jour les appelants lors de la refactorisation du code en modifiant les noms de méthodes ou le nombre de paramètres. De plus, j’ai trouvé que dans les équipes où il y avait une fusion mentale entre deux ou quatre membres de l’équipe, tout se passait bien pour Ruby, mais comme nous essayions d’intégrer de nouveaux membres à l’équipe, les liens mentaux étaient difficiles à transmettre aux nouveaux membres de l’équipe .

Je suis parti à la recherche d'un nouveau langage et d'un environnement de développement. Je recherchais un langage aussi expressif que Ruby mais aussi sûr et performant que Java ...

Comme vous pouvez le constater, la mise à l'échelle des projets pour l'auteur s'est révélée être un défi majeur en termes de développement de tests et de transfert de connaissances.

En particulier, l'auteur explique plus en détail les différences entre les langages typés de manière dynamique et statique dans la rédaction de tests au chapitre 7. Dans la section "Poignly Killing Bunnies: Dwemthy's Stairs", l'auteur traite du port Scala d'un exemple Ruby particulier:

Why the Lucky Stiff ... présente certains des concepts de métaprogrammation de Ruby dans Dwemthy Array, dans lesquels un lapin combat un éventail de créatures. N8han14 a mis à jour l' exemple pour qu'il fonctionne en Scala ...

Comparé au code Ruby, les éléments de bibliothèque du code Scala étaient plus complexes. Nous avons dû faire beaucoup de travail pour nous assurer que nos types étaient corrects. Nous avons dû réécrire manuellement les propriétés de Creature dans les classes DupMonster et CreatureCons. C'est plus de travail que method_missing. Nous avons également dû faire pas mal de travail pour soutenir l’immuabilité de nos Créatures et Armes.

Par contre, le résultat était beaucoup plus puissant que la version Ruby. Si nous devions écrire des tests pour notre code Ruby afin de vérifier ce que le compilateur Scala nous assure, nous aurions besoin de beaucoup plus de lignes de code. Par exemple, nous pouvons être sûrs que notre lapin ne pourrait pas manier une hache. Pour obtenir cette assurance dans Ruby, nous devons écrire un test qui vérifie que l’invocation |^sur un lapin échoue. Notre version Scala garantit que seules les armes définies pour une créature donnée peuvent être utilisées par cette créature, ce qui nécessiterait beaucoup de réflexion à l'exécution en Ruby ...


La lecture ci-dessus peut laisser penser que, à mesure que les projets prennent de l'ampleur, la rédaction de tests peut devenir extrêmement lourde. Ce raisonnement serait faux, comme en témoignent des exemples de très grands projets réussis mentionnés dans cette question ("Python est utilisé avec succès pour ... YouTube").

Le problème est que la mise à l'échelle des projets n'est pas vraiment simple. Les très grands projets à longue durée de vie peuvent «se permettre» différents processus de développement de tests, avec des suites de tests de qualité de production, des équipes de développement de tests professionnelles et d’autres types de produits lourds.

Les suites de tests Youtube ou le kit de compatibilité Java ont une vie différente de celle des tests dans un petit projet de tutoriel tel que Dwemthy's Array .

moucheron
la source
24

Votre affirmation n'est pas fausse. Vous avez juste besoin de creuser un peu plus profond.

En termes simples, les grands systèmes utilisent plusieurs langues, pas une seule. Certaines parties peuvent être construites à l'aide de langages "stricts", et d'autres peuvent être construites à l'aide de langages dynamiques.

En ce qui concerne votre exemple Google et YouTube, j'ai entendu dire qu'ils utilisaient Python principalement comme "colle" entre différents systèmes. Seul Google sait avec quoi ces systèmes sont construits, mais je parie que beaucoup de ses systèmes critiques sont construits avec des langages stricts et "d'entreprise" comme C ++ ou Java, ou peut-être quelque chose qu'ils ont eux-mêmes créé, comme Go.

Ce n'est pas que vous ne pouvez pas utiliser les langues tolérantes pour les systèmes à grande échelle. Beaucoup de gens disent que Facebook utilise PHP, mais ils oublient de mentionner que Facebook devait créer des directives de programmation extrêmement strictes pour pouvoir l'utiliser efficacement à cette échelle.

Alors oui, un certain niveau de rigueur est requis pour les projets de grande envergure. Cela peut venir soit de la rigueur du langage ou du framework, soit des instructions de programmation et des conventions de code. Vous ne pouvez pas vous contenter de quelques diplômés universitaires, leur donner Python / Ruby / JavaScript et vous attendre à ce qu’ils écrivent des logiciels pouvant être utilisés par des millions d’utilisateurs.

Euphorique
la source
"Vous ne pouvez pas attraper quelques diplômés" ... "et vous attendre à ce qu'ils écrivent des logiciels pouvant être utilisés par des millions d'utilisateurs." aurait probablement suffi.
Dyesdyes
Il convient de noter ici que, comme avec Google et Python, l'utilisation de PHP par Facebook est en grande partie liée ... Je crois comprendre que pour la plupart des fonctions, PHP n'est utilisé que comme un client relativement simple sur un système de serveur plus complexe généralement implémenté dans un langage "poids lourd" plus traditionnel, tel que Java, C ++, Haskell, OCaML, etc.
Jules
"Seul Google sait ce que ces systèmes sont construits avec" .. J'ai même des doutes à ce sujet :) D'après mon expérience, aucune entité (personne ou autre) ne peut répertorier toutes les parties d'un très grand système. Dans de nombreux cas, enfoui dans les cuvettes de certains serveurs est un morceau de script Perl, Fortran ou KSH oublié depuis longtemps qui exécute «Magic».
mattnz
3

Il existe deux types d'erreurs à vérifier: les erreurs de type (concaténer un entier + liste de flottants) et les erreurs de logique métier (virer de l'argent sur un compte bancaire, vérifier si le compte source a de l'argent).

La partie "dynamique" d'un langage de programmation dynamique est simplement l'endroit où la vérification de type a lieu. Dans un langage de programmation "typé dynamiquement", la vérification du type est effectuée lors de l'exécution de chaque instruction, tandis que dans un langage "langage typé de manière statique", la vérification du type est effectuée au moment de la compilation. Et vous pouvez écrire un interpréteur pour un langage de programmation statique (comme emscriptem ) et un compilateur statique pour un langage de programmation dynamique (comme gcc-python ou shed-skin ).

Dans un langage de programmation dynamique tel que Python et Javascript, vous devez écrire des tests unitaires non seulement pour la logique métier du programme, mais également pour vérifier si votre programme ne contient aucune erreur de syntaxe ou de type. Par exemple, si vous ajoutez "+" un entier à une liste de flottants (ce qui n'a pas de sens et émettra une erreur), dans un langage dynamique, l'erreur sera générée au moment de l'exécution lors de la tentative d'exécution de l'instruction. Dans un langage de programmation statique tel que C ++, Haskell et Java, ce type d'erreur de type sera intercepté par le compilateur.

Une petite base de code dans un langage de programmation vérifié de manière dynamique est plus facile à rechercher les erreurs de type car il est plus facile d'avoir une couverture à 100% du code source. Ça y est, vous exécutez le code à la main plusieurs fois avec des valeurs différentes et vous avez terminé. Avoir une couverture de 100% du code source vous donne une bonne idée que votre programme peut ne pas avoir d' erreur de type .

Avec une base de code volumineuse dans un langage de programmation vérifié de manière dynamique, il est plus difficile de tester chaque instruction avec toutes les combinaisons de types possibles, en particulier si vous êtes insouciant et écrivez une fonction pouvant renvoyer une chaîne, une liste ou un objet personnalisé en fonction de ses arguments.

Dans un langage de programmation vérifié statiquement, le compilateur détecte la plupart des erreurs de type lors de la compilation. Je dis le plus parce qu'une erreur de division par zéro ou une erreur de tableau hors limites sont aussi des erreurs de type.

Le plus souvent, la vraie discussion ne porte pas sur les langages de programmation, mais sur les personnes qui les utilisent. Et cela est vrai parce que, par exemple, le langage assembleur est aussi puissant que tout autre langage de programmation, et pourtant nous écrivons du code en JavaScript. Pourquoi? Parce que nous sommes des humains. Premièrement, nous commettons tous des erreurs et il est plus facile et moins enclin à utiliser un outil dédié spécialisé pour une tâche spécifique. Deuxièmement, il existe une contrainte de ressources. Notre temps est limité et la rédaction de pages Web sur l'assemblage prendrait un temps fou.

vz0
la source
3

Mon expérience avec les grands systèmes est qu'ils ne tiennent pas ou ne tombent pas par choix de langue, mais par des problèmes de conception / architecture ou de couverture de test . Je préfère avoir une équipe Python talentueuse sur mon projet de grande entreprise plutôt qu'une équipe médiocre en Java.

Cela dit, toute langue qui vous permet d'écrire beaucoup moins de code doit être regardée (par exemple, Python vs Java). Peut-être que l'avenir est dans des langages astucieux à typage statique avec une inférence de type avancée (par exemple dans le moule de Scala). Ou hybride, tel que C # tente avec son dynamicqualificatif ...?

Et n'oublions pas "l'autre" avantage du typage statique: l'achèvement de code IDE / intellisense approprié, qui, à mon avis, est une fonctionnalité essentielle et non une bonne chose à faire.

Cornel Masson
la source
1
"complétion de code / intellisense" - le refactoring automatisé est également très important.
Den
@ Den Absolutely. Se pourrait-il que les langages dynamiques vous aident à écrire très rapidement les versions initiales (plus facile, moins de code à écrire), mais s’enlisent plus tard, car il devient de plus en plus difficile d’évaluer l’impact du changement ou de refactoriser (sans outils de refactoring automatisés)?
Cornel Masson
0

Une autre considération est le qui derrière l’écriture d’applications à grande échelle. J'ai travaillé dans de nombreux endroits qui souhaitent utiliser Ruby ou Python sur des projets de grande taille, mais je suis systématiquement "abattu" par les responsables informatiques et les équipes de sécurité de l'entreprise, précisément à cause de la nature open source de leurs projets.

On m'a dit: "Nous ne pouvons pas utiliser Ruby on Rails car il s'agit d'une source ouverte et quelqu'un pourrait y installer des piratages qui volent des informations critiques ou protégées." Je suis désolé, mais une fois que quelqu'un a cette mentalité open source == diabolique, il est presque impossible de la changer. Cette ligne de pensée est une maladie d'entreprise.

C # et Java sont des langues de confiance avec des plates-formes de confiance . Ruby et Python ne sont pas des langues de confiance.

Jarrett Meyer
la source
2
Je ne suis pas d'accord avec la dernière ligne. Java est à l'un de ses points de confiance les plus bas jamais. C # est considéré avec méfiance par toute la communauté open source. Ruby est considéré comme solide mais lent (même s’il ne l’est pas plus longtemps) et Python est l’enfant glamour digne de confiance de toutes les industries (apprentissage automatique et informatique des données?).
CodeBeard
1
Les langages dynamiques sont mauvais pour la sécurité, mais "open source" n’est pas une bonne raison. Peut-être qu'ils voulaient dire "il est facile d'influencer une partie du code à partir d'une partie complètement différente du code". Voir programmers.stackexchange.com/questions/206558/…
Euphoric
1
Notons qu’en réalité, "l’approche ouverte" est l’un des aspects du choix d’une langue. C'est par exemple l' une des trois raisons données par Jeff Atwood pour expliquer pourquoi Discourse utilise Ruby.
Arseni Mourzenko
C # est maintenant complètement open-source, mais il est toujours organisé, planifié et développé par des développeurs professionnels, ce qui est bien, je suppose. Espérons que le type "Python 3 vs 2" ne se produira pas ici.
Den
Les bogues et les failles de sécurité sont introduits par les programmeurs et non par les langages. Pour mémoire, j'ai fourni un certain nombre de correctifs de sécurité pour des projets open source. Combien de projets fermés ai-je aidé ??? zéro!
Reactgular