2016-02-25 6 views
1

Je aime vraiment les NodeJS façon (et ses contreparties côté navigateur) modules gérer:Langues avec un NodeJS/système modulaire de style CommonJS

var $ = require('jquery'); 

var config = require('./config.json'); 

module.exports = function(){}; 

module.exports = {...} 

Je suis en fait assez déçu par le ES2015 'import' spec qui est très similaire à la majorité des langues. Par curiosité, j'ai décidé de chercher d'autres langages qui implémentent ou même prennent en charge un style d'import/export similaire, mais en vain. Peut-être qu'il me manque quelque chose, ou plus probablement, mon Google Foo n'est pas à la hauteur, mais il serait vraiment intéressant de voir quelles autres langues fonctionnent de la même manière.

Est-ce que quelqu'un a rencontré des systèmes similaires? Ou peut-être quelqu'un peut même fournir des raisons pour lesquelles il n'est pas souvent utilisé.

+0

Quelle est exactement la fonctionnalité que vous recherchez, celle qui distingue les deux systèmes? – svick

+0

@svick Principalement la fonction require, qui renvoie une fonction ou d'autres données structurées. Par opposition à 'import x from y' qui crée implicitement une propriété globalement accessible et ne peut être effectuée qu'en haut d'un fichier. – ISNIT

Répondre

3

Il est presque impossible de comparer correctement ces caractéristiques. On ne peut que comparer leur mise en œuvre dans des langues spécifiques. J'ai rassemblé mon expérience principalement avec la langue Java et nodejs.

J'observé ces différences:

  • Vous pouvez utiliser require pour plus que faire d'autres modules disponibles à votre module. Par exemple, vous pouvez l'utiliser pour analyser un fichier JSON.
  • Vous pouvez utiliser require partout dans votre code, tandis que import est uniquement disponible en haut d'un fichier. Exécute effectivement le module requis (s'il n'a pas encore été exécuté), tandis que import a un caractère plus déclaratif. Cela peut ne pas être vrai pour toutes les langues, mais c'est une tendance.
  • require peut charger des dépendances privées à partir de sous-répertoires, tandis que import utilise souvent un espace de noms global pour tout le code. Encore une fois, ce n'est pas vrai en général, mais simplement une tendance.

Responsabilités

Comme vous pouvez le voir, la méthode require a de multiples responsabilités: déclarer les dépendances du module et la lecture des données. Ceci est mieux séparé avec l'approche d'importation, puisque import est censé gérer seulement les dépendances de module. Je suppose que ce que vous aimez de pouvoir utiliser la méthode require pour lire JSON, c'est qu'il fournit une interface vraiment facile au programmeur. Je suis d'accord qu'il est agréable d'avoir ce type d'interface de lecture JSON facile, mais il n'est pas nécessaire de le mélanger avec le mécanisme de dépendance du module. Il peut simplement y avoir une autre méthode, par exemple readJson(). Cela permettrait de séparer les préoccupations, donc la méthode require serait seulement nécessaire pour déclarer les dépendances du module.

Situation dans le Code

Maintenant que nous utilisons uniquement require pour les dépendances du module, il est une mauvaise pratique de l'utiliser ailleurs que dans la partie supérieure de votre module. Cela rend difficile la visualisation des dépendances du module lorsque vous l'utilisez partout dans votre code. C'est pourquoi vous pouvez utiliser l'instruction import uniquement par-dessus votre code.

Je ne vois pas le point où import crée une variable globale.Il crée simplement un identificateur cohérent pour chaque dépendance, qui est limité au fichier en cours. Comme je l'ai dit plus haut, je recommande de faire la même chose avec la méthode require en l'utilisant seulement en haut du fichier. Cela aide vraiment à augmenter la lisibilité du code.

Comment ça marche

exécution de code lors du chargement d'un module peut aussi être un problème, en particulier dans les grands programmes. Vous pourriez courir dans une boucle où un module a besoin de lui-même. Cela peut être vraiment difficile à résoudre. A ma connaissance, gère NodeJS cette situation comme ceci: Quand A demande B et B nécessite A et vous commencez en exigeant A, puis:

  • le système du module se souvient qu'il se charge actuellement A
  • il exécute le code dans un
  • il rappelle que des charges est actuellement B
  • il exécute le code B
  • il tente de charger A, mais A est déjà chargement
  • A est pas encore terminé le chargement
  • il retourne la moitié chargée A à B
  • B ne prévoit pas un à moitié chargé

Cela pourrait être un problème. Maintenant, on peut faire valoir que les dépendances cycliques devraient vraiment être évitées et je suis d'accord avec cela. Cependant, les dépendances cycliques ne doivent être évitées qu'entre des composants séparés d'un programme. Les classes d'un composant ont souvent des dépendances cycliques. Maintenant, le système de modules peut être utilisé pour les deux couches d'abstraction: Classes et Composants. Cela pourrait être un problème.

Ensuite, l'approche require conduit souvent à des modules singleton, qui ne peuvent pas être utilisés plusieurs fois dans le même programme, car ils stockent l'état global. Cependant, ce n'est pas vraiment la faute du système mais la faute des programmeurs qui utilisent le système de la mauvaise façon. Pourtant, mon observation est que l'approche require trompe en particulier les nouveaux programmeurs pour ce faire.

La gestion des dépendances

La gestion de la dépendance qui les sous-couches différentes approches est en effet un point intéressant. Par exemple Java manque toujours un bon système de module dans la version actuelle. Encore une fois, il est annoncé pour la prochaine version, mais qui sait si cela deviendra jamais vrai. Actuellement, vous ne pouvez obtenir des modules qu'en utilisant OSGi, ce qui est loin d'être facile à utiliser.

La sous-couche de gestion des dépendances nodejs est très puissante. Cependant, ce n'est pas parfait. Par exemple, les dépendances non privées, qui sont des dépendances qui sont exposées via l'API des modules, sont toujours un problème. Cependant, il s'agit d'un problème courant pour la gestion des dépendances, il n'est donc pas limité à nodejs.

Conclusion

Je suppose que les deux ne sont pas si mal que ça, puisque chacun est utilisé avec succès. Cependant, à mon avis, import a des avantages objectifs sur require, comme la séparation des responsabilités. Il s'ensuit que import peut être limité au début du code, ce qui signifie qu'il n'y a qu'un seul endroit pour rechercher les dépendances du module. En outre, import peut être un meilleur ajustement pour les langages compilés, car ceux-ci n'ont pas besoin d'exécuter du code pour charger du code.