<![CDATA[node.js - ]]>http://localhost:2368/Ghost 0.11Tue, 10 Oct 2017 14:25:12 GMT60<![CDATA[Node.js Module mit JSDoc dokumentieren]]>Das Revealing Module Pattern ist eine bewährte Methode, um JavaScript-Code zu kapseln und eine private Implementierung hinter einer definierten öffentlichen Schnittstelle zu verbergen. In diesem Artikel werde ich zeigen, wie man das Revealing Module Pattern in Node.js verwendet und wie man so ein Modul mit http://usejsdoc.org/.

Als

]]>
http://localhost:2368/2016/05/24/node-js-module-mit-jsdoc-dokumentieren/6772fa6c-1640-476b-8fe9-bd09cd5fd4faTue, 24 May 2016 19:02:24 GMTDas Revealing Module Pattern ist eine bewährte Methode, um JavaScript-Code zu kapseln und eine private Implementierung hinter einer definierten öffentlichen Schnittstelle zu verbergen. In diesem Artikel werde ich zeigen, wie man das Revealing Module Pattern in Node.js verwendet und wie man so ein Modul mit http://usejsdoc.org/.

Als ersten Schritt implementieren wir ein generisches Modul nach den Richtlinien des Revealing Module Pattern:

var katzenModul = (function () {  
    var privaterName = 'kitty';

    function publicGetName(){
        return privaterName;
    }

    return {
        getName : publicGetName
    };
})();

katzenModul.getName();  

Dieses Modul definiert eine Funktion publicGetName(), die nach aussen als getName deklariert wird. Der Name der Katze ist privat und kann nicht von aussen zugegriffen werden, wie die entsprechenden Tests beweisen:

describe('katzenModul', function() {

  it('should return the name of the cat', function() {
      var name = katzenModul.getName();
      assert.equal(name, 'kitty');
  });

  it('should not allow access to private variables', function() {
      assert.equal( undefined, katzenModul.privaterName );
  });

  it('should not allow access to private functions', function() {
      assert.equal( undefined, katzenModul.publicGetName );
  });
});

Als nächstes machen wir aus unserem generischen Modul ein Node-Modul:

var katzenModul = (function () {  
    var privaterName = 'kitty';

    function publicGetName(){
        return privaterName;
    }

    return {
        getName : publicGetName
    };
})();
module.exports = katzenModul;  

Durch die letzte Zeile module.exports = katzenModul; haben wir unser Modul Node.js bekannt gemacht. Nun können wir das Modul z.B. wie folgt verwenden:

var katzenModul = require('./katzenModul');

console.log( katzenModul.getName() );  

Ein weiterer Vorteil des Revealing Module Pattern ist, dass es sich sehr gut eignet, um Dokumentation zu schreiben, ohne die Lesbarkeit des Codes zu beeinträchtigen. Der Grund dafür ist, dass die Dokumentation der "öffentlichen" Schnittstelle eines solchen Moduls am Ende der Datei steht und nicht den eigentlichen Code "verunreinigt". So sieht z.B. eine dokumentierte Version von katzenModul aus:

/**
 * @description Dieses Module liefert Katzennamen
 * @module katzenModul
 * @author Marcelo Emmerich
 */
var katzenModul = (function () {  
    var privaterName = 'kitty';

    function publicGetName(){
        return privaterName;
    }

    return {
        /**
         * @function
         * @description Liefert den Namen der Katze
         * @memberof module:katzenModul
         * @returns {String} Den Namen der Katze als String
         */
        getName : publicGetName
    };
})();
module.exports = katzenModul;  

Zuerst habe ich das Modul als solches mit dem JSDoc Tag @module definiert, um es später referenzieren zu können. @author und @description sind vermutlich selbst erklärend, also schauen wir uns die interessanteren Tags an. Die Funktion getName ist mit @function markiert. Das ist deswegen notwendig, weil der JSDoc Parser sonst nicht mit der Syntax des Revealing Module Pattern klar kommt und die Funktion nicht als solche erkennt. Weiter müssen wir JSDoc auch damit auf die Sprünge helfen, die Funktion getName als zum Modul katzenModul zugehörig anzuerkennen. Das erreichen wir mit dem @memberof module:<Modulname> Tag. Wenn wir nun mit JSDoc die Dokumentation erzeugen, wird unser Modul als solches aufgeführt und die Funktion getName korrekt referenziert.

]]>
<![CDATA[Leserliche require Anweisungen für mocha Unit Tests in Clean Architecture Node Applications]]>Bei Pulsar Solutions versuchen wir die Richtlinien von Clean Architecture zu befolgen, um Code zu produzieren, der testbar ist und unabhängig von Frameworks, UI, Datenbanken und sogar das Web. Gleichzeitig sollte der Zweck der Applikation offensichtlich werden, indem man sich die Dateistruktur ansieht. Das resultiert allerdings oft in einem weit

]]>
http://localhost:2368/2016/01/13/readable-require-statements-for-mocha-unit-tests-in-clean-architected-node-applications/50c71325-4fda-405b-956a-335b831c163bWed, 13 Jan 2016 21:33:17 GMTBei Pulsar Solutions versuchen wir die Richtlinien von Clean Architecture zu befolgen, um Code zu produzieren, der testbar ist und unabhängig von Frameworks, UI, Datenbanken und sogar das Web. Gleichzeitig sollte der Zweck der Applikation offensichtlich werden, indem man sich die Dateistruktur ansieht. Das resultiert allerdings oft in einem weit verzweigten Dateibaum, was zu unleserlichen und schwer wartbaren require Anweisungen führt.

In diesem Artikel liegt der Fokus darin, leserliche und wartbare require Anweisungen für die Unit Tests einer Anwendung zu ermöglichen. Der Einfachheit halber setze ich voraus, dass mocha als Testing Framework eingesetzt wird. Für andere beliebte Frameworks kann ein ähnlicher Ansatz verwendet werden.

Gehen wir von der folgenden Verzeichnisstruktur aus:

-- root
  -- node_modules
  -- src
    -- 0_externals
    -- 1_controllers_gateways_presenters
    -- 2_use_cases
      -- searchCats.js
    -- 3_entities
  -- tests
    -- ...
    -- 2_use_cases
      -- searchCatsTest.js
    -- ...
  -- ...

Dem entsprechend soll searchCatsTest.js den Code in searchCats.js testen. Mit mocha und der oben gezeigten Struktur würde die require Anweisung so aussehen:

var searchCats = require('../../../src/2_use_cases/searchCats');  

für einen Node Modul mit dieser Definition:

module.exports = searchCats;  

Das ist offensichtlich schlecht. Es ist unleserlich und, sollte sich die Verzeichnisstruktur aus irgend einem Grund nach einigen Monaten Entwicklung verändern, müssten alle require Anweisungen angepasst werden.

Wäre es nicht besser wenn wir schreiben könnten

var searchCats = require('2_use_cases/searchCats');  

und wir könnten das Root Verzeichnis global setzen? Leider funktioniert die o.g. Syntax nicht out-of-the-box, da require nicht weiss wo die Datei searchCats.js liegt.

Bevor wir weitermachen sollten wir einen Blick darauf werfen, wie mocha in der Kommandozeile aufgerufen wird:

mocha -R spec -u bdd ./tests  

Dieser Aufruf teilt mocha mit, dass alle Tests im Verzeichnis ./tests rekursiv auszuführen sind, dass der BDD Style verwendet werden soll und dass der Fortschritt im spec Format erfolgen soll. Da wir aber diesen Aufruf aus dem Root-Verzeichnis ausführen, überrascht es nicht, dass searchCats.js nicht gefunden wird. Wir kriegen eine Exception.

Googelt man ein wenig gelangt man schnell zu dieser interessanten Sammlung von Lösungen für ein ähnliches Problem aus der Node.js Welt: (Better local require() paths for Node.js) Ich bevorzuge Lösung Nummer 7, den globalen Wrapper um require. Aber wie können wir diese Technik auf unsere Mocha Tests anwenden? Klar ist, dass es nicht funktionieren wird, wenn mocha weiterhin mit dem o.g. Aufruf gestartet wird. Glücklicherweise kann man einen eigenen Mocha Runner als minimalistische Node.js Anwendung implementieren. Wie der Zufall so will hat das jemand bereits getan: (Starting Mocha Tests Programmically With Runner.js).

Alles was wir jetzt tun müssen, ist den Wrapper um require herum am Anfang des Runners einzubauen. Der Runner sieht dann so aus:

var fs = require('fs'),  
    Mocha = require("mocha"),
    path = require('path');

global.rootRequire = function (name) {  
    return require(__dirname + '/src/' + name);
}

// Our Mocha runner
var mocha = new Mocha({  
    ui: "bdd",
    reporter: "spec",
    timeout: 60000,
    slow: 10000
});

// Files which need to be ignored
var avoided = [  
    "node_modules"
];

// Add the tests to the Mocha instance
(addFiles = function (dir) {
    fs.readdirSync(dir).filter(function (file) {
        if (!~avoided.indexOf(file)) {
            if (fs.statSync(dir + '/' + file).isDirectory()) {
                addFiles(dir + '/' + file);
            }
            return file.substr(-3) === '.js';
        }
    }).forEach(function (file) {
        mocha.addFile(dir + '/' + file);
    });
})(path.join(process.cwd(), process.argv[2] || "."));

// Run the files in Mocha
mocha.run(function (failures) {  
    process.exit(failures);
});

Damit sieht jetzt die require Anweisung so aus:

var searchCats = rootRequire('2_use_cases/searchCats');  

und der Aufruf von Mocha sieht so aus:

node runner.js tests  

Viel besser oder?

]]>