Les conflits persistants entre le typage statique et le typage dynamique - TypeScript n'aidera pas



Quand mon ami et moi étions d'âge scolaire et aspirions à devenir développeurs de logiciels, nous rêvions de concevoir des trucs sympas ensemble - comme un jeu ou une application méga-utile.

J'ai choisi d'apprendre le C ++ et le C #, il a choisi JavaScript. Nous avons terminé nos études, diplômé de nos universités, servi dans l'armée et commencé nos emplois. Nous avons eu une période assez occupée dans le génie logiciel industriel, avec de nombreux emplois et postes différents, et après que tout a commencé à nous fatiguer, nous nous sommes rappelé où tout avait commencé.

Ayant enfin fait équipe en tant que développeurs matures, nous avons décidé de travailler sur notre propre projet - un jeu vidéo 2D. Étant donné que le domaine de mon ami était frontal et que j'étais un développeur à pile complète, notre choix immédiat de plate-forme de développement était un navigateur Internet. Comme je n'avais l'habitude de travailler avec TypeScript que lors de la conception du front-end, nous avons pensé, ok, pas de problème, après tout, TS n'est que du JavaScript à grande échelle. Utilisons-le et les choses se passeront bien. Si seulement je savais à quel point je me trompais! Lorsque nous avons commencé à discuter du projet, nous nous sommes heurtés à un vaste gouffre de malentendus entre nous.

Voici ma vision du jeu. J'étais comme, ok, nous avons des types tels que jeu, outil, élément, carte, emplacement. J'ai une compréhension de base de la façon dont ils fonctionnent ensemble, alors je les décris, compile le projet - et cela fonctionne. Après tout, le compilateur a vérifié mon code et je l'ai fait correctement. Ensuite, je commence à écrire du code qui utilise ces types. Ils me rendent la vie beaucoup plus facile. Mon IDE me donne des info-bulles et vérifie les erreurs. Si un projet peut être compilé, cela fonctionne probablement. J'ai consacré quelques efforts à la description du type et cela a donné des résultats. C'est mon approche en un mot.

Mon ami a eu l'idée opposée - passer immédiatement à l'écriture de code sans prendre le temps de décrire les types. Il n'était pas prêt à définir le problème comme une famille de types. Il ne souhaitait pas l'utiliser comme base, car il ne voyait pas le problème comme un ensemble de classes, de types, d'enregistrements de tout genre. Je pensais que c'était inconcevable. Nous avions tous deux un point, c'est juste que nos points étaient mutuellement exclusifs.

Sérieusement, nous parlions pendant des heures, mais chacun disait son propre truc, comme si nous parlions des langues différentes. Remarquez, je ne pourrais pas le blâmer sur le fait que nous soyons coincés dans nos anciennes habitudes. Il y a tout juste un an, j'ai migré sans douleur du monde de la programmation orientée objet vers le monde de la programmation fonctionnelle et inversement. De plus, j'ai passé pas mal de temps à apprendre JS, et lui - à apprendre un certain nombre de langues typées statiquement.

Cependant, pour tout développeur, la technologie qu'ils ont utilisée pour leur premier vrai travail les définit souvent dans la mesure où deux adultes expérimentés manquent simplement de patience pour s'écouter. Au cours de ces années d'ingénierie logicielle, nos visions ont été façonnées de différentes manières que nos approches de résolution de problèmes ne se sont pas bien adaptées.

Nous avons finalement abandonné l'idée de travailler en équipe. Votre première réponse pourrait être que le problème était dans nos personnalités. Vous avez peut-être raison, mais j'ai aussi vu cela se produire pour d'autres dans l'industrie.

La différence fondamentale et inconciliable entre le typage statique et le typage dynamique


Mon code fournit la solution au problème de la façon de travailler avec lui, tandis que le code des défenseurs de la frappe dynamique chevronné résout le problème de son fonctionnement. Les deux mentalités sont légitimes et prises en charge par les ensembles d'outils existants, mais un seul peut avoir la priorité la plus élevée à un moment donné.

Le typage statique est bon pour les projets à grande échelle impliquant des centaines de développeurs qui y travaillent pendant des années, tandis que le typage dynamique est bon pour les petites équipes et les projets qui nécessitent souvent du code en écriture seule. La frappe dynamique vous permet de gagner du temps et des efforts au début du développement, tandis que la frappe statique vous donne un coup de pouce à la fin.

L'idée de mettre les types en premier a sérieusement affecté ma réflexion en tant que développeur. Ayant choisi C # au début de ma carrière, j'ai une saisie statique codée en dur dans ma mentalité, et je paie le prix de cette inflexibilité maintenant. Une fois que je vois une tâche, j'essaie d'imaginer sa solution comme un ensemble de types et de règles de leur relation. Lorsque je développe un module, ma première étape consiste à définir les types qu'il exploite et utilise pour interagir avec son environnement. Je ne me souviens tout simplement pas comment j'avais l'habitude de résoudre des problèmes avant cela.

L'ensemble du processus d'apprentissage de la programmation en Java consiste à apprendre à concevoir et à utiliser des types. .NET CLR - le runtime C # - est construit sur des types et pour des types. Le typage statique est au cœur du paradigme de programmation orientée objet (bonjour, classes JS, j'ai décidé de vous donner une pause). Les implémentations canoniques de la plupart des modèles OOP sont saturées par le mot-clé Interface, ce qui n'a aucun sens dans un langage typé dynamiquement.

Les modèles de conception eux-mêmes sont des concepts multilingues, mais quelqu'un peut-il me dire pourquoi diable j'aurais besoin du modèle State dans un langage typé dynamiquement? Et Builder? Ces modèles n'ont rien à voir avec le développement, ils concernent principalement les types. Les types et la POO ont un lien étroit.

Vous ne pouvez pas construire votre logique métier sur des types et pourtant vous ne savez rien à leur sujet lorsque vous commencez à écrire du code. C'est pourquoi nous avons des développeurs frontaux qui arment leur code avec un nombre incroyable de tests unitaires qui vérifient spécifiquement la base de code pour toute erreur de type.
Nous savons tous que la protection basée sur la couverture du code est une illusion. Les tests sont écrits manuellement et sont par définition moins fiables que le système intégré de vérification de type disponible dans la langue.

Cela ne signifie pas que les langages typés dynamiquement n'ont pas de sens (bien que j'avoue que je ne pense pas). Cela signifie qu'en les utilisant, vous devez vous éloigner de la POO en tant que paradigme dominant. Toute cette unité de données et d'opérations pilotées par les données est destinée aux boursiers qui ont un typage statique.

Les développeurs que j'ai rencontrés ne pensent pas que le typage statique affecte la façon de coder dans une certaine mesure, ils écrivent simplement leur code comme s'ils utilisaient un langage dynamique, ils ajoutent seulement la vérification de type. Je pense que c'est intrinsèquement mauvais. Cela est particulièrement évident dans le cas d'un frontal moderne.
Je sais, je sais, il y a un tabou sur la critique des développeurs front-end. Mon ami et moi avons une fois monté un robot d'intelligence artificielle qui a trollé les utilisateurs de Twitter, et nous avons attrapé Brendan Eich. Sérieusement, le créateur de JavaScript a eu un va-et-vient avec notre réseau de neurones dans les commentaires.



Pour une raison quelconque, ces gars-là ne sont tout simplement pas prêts à vivre dans un monde où leur vision présente des lacunes tangibles. C'est pourquoi je ne critique que ceux d'entre eux qui complotent avec mon projet définitivement typé pour le retravailler à leur manière décontractée, "Any".

Nous resterions dans nos minuscules mondes, mais TypeScript nous a réunis


Prenez-moi par exemple: en raison des restrictions de type, mon code est impossible à utiliser de manière incorrecte. Lorsque je travaille sur un projet, je compte sur les autres pour utiliser également les types. Ensuite, mon code fonctionnera comme prévu. Donc, je ne couvre pas délibérément tous les cas dans lesquels ce code peut être utilisé de manière incorrecte (car la saisie le rend impossible). Mais ensuite, un développeur JS rejoint mon projet, prend mon type, l'enveloppe dans Any et commence à l'utiliser de manière incorrecte, ce qui entraîne des bogues difficiles à répliquer.

Les développeurs JavaScript sont convaincus que TypeScript est le même ancien JS, mais avec une option pour ajouter des vérifications de type statiques s'ils en ont besoin. C'est faux. TypeScript est cent fois plus puissant, mais ils ne s'intéressent qu'à une fraction de son potentiel.

Leur argument décisif est que TypeScript n'est qu'un sur-ensemble de JS. Dans la pratique, on ne peut ignorer le fait que TypeScript est un langage indépendant, même si l'on est un roi flippant du front-end. Parce que cela nécessite une approche différente - celle de la vérification statique et non dynamique.

Le principal avantage du typage statique est qu'il vous donne des garanties. Si vous l'utilisez dans un module et choisissez de ne pas l'utiliser dans un autre, vous perdez simplement votre temps et votre énergie à décrire et à concevoir ces types, sans aucune garantie.

Beaucoup pensent que TypeScript est un compromis des systèmes de types entre JS et Java. Eh bien, ce n'est pas un compromis d'aucune sorte, il a un système de type spécial qui lui est propre.

Pire encore, aujourd'hui, une position frontale sur deux nécessite une maîtrise de TypeScript. Cela incite les développeurs JS à jeter un coup d'œil sur les fonctionnalités de TypeScript et à passer immédiatement à l'écriture de code, générant une prolifération de pratiques nuisibles. Les situations se produisent quand ils n'ont pas vraiment besoin d'une vérification de type statique, mais cela leur a été imposé, alors ils ont foiré. Nous devons enfin reconnaître que les approches de programmation avec typage statique vs dynamique sont en conflit et ne peuvent pas être mélangées.

Je vois JavaScript comme un excellent outil pour écrire du code de piratage rapide qui fournit des solutions sans travailler sur des abstractions inutiles. L'exemple le plus scandaleux ici est le modèle Ice Factory. Vous pouvez lui fournir vos instances, et il les encapsulera dans l'immuabilité d'exécution. Si je traite mon objet via une telle usine, il retournera son équivalent, mais si j'essaie de changer l'une de ses propriétés, il lèvera une exception. WAT?!?

Le modèle a émergé parce que les développeurs frontaux ont entendu parler de l'immuabilité, ils ont donc décidé de faire glisser cette merde dans leur langage, qui en a besoin comme un trou dans la tête. Dans TypeScript, je peux concevoir une usine similaire, mais avec une restriction au moment de la compilation sur les mutations et sans aucune exception.

D'un autre côté, je n'en ai guère besoin car il y a la programmation fonctionnelle pure. Prenez F #, Haskell, OCaml, Clojure, ReasonML par exemple - ils ont une interdiction de mutabilité prête à l'emploi. Mais quelque chose me dit que si un développeur frontal met la main sur un langage fonctionnel, il sera prêt à le mettre à niveau pour rendre son comportement similaire à celui de JavaScript.

En effet, le choix de votre religion de frappe est un aller simple. Toutes les solutions intermédiaires n'offrent qu'une illusion de compromis. Soit vous vous fiez aux types, soit vous ne le faites pas. Je ne sais pas si ma vie serait différente si j'avais commencé à apprendre C # et JavaScript en parallèle. Aujourd'hui, je m'identifie si désespérément à mon état d'esprit que je ne vois tout simplement aucun avantage du typage dynamique (et je ne souhaite pas les voir). Ils existent, uniquement en dehors de ma portée de visibilité, donc tout ce que je peux faire, c'est fermer les yeux sur eux comme je le fais sur tous les phénomènes que je dois supporter dans ce monde. Je sais que je me trompe, mais je dois travailler ici et maintenant, et je n'ai pas le budget pour rester assis sur la clôture.

Je ne veux donc pas chercher de compromis, mais je vais le dire. Si vous ne faites que vos premiers pas dans le développement, commencez par la frappe statique!

Source: https://habr.com/ru/post/fr437844/


All Articles