J'ai eu une brève conversation inhabituelle avec un architecte très senior sur les langages dynamiques et statiques. Il a déclaré que les données de l'entreprise montrent qu'il existe des preuves d'une productivité plus élevée lorsque des langages statiques sont utilisés. Notez que c'est une grande entreprise avec une longue histoire. À ma surprise (et à d'autres), la métrique qu'il a utilisée était des lignes de code ajoutées.
Il a rapidement rejeté les objections concernant la métrique, affirmant qu'au sein d'une même entreprise, avec une culture, un secteur d'activité et des données similaires, les différences (quant aux situations et capacités uniques des individus) se mélangent suffisamment pour que la métrique SLOC soit utile pour comparer la productivité des outils et langues.
Bien que je ne pense pas que cette affirmation soit étayée par une analyse statistique rigoureuse, y a-t-il des preuves dans l'industrie qui pourraient soutenir cette ligne de pensée?
L'argument de l'architecte senior pourrait signifier deux choses.
Cela peut signifier qu'un développeur moyen dans l'entreprise produit plus de lignes de code lors de l'utilisation de langages statiques que lors de l'utilisation de langages dynamiques. Par exemple, si quinze développeurs travaillent avec Java pendant six mois, ils écriront 100 KLOC, et si les mêmes quinze développeurs travaillent avec Python pendant six mois, ils n'écriront que 50 KLOC .
Il n'y a pas de corrélation entre LOC et productivité ici. Que faire s'il faut quatre fois plus de lignes de code dans Java pour produire la même fonctionnalité qu'en Python? Si cela est vrai, l'utilisation de Python entraînerait deux fois la productivité, sur la base des métriques KLOC ci-dessus.
Il peut également signifier qu'un développeur moyen dans l'entreprise produit moins de lignes de code lors de l'utilisation de langages statiques que lors de l'utilisation de langages dynamiques: quinze développeurs écriraient en six mois 100 KLOC en Java, ou 200 KLOC en Python .
Bien que moins de lignes de code soient généralement meilleures (moins de code à écrire, à lire et à entretenir), on ne sait toujours pas combien de fonctionnalités les développeurs Java ont produites par rapport à Python celles. Peut-être ont-ils écrit des demi-lignes de code par rapport aux développeurs de Python, mais ont également produit la moitié du nombre de fonctionnalités?
Dans les deux cas, LOC n'est pas une mesure valable, car la même fonctionnalité ne se traduirait pas dans la même quantité de lignes de code dans différentes langues . Certaines langues ont tendance à être plus verbeuses; d'autres — plus compact. Alors que dans certains cas, la compacité est précieuse, il n'y a pas de règle générale pour cela. Un exemple extrême serait le langage Brainfuck qui a une extrême compacité, mais qui n'est pas populaire pour sa lisibilité. Comparer des langages même similaires pourrait être délicat: par exemple, en ce qui concerne les accolades, Java suit le style K&R, tandis qu'en C #, l'accolade ouvrante est sur sa propre ligne dans la plupart des cas en suivant le style officiel , ce qui conduit à une augmentation artificielle des LOC pour C #. Et que se passe-t-il quand on compare un langage procédural avec un langage orienté objet, ou avec un langage fonctionnel?
Au lieu d'utiliser une métrique sujette aux erreurs, l'architecte senior pourrait s'appuyer sur un groupe de métriques qui mesurent la productivité lorsqu'elles sont utilisées ensemble: le nombre de fonctionnalités développées par mois, le nombre de bogues introduits dans la base de code et le temps passé à résoudre ces bugs, l'évolution de la dette technique, etc. Cette comparaison pourrait être délicate au début, car il faut tenir compte de la méconnaissance de l'équipe avec le nouveau langage. Une fois que l'équipe s'y est familiarisée, le choix doit être basé sur des paramètres stables, ainsi que sur la préférence des membres de l'équipe eux-mêmes.
LOC a une valeur dans certaines situations étroites. Par exemple, cela pourrait donner un indice sur la taille du projet et des parties du projet (et en moyenne est en corrélation avec les points de fonction, tout en étant souvent plus facile à mesurer), ou il pourrait indiquer les méthodes et les classes qui pourraient nécessiter une attention supplémentaire car de leur grande taille. Cependant, le LOC doit être utilisé avec précaution, car il est utilisé trop souvent par des personnes qui imaginent une certaine corrélation entre des choses indépendantes. Dans le passé, l'utilisation la plus désastreuse des LOC était la tentative de mesurer la productivité d'un développeur individuel sur la base des LOC écrites par mois.
Le problème avec la métrique SLOC est qu'elle mesure une approximation de la quantité de code écrit, sans prendre en compte:
Autrement dit, la production de code de spaghetti incontrôlable sujet aux erreurs avec beaucoup de pièces copiées-collées sera considérée comme plus productive que le code réutilisable soigneusement conçu.
Le SLOC n'est donc définitivement pas le meilleur moyen de mesurer la productivité.
La productivité est mesurée pour un processus. Le SLOC pourrait donc être un indicateur parfaitement valable pour le seul processus de codage.
Si, par exemple, vous comprenez mal les exigences, passez cinq mois à produire le logiciel, montrez-le à l'utilisateur, découvrez qu'il est tout simplement faux et passez encore 5 mois à le réécrire pour de bon, vous auriez la même productivité dans SLOC/mois, qu'une équipe écrive le code dès la première fois, par exemple parce qu'elle a utilisé un processus agile qui réduit les malentendus grâce à des retours fréquents. Cette productivité apparemment égale cache d'énormes problèmes.
Ainsi, la mesure de la productivité du développement logiciel doit prendre en compte l'ensemble du processus, y compris l'analyse des exigences, la conception des éléments à coder, le codage, les tests, le débogage et la vérification que les attentes des utilisateurs sont satisfaites. Comme toutes ces activités sont très différentes, le mieux est de mesurer la seule pensée qui compte: logiciel fonctionnel, c'est-à-dire ce que le logiciel produit signifie pour l'utilisateur .
Plusieurs approches existent:
Je dois avouer que je suis personnellement un fan des langages typés statiquement, car dans mon moi intérieur, je sais que c'est plus fiable (des années de codage me l'ont prouvé).
Donc, une chose que je prends pour sûr, c'est que le langage typé statiquement est capable d'empêcher beaucoup plus d'erreurs/bogues au moment de la compilation (par exemple, les fautes de frappe, la non-concordance dans les types attendus, etc.) que les langages non typés statiquement. Mais en toute objectivité, je n'oserais pas généraliser abusivement cela comme une productivité plus élevée.
Peut-être peut-être pas.
Mais ses arguments ne semblent pas valables: le gain de productivité d'un langage de type statique provient d'un nombre important d'erreurs qui sont détectées d'emblée par le compilateur.
Par conséquent, il n'est pas possible de découvrir ce gain de productivité "plus élevé" en examinant le SLOC seul sans examiner le remaniement requis pour les langages typés dynamiquement. Sa comparaison ne peut donc pas être juste.
L'argument de circonstances comparables ne tient pas non plus. Certains langages typés dynamiquement permettent des constructions de niveau supérieur qui nécessitent moins de code que de faire la même chose dans l'un des langages classiques typés statiquement. Vous pourriez donc avoir besoin de moins de temps, d'écrire moins de code, mais d'ajouter les mêmes frais généraux d'analyse, de test et de vérification. Ainsi, mesurer la productivité par le SLOC diluerait les gains de productivité potentiels, créant ainsi un biais contre le langage typé dynamiquement.
Plusieurs études universitaires récentes existent sur le sujet. Bien que certains d'entre eux voient un avantage du typage statique, il est en général limité à un usage spécifique (documentation, réutilisation de code ou API mal documenté, etc.). Une formulation prudente est également utilisée car les IDE modernes ont considérablement réduit les risques liés à la frappe dynamique:
Voici un contre-exemple pour votre architecte senior: Supposons que je veuille écrire une hiérarchie de trois classes, dont deux dérivent de la troisième, implémentant certaines fonctions virtuelles définies par la classe de base.
Si j'écris ces trois classes en C++, c'est assez simple. Je déclare les cours, j'utilise le virtuel aux bons endroits et j'ai terminé.
Si j'écris ces trois classes en C, je vais devoir ajouter pas mal de code: j'ai besoin de définir struct
s pour les v-tables, j'ai besoin d'ajouter un pointeur v-table à la classe de base , J'ai besoin d'ajouter du code aux constructeurs pour définir réellement les pointeurs v-table, j'ai besoin d'ajouter du code aux constructeurs pour appeler réellement le constructeur de la classe de base, j'ai besoin d'ajouter du code pour effectuer l'allocation de mémoire explicitement avant d'appeler un constructeur (qui C++ new
le fait en une seule étape), de même, j'ai besoin de séparer la destruction de l'appel free()
suivant, et ainsi de suite, etc.
Le fait est que toutes ces choses supplémentaires sont assez stupides. Je peux les faire très rapidement. Donc, je ne prendrai pas beaucoup plus de temps pour écrire la version C que ce dont j'ai besoin pour écrire la version C++. Néanmoins, j'ai produit beaucoup plus de lignes de code C que de code C++. Tant et si bien que je semble avoir été plus productif en C en termes de SLOC.
Toute langue qui nécessite une certaine quantité de code passe-partout apparaîtra plus productive en termes de SLOC qu'une langue qui ne nécessite pas la même quantité de code passe-partout.
Vous voyez, l'argument SLOC est si fondamentalement imparfait que je le verrais en fait dans l'autre sens: je prendrais la déclaration "les programmeurs ont tendance à produire plus de SLOC dans les langages statiques" pour signifier: "les langages statiques semblent exiger plus code passe-partout, et ainsi réduire la productivité ".
Je serai le contraire.
Nous suivons le SLoC dans notre travail (bien que nous ne l'utilisions pas directement dans les décisions de dotation), et j'ai eu des gens qui discutent de ce que la plupart des gens disent dans leurs réponses. En effet, "LoC n'a pas d'importance parce que la technologie X nous permet de faire plus avec moins de code" ou "De meilleurs développeurs écrivent un code meilleur et plus court, et donc ils n'écrivent pas plus que quiconque". D'après mon expérience (même si je n'ai pas de chiffres précis pour étayer ces choses), ces objections ne sont tout simplement pas correctes. Dans mon propre temps, j'ai vu une corrélation claire dans le taux et la qualité de la production de code pour nos développeurs, par rapport à toutes les autres mesures significatives de leur "compétence" globale en tant qu'ingénieur. Pour donner quelques contre-exemples aux types d'arguments présentés ci-dessus:
Cette dernière partie est mon résumé global, BTW. Ce que j'ai trouvé, c'est que, indépendamment de la pile technologique ou du type de projet, la plupart des développeurs ont leur propre rythme, qui est le rythme auquel ils opèrent. Si un langage a beaucoup de fonctionnalités qui rendent le code des développeurs plus efficace, alors c'est une grande aubaine pour l'entreprise, mais cela ne signifie pas qu'ils écriront moins de code en conséquence. Au lieu de cela, ils obtiennent des fonctionnalités plus rapidement et passent rapidement à un nouveau code. Encore une fois, le résultat final est que le taux auquel ils codent dépend principalement de leurs compétences et moins de leur pile technologique. En fait, à cause de cela, je m'attendrais généralement à ce que la pile technologique fasse plus de différence sur la vitesse à laquelle les tickets et les fonctionnalités sont développés que sur la vitesse à laquelle les gens codent. Je serais donc probablement inclus aux côtés de votre architecte principal plus que les autres réponses ici.
Cela étant dit, ni le taux d'écriture de code ni le taux de clôture des tickets ne sont une mesure parfaite de la productivité, c'est pourquoi nous ne prenons pas directement des décisions de dotation sur la base du SLoC. Au lieu de cela, cela fait partie du processus et les évaluations des employés sont effectuées en utilisant autant de points de données que possible. Je dirais cependant que votre architecte n'est certainement pas fou.
ne exception
La seule exception avec laquelle je suis d'accord est la possibilité d'un code de plaque de chaudière. S'il y a beaucoup de copier-coller d'une classe (ou autre) à une autre pour la mettre en place, cela va évidemment fausser les métriques. Cela est également vrai si vous disposez d'outils qui peuvent générer automatiquement de grandes quantités de code pour vous. Cependant, je pense que ce sera souvent l'exception plutôt que la règle. Si vos développeurs passent du temps à copier le code de la plaque chauffante pour commencer, vous utilisez le mauvais ensemble de technologies. S'ils sont en train d'écrire le code, même s'il est assez répétitif, je m'attends à ce que cela biaise les mesures seulement une petite quantité: lors de l'écriture du code, la plupart du temps nous sommes limités par la vitesse à laquelle nous pouvons réfléchir au problème plutôt que la vitesse à laquelle nous pouvons taper. Même lorsque vous écrivez du code relativement répétitif, votre cerveau est toujours engagé et réfléchissez au processus.
De toute évidence, tout ce qui précède est basé sur ma propre expérience personnelle. Votre kilométrage peut varier, et je suis évidemment en minorité. N'hésitez pas à être en désaccord. En résumé cependant:
Je trouve que le taux de codage dépend plus de la rapidité avec laquelle vous pouvez réfléchir à vos problèmes qu'autre chose. Par conséquent, j'ai trouvé que le taux de codage est une mesure décente de la productivité, même entre les ensembles technologiques, avec seulement un quelques exceptions possibles.
Bien que je saute dans le train en marche. Je pense que l'impact sur le comportement des programmeurs doit être souligné.
L'utilisation du SLOC comme mesure de la productivité a un effet toxique sur le moral du programmeur. Au moment où un ingénieur de votre équipe/entreprise se rend compte qu'il est mesuré sur le SLOC, plusieurs choses se produisent:
Je ne saurais trop insister sur la corrosivité du génie moral, car je l'ai vu se produire deux fois dans 2 entreprises différentes. Quels que soient les cas d'utilisation apparemment valides que vous en avez, je soutiens que cela ne vaudra probablement pas l'impact sur votre équipe/entreprise, même s'il n'y a qu'une faible chance que son utilisation soit découverte. Même s'il existe dans certains cas une corrélation entre le nombre de lignes écrites et la quantité de fonctionnalités utiles, cela encourage tous les mauvais comportements de vos programmeurs et envoie le message que la qualité n'est pas importante.
Il n'est généralement pas considéré comme un moyen valable de mesurer la productivité. Un code plus petit est généralement meilleur qu'un code plus gros, donc un développeur plus productif produit généralement moins de code. La productivité prend son plus grand coup dans le débogage; les développeurs efficaces passent peu de temps à déboguer.
Les langages typés statiquement sont plus productifs (si vous contrôlez toutes les autres différences entre les langues), car lorsqu'ils sont utilisés à bon escient, ils réduisent le temps de débogage, interceptant les erreurs dans la phase de compilation, où ils sont plus rapides à corriger.
La seule métrique que vous pouvez utiliser pour comparer la productivité des développeurs entre les langues est une métrique qui ne compare pas le code entre les langues. Certains langages sont notoirement verbeux (COBOL pour la victoire héritée), et d'autres nécessitent plusieurs étapes pour faire quelque chose que vous pouvez faire dans une seule ligne de code (Assembly vs à peu près tout le reste). Même si vous ne comparez que les lignes de code actives (c'est-à-dire ne comptez pas les déclarations et ne comptez que le code comportant une action), vous pouvez toujours biaiser vos résultats.
Vous pourriez être en mesure de faire valoir les taux de changement. C'est à dire. lignes de code ajoutées, comparant la pente de la productivité sur la même période. Cependant, cela ne tient pas compte des changements négatifs dans les lignes de code. Par exemple, vous héritez d'un projet contenant du code copier-coller partout. Vous effectuez des refactorisations rapides et faciles pour réduire le nombre de blocs de code répétés - par définition, vous avez une pente négative.
Sérieusement, comparer la productivité des équipes/langues n'a pas de sens car il y a tellement de facteurs supplémentaires qui affectent la productivité d'une équipe que vous ne pouvez pas en tirer de conclusions significatives.
J'ai travaillé sur un projet où l'infrastructure était très fragile et les outils dépassés. Le projet a été construit sur Java avec une application de page unique giflée dessus, mais hébergé dans un conteneur de portlet sans aucun avantage apparent. Le temps qu'il a fallu pour effectuer des modifications même simples était ridiculement long. Si vous deviez baser toutes vos conclusions sur ce projet particulier, vous pourriez conclure que Java était mauvais, ou les applications à page unique étaient mauvaises. Ni l'un ni l'autre ne sont vrais. Le système que le vilain projet était censé remplacer était construit sur C # et WebForms. Lorsque nous avons fait l'analyse de rentabilisation pour étendre l'application existante pour répondre aux besoins des clients, notre productivité a monté en flèche. Cela signifie-t-il qu'une application WebForms étroitement couplée est supérieure? Vous ne pouvez tirer cette conclusion que pour ce cas particulier et il ne s’étend pas au monde entier. Et cela seulement est logique car il y avait une application existante avec une maturité suffisante pour s’étendre.
Même la comparaison des taux de résolution des éléments dans le système de suivi des problèmes est erronée dans le sens où vous comparez les infrastructures de projet complètes les unes aux autres. Les bibliothèques et les frameworks utilisés peuvent accélérer ou ralentir la progression. Vous pourriez être dans la phase de démarrage avec très peu d'inertie à surmonter, où le projet que vous êtes "meilleur que" est dans une phase de maintenance où le nombre de nouveaux billets est relativement faible. Il ne s'agit jamais de comparer des choses semblables.