Comparaison entre les applications du Windows Store en JavaScript et les applications Web classiques

Cette rubrique décrit les différences entre les styles de codage utilisés dans les applications Web écrites pour JavaScript et ceux utilisés dans les applications du Windows Store en JavaScript. Les informations qu’elle contient permettront aux développeurs Web de comprendre facilement les liens existant entre le code optimisé pour Windows et les applications devant être migrées entre les plateformes. Cet article suppose que le lecteur est familiarisé avec la programmation JavaScript et les normes W3C (World Wide Web Consortium).

Introduction

Windows 8 fournit une plateforme pour la génération de nouvelles applications du Windows Store pour Windows. Les applications du Windows Store peuvent être écrites dans différents langages de programmation, notamment en JavaScript compatible avec l’édition ECMAScript 5.

Grâce à Windows Runtime, les applications bénéficient de la puissance et des nombreuses fonctionnalités de Windows combinées à la force, l’omniprésence et la simplicité des technologies Web normalisées.

En effet, lorsqu’ils créent une application en JavaScript, les développeurs ont la possibilité d’utiliser des normes Web existantes, ce qui a pour avantage d’optimiser l’interopérabilité avec d’autres plateformes normalisées. Windows Runtime leur permet aussi de générer des applications du Windows Store utilisant JavaScript qui sont optimisées pour la plateforme Windows.

La meilleure approche pour architecturer les applications diffère selon les objectifs visés. Le choix sera plus simple si vous tenez compte des recommandations indiquées dans cet article.

Modèles de conception JavaScript Windows Runtime

Windows Runtime offre un environnement de développement qui permet aux programmeurs de tirer parti de leur expérience en matière de développement Web. Pour l’essentiel, les API Windows Runtime ressemblent à ce que les développeurs Web expérimentés connaissent déjà. Ces API représentent une extension soignée des API de développement Web normalisées et elles sont disponibles en fonction des besoins, sans que les développeurs soient obligés d’importer des constructions étrangères pour exploiter leur code. Les API Windows Runtime permettent néanmoins au développeur d’exercer un contrôle plus précis sur certains aspects de la plateforme (par exemple, l’interfaçage avec les périphériques d’E/S).

Par ailleurs, Windows Runtime introduit certains modèles de codage dans la plateforme Windows qui peuvent être nouveaux pour les développeurs Web habitués à utiliser les modèles définis dans certaines spécifications W3C, ainsi que certaines des infrastructures connues bâties par-dessus.

Les sections suivantes aborderont ces modèles et en expliqueront brièvement la logique.

Programmation asynchrone sur le Web

Par nature, les applications Web connaissent des délais plus longs entre les demandes et les réponses que ceux des applications devant accéder uniquement aux ressources locales. Les appels synchrones à un serveur distant bloqueraient l’interface utilisateur d’une application Web, avec des conséquences inacceptables pour l’utilisateur. Le multithreading pourrait être utilisé pour contourner le problème mais au prix d’une augmentation considérable de la complexité architecturale. C’est pour cette raison que les API JavaScript implémentent généralement des constructions de programmation asynchrones et que la plupart des API standard les exploitent de façon étendue.

Windows Runtime adopte la programmation asynchrone sur l’ensemble de la plateforme, en apportant une richesse de fonctions d’E/S aux développeurs et en appliquant ce concept aux nouveaux types d’interactions de disque, de réseau et de périphérique. Pour ce faire, Windows Runtime utilise des paradigmes éprouvés déjà utilisés dans plusieurs langages de programmation, ainsi que dans certaines infrastructures JavaScript populaires.

Les développeurs peuvent créer des applications en tirant parti de composants aussi variés que FileReader, Web Sockets, Geolocation ou IndexedDB, en utilisant toujours le même modèle de base. Il en découle un code lisible facile à administrer, notamment lorsque plusieurs opérations asynchrones dépendent les unes des autres. Grâce à Windows Runtime, le flux des rappels en cascade dans le code, qui s’avère être généralement un exercice délicat même pour un développeur expérimenté, devient plus facile et plus intuitif.

Promesses

Dans Windows 8, la programmation asynchrone en JavaScript est gérée par le modèle Promises, que l’on trouve également dans les autres boîtes à outils JavaScript connues. Promises fournit une méthode uniforme de programmation sur les résultats asynchrones, la possibilité de composer des opérations asynchrones ainsi qu’un modèle de traitement des erreurs asynchrones unifié.

Qu’est-ce qu’une promesse ?

Une promesse est un objet contournable représentant une valeur qui n’a pas encore été calculée, une erreur qui n’a pas encore été trouvée ou une tâche qui n’a pas encore été effectuée.

  • C’est un mécanisme qui simplifie le modèle de programmation pour consommer les composants asynchrones.
  • Une promesse est un moyen de créer un wrapper composable sur vos opérations asynchrones.

Comment dois-je faire pour utiliser des promesses ?

L’API permettant de consommer des promesses est simple. En fait, elle se limite à deux méthodes d’instance :



.then(onComplete, onError, onProgress)
.cancel()


La méthode .then() prend en entrée un ou plusieurs gestionnaires qui seront appelés lorsque la valeur promise sera disponible, une erreur se sera produite lors du calcul de la valeur ou que des avancées vers la disponibilité de la valeur auront eu lieu. La valeur renvoyée par then() est une promesse pour la valeur de retour provenant de l’appel de onComplete ou du gestionnaire onError. Si une exception se produit lors de l’exécution de onComplete ou du gestionnaire onError, la valeur renvoyée sera remplie par une valeur d’erreur représentant la valeur d’exception.

Chacun des gestionnaires reçoit une valeur unique correspondant à l’état approprié de ce gestionnaire.

  • Dans le gestionnaire onComplete, il s’agit de la valeur promise.
  • Dans le gestionnaire onError, il s’agit de l’erreur qui s’est produite.
  • Dans le gestionnaire onProgress, il s’agit d’une valeur définie par l’opération (essentiellement, un élément lié à la valeur promise).

N’importe quel argument peut ne pas être défini. Si l’argument onComplete n’est pas défini, c’est comme si le développeur avait transféré :



function (v) { return v; }


Si l’argument onError n’est pas défini, c’est comme si le développeur avait transféré :



function (e) { throw e; }


Si l’argument onProgress n’est pas défini, c’est comme si le développeur avait transféré :



function () { }


La méthode .cancel() peut être utilisée pour demander qu’une promesse et l’ensemble du travail non calculé dont elle dépend soient rejetés.

Les promesses facilitent l’asynchronie composable. Par exemple, la lecture du texte à partir d’un fichier dans Windows Runtime nécessite un certain nombre d’opérations asynchrones. Grâce à un langage compatible avec les promesses, les différentes API sont aisément composables dans une fonction readAllTextAsync() simple.



function readAllTextAsync(path) {
    return Windows.Storage.getFileItemFromPathAsync(path).
       then(function (item) { 
           var mode = Windows.Storage.FileAccesMode.read;
           return item.getStreamAsync(mode);
       }).
       then(function (seeker) {
           var bbrw 
         = new Windows.Storage.BasicBinaryReaderWriter();
           return bbrw.readStringAsync(seeker.getReaderAt(0));
       });
}


En effet, un utilisateur de readAllTextAsync() n’a plus qu’à se soucier du chemin d’accès au fichier et de ce qu’il va faire du résultat :



    readAllTextAsync(path).
        then(console.log);


Cette fonctionnalité serait plus complexe et plus exposée aux erreurs si elle était empaquetée à nouveau dans un style de codage plus classique, dans lequel les rappels seraient utilisés en lieu et place de la construction .then. Dans ce paradigme, le chaînage des appels asynchrones ressemblerait à ce qui suit, ce qui (notamment si les clauses et onErroronProgress étaient ajoutées), serait plus difficile à administrer :



doSomethingAsync(1, 2, function (result) {
    doSomethingAsync(result, 5, function (result) {
        doSomethingAsync(result, 10, function (result) {
            console.log(value);
        });
    });
});


Événements DOM

La documentation W3C définit les événements DOM comme « une plateforme générique et un système d’événements indépendant du langage qui permet l’enregistrement des gestionnaires d’événements, décrit le flux des événements dans une arborescence et fournit des informations contextuelles de base pour chaque événement. » Windows Runtime implémente un sous-ensemble pertinent de la spécification d’événements DOM de niveau 3.

Dans les applications du Windows Store notamment, les événements système sont exposés de la même façon que les événements DOM : par conséquent, un développeur peut appeler les fonctions addEventListener() et removeEventListener(), ainsi que la sémantique associée pour les gérer. Il peut donc exercer un contrôle très précis sur les événements survenant dans l’interface utilisateur et sur la façon dont le programme doit y répondre, sans avoir à acquérir de nouvelles compétences.

Un domaine de différentiation notable par rapport à la spécification Événements DOM est que Windows Runtime dissuade les applications du Windows Store de déclencher des événements artificiellement (c’est-à-dire, des événements de souris et de clavier). Pour cette raison, la méthode dispatchEvent() n’est pas prise en charge. Ces aspects de la maintenabilité de la sécurité et du code ont notamment motivé ce choix.

Les événements sont parfois générés artificiellement par les développeurs à des fins de test et d’automatisation de l’interface utilisateur. Dans la plupart des cas, cette opération n’est pas nécessaire puisque les modèles de conception appropriés sont adoptés automatiquement. Nous conseillons aux développeurs d’applications du Windows Store d’architecturer leurs applications en séparant clairement la vue du modèle de données sous-jacent (c’est-à-dire, en utilisant le modèle MVC). De cette façon, l’automatisation peut directement cibler la logique métier au lieu d’emprunter l’identité de l’utilisateur au niveau de l’interface graphique utilisateur.

La propagation et la capture, ainsi que certaines propriétés associées qui sinon auraient été transférées au gestionnaire d’événements, ne font pas non plus partie du flux de travail de répartition de l’API Windows Runtime. Ceci est une conséquence naturelle du fait que les événements Windows Runtime ne sont pas naturellement associés à un DOM structuré en arborescence. Par conséquent, il n’y a généralement pas de hiérarchie d’objets dans laquelle ces événements doivent être propagés.

Espaces de noms

Windows Runtime est une plateforme assez grande qui comprend jusqu’à 800 classes et énumérations individuelles. Le plus grand soin doit être apporté à la phase de conception afin de créer la structure d’espace de noms le plus intuitive possible, tout en tenant compte des perspectives de développement.

Des spécifications W3C sont généralement ajoutées à l’espace de noms global. Cette pollution de l’espace de noms global peut être pratique mais elle pose déjà des problèmes d’extensibilité, car le nombre d’API de la plateforme Web augmente à un rythme rapide. Compte tenu de la taille de Windows Runtime et de l’évolution indépendante des plateformes Windows et Web, il est irréaliste d’exposer des API Windows dans l’environnement global.

Le résultat est une hiérarchie d’espaces de noms dans laquelle les API sont catégorisées en domaines de fonctionnalités facilement reconnaissables. Cette hiérarchie est soit trop plate (l’alignement d’un nombre d’objets trop important au niveau de la racine peut être déroutant et irréalisable), soit trop profonde (ce qui peut créer du code non intuitif difficilement lisible). Dans certains cas, pour éviter la confusion liée à la similitude de dénomination des classes qui effectuent des tâches très différentes, les différences sont intentionnelles. Dans tous les cas, il y a une désambiguïsation claire entre les objets Windows Runtime et les objets normalisés. Cette mesure d’équilibrage soigneuse a permis de générer une structure de dénomination qui diffère quelque peu de ce qu’on trouve habituellement dans des exemples de programmation de navigateur disponibles sur le Web.

Par exemple, pour accéder à la fonctionnalité de géolocalisation décrite dans la spécification de géolocalisation W3C, il faut appeler :



navigation.geolocation


Chaque fois que Windows Runtime expose cette fonctionnalité de la sorte :



Windows.Devices.Geolocation.Geolocator()


La première différence et la plus évidente est l’utilisation de l’espace de noms racine « Windows », qui est le seul objet global exposé par Windows Runtime. L’un des principaux objectifs de la mise en dessous des classes est de pouvoir distinguer clairement tout ce qui exploite les capacités uniques de Windows. Cela permet également aux fonctionnalités basées sur les normes Web de coexister dans un souci de simplification de la portabilité.

Dans les cas où l’énoncé des espaces de noms multiniveau en entier n’est pas nécessaire, il est pratique de pouvoir mettre un alias de l’espace de noms au début du programme afin de réduire la verbosité du code au minimum, comme par exemple :



var geo = Windows.Devices.Geolocation;
///...
var x = new geo.Geolocator();


De plus, l’utilisation des espaces de noms simplifie la reconnaissance des API dans les outils de développement et la documentation.

Énumérations

Les objets définis selon les normes Web définissent des propriétés à partir d’un petit ensemble de valeurs acceptables à l’aide d’une grande variété de méthodologies. Ils utilisent des énumérations à l’occasion mais acceptent souvent des chaînes. Une importante raison à cela est de laisser le champ libre pour l’expérimentation par différentes organisations avant que de nouvelles propriétés ne deviennent normalisées (ce qui est plus simple si des chaînes simples sont utilisées pour les affecter et les désigner). C’est en partie parce que ce besoin n’est pas vital que Windows Runtime a une tendance plus marquée pour les énumérations.

Ce choix met en avant la simplicité d’une instruction telle que celle-ci :



reader.readAsText(readFile, "UTF-16");


En faveur de la syntaxe de Windows Runtime :



reader.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf8;
reader.readString(someValue);


Cette syntaxe est plus robuste et moins exposée aux fautes de frappe ou à d’autres problèmes. Les valeurs légales des paramètres sont également beaucoup plus faciles à reconnaître : De plus, les énumérations permettent la cohérence et l’interopérabilité entre les langages de programmation pris en charge par la plateforme Windows.

Constructeurs

Bien que les spécifications W3C utilisent différents styles pour créer des objets, qui incluent l’utilisation des constructeurs, bon nombre d’entre eux décrivent des objets singletons instanciés explicitement et effectuent leurs tâches à l’aide d’une multitude de méthodes et propriétés. Un exemple est l’objet de navigateur mentionné dans les précédentes sections de cette rubrique.

Dans Windows Runtime, il est possible que des API similaires soient exposées différemment. Alors que la cohérence avec les normes Web existantes a été recherchée autant que possible, au final la conception la plus appropriée pour chaque fonction a été adoptée. Plus spécifiquement, Windows Runtime est subdivisé en un ensemble plus précis de classes associées mais spécialisées, chacune d’entre elles étant généralement instanciée via son propre constructeur ou via une méthode de fabrique statique.

Visual Studio simplifie considérablement la génération de telles instructions grâce à l’intégration d’Intellisense (achèvement du code). De plus, les erreurs de syntaxe sont identifiées à la volée afin d’aider les développeurs à créer du code généré et exécuté de manière plus fiable.

Rubriques associées

Spécification d’événements HML5 DOM Niveau 3
Wiki standard proposé « Common JS Promises/A »

 

 

Afficher:
© 2014 Microsoft