Catégories
Astuces et Design

Un standard ouvert pour les fonctions JavaScript – Smashing Magazine

A propos de l'auteur

Kelvin Omereshone est le CTO de Quru Lab. Kelvin était auparavant ingénieur front-end chez myPadi.ng. Il est le créateur de la communauté Nuxtjs Africa et très passionné…
Plus à propos
Kelvin

Dans cet article, Kelvin Omereshone vous présente les machines, un standard ouvert pour les fonctions JavaScript. À la fin de cet article, vous devez savoir ce que sont les machines et comment les implémenter.

En tant que développeurs, nous cherchons toujours des moyens de mieux faire notre travail, que ce soit en suivant des modèles, en utilisant des bibliothèques et des cadres bien écrits, ou ce que vous avez. Dans cet article, je vais partager avec vous une spécification JavaScript pour les fonctions facilement consommables. Cet article est destiné aux développeurs JavaScript et vous apprendrez à écrire des fonctions JavaScript avec une API universelle qui facilite la consommation de ces fonctions. Cela serait particulièrement utile pour la création de packages npm (comme nous le verrons à la fin de cet article).

Il n'y a aucun prérequis spécial pour cet article. Si vous pouvez écrire une fonction JavaScript, vous pourrez suivre. Cela dit, plongeons-nous.

Que sont les machines?

Les machines sont des fonctions JavaScript prévisibles et auto-documentées qui suivent les spécifications de la machine, écrites par Mike McNeil. Une machine se caractérise par les éléments suivants:

  • Il doit avoir un objectif clair, qu'il s'agisse d'envoyer un e-mail, d'émettre un jeton Web JSON, de faire une demande de récupération, etc.
  • Il doit suivre les spécifications, ce qui rend les machines prévisibles pour la consommation via les installations npm.

À titre d'exemple, voici une collection de machines qui fournit des API simples et cohérentes pour travailler avec Cloudinary. Cette collection expose des fonctions (machines) pour télécharger des images, supprimer des images, etc. C’est tout ce que les machines sont vraiment: elles exposent simplement une API simple et cohérente pour travailler avec les fonctions JavaScript et Node.js.

Caractéristiques des machines

  • Les machines sont auto-documentées. Cela signifie que vous pouvez simplement regarder une machine et savoir ce qu'elle fait et ce qu'elle va exécuter (les paramètres). Cette fonctionnalité m'a vraiment vendu sur eux. Toutes les machines sont auto-documentées, ce qui les rend prévisibles.
  • Les machines sont rapides à mettre en œuvre, comme nous le verrons. En utilisant l'outil machinepack pour l'interface de ligne de commande (CLI), nous pouvons rapidement échafauder une machine et la publier sur npm.
  • Les machines sont faciles à déboguer. Cela est également dû au fait que chaque machine possède une API standardisée. Nous pouvons facilement déboguer des machines car elles sont prévisibles.

Y a-t-il des machines là-bas?

Vous vous demandez peut-être: "Si les machines sont si bonnes, alors pourquoi n'en ai-je pas entendu parler jusqu'à présent?" En fait, ils sont déjà largement utilisés. Si vous avez utilisé le framework Node.js MVC Sails.js, vous avez soit écrit une machine, soit interfacé avec un couple. L'auteur de Sails.js est également l'auteur de la spécification de la machine.

En plus du framework Sails.js, vous pouvez parcourir les machines disponibles sur npm en recherchant machinepack, ou vous rendre sur http://node-machine.org/machinepacks, qui est le démon de registre de machinepack; il se synchronise avec npm et se met à jour toutes les 10 minutes.

Les machines sont universelles. En tant que consommateur de forfaits, vous saurez à quoi vous attendre. Donc, n'essayez plus de deviner l'API d'un package particulier que vous avez installé. S'il s'agit d'une machine, vous pouvez vous attendre à ce qu'elle suive la même interface facile à utiliser.

Maintenant que nous avons une idée de ce que sont les machines, examinons les spécifications en analysant un exemple de machine.

La spécification de la machine

    module.exports = {
  friendlyName: 'Do something',
  description: 'Do something with the provided inputs that results in one of the exit scenarios.',
  extendedDescription: 'This optional extended description can be used to communicate caveats, technical notes, or any other sort of additional information which might be helpful for users of this machine.',
  moreInfoUrl: 'https://stripe.com/docs/api#list_cards',
  sideEffects: 'cacheable',
  sync: true,

  inputs: {
    brand: {
      friendlyName: 'Some input',
      description: 'The brand of gummy worms.',
      extendedDescription: 'The provided value will be matched against all known gummy worm brands. The match is case-insensitive, and tolerant of typos within Levenstein edit distance 

L'extrait ci-dessus est tiré de l'exemple interactif sur le site officiel. Décortiquons cette machine.

En regardant l'extrait ci-dessus, nous pouvons voir qu'une machine est un objet exporté contenant certaines propriétés standardisées et une seule fonction. Voyons d'abord quelles sont ces propriétés et pourquoi elles le sont.

  • friendlyName
    Il s'agit d'un nom d'affichage pour la machine et il suit ces règles:
    • est phrase-cas (comme une phrase normale),
    • ne doit pas avoir de ponctuation de fin,
    • doit contenir moins de 50 caractères.
  • description
    Cela devrait être une description claire en une phrase dans l'humeur impérative (c'est-à-dire la voix faisant autorité) de ce que fait la machine. Un exemple serait «Émettre un jeton Web JSON», plutôt que «Émettre un jeton Web JSON». Sa seule contrainte est:
    • Il doit contenir moins de 80 caractères.
  • extendedDescription (optionnel)
    Cette propriété fournit des informations supplémentaires facultatives, étendant ce qui a déjà été dit dans la propriété description. Dans ce champ, vous pouvez utiliser des signes de ponctuation et des phrases complètes.
    • Il doit contenir moins de 2 000 caractères.
  • moreInfoUrl (optionnel)
    Ce champ contient une URL dans laquelle des informations supplémentaires sur le fonctionnement interne ou les fonctionnalités de la machine peuvent être trouvées. Cela est particulièrement utile pour les machines qui communiquent avec des API tierces telles que GitHub et Auth0.
  • sideEffects (optionnel)
    Il s'agit d'un champ facultatif que vous pouvez ignorer ou définir comme cacheable ou idempotent. S'il est défini sur cacheable, puis .cache() peut être utilisé avec cette machine. Notez que seules les machines qui n'ont pas sideEffects doit être défini sur cacheable.
  • sync (optionnel)
    Les machines sont asynchrones par défaut. Réglage du sync option pour true désactive l'async pour cette machine, et vous pouvez ensuite l'utiliser comme une fonction régulière (sans async/await, ou then()).

contributions

Il s'agit de la spécification ou de la déclaration des valeurs attendues par la fonction machine. Examinons les différents champs de saisie d'une machine.

  • brand
    En utilisant l'extrait de machine ci-dessus comme guide, le champ de la marque est appelé la clé de saisie. Il est normalement en chameau et doit être une chaîne alphanumérique commençant par une lettre minuscule.
    • Aucun caractère spécial n'est autorisé dans un identificateur ou un champ de clé d'entrée.
  • friendlyName
    Il s'agit d'un nom d'affichage lisible par l'homme pour l'entrée. Cela devrait:
    • être phrase-cas,
    • n'ont pas de ponctuation finale,
    • avoir moins de 50 caractères.
  • description
    Il s'agit d'une courte description décrivant l'utilisation de l'entrée.
  • extendedDescription
    Tout comme le extendedDescription sur la machine elle-même, ce champ fournit des informations supplémentaires sur cette entrée particulière.
  • moreInfoUrl
    Il s'agit d'une URL facultative qui fournit plus d'informations sur l'entrée, si nécessaire.
  • required
    Par défaut, chaque entrée est facultative. Cela signifie que si, au moment de l'exécution, aucune valeur n'est fournie pour une entrée, fn serait indéfini. Si vos entrées ne sont pas facultatives, il est préférable de définir ce champ comme vrai, car cela entraînerait une erreur de la part de la machine.
  • example
    Ce champ est utilisé pour déterminer le type de données attendu de l'entrée.
  • whereToGet
    Il s'agit d'un objet de documentation facultatif qui fournit des informations supplémentaires sur la façon de localiser les valeurs adéquates pour cette entrée. Cela est particulièrement utile pour des choses comme les clés API, les jetons, etc.
  • whereToGet.description
    Il s'agit d'une description claire d'une phrase, également dans l'état d'esprit impératif, qui décrit comment trouver la bonne valeur pour cette entrée.
  • extendedDescription
    Cela fournit des informations supplémentaires sur où obtenir une valeur d'entrée appropriée pour cette machine.

sorties

Il s'agit de la spécification de tous les rappels de sortie possibles que cette machine fn la mise en œuvre peut déclencher. Cela implique que chaque sortie représente un résultat possible de l'exécution de la machine.

  • success
    Il s'agit de la clé de sortie standardisée dans les spécifications de la machine qui signifie que tout s'est bien passé et que la machine a fonctionné sans aucune erreur. Voyons les propriétés qu'il pourrait exposer:
    • outputFriendlyName
      Il s'agit simplement d'un nom d'affichage pour la sortie de sortie.
    • outputDescription
      Cette courte phrase nominale décrit la sortie d'une sortie.

D'autres sorties indiquent que quelque chose s'est mal passé et que la machine a rencontré une erreur. La convention de dénomination de ces sorties doit suivre la convention de dénomination de la clé d'entrée. Voyons les champs sous ces sorties:

  • description
    Il s'agit d'une brève description décrivant le moment où la sortie sera appelée.
  • extendedDescription
    Cela fournit des informations supplémentaires sur le moment où cette sortie sera appelée. C'est facultatif. Vous pouvez utiliser la syntaxe Markdown complète dans ce champ et, comme d'habitude, elle doit contenir moins de 2000 caractères.

Tu l'as fait!

C'était beaucoup à prendre en compte. Mais ne vous inquiétez pas: lorsque vous commencez à créer des machines, ces conventions resteront en place, en particulier après votre première machine, que nous écrirons ensemble sous peu. Mais d'abord…

Machinepacks

Lors de la création de machines, les packs machine sont ce que vous publiez sur npm. Ils sont tout simplement ensembles d'utilitaires associés pour effectuer des tâches de développement répétitives courantes avec Node.js. Supposons donc que vous ayez un pack machine qui fonctionne avec les tableaux; ce serait un ensemble de machines qui fonctionne sur des tableaux, comme concat(), map(), etc. Voir le pack machine Arrays dans le registre pour obtenir une vue complète.

Convention de dénomination des machinepacks

Tous les packs machine doivent suivre la norme d'avoir "machinepack-" comme préfixe, suivi du nom de la machine. Par exemple, machinepack-array, machinepack-sessionauth.

Notre premier pack machine

Pour mieux comprendre les machines, nous allons écrire et publier un pack machine qui est un wrapper pour le package npm contributeurs de fichiers.

Commencer

Nous avons besoin des éléments suivants pour fabriquer notre pack machine:

  1. Outil CLI Machinepack
    Vous pouvez l'obtenir en exécutant:
    npm install -g machinepack
    
  2. Outil d'échafaudage Yeoman
    Installez-le globalement en exécutant:
     npm install -g yo
    
  3. Générateur Machinepack Yeomen
    Installez-le comme ceci:
    npm install -g generator-machinepack
    

Remarque: Je suppose que Node.js et npm sont déjà installés sur votre machine.

Générer votre premier pack machine

À l'aide des outils CLI que nous avons installés ci-dessus, générons un nouveau pack machine à l'aide du générateur de pack machine. Pour ce faire, accédez d'abord au répertoire dans lequel vous souhaitez que le générateur génère les fichiers, puis exécutez ce qui suit:

yo machinepack

La commande ci-dessus lancera un processus interactif de génération d'un pack machine barebones pour vous. Il vous posera quelques questions; assurez-vous de lui dire oui en créant un exemple de machine.

Remarque: J'ai remarqué que le générateur Yeoman a des problèmes lors de l'utilisation de Node.js 12 ou 13. Donc, je recommande d'utiliser nvm et d'installer Node.js 10.x, qui est l'environnement qui a fonctionné pour moi.

Si tout s'était déroulé comme prévu, nous aurions généré la couche de base de notre machinepack. Jetons un coup d'œil:

DELETE_THIS_FILE.md
machines/
package.json
package.lock.json
README.md
index.js
node_modules/

Les fichiers ci-dessus sont générés pour vous. Jouons avec notre exemple de machine, qui se trouve à l'intérieur du machines annuaire. Étant donné que l'outil CLI de machinepack est installé, nous pouvons exécuter les éléments suivants:

machinepack ls

Cela répertorierait les machines disponibles dans notre machines annuaire. Actuellement, il y en a une, la machine à dire bonjour. Voyons ce que say-hello fait en lançant ceci:

machinepack exec say-hello

Cela vous demandera de saisir un nom et imprimera la sortie de la machine say-hello.

Comme vous le remarquerez, l'outil CLI tire parti de la standardisation des machines pour obtenir la description et les fonctionnalités de la machine. Génial!

Faisons une machine

Ajoutons notre propre machine, qui encapsulera les contributeurs de fichiers et les packages d'extraction de nœuds (nous devrons également installer ceux avec npm). Alors lancez ceci:

npm install file-contributors node-fetch --save

Ensuite, ajoutez une nouvelle machine en exécutant:

machinepack add

Vous serez invité à saisir le nom convivial, la description (facultative) et la description étendue (également facultative) de la machine. Après cela, vous aurez réussi à générer votre machine.

Maintenant, développons les fonctionnalités de cette machine. Ouvrez la nouvelle machine que vous avez générée dans votre éditeur. Ensuite, exigez le package file-contributors, comme ceci:

const fetch = require('node-fetch');
const getFileContributors = require('file-contributors').default;

global.fetch = fetch; // workaround since file-contributors uses windows.fetch() internally

Remarque: Nous utilisons le package node-fetch et le global.fetch = fetch solution de contournement car le package contributeurs de fichiers utilise windows.fetch() en interne, qui n'est pas disponible dans Node.js.

Les contributeurs de fichiers getFileContributors nécessite trois paramètres pour fonctionner: owner (le propriétaire du référentiel), repo (le référentiel), et path (le chemin d'accès au fichier). Donc, si vous avez suivi, vous saurez que ceux-ci iraient dans notre inputs clé. Ajoutons-les maintenant:

...
 inputs: {
    owner: {
      friendlyName: 'Owner',
      description: 'The owner of the repository',
      required: true,
      example: 'DominusKelvin'
    },
    repo: {
      friendlyName: 'Repository',
      description: 'The Github repository',
      required: true,
      example: 'machinepack-filecontributors'
    },
    path: {
      friendlyName: 'Path',
      description: 'The relative path to the file',
      required: true,
      example: 'README.md'
    }
  },
...

Maintenant, ajoutons les sorties. À l'origine, la CLI a ajouté un success sortie pour nous. Nous modifierions cela, puis ajouterions une autre sortie au cas où les choses ne se passeraient pas comme prévu.

exits: {

    success: {
      outputFriendlyName: 'File Contributors',
      outputDescription: 'An array of the contributors on a particular file',
      variableName: 'fileContributors',
      description: 'Done.',
    },

    error: {
      description: 'An error occurred trying to get file contributors'
    }

  },

Enfin, fabriquons la viande de la machine, qui est la fn:

 fn: function(inputs, exits) {
    const contributors = getFileContributors(inputs.owner, inputs.repo, inputs.path)
    .then(contributors => {
      return exits.success(contributors)
    }).catch((error) => {
      return exits.error(error)
    })
  },

Et voilà! Nous avons conçu notre première machine. Essayons-le à l'aide de l'interface CLI en exécutant ce qui suit:

machinepack exec get-file-contributors

Une invite apparaîtra demandant owner, repo, et path, successivement. Si tout se passe comme prévu, notre machine se terminera avec succès et nous verrons un tableau des contributeurs pour le fichier de référentiel que nous avons spécifié.

Utilisation dans le code

Je sais que nous n'utiliserons pas la CLI pour consommer le pack machine dans notre base de code. Voici donc un extrait de la façon dont nous consommerions des machines à partir d'un pack machine:

    var FileContributors = require('machinepack-filecontributors');

// Fetch metadata about a repository on GitHub.
FileContributors.getFileContributors({
  owner: 'DominusKelvin',
  repo: 'vue-cli-plugin-chakra-ui',
   path: 'README.md' 
}).exec({
  // An unexpected error occurred.
  error: function (){
  },
  // OK.
  success: function (contributors){
    console.log('Got:n', contributors);
  },
});

Conclusion

Toutes nos félicitations! Vous venez de vous familiariser avec les spécifications de la machine, de créer votre propre machine et de voir comment consommer des machines. Je serai ravi de voir les machines que vous créez.

Ressources

Consultez le référentiel de cet article. Le package npm que nous avons créé est également disponible sur npm.

Smashing Editorial(ra, il, al)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *