Langage de programmation JavaScript : informations pour les débutants. Pourquoi utiliser des types statiques en JavaScript ? (Avantages et inconvénients)

Le langage PHP est utilisé très activement pour le développement d'applications Web, et aujourd'hui trois sites Web sur cinq fonctionnent dessus. Cependant, vous devez absolument prêter attention aux alternatives possibles. L'un d'eux est Node.js.

Avantages de Node.js

Le nombre de fans de cette plateforme logicielle augmente rapidement, car dans de nombreuses situations, elle présente des avantages indéniables par rapport à PHP. Javascript, utilisé pour écrire du code côté serveur sur Node.js, est un langage puissant et flexible. Il a ses propres bizarreries et même ses bizarreries, mais une fois que vous aurez compris le concept, travailler avec lui vous captivera certainement. Javascript permet une variété de styles de programmation et offre une grande flexibilité au développeur.

Node.js étend encore ses fonctionnalités. Si auparavant Javascript était utilisé exclusivement pour développer des applications de navigateur, il peut désormais également être utilisé pour écrire des applications mobiles et de bureau. PHP peut également être utilisé pour développer des applications de bureau et des utilitaires de console, mais cela se fait assez rarement.

Par défaut, Node.js est livré avec un gestionnaire de packages pratique et fonctionnel - npm. Il rend la gestion des modules et des dépendances simple et confortable. Et grâce aux bibliothèques intégrées pour traiter les demandes et les réponses avec Noda, vous ne dépendrez pas de serveurs tiers. Cette plateforme offre également de meilleures performances dans certaines situations.

Et enfin, Node.js bénéficie de nombreux retours positifs de la part des développeurs. Peu de gens qui écrivent du PHP sont passionnés par le langage, mais avec Javascript la situation est complètement différente.

Défauts

Cependant, il faut garder à l’esprit que Node n’est pas sans inconvénients :

  • il est plus difficile à apprendre, et commencer à travailler avec cette technologie ne sera pas si facile, surtout si vous débutez en programmation web, alors que créer un site web en PHP est beaucoup plus simple ;
  • La technologie des nœuds est relativement jeune, il y a donc beaucoup moins d'informations à ce sujet que sur PHP ;
  • N'importe quel hébergement fera l'affaire pour PHP, mais vous devrez rechercher une plateforme adaptée pour Node ;

Ainsi, il n'y a pas de réponse claire à la question de savoir lequel est le meilleur : PHP ou Node.js. Cependant, il faut garder à l’esprit que ce dernier gagne rapidement en popularité. Aujourd'hui, il est utilisé par Microsoft, PayPal, LinkedIn, Yahoo et de nombreuses autres grandes entreprises.

De nombreuses personnes sont habituées à utiliser PHP depuis les années 90 et ne sont pas pressées de le changer pour quoi que ce soit. Cependant, les progrès ne s'arrêtent pas et les technologies de développement Web se sont développées rapidement ces dernières années. Si vous ignorez les nouvelles tendances, vous remarquerez tôt ou tard que les produits que vous développez ne sont tout simplement pas suffisamment pertinents et demandés.

Maintenant que nous en avons terminé avec la syntaxe, passons enfin à la partie amusante : apprendre les avantages et les inconvénients de l'utilisation de types statiques.

Avantage n°1 : vous pouvez détecter les bugs et les erreurs plus tôt

La vérification de type statique nous permet de vérifier qu'un invariant que nous définissons est évalué comme vrai sans même exécuter le programme. Et s'il y a une violation de ces invariants, elle sera détectée avant le démarrage du programme, et non pendant son exécution.

Un exemple rapide : disons que nous avons une petite fonction qui prend le rayon et calcule l'aire :

Const calculateArea = (rayon) => 3,14 * rayon * rayon ; var zone = calculateArea(3); // 28.26
Maintenant si on veut passer un rayon à une fonction qui n'est pas un nombre (comme « intrus »)...

Var area = calculateArea("je suis méchant"); // NaN
Nous récupérerons NaN. Si certaines fonctionnalités sont basées sur le fait que la fonction calculateArea renvoie toujours un nombre, cela entraînera une vulnérabilité ou un crash. Pas très sympa, non ?

Si nous utilisions des types statiques, nous définirions un type spécifique de paramètres passés et renverrions des valeurs pour cette fonction :

Const calculateArea = (rayon : nombre) : nombre => 3,14 * rayon * rayon ;
Essayez maintenant de transmettre autre chose qu'un nombre à la fonction calculateArea - et Flow renverra un message pratique et agréable :

CalculateArea("Je suis méchant"); ^^^^^^^^^^^^^^^^^^^^^^^ appel de fonction calculateArea("Je suis méchant");
^^^^^^^^^ chaîne. Ce type est incompatible avec const calculateArea = (radius: number): number => 3.14 * radius * radius;

^^^^^^ numéro

Avantage n°2 : vous disposez d’une documentation vivante

Les types agissent comme une documentation vivante et respirante pour vous et pour les autres.

Pour comprendre comment, regardons une méthode que j'ai trouvée une fois dans une grande base de code avec laquelle je travaillais :

Fonction calculatePayoutDate(quote, montant, paymentMethod) ( let payoutDate; /* logique métier */ return payoutDate; )
À première vue (deuxième et troisième), on ne sait absolument pas comment utiliser cette fonction.

Le devis est-il un numéro ? Ou une valeur logique ? Le moyen de paiement est-il un objet ? Ou pourrait-il s’agir d’une chaîne qui représente le type de mode de paiement ? La fonction renvoie-t-elle la date sous forme de chaîne ? Ou est-ce un objet Date ?

Aucune idée.

À ce moment-là, j'ai décidé d'évaluer toute la logique métier et de saisir la base de code jusqu'à ce que je comprenne tout. Mais c'est trop de travail simplement pour comprendre comment fonctionne une fonction simple.

Par contre, si vous écrivez quelque chose comme ceci :

Fonction calculatePayoutDate(quote: boolean, montant: nombre, paymentMethod: string): Date ( let payoutDate; /* logique métier */ return payoutDate; )
il deviendrait immédiatement clair quel type de données la fonction accepte et quel type elle renvoie. Ceci est un exemple de la façon dont les types statiques peuvent être utilisés pour communiquer ce qu'est une fonction a l'intention faire. Nous pouvons dire aux autres développeurs ce que nous attendons d’eux, et nous pouvons voir ce qu’ils attendent de nous. La prochaine fois, si quelqu'un utilise cette fonction, il n'y aura pas de questions.

Vous pouvez parier que ce problème est résolu en ajoutant des commentaires au code ou à la documentation :

/* @function Détermine la date de paiement pour un achat @param (booléen) devis - S'agit-il d'un devis ?
@param (boolean) montant - Montant de l'achat @param (string) paymentMethod - Type de mode de paiement utilisé pour cet achat */ function calculatePayoutDate(quote, montant, paymentMethod) ( let payoutDate; /* .... Logique métier ... . */ return date de paiement ;

Ça marche. Mais il y a bien plus de mots ici. En plus d'être verbeux, ces commentaires dans le code sont difficiles à maintenir car ils sont fragiles et manquent de structure - certains développeurs écrivent de bons commentaires, tandis que d'autres peuvent écrire quelque chose de peu clair, et certains peuvent même oublier de laisser un commentaire.

Avantage n°3 : élimine la gestion confuse des erreurs

Les types aident à éliminer la gestion confuse des erreurs dans votre code. Revenons à notre fonction calculateArea et voyons comment cela se produit.

Cette fois, je vais lui passer un tableau de rayons pour calculer les aires de chaque rayon :

Const calculateAreas = (rayons) => ( var zones = ; pour (let i = 0; i< radii.length; i++) { areas[i] = PI * (radii[i] * radii[i]); } return areas; };
Cette fonction fonctionne, mais ne gère pas correctement les arguments d'entrée non valides. Si nous voulons nous assurer que la fonction gère correctement les situations où les arguments d'entrée ne sont pas des tableaux de nombres valides, nous obtiendrons une fonction ressemblant à ceci :

Const calculateAreas = (rayons) =>< radii.length; i++) { if (typeof radii[i] !== "number") { throw new Error("Array must contain valid numbers only"); } else { areas[i] = 3.14 * (radii[i] * radii[i]); } } return areas; };
Ouah. Il y a beaucoup de code pour une si petite fonctionnalité.

Et avec les types statiques, nous écrivons simplement :

): Tableau => < radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
Maintenant, la fonction ressemble réellement à ce qu'elle était avant d'ajouter tous les déchets visuels dus à la gestion des erreurs.

Il est facile de comprendre les avantages des types statiques, n'est-ce pas ?

Avantage n°4 : vous pouvez refactoriser avec plus de confiance

Laissez-moi vous expliquer cela avec une histoire de ma vie. Un jour, je travaillais avec une très grande base de code et j'avais besoin de mettre à jour une méthode définie dans la classe User. En particulier, modifiez l'un des paramètres de la fonction de string à object .

J'ai fait le changement, mais j'avais peur de m'engager - il y avait tellement d'appels à cette fonction dispersés dans le code que je n'étais pas sûr d'avoir mis à jour correctement toutes les instances. Et si un appel était laissé quelque part au fond d'un fichier auxiliaire non vérifié ?

La seule façon de tester est de soumettre le code et de prier pour qu'il n'explose pas avec un tas d'erreurs.

Lors de l'utilisation de types statiques, ce problème ne se posera pas. Là, j'aurai l'esprit tranquille : si je mets à jour une fonction et des définitions de type, le vérificateur de type sera là pour détecter toutes les erreurs que j'aurais pu manquer. Il ne reste plus qu'à parcourir ces erreurs de type et à les corriger.

Avantage n°5 : données et comportements séparés

Un avantage rarement mentionné des types statiques est qu’ils aident à séparer les données du comportement.

Regardons à nouveau notre fonction calculateArea avec des types statiques :

Const calculateAreas = (rayons : Tableau ): Tableau => ( var zones = ; pour (var i = 0; i< radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
Considérez comment nous aborderions la composition de cette fonction. Parce que nous spécifions les types de données, nous sommes obligés de réfléchir aux types de données que nous allons utiliser en premier, afin de pouvoir définir les types des paramètres transmis et renvoyer les valeurs en conséquence.

Ce n'est qu'après cela que nous implémentons la logique :

Être capable d'exprimer avec précision les données séparément du comportement nous permet de rendre nos hypothèses explicites et de transmettre l'intention avec plus de précision, ce qui soulage une partie de la charge mentale et donne au programmeur une certaine clarté mentale. Sinon, il vous suffit de tout garder à l’esprit d’une manière ou d’une autre.

Avantage n°6 : élimine toute une catégorie de bugs

Les erreurs de type d'exécution sont l'une des erreurs ou bogues les plus courants rencontrés par les développeurs JavaScript.

Par exemple, supposons que l'état initial de l'application soit défini sur :

Var appState = ( isFetching : false, messages : , );
Et disons que nous effectuons ensuite un appel API pour récupérer les messages et remplir notre appState . Ensuite, notre application dispose d'un composant de visualisation trop simplifié qui prend les messages (répertoriés dans l'état ci-dessus) et affiche le nombre de messages non lus et chaque message sous forme d'élément de liste :

Importer un message depuis "./Message" ; const MyComponent = (( messages )) => ( return (

( messages.map(message => )}
); };
Si l'appel d'API pour récupérer les messages échoue ou renvoie undefined , vous rencontrerez une erreur de type en production :

TypeError : Impossible de lire la propriété « longueur » non définie
...et votre programme plantera. Vous perdrez un client. Rideau.

Voyons comment les types statiques peuvent aider. Commençons par ajouter des types de flux à l'état de l'application. J'utilise un alias de type AppState pour définir l'état :

Tapez AppState = ( isFetching : booléen, messages : ?Array ); var appState : AppState = ( isFetching : false, messages : null, );
Puisqu'il est connu que les API de récupération de messages ne fonctionnent pas de manière fiable, nous spécifierons le type peut-être pour la valeur des messages pour un tableau de chaînes.

Tout comme la dernière fois, nous récupérons les messages via l'API peu fiable et les utilisons dans le composant view :

Importer un message depuis "./Message" ; const MyComponent = (( messages )) => ( return (

Vous avez ( messages.length ) des messages non lus

( messages.map(message => )}
); };
Mais à ce moment-là, Flow détectera une erreur et se plaindra :

^^^^^^ propriété `longueur`. La propriété n'est pas accessible sur une valeur éventuellement nulle

Vous avez (messages.length) messages non lus

^^^^^^^^ nul

Vous avez (messages.length) messages non lus

^^^^^^ propriété `longueur`. La propriété n'est pas accessible sur une valeur éventuellement indéfinie

Vous avez (messages.length) messages non lus

^^^^^^^^ non défini ( messages.map(message => )) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ de la méthode `map`. La méthode ne peut pas être appelée sur une valeur éventuellement nulle ( messages.map(message => )) ^^^^^^^^ null ( messages.map(message => )) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ de la méthode `map`. La méthode ne peut pas être appelée sur une valeur éventuellement non définie ( messages.map(message => )) ^^^^^^^^ non défini
Attends une minute, mon pote !

Puisque nous avons défini les messages comme étant de type peut-être, nous leur permettons d'être nuls ou indéfinis. Mais cela ne nous donne pas le droit d'effectuer des opérations dessus (comme .length ou .map) sans vérifier null, car si la valeur des messages est réellement nulle ou indéfinie, alors une erreur de type se produira lorsque nous essaierons d'opérer sur il.

Revenons donc en arrière et mettons à jour notre fonction d'affichage pour quelque chose comme ceci :

Const MyComponent = (( messages, isFetching ): AppState) => ( if (isFetching) ( return ) else if (messages === null || messages === non défini) ( return

Échec du chargement des messages. Essayer à nouveau.
) sinon (retour (

Vous avez ( messages.length ) des messages non lus

( messages.map(message => )}
); } };
Flow sait maintenant que nous avons pris en compte toutes les situations dans lesquelles messages est null ou undefined , donc la vérification du type de code échoue avec 0 erreur. Adieu les erreurs d'exécution !

Avantage n°7 : Réduisez le nombre de tests unitaires

Nous avons déjà vu comment les types statiques peuvent aider à éliminer les erreurs d'analyse confuses, car ils garantissent les types de paramètres transmis à une fonction et renvoient des valeurs. En conséquence, les types statiques réduisent également le nombre de tests unitaires.

Par exemple, revenons à notre fonction calculateAreas avec les types dynamiques et la gestion des erreurs.

Const calculateAreas = (radii) => ( // Gérer les entrées non définies ou nulles if (!radii) ( throw new Error("L'argument est manquant"); ) // Gérer les entrées non-tableaux if (!Array.isArray(radii) ) ( throw new Error("L'argument doit être un tableau"); ) var zones = ; for (var i = 0; i< radii.length; i++) { if (typeof radii[i] !== "number") { throw new Error("Array must contain valid numbers only"); } else { areas[i] = 3.14 * (radii[i] * radii[i]); } } return areas; };
Si nous étions des programmeurs assidus, nous pourrions envisager de tester les paramètres transmis non valides pour vérifier qu'ils sont correctement gérés par notre programme :

It("ne devrait pas fonctionner - cas 1", () => ( expect(() => calculateAreas()).to.throw(Error); )); it("ne devrait pas fonctionner - cas 2", () => ( expect(() => calculateAreas(undefined).to.throw(Error); )); it("ne devrait pas fonctionner - cas 2", () => ( expect(() => calculateAreas("hello")).to.throw(Error); ));
… et ainsi de suite. Mais il est très probable que nous oublierons de tester certains cas extrêmes - et ce sera notre client qui découvrira le problème. :(

Puisque les tests sont basés uniquement sur des situations que nous avons imaginées pour tester, ils sont existentiels et, en pratique, ils sont faciles à contourner.

En revanche, lorsque nous devons définir des types :

Const calculateAreas = (rayons : Tableau ): Tableau => ( var zones = ; pour (var i = 0; i< radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
... non seulement nous avons la garantie que notre objectif correspond à la réalité, mais ces tests sont tout simplement plus fiables. Contrairement aux tests empiriques, les types sont universels et plus difficiles à battre.

Si vous le regardez dans son ensemble, le tableau est le suivant : les tests sont bons pour vérifier la logique, et les types sont bons pour vérifier les types de données. Lorsqu’elles sont combinées, la somme des parties produit un effet encore plus grand.

Avantage n°8 : outil de modélisation de domaine

L'un de mes exemples préférés d'utilisation de types statiques est la modélisation de domaine. Dans ce cas, un modèle est créé qui inclut à la fois les données et le comportement du programme basé sur ces données. Dans ce cas, il est préférable de comprendre, à l'aide d'un exemple, comment utiliser les types.

Supposons que l'application propose à l'utilisateur un ou plusieurs modes de paiement pour effectuer des achats sur la plateforme. L'utilisateur a le choix entre trois modes de paiement (Paypal, carte bancaire, compte bancaire).

Nous allons donc d’abord appliquer des alias de type pour trois méthodes de paiement :

Tapez Paypal = ( id : numéro, tapez : "Paypal" ); tapez CreditCard = ( id : numéro, tapez : "CreditCard" ); tapez Bank = ( id : numéro, tapez : "Banque" );
Vous pouvez désormais définir le type PaymentMethod comme étant un ensemble disjoint avec trois cas :

Tapez Méthode de paiement = Paypal | Carte de crédit | Banque;
Créons maintenant un modèle d'état pour notre application. Pour faire simple, supposons que ces applications sont constituées uniquement de moyens de paiement mis à la disposition de l'utilisateur.

Type Modèle = ( méthodes de paiement : tableau };
Est-ce acceptable ? Eh bien, nous savons que pour obtenir les moyens de paiement de l'utilisateur, vous devez faire une demande à l'API et, en fonction du résultat et de l'étape du processus, l'application peut prendre différents états. En réalité, quatre états sont possibles :

1) Nous n'avons pas reçu de moyens de paiement.
2) Nous sommes en train d'obtenir des moyens de paiement.
3) Nous avons reçu avec succès les modes de paiement.
4) Nous avons essayé d'obtenir des modes de paiement, mais une erreur s'est produite.

Mais notre simple type de modèle avec paymentMethods ne couvre pas tous ces cas. Au lieu de cela, il suppose que paymentMethods existe toujours.

Hummm. Existe-t-il un moyen de construire un modèle pour que l'état de l'application prenne l'une de ces quatre valeurs, et seulement elles ? Voyons:

Tapez AppState = (tapez : "NotFetched" ) | ( tapez : "Récupération" ) | ( tapez : "Échec", erreur : E ) | ( tapez : "Succès", méthodes de paiement : Array };
Nous avons utilisé le type d'ensemble disjoint pour définir AppState sur l'un des quatre états décrits ci-dessus. Remarquez comment j'utilise la propriété type pour déterminer dans lequel des quatre états se trouve l'application. C'est cette propriété de type qui crée un ensemble disjoint. Grâce à lui, nous pouvons analyser et déterminer quand nous disposons de moyens de paiement et quand nous n’en avons pas.

Vous remarquerez également que je passe les types paramétrés E et D à l'état d'application. Le type D représentera le mode de paiement de l'utilisateur (PaymentMethod défini ci-dessus). Nous n'avons pas défini le type E comme type d'erreur, alors faisons-le maintenant :

Tapez HttpError = ( id : chaîne, message : chaîne );
Vous pouvez désormais modéliser le domaine d'application :

Type de modèle = AppState ;
En général, la signature pour l'état de l'application est désormais AppState où E est de la forme HttpError et D est PaymentMethod . Et AppState a quatre (et seulement ces quatre) états possibles : NotFetched, Fetching, Failure et Success.

Je trouve de tels modèles de domaine utiles pour réfléchir et concevoir des interfaces utilisateur selon certaines règles métier. Les règles métier nous indiquent qu'une application ne peut être que dans l'un de ces états, ce qui nous permet d'exposer explicitement un AppState et de garantir qu'elle ne sera que dans l'un de ces états prédéfinis. Et lorsque nous développons selon ce modèle (par exemple, en créant un composant de vue), il devient absolument évident que nous devons gérer les quatre états possibles.

De plus, le code se documente lui-même - il suffit de regarder les ensembles disjoints et il devient immédiatement clair comment AppState est structuré.

Inconvénients de l'utilisation de types statiques

Comme tout le reste dans la vie et la programmation, la vérification de type statique nécessite certains compromis.

Il est important de comprendre et de reconnaître ces lacunes afin que nous puissions prendre une décision éclairée lorsqu'il est judicieux d'utiliser des types statiques et lorsqu'ils n'en valent tout simplement pas la peine.

Voici quelques-unes de ces considérations :

Inconvénient n°1 : les types statiques nécessitent un apprentissage préalable

L'une des raisons pour lesquelles JavaScript est un langage si fantastique pour les débutants est que ceux-ci n'ont pas besoin d'apprendre le système de type complet avant de devenir productifs.

Lorsque j’ai appris Elm pour la première fois (un langage fonctionnel typé statiquement), les types me gênaient souvent. J'ai continué à rencontrer des erreurs de compilateur à cause de mes définitions de type.

Apprendre à utiliser efficacement les caractères représentait la moitié de la bataille dans l’apprentissage de la langue elle-même. En conséquence, la courbe d'apprentissage d'Elm est plus abrupte que celle de JavaScript en raison de ses types statiques.

Ceci est particulièrement important pour les débutants, qui ont la charge cognitive la plus élevée liée à l’apprentissage de la syntaxe. Ajouter de la syntaxe à ce mélange peut être écrasant pour un débutant.

Inconvénient n°2 : peut s'enliser dans la verbosité

Les types statiques donnent souvent l’impression que les programmes sont plus verbeux et encombrés.

Par exemple, à la place :

Fonction asynchrone montantExceedsPurchaseLimit(montant, getPurchaseLimit)( var limit = wait getPurchaseLimit(); return limit > montant; )
Il faut écrire :

Fonction asynchrone montantExceedsPurchaseLimit(montant : nombre, getPurchaseLimit : () => Promesse ): Promesse ( var limit = wait getPurchaseLimit(); return limit > montant; )
Et à la place :

Var user = ( identifiant : 123456, nom : "Preethi", ville : "San Francisco", );
Il faut écrire ceci :

Tapez User = ( id : numéro, nom : chaîne, ville : chaîne, ); var user : User = ( identifiant : 123456, nom : "Preethi", ville : "San Francisco", );
Évidemment, des lignes de code supplémentaires sont ajoutées. Mais il existe quelques arguments contre le fait de considérer cela comme un inconvénient.

Premièrement, comme nous l’avons mentionné précédemment, les types statiques tuent toute une catégorie de tests. Certains développeurs peuvent considérer cela comme un compromis tout à fait raisonnable.

Deuxièmement, comme nous l’avons vu précédemment, les types statiques peuvent parfois éliminer le besoin d’une gestion complexe des erreurs, ce qui réduit considérablement l’encombrement du code.

Il est difficile de dire si la verbosité est un véritable argument contre les types, mais cela vaut la peine de le garder à l'esprit.

Inconvénient n°3 : il faut du temps pour maîtriser l'utilisation des types.

Il faut beaucoup de temps et de pratique pour apprendre à sélectionner au mieux les types dans un programme. De plus, développer une bonne idée de ce qui mérite d’être suivi de manière statique et de ce qu’il est préférable de laisser dynamique nécessite également une approche prudente, de la pratique et de l’expérience.

Par exemple, une approche consiste à coder la logique métier critique avec des types statiques, mais à laisser dynamiques les éléments logiques de courte durée ou sans importance pour éviter une complexité inutile.

Connaître la différence peut être difficile, surtout si un développeur moins expérimenté doit prendre des décisions à la volée.

Inconvénient n°4 : les types statiques peuvent retarder un développement rapide

Comme je l'ai mentionné plus tôt, j'ai trébuché un peu avec les types en apprenant Elm - en particulier lorsque j'ajoutais du code ou y apportais des modifications. Être constamment distrait par les erreurs du compilateur rend difficile l'exécution du travail et la sensation de progrès.

L'argument ici est que la vérification de type statique peut amener un programmeur à perdre trop souvent sa concentration - et vous savez, la concentration est la clé pour écrire un bon programme.

Ce n'est pas seulement ça. Les contrôleurs de type statique ne sont pas non plus toujours idéaux. Parfois, une situation survient lorsque vous savez quoi faire, mais la vérification du type vous gêne et vous gêne.

Je suis sûr que j'ai manqué d'autres défauts, mais ceux-ci sont les plus importants pour moi.

Dois-je utiliser des types statiques en JavaScript ou non ?


Les premiers langages de programmation que j'ai appris ont été JavaScript et Python, tous deux langages typés dynamiquement.

Mais la maîtrise des types statiques a ajouté une nouvelle dimension à ma façon de concevoir la programmation. Par exemple, même si j'ai trouvé les messages d'erreur constants du compilateur d'Elm écrasants au début, déterminer les types et plaire au compilateur est devenu une seconde nature et a réellement amélioré mes compétences en programmation. De plus, il n’y a rien de plus libérateur qu’un robot intelligent qui me dit ce que je fais de mal et comment y remédier.

Oui, il existe des compromis inévitables avec les types statiques, comme être trop verbeux et devoir passer du temps à les apprendre. Mais les types ajoutent de la sécurité et de l'exactitude aux programmes, ce qui élimine pour moi personnellement l'importance de ces « inconvénients ».

Les types dynamiques semblent plus rapides et plus simples, mais ils peuvent échouer lorsque vous mettez réellement le programme en action. Dans le même temps, vous pouvez parler à n'importe quel développeur Java qui s'occupe de types paramétrés plus complexes et il vous dira à quel point il les déteste.

En fin de compte, il n’existe pas de solution universelle. Personnellement, je préfère utiliser des types statiques dans les conditions suivantes :

  1. Le programme est essentiel pour votre entreprise.
  2. Le programme sera probablement remanié pour répondre aux nouveaux besoins.
  3. Le programme est complexe et comporte de nombreuses pièces mobiles.
  4. Le programme est pris en charge par une grande équipe de développeurs qui doivent comprendre le code rapidement et avec précision.
En revanche, je refuserais les types statiques dans les conditions suivantes :
  1. Le code est de courte durée et n’est pas essentiel à la mission.
  2. Vous réalisez un prototype et essayez d’avancer le plus rapidement possible.
  3. Le programme est petit et/ou simple.
  4. Vous êtes le seul développeur.
La beauté du développement JavaScript de nos jours est que, grâce à des outils comme Flow et TypeScript, nous avons enfin le choix d'utiliser des types statiques ou le bon vieux JavaScript.

Conclusion

J'espère que ces articles vous ont aidé à comprendre l'importance des types, comment les utiliser et surtout... *Quand* utilisez-les.

La possibilité de basculer entre les types dynamiques et statiques est un outil puissant pour la communauté JavaScript et passionnant :)

Javascript est un langage très puissant et possède beaucoup de potentiel. Avec la croissance rapide des technologies Web, il peut devenir l'un des leaders parmi les langages de programmation. L'environnement d'exécution du code javascript est présent sur n'importe quel ordinateur, dans la plupart des téléphones, et les logiciels serveur peuvent être développés dans ce merveilleux langage.

Mais le langage n’est pas sans défauts. Les plus significatifs d'entre eux :

  1. Le langage est compilé au moment de l'exécution du code. Chaque fois que vous ouvrez le site, le code javascript commence à se compiler. Au minimum, le temps d'exécution du programme augmente.
  2. Il n'y a pas de saisie de données. Le problème avec tous les langages de script. Jusqu'à ce que l'exécution du code atteigne la ligne souhaitée, vous ne saurez pas si cela fonctionne. Mais le compilateur pourrait assumer une part importante de la recherche des erreurs s’il connaissait les types de données avec lesquels il travaille. Et en termes de vitesse d’exécution, le code tapé est plus rapide.
  3. Un modèle objet peu familier à de nombreux programmeurs. Les classes et l'héritage de classes sont présents, mais ils sont très différents des implémentations familières dans les langages de programmation C++/C#/Java.

Plus le logiciel devient volumineux et important, plus les problèmes de débogage du code et de ses performances se feront sentir.

Quelles sont les solutions ? Arrêter d'utiliser Javascript ? Google, par exemple, a déjà proposé un remplaçant : le langage Google Dart. Mais qu’en est-il du code déjà écrit ? Des années de travail utile de la part de nos merveilleux programmeurs ?

Tout n'est pas si triste.

  1. Le problème de saisie peut être résolu par un logiciel étonnant de Google - le compilateur de fermeture. Il est nécessaire d'ajouter des commentaires spécialement conçus dans le code à côté des variables, des fonctions et des paramètres de fonction - des annotations dans lesquelles les types de données sont indiqués. Et le logiciel intelligent de Google vous indiquera où vous avez commis une erreur.
  2. Le code ne peut pas être compilé pour le moment. Mais vous pouvez réduire la quantité de code en le compressant à la fois logiquement (renommer les variables, supprimer les espaces supplémentaires, transformer le code, etc.) et en utilisant des algorithmes de compression (par exemple, gzip). Il y a également de la place pour les navigateurs. Les navigateurs peuvent compiler du code uniquement la première fois qu'il est téléchargé à partir d'un site et mémoriser le code déjà compilé. Et la prochaine fois que vous démarrerez, utilisez le code déjà compilé. Les performances matérielles suivent également le rythme, désormais même un téléphone peut être aussi puissant qu’un simple ordinateur de bureau.
  3. Le langage javascript lui-même permet de s'affranchir du modèle objet « maladroit ». Il existe d’excellents outils disponibles :

    La description des classes se rapproche extérieurement de la description des classes dans le langage C++/C#/Java. C'est vraiment pratique pour comprendre et maintenir le code. Le deuxième outil introduit des méthodes publiques, protégées et privées à part entière, et ajoute des propriétés de classe à part entière. Tout est simple et élégant.

Tous les défauts du langage javascript peuvent être éliminés. Il peut être utilisé en toute sécurité dans des projets à grande échelle. Il n’est pas encore nécessaire de recourir à une langue de remplacement.

Mots-clés : javascript, framework javascript

24/11/14 15,6K

La programmation n'est pas seulement un moyen de gagner beaucoup d'argent et n'est même pas entièrement un travail mental. C'est l'occasion de comprendre en quoi consiste le monde qui nous entoure, de le décomposer en petites particules, puis de le réassembler, guidé par notre propre logique et nos connaissances.

Les langages de programmation ne sont qu'un outil avec lequel une personne construit des règles dans les systèmes créés.

Internet présente une multitude d’opportunités que les esprits brillants et entreprenants saisissent. Bien entendu, le développement Web dispose également de ses propres outils pour donner vie aux idées. L'un d'eux est le langage de programmation JavaScript, qui sera abordé dans cet article :

informations générales

De nombreuses personnes, même celles qui n'ont rien à voir avec le domaine informatique, ont entendu le mot Java. Un langage révolutionnaire indépendant de la plate-forme dans lequel les applications pour systèmes mobiles sont activement écrites. Il a été développé par la prometteuse société Sun, qui passait alors sous l'aile d'Oracle. Mais aucune des deux sociétés n’a rien à voir avec JavaScript :

Tout ce qui était demandé à Sun était l'autorisation d'utiliser une partie du nom. Étonnamment, JavaScript n’appartient à aucune entreprise.

Lors de l'écriture d'applications Web, la programmation JavaScript est le plus souvent utilisée. Si nous énumérons brièvement les principales caractéristiques de ce langage, nous devons souligner les suivantes :

  • Orientation de l'objet. L'exécution du programme représente l'interaction des objets ;
  • La conversion du type de données est effectuée automatiquement ;
  • Les fonctions sont des objets de la classe de base. Cette fonctionnalité rend JavaScript similaire à de nombreux langages de programmation fonctionnels tels que Lisp et Haskell ;
  • Effacement automatique de la mémoire. Ce que l'on appelle le garbage collection rend JavaScript similaire à C# ou Java.

Si nous parlons de l'essence de l'utilisation de JavaScript, alors ce langage vous permet de « faire revivre » des pages de sites Web immobiles à l'aide de code qui peut être exécuté ( soi-disant scripts). Autrement dit, nous pouvons faire une analogie avec les dessins animés, où HTML et CSS sont les caractères dessinés, et JavaScript est ce qui les fait bouger.

Si nous parlons de syntaxe JavaScript, elle présente les caractéristiques suivantes :

  • L'inscription est importante. Les fonctions appelées func() et Func() sont complètement différentes ;
  • Les opérateurs doivent être suivis d'un point-virgule ;
  • Objets et opérations intégrés ;
  • Les espaces ne sont pas comptés. Vous pouvez utiliser autant d'indentations que vous le souhaitez, ainsi que des sauts de ligne, pour formater votre code.

Le code JavaScript le plus simple ressemble à ceci :

Champ d'application

Afin de comprendre pourquoi JavaScript est nécessaire et combien il est nécessaire de l’apprendre, nous devons souligner certains domaines dans lesquels ce langage de programmation est utilisé.

  • Développement d'applications Web. Vous souhaitez installer un simple compteur, organiser le transfert de données entre formulaires ou placer un jeu sur votre site Internet ? Alors JavaScript sera un fidèle assistant en la matière ;
  • "Participation active" à AJAX. Cette technologie a permis d'accélérer considérablement le fonctionnement des applications en échangeant des données avec le serveur en mode « background » :

  • Systèmes d'exploitation. Certaines personnes ne le savaient peut-être pas, mais Windows, Linux et Mac ont leurs propres navigateurs concurrents, dont la part du lion est écrite en JavaScript ;
  • Applications mobiles ;
  • Domaine d'études. Toute spécialité en programmation dans une université inclut l'étude de JavaScript dans une mesure ou une autre. Cela est dû au fait que le langage a été développé à l'origine pour des programmeurs peu forts. Les leçons JavaScript sont logiquement intégrées au cours HTML de base, l'apprentissage est donc assez simple.

Avantages et inconvénients

Ne pensez pas que JavaScript est une sorte de panacée à tous les problèmes, et chaque programmeur utilise ce langage avec le sourire aux lèvres. Tout dans le monde a ses côtés positifs et négatifs. Notons d’abord les lacunes.

  • La nécessité d’assurer une compatibilité entre navigateurs. Étant donné que JavaScript agit comme une technologie Internet, vous devez vous conformer aux règles établies par le World Wide Web. Le code doit fonctionner correctement dans tous les navigateurs, ou du moins dans les navigateurs les plus populaires ;
  • Le système d’héritage d’une langue rend difficile la compréhension de ce qui se passe. JavaScript implémente l'héritage basé sur un prototype. Les personnes qui ont étudié d'autres langages de programmation orientés objet sont habituées au familier " la classe enfant hérite de la classe parent" Mais en JavaScript, de telles choses sont directement gérées par les objets, et cela dépasse votre compréhension ;
  • Il n'existe pas de bibliothèque standard. JavaScript ne fournit aucune fonctionnalité permettant de travailler avec des fichiers, des flux d'E/S ou d'autres éléments utiles ;
  • La syntaxe en général rend la compréhension difficile. La beauté du code n’est clairement pas le point fort de JavaScript, mais la règle principale des programmeurs est respectée : « Travaux? Ne touchez pas !».

Il convient maintenant de noter quelques avantages

  • JavaScript offre un grand nombre de fonctionnalités permettant de résoudre une grande variété de problèmes. La flexibilité du langage permet l'utilisation de nombreux modèles de programmation en fonction de conditions spécifiques. L'esprit inventif aura un réel plaisir ;
  • La popularité de JavaScript ouvre au programmeur un nombre considérable de bibliothèques prêtes à l'emploi, qui peuvent considérablement simplifier l'écriture de code et niveler les imperfections de syntaxe ;
  • Application dans de nombreux domaines. Les larges capacités de JavaScript donnent aux programmeurs la possibilité de s'essayer en tant que développeur d'une grande variété d'applications, ce qui, bien sûr, suscite l'intérêt pour les activités professionnelles.

Ne faites pas attention au fait qu'il y avait plus d'inconvénients que d'avantages. JavaScript est fermement ancré dans son créneau, et aucune critique ne le fera sortir de là pour le moment.

Pour ceux qui veulent étudier

Un chemin difficile et long attend ceux qui décident d'étudier en profondeur JavaScript. Pour les débutants, il existe des recommandations de base, à la suite desquelles vous pouvez simplifier considérablement votre apprentissage.

  • Tout d'abord, HTML. Vous ne pouvez pas commencer à faire quoi que ce soit pour Internet sans les bases. Les feuilles de style en cascade (CSS) seront également très utiles ;
  • Utilisez de la nouvelle littérature. La programmation n’est pas de la physique, dont les lois sont inviolables, et les nouveaux manuels sont des anciens dépouillés. Les technologies informatiques évoluent constamment et les mises à jour utiles ne doivent pas être négligées ;
  • Essayez d'écrire vous-même toutes les sections du programme. Si quelque chose ne fonctionne pas du tout, vous pouvez emprunter le code de quelqu'un d'autre, mais seulement après avoir d'abord compris chaque ligne par vous-même ;
  • Le débogage est votre meilleur ami. Trouver rapidement les erreurs est l’un des aspects les plus importants de la programmation ;
  • N'ignorez pas les règles de formatage. Bien sûr, le code ne deviendra ni meilleur ni pire en raison du nombre différent d'indentations et d'espaces, mais la facilité de lecture et de compréhension par le programmeur est également un point important. Le code ci-dessous ? très difficile à percevoir, surtout si vous n'êtes pas lui

  • Les noms de variables doivent avoir une signification lexicale. Dans le processus d'écriture de programmes simples, cela ne semble pas du tout important, mais lorsque le nombre de lignes de code dépasse le millier, tous les diables se cassent les jambes ;


Des questions ?

Signaler une faute de frappe

Texte qui sera envoyé à nos rédacteurs :