Le typage fort

Par l'exemple du PHP

a marqué ce sujet comme résolu.

Bonsoir,

J’ai hésité à créer ce sujet dans « Développement Web », mais ce sujet est généraliste avec pour langage de support le PHP.

Je vois beaucoup de monde dire qu’un langage non fortement typé est mauvais. Je n’ai pas les connaissances pour savoir quels sont les pour et les contre. C’est pour cela que j’écris ce sujet ! En fait, depuis PHP 7, il est possible (et donc non obligatoire) de typer les fonctions et ses arguments. Il est possible de le rendre obligatoire avec cette ligne en début de script : declare(strict_types=1);. Quand cette ligne est ajoutée, une erreur est retournée.

Voici un exemple de typage en PHP 7 pour les curieux (exemple de Tutorials Point) :

<?php
declare(strict_types = 1);

function returnIntValue(int $value): int {
    return $value;
}
?>

Or, depuis la publication de PHP 7, je vois de plus en plus de personnes défendant le fait que le typage faible du PHP est une de ces forces. Voici un exemple parmi tant d’autres.

Je cherche à savoir si je devrais me lancer dans le typage en PHP. D’ailleurs, peut être que ce langage sera fortement typé dans le futur). Mais si j’ai créé ce sujet, c’est surtout pour avoir une plus grande connaissance sur ce sujet qu’est le typage dans un langage informatique.

EDIT : au vu de la qualité et du type des échanges, j’ai fait le choix de ne marquer aucun sujet comme « cette réponse m’a aidé ».

Le typage aide à maintenir du code qui marche sur le long terme; faire du refactoring dans un langage non typé est souvent une souffrance à cause du manque de retour du langage quand on fait une erreur.

C’est pour cela que tous les langages traditionnellement dynamiques (Python, PHP, Ruby, etc.) subissent une pression, quand ils deviennent utilisés pour de gros projects, pour ajouter une forme de typage statique au langage. Quand on a des centaines de milliers de ligne de code, des millions de lignes de code, on a envie de typage pour s’en sortir.

Mais alors il y a deux problèmes :

  • Souvent le langage s’est construit autour d’une communauté qui n’aime pas le typage, donc ça crée des tensions. On voit apparaître des argumentaires de bas étage, comme celui que tu cites dans ton message ("l’absence de typage est meilleure parce qu’elle force les gens à être soigneux et réfléchis avec leur code", ben voyons).

  • Il y a une symbiose entre un langage et son système de typage, qui rend difficile et coûteux de rajouter du typage après-coup. Un langage conçu pour être typé pourra avoir un système de typage simple, là ou un langage non prévu pour être typé utilisera des constructions difficiles à typer, et aura donc besoin de types nettement plus complexes pour un degré de sûreté équivalent. ML est plus facile à typer que Lisp, et peut faire plus avec des types plus simples car les constructions s’y prêtent. Python, Ruby, Javascript et PHP utilisent de façon centrale l’introspection, l’évaluation de code et autres fonctionnalités non-typables, donc on ne peut pas espérer avoir un système de typage raisonnable; soit on propose quelque chose de trop compliqué, soit on propose quelque chose d’inexact qui marche une partie du temps mais pas dans les cas avancés.

Il n’y a pas de solution miracle; quand on a un langage non typé au départ¹, il est beaucoup plus difficile de changer de direction après-coup. Facebook a investi des millions pour essayer de rendre PHP utilisable, et n’a pas réussi; ce qu’ils ont fini par faire c’est partir sur leur propre langage, Hack, et le faire diverger petit à petit de PHP, pour le rendre plus civilisé et plus facile à typer. Ça reste très cher, très difficile, et ça demande beaucoup d’outils avancés pour être mené à bien (transformation automatique de code, etc.). Le reste de la communauté PHP est destiné à continuer à souffrir — par choix.

¹: bien sûr, un langage peut aussi être non typé et bien conçu (ou fortement typé et mal conçu).

+12 -0

Salut !

Je risque d’être moins précis que mon vdd mais, personnellement, je dirais qu’il vaut mieux épouser la philosophie du langage et faire quelques exceptions seulement si tu es sûr de ce que tu fais.

Concrètement, PHP n’a pas été conçu dans l’optique de permettre à l’utilisateur final de gérer le typage des données alors autant éviter sauf si c’est peu coûteux et que ça ne te demandera pas plus de manipulations. A l’inverse, ne typer aucune de tes données en Java est totalement possible mais c’est du suicide (bon, l’exemple de Java est peut-être extrême, mais j’imagine que tu as compris où je voulais en venir).

Quoi qu’il en soit, amuse-toi bien !

La réponse de gasche est top. Je me permets juste d’ajouter quelques toutes petites notions autour du typage.

Déjà, il faut faire attention entre typage fort, et typage statique.

Un typage statique vs. un typage dynamique, c’est en gros si les types sont checkés à la compilation ou au runtime. Et c’est un peu ça que j’ai entendu parfois "non mais en Ruby du coup ça t’oblige à écrire des tests pour tout vérifier au runtime ! c’est bien que ça force à écrire des tests" 🤷🏻‍♂️

Un typage fort vs. un typage faible, c’est ce que tu décris (le fait que le type soit strict, et qu’on n’additionne pas des chaînes de caractères avec des nombres entiers).

Y’a quand même un truc que j’ajouterai là-dedans, c’est la puissance du système de types.

Si je prends par exemple Java, on pourrait se dire : c’est un typage statique et fort, parfait ! (bon, déjà fort c’est pas vraiment vrai hein y’a un fameux exemple avec String[] strs = {"aaa"};Object[] objs = strs; objs[0] = 3;, et les génériques et l’effacement de types sont pourris, mais passons). Pourtant, son système de types n’est pas puissant si on le compare à Haskell ou d’autres plus proches de lui comme Scala qui tourne sur la même plateforme. (composition de types, co/contra-variance, types de plus haut niveau, etc. y’a plein de comparaisons partout sur le net). Aussi, le fait que le système de type soit poussé / paranoïaque : évidemment fournir un type explicite pour la gestion des null, mais pas que, la possibilité d’encapsuler des effets (notamment les exceptions) facilement, pas forcément simple sans HKT/monades… Future[String] ça permet de raisonner sur le fait que la chaîne de caractère est là ou pas encore là, IO[String] ça permet de rendre explicite que y’a un effet derrière… Bref, écrire clairement "c’est pas vraiment une chaîne de caractère, c’est un truc avec lequel tu peux bosser, qui a plein de propriétés interessantes, mais pas celles d’une chaîne de caractère". Et au plus le système de types est puissant, au plus ces types IO, Future, Either, Maybe ont des propriétés intéressantes, au mieux on peut les "assembler" en quelques sortes.

Souvent, au plus le système de types est strict et statique, au plus il permet de faire des choses (parce qu’il est SÛR en fait) et s’il est statiquement typé, toutes ces choses seront faîtes à la compilation, c’est toujours ça de pris.

Un bon exemple que j’avais trouvé sur l’emploi concret d’un système de type avancé, c’est des gens qui avaient écrit (en Scala, il me semble) tout un système d’équation aux dimensions. En gros, le système de type se chargeait de vérifier qu’on pouvait ajouter une longueur avec une autre longueur (OK ça ça va), qu’en la divisant par une durée, on obtenait un truc homogène à un vitesse, elle-même divisible par du temps pour obtenir une accélération, elle même homogène à une force divisée par une masse, etc. etc. ici. On pourrait même faire encore beaucoup mieux, mais j’avais trouvé ça déjà assez convaincant.

+1 -0

Pour rebondir sur le downvote de @artragis (dont j’imagine la raison): je me suis peut-être mal exprimé, mais l’idée n’était pas de conseiller d’être dogmatique hein, mais juste de ne pas forcer sur certains concepts si le langage n’a pas été conçu pour ça dans un premier temps.

(et encore une fois, je n’ai pas dit que le typage en PHP était une mauvaise idée)

+0 -0

Le principal problème c’est que le typage en PHP n’est ni un typage fort ni un typage statique. La technologie que PHP a choisi est le "type hint". Seulement ils l’ont implémenté en plusieurs fois : au début les seults "types" qui existaient c’était array et le nom des classes et interface pour les arguments des fonctions.

Avec php 7.4 et plus tu as la possibilité de typehinter tous les types même les types "scalaire" (c’est à dire int, float, bool en PHP), dans les attributs de classes et le retour des fonctions.

En python ils ont aussi choisi le concept de type hinting mais ils l’ont fait d’une autre manière. Je sais qu’il se sont inspiré d’autres langages, mais je ne me souviens plus desquels. Du coup en python 3.5+ tu n’as des "astuces de typing" à base de Tuple[a,b], de Iterable[c] voire de IO. Ce sont les "comportements" qui sont type hintés, pas le type manipulé par l’engine lui-même.

Le typehint de php, au départ c’était simplement un raccourcis pour ne pas avoir à écrire if($a instanceof b) je ne sais pas si avec leur réécriture du moteur pour php 7.4 ils ont ajouté des optimisations pour l’interprétation mais on est loin d’un système de typage fort.

PHP reste un langage de typage dynamique ET faible, python de typage dynamique ET fort, Go de typage fort ET statique.

Quant à l’idée "ça a pas été conçu pour ça au départ alors fout pas faire ça avec" m’a toujours paru faible comme argument : les techno évoluent et les "fonctionnalités accidentelles" finissent par être là "by design" car on a suffisament travaillé le moteur de la techno pour qu’il ne ressemble plus du tout à ce qu’il était au départ. Je rappelle que le moteur de PHP est à sa 4ème version majeure (première version = PHP 1=>3, puis Zend Engine 1 pour la v4, puis Zend Engine2 pour v5 à 5.7 puis je sais plus le nom pour PHP 7.X+)

+1 -0

ça a pas été conçu pour ça au départ alors fout pas faire ça avec

Tu simplifies mon propos, je n’ai pas dit ça. D’autant plus que le typage PHP n’a rien d’accidentel donc je ne vois pas vraiment le rapport.

Du plus, je parlais dans un cas général et par particulièrement de PHP (qui ici ne me servait que d’exemple pour l’auteur).

C’est quand même consternant à quel point certains développeurs peuvent être gorgés d’affect lorsqu’il est question de leurs outils favoris.

M’enfin, bonne journée à tous.

C’est quand même consternant à quel point certains développeurs peuvent être gorgés d’affect lorsqu’il est question de leurs outils favoris.

il s’avère que je n’ai pas écrit une ligne de PHP depuis 4 ans, donc c’est pas mon outil favoris. Et pour info, si j’ai parlé de "technologie" c’est parce que j’étais aussi très général. En fait le plus bel exemple que j’ai en tête c’est elastic search qui depuis quelques versions a un module de plus en plus efficace de timeseries. Un jour on m’a dit "c’est pas fait pour au départ alors fais pas avec ça" mais à chaque nouvelle version les benchmark tendent à montrer que ça devient prévu pour, même si c’est pas vraiment la partie la plus scalable de elastic.

L’exemple de PHP est aussi un bon exemple, d’une "glue" entre C et HTML, c’est devenu un langage de prototypage avec la v4, puis un langage de script et de développement industriel avec la v5.3 et l’écosystème autour des PSR (composer, par exemple) et là ils ont mis PHP7 en mode "langage performant", le but étant de rattraper node. Le moteur de php a tellement changer que dire qu’il n’est pas "prévu pour le type hinting" est peut être un peu prématuré, non?

En soi je n’ai pas trop d’affect dans la situation, ceci dit ton message c’est :

mais juste de ne pas forcer sur certains concepts si le langage n’a pas été conçu pour ça dans un premier temps.

personnellement je l’ai compris comme "ça a pas été conçu pour ça au départ alors fout pas faire ça avec ou du moins faut éviter d’investir dans ça trop de temps". Peut être que je me trompe, tu peux expliciter du coup?

+0 -0

Je suis d’accord avec les propos de Gasche. En revanche, je trouve que ça ne suffit pas le typage fort … l’idéal c’est un linter !

Depuis que je code sur React, j’apprécie particulièrement le combo ESLint + Prettier. Plutôt que perdre des minutes à ré-indenter mon code (parfois des bouts récupérés ici et là), vérifier que toutes mes variables sont bien assignés et utilisés, oublié la fermeture d’une accolade etc ; c’est le duo parfait qui corrige derrière moi ou m’alerte. En un mot : GARDE-FOU.

Je pense que si le linter est efficace, automatique et bien intégré cette question sur le typage n’aurait même plus lieu d’être - on s’adapterait au fil des modifications au fonctionnement du linter. C’est en tout cas ce que je ressens après 2 ans d’expérience avec ESLint+Prettier. Qu’en pensez-vous ? Et utilisez-vous un linter PHP ?

+0 -0

Je lis à chaque fois chaque réponse et je trouve qu’il y a plein de choses intéressantes :) ! Je prépare une réponse prenant en compte chaque message. Je n’ai pas accès à un ordinateur pour l’instant donc niveau citation, c’est un peu la galère :-° !

Je me permets par contre de demander une chose : pourquoi personne n’a évoqué les avantages d’un langage faiblement typé ? S’il y en a, c’est pour une raison particulière, non ?

Je me permets par contre de demander une chose : pourquoi personne n’a évoqué les avantages d’un langage faiblement typé ? S’il y en a, c’est pour une raison particulière, non ?

Je crois que c’est avant tout une question de simplicité et de rapidité de mise en oeuvre. C’est aussi une question de savoir quels risques on est prêt à prendre à quel moment.

L’avantage du typage statique est qu’un maximum de choses sont vérifiées dès la compilation. Du coup tu as moins de risques d’avoir un crash au runtime. Une fois de plus le typage fort t’offre certaines garanties, celle de ne pas additionner par inadvertance des slips et des chaussettes si l’opération n’est pas rigoureusement prévue.

Ce genre de garanties est extrêmement intéressant et important pour du logiciel risqué, ou autrement dit où chaque erreur peut coûter très cher. Ainsi il ne viendrait probablement à personne l’idée d’utiliser un langage à typage dynamique pour faire de l’aérospatial, ou de la recherche scentifique du genre celles du CERN…

Pour les sites web et le e-commerce, je ne dis pas que le coût d’une erreur est nul, mais en tout cas beaucoup moins important (au pire ce n’est qu’un coût purement économique) L’intérêt du langage à typage dynamique dans ce contexte c’est qu’on développe beaucoup plus vite. C’est parfait pour du scripting, du prototypage rapide ou du développement à la chaîne.

Quand tu développes, tu n’as pas ou peu de questions à te poser sur le typage, du coup tu peux plus vite te concentrer sur les algorithmes, ou ce que ton programme doit faire et les résultats que tu veux obtenir. Tu arrives rapidement et pas trop difficilement à un truc qui marche à 90%.

En web le 90% du temps on fait toujours la même chose: gérer l’interface utilisateur, valider ses entrées, requêter une base de données pour mettre à jour les informations ou afficher des résultats…

LE typage statique et/ou fort arrivent quand on ne veut/peut plus se contenter de ces 90% qui marchent. Ainsi on franchit un seuil quand on passe de python, JS ou PHP à Java. ON en franchit un autre quand on part sur un langage fonctionnel strict genre haskell (tiens d’ailleurs, je n’ai aucune idée s’il existe des sites web qui fonctionnent avec un langage fonctionel)

A noter que de plus en plus, on mélange les deux: les opérations critiques sont développés avec un langage à typage statique, tandis que les opérations à plus haut niveau et la glue en langage à typage dynamique. Ainsi le site web peut être en python mais les algorithmes de machine learning derrière en C++. OU le moteur du jeu vidéo en C# mais le scripting du jeu en JavaScript.

+1 -0

Je me permets par contre de demander une chose : pourquoi personne n’a évoqué les avantages d’un langage faiblement typé ? S’il y en a, c’est pour une raison particulière, non ?

Helmasaur

Si on prend l’exemple des scripts shell, les valeurs n’ont pas besoin d’être typées car ce sont les opérateurs utilisés qui définissent le type de l’opération. Aussi, comme toutes les commandes renvoient du texte, ça évite des opérations de conversion dans tous les sens.

Ainsi il ne viendrait probablement à personne l’idée d’utiliser un langage à typage dynamique pour faire de l’aérospatial, ou de la recherche scentifique du genre celles du CERN…

QuentinC

Tu ne penses pas qu’il y a aussi des bouts de code en Python/numpy (qui ajoute plus de rigueur sur les types des collections de données mais qui reste du typage dynamique) ?

Ainsi on franchit un seuil quand on passe de python, JS ou PHP à Java.

QuentinC

Je ne suis pas sûr que Java soit utilisé dans le web pour son système de types.

tiens d’ailleurs, je n’ai aucune idée s’il existe des sites web qui fonctionnent avec un langage fonctionel

QuentinC

Oui, il y a pas exemple un framework Ocsigen pour OCaml.

Tu ne penses pas qu’il y a aussi des bouts de code en Python/numpy (qui ajoute plus de rigueur sur les types des collections de données mais qui reste du typage dynamique) ?

Si, très certainement. Mais pour moi ça rentre dans la case mix, à deux égards:

  1. L’algorithme à haut niveau peut être en python mais toutes les simulations et les calculs se basent quand même sur une bibliothèque C/C++, et à mon avis cette dernière est en C/C++ pas uniquement pour la rapidité d’exécution
  2. L’analyse de données est la partie la moins risquée du projet… si ça foire ou si tu n’es pas convaincu du résultat, tu recommences, c’est tout. Donc ça peut très bien être en python. C’est pas pareil que le pilotage d’une fusée, ou que la fiabilité des capteurs pendant l’expérience (compte tenu des moyens à mettre en oeuvre pour démarrer une expérience)

Je ne suis pas sûr que Java soit utilisé dans le web pour son système de types.

Oui et non. LE typage de Java apporte quand même de la sécurité. Il te permet quand même d’éviter une bonne partie des injections qui sont possibles en PHP ou JS parce que tu peux passer une String à la place d’un int, ou les bugs à la con genre 1+1=11….

Ce n’est pas pour rien qu’ils essayent d’ajouter des vérifications de type à PHP. Je ne le savais pas, je n’ai pratiquement plus fait de PHP depuis 3 ou 4 ans, et ça ne me surprend pas.

En même temps le typage de Java reste assez simple là où ça nous arrange. Ce bon compromis a probablement contribué à son succès.

Ce qu’on pourrait reprocher aux langages fonctionels, c’est qu’ils poussent leur truc trop loin. C’est assurément très intéressant du point de vue théorique. Mais en pratique la plupart du temps c’est overkill, on n’a pas besoin de ça.

Je carricature un peu, mais en fait, ça se résume à ça: est-ce qu’on veut rapidement un truc qui marche à 90%, ou bien on préfère prendre le temps pour faire un truc dont on est absolument sûr qu’il marchera du premier coup à 100% ? Là où il y a des vies ou du matériel rare en jeu, la question ne se pose même pas. Pour le reste, dans notre monde capitaliste, on préfèrera sûrement avoir rapidement les 90%, quitte à revenir sur les 10% plus tard… souvent jamais en fait, mais c’est un autre sujet.

+2 -0

Une bonne partie des faiblesses du typage de Java, en particulier de tout ce qui est generics, viennent d’un mélange entre le fait que lesdits generics sont une invention postérieure à la création du langage et de la Sainte Rétrocompatibilité de la JVM.

Du coup, si les compilateurs gèrent très bien les types génériques à la compilation (et de façon très poussée), ces informations supplémentaires sont supprimées dans la JVM pour permettre l’exécution de codes anciens… et comme la JVM doit rester rétro-compatible, on a ce problème de suppression qui persiste et qui impacte tous les langages à JVM (donc Scala et Kotlin pour les deux principaux). Et c’est un peu casse-pieds parce que ça empêche des constructions qui auraient été pratiques et en complexifie d’autres.

C’est orthogonal avec le concept de générique indéfini, qui permet de faire par exemple une List<*> dans laquelle tu peux mettre n’importe quel objet… ce qui est pratique 10 % du temps, et une gigantesque erreur les 90 % restants (et reprendre un code qui utilise ce genre d’astuce à mauvais escient est atroce).

Pour le reste, dans notre monde capitaliste, on préfèrera sûrement avoir rapidement les 90%, quitte à revenir sur les 10% plus tard… souvent jamais en fait

"Dans un monde capitaliste" : ça dépend combien coûte les 10% du coup ;)

je n’ai aucune idée s’il existe des sites web qui fonctionnent avec un langage fonctionel

Attention à fonctionnel / typage.

Y’a évidemment des exemples de langages qu’on pourrait qualifier de fonctionnels (dans le sens qui manipulent les fonctions "as first-class citizen", permettent de les composer, mettent en oeuvre la transparence référentielle, etc.) sans pour autant avoir un typage statique par exemple.

C’est souvent le cas, mais y’a des contre-exemples : https://en.wikipedia.org/wiki/Comparison_of_functional_programming_languages Clojure & Elixir par exemple. Du coup bah oui, y’a plein de sites web codés avec Elixir/Phoenix par exemple.

Haskell je sais pas trop, faudrait aller voir les pages de yesod ou happstack.

Mais rien que Scala si tu le considère comme fonctionnel et fortement typé, il suffit de regarder qui utilise akka-http (en Scala). Ou même plus simplement, Twitter a sorti Finagle un framework web basé sur netty en Scala (c’est pas franchement ce qu’il y a de plus "fonctionnel" dans Scala… m’enfin ça compte j’imagine).

+0 -0

"Dans un monde capitaliste" : ça dépend combien coûte les 10% du coup

JE partais implicitement du principe que les 10% restants sont exponentiellement plus chers. Genre si pour 90% ça coûte x, pour 99% ça coûte 10x, pour 99.9% c’est 100x, et pour 99.99% ça serait 1000x.

JE simplifie sans doute beaucoup (je ne suis pas économiste), mais il me semble que généralement en analyse de risque sur un projet ça doit vaguement être ça.

Mais rien que Scala si tu le considère comme fonctionnel

Quand j’ai posé cette question, je pensais plutôt à des langages fonctionels purs ou proches d’être purs genre Haskell ou Caml, pas à scala qui est multiparadygme. Sinon à ce moment-là on peut classer JS comme fonctionel aussi, ou même Java 8+.

+0 -0

En web le 90% du temps on fait toujours la même chose: gérer l’interface utilisateur, valider ses entrées, requêter une base de données pour mettre à jour les informations ou afficher des résultats…

Avec un langage typé statique qui supporte des types algébriques, on peut définir des types rendant les cas interdits non représentables. L’utilité est très concrète, notamment dans le 90% auquel tu fais référence. L’article suivant est je pense un des meilleurs exemples pour illustrer ça : https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/ (exemple en F#)

C’est sympa que les erreurs d’inattention (additionner des patates et des carottes) soient gérées avant l’exécution. Mais, si le langage offre un système de type assez bon pour encoder la complexité métier (OCaml, Haskell, F#, Rust, …) , on peut aller bien plus loin !

pas à scala qui est multiparadygme. Sinon à ce moment-là on peut classer JS comme fonctionel aussi, ou même Java 8+

Ouais alors y’a quand même une différence monumentale entre le système de type de Java 8 et celui de Scala. Oui il est multi-paradigme, mais on est en train de parler de types non ?

Je relève même pas l’allusion au JS, alors qu’on parle de typage ???

+0 -0

Avec un langage typé statique qui supporte des types algébriques, on peut définir des types rendant les cas interdits non représentables. L’utilité est très concrète, notamment dans le 90% auquel tu fais référence. L’article suivant est je pense un des meilleurs exemples pour illustrer ça : https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/ (exemple en F#)

Intéressant, l’aspect auto-documenté. Par contre la complexité du truc me fait peur. Je pense à l’explosion combinatoire de différents cas à gérer, si dans leur exemple on ajoute un numéro de téléphone, un e-mail de secours, une adresse postale secondaire…

L’avantage c’est que ça te force à penser à tous les cas et donc on élimine un maximum de surprises par la suite.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte