Les langages dynamiques comme Python, PHP, Ruby ou encore Javascript ont le
vent en poupe, car ils apportent un net gain en productivité
éphémère instantanée.
Lorsque l’on développe dans ces langages, on boucle sur des cycles :
coder puis regarder :
- on modifie le code source du programme, et,
- on va directement voir le résultat en exécutant l’application …
Dans le cas des langages à typage statique, nous sommes obligés de rajouter une étape intermédiaire : coder, compiler et éventuellement regarder :
- on commence toujours pas modifier notre code source, puis,
- nous sommes obligés de cliquer sur un bouton ou de lancer un make pour la compilation, et enfin,
- suivant le résultat de la compilation, soit on se lance dans un nouveau
cycle en cas d’erreur, ou alors, on exécute l’application pour valider des
besoins fonctionnels ou visuels.
Donc oui, un programme développé à l’aide d’un langage statique prendra plus
de temps car l’étape de compilation nous oblige à supprimer toute erreur de
typage, de syntaxe et souvent bon nombre d’erreurs d’inattention. De plus cette
étape de compilation ne supprime pas l’étape "lancer le programme", que nous
devons toujours effectuer afin de valider les specs fonctionnelles ou
graphiques.
Mais ce temps passé à faire valider notre code par le compilateur n’est pas
sans bénéfices, puisque notre programme sera plus fiable et n’émettra aucune
erreur purement informatique : typage, syntaxe, …
Ainsi, les erreurs sont présentées au développeur et en aucun cas à
l’utilisateur qui ne devrait en aucun cas avoir à gérer, ni
comprendre, ni même voir une telle erreur! [1]
Tests unitaires
Oui mais certains diront : on peut développer en mode Extreme
programming ou encore Programmation agile en agrémentant une
base de tests unitaires tout au long du développement. Cela se tient si l’on
fait des tests unitaires doublés de couverture de
code maintenue à 100% afin de s’assurer d’exécuter l’intégralité du code
source par les tests et ainsi éviter l’affichage de moultes erreurs aux yeux
ébahis de nos utilisateurs.
Mais cela engendre un volume de travail supplémentaire loin d’être négligeable!
On peut même se demander si les tests ne font pas que reproduire l’action d’un
compilateur analysant notre programme ?
Pour rester objectif, je dirais que de tels tests vont plus loin et permettent
par exemple de valider des specs fonctionelles et nous obtenons au final un
logiciel modulaire, spécifié et solide.[2]’
Mais je reste perplexe quand au temps de développement nécessaire si l’on
compare à n’importe quel langage statique agrémenté de quelques tests
unitaires/fonctionnels (naturellement plus succincts).
D’autre part, il ne faut pas oublier que la règle des 80/20
s’applique à tout, y compris à l’informatique et à notre sujet de
discussion : on peut souvent réaliser une application fonctionnelle à 80%
avec 20% du temps nécessaire pour faire l’application finale : fiable et
maintenable par d’autres développeurs.
Refactoring et évolution [3]
Enfin, je tiens à mettre en avant un problème sérieux lorsque l’on doit
faire évoluer une application écrite à l’aide d’un langage dynamique. En effet,
dans ce cas de figure, nous devons à coup sûr modifier des structures de
données : faire évoluer un attribut entier vers un objet plus complexe, ou
encore modifier le nom d’une fonction ou ses paramètres, ou pire encore :
changer le type de sortie d’une fonction! Et à moins d’utiliser des outils
avancés comme IntelliJ ou Eclipse, les étapes de refactoring(réécriture
de code) seront laborieuses, incomplètes et vont décupler le nombre d’erreur
signalées à l’exécution …
Enfin, il faut rester conscient que ces outils ne pourront jamais rejoindre le
niveau de vérification effectué par le compilateur d’un langage typé
statiquement, et ce, à cause de la nature dynamique du langage.
Notes
[1] Billet sur les erreurs à l’exécution
[2] les tests unitaires sont une bonne chose et je reviendrais la dessus