11. 09. 2017 Valentina Da Rold Development, NetEye

JavaScript Design Patterns in Icinga Web 2

Picture5

Sie sind auf der Suche nach Guidlines um neue JavaScript Funktionen in Icinga Web 2 zu erzeugen? Im Folgenden versuche ich Ihnen die Struktur, die Ihre Funktion haben sollte um korrekt von Icinga Web 2 kompiliert zu werden, zu erklären.

Sollten Sie bereits den Code analysiert haben, wird Ihnen aufgefallen sein, dass die JavaScript Funktionen von Icinga durch die typische Struktur der JavaScript Design Patterns auszeichnet.

Was genau sind Design Pattern?

Design Pattern sind advanced Lösungen der objekt-orientierten Entwicklung, die normalerweise in der Entwicklung von Softwarelösungen eingesetzt werden. Jeder Entwickler sollte hierbei Code produzieren, der sich nicht nur leicht interpretieren lässt, sondern auch wiederverwendbar ist und die Wartung vereinfacht. Die Design Pattern sind der Schlüssel zur Lösung dieses Problems. Eine Design Pattern basierte Entwicklung sieht vor, dass Funktionen aus Code Blöcken bestehen und erzeugt werden. Diese Code Blocke sind nichts anderes als Problemlösungen bzw. funktionelle Einheiten, die häufig in der Software vorkommen und somit innerhalb von Funktionen wiederverwendet werden können und zusammen eine komplexere Struktur ergeben.

Design Pattern in JavaScript

JavaScript ist eine objektorientiere Skriptsprache. Sie basiert auf dem Konzept des Prototypes und unterscheidet sich somit durch ihre Klassenlosigkeit von den meisten Programmiersprachen. Im Gegensatz zu trafizionallen objektorientierten Sprachen, wo eine Klasse alle Eigenschaften eines Objektes definiert, ist es in JavaScript moeglich, nur einige Eigenschaften des Objektes zu definieren und es mit neuen Eingeschaften und Methoden anzureichern, indem man das Objekt von anderen Objekten nach dem klar definierten Konzept der “prototypical inheritance” erben laesst. Kurz gesagt bedeutet das, dass ein Datentype erzeugt werden kann indem man seine Kontruktorfunktion aufruft. Sehen wir uns im Folgenden einmal an, wie das im Detail passiert, wenn man es in Icinga anwendet:

// Definition of constructor function
var EventListener = function (icinga) {
 this.icinga = icinga;
 this.handlers = [];
};

// Adding an "Event Handler" to the new function EventListener
EventListener.prototype.on = function(evt, cond, fn, scope) {
 if (typeof cond === 'function') {
 scope = fn;
 fn = cond;
 cond = 'body';
 }
 this.icinga.logger.debug('on: ' evt '(' cond ')');
 this.handlers.push({ evt: evt, cond: cond, fn: fn, scope: scope });
};

Codeanalyse: Was bedeuten die jeweiligen Bestandteile?

Die Konsturktorfunktion

Um Objekte nicht vollkommen neu definieren zu müssen, wenn sie die gleiche Struktur haben, lässt sich ein Konstruktor verwenden. Ein Konstruktor ist nichts anders als eine JavaScript Funktion die durch den Operator new aufgerufen wird. Diese Funktion definiert die Eigenschaften unseres Objektes indem sie ihm sich selbst (this) als Objekt zuweist und ihre vordefinierten Werte übergibt.

EventListener.prototype.on

Die Eigenschaft “on” ist nicht direkt an das Objekt EventListener angehanegt, sondern man kann auf sie zugreifen, als ob sie eine seiner Eigenschaften waere. Eben dies hängt mit dem Prototyping Mechanismus zusammen, auf dem alle Vererbungsprinzipien von JavaScript aufbauen. In JavaScript ist der Prototype eines Objektes sozusagen eine Art Link zu einem weiteren Objekt. Der der “prototypal inheritance” unterliegende Mechanismus ist ziemlich einfach: wenn sich eine Eigenschaft nicht in einem Objekt selbst findet, dann wird sie in dessen Prototyp gesucht. Der Prototype eines Objektes kann wiederum seinen eigenen Prototyp haben. In diesem Fall entwickelt sich die Suche nach einer Eigenschaft eines Objektes entlang der Kette der Prototypen, bis man nicht beim Objekt Object ankommt. Das Objekt Object ist der prototyp aller Objekte.

Mehrere Inheritance Ebenen

var ApplicationState = function (icinga) {
 Icinga.EventListener.call(this, icinga);
 this.on('rendered', this.onRendered, this);
 this.icinga = icinga;
};

ApplicationState.prototype = new Icinga.EventListener();

Wie im Beispiel ersichtlich, wird auch in Icinga eine Vererbung über mehrere Ebenen hinweg verwendet. Das geschieht insbesondere (wie im obigen Beispiel) wenn man ein Objekt erzeugen will, das von einem anderen Konstruktor Funktionen und Eigenschaften erbt: eine ideale Methode um bereits existierende Funktionen wiederzuverwenden.

Nach dieser kurzen Einführung in die objekt-orientierete Skriptsprache JavaScript sollten Sie in der Lage sein das genannte Prinzip in Ihren neuen Funktionen umzusetzen: die Wahl dieses Prinzips zahlt sich insbesondere in komplexen Funktionen aus, kann aber selbstverständlich auch für einfache Funktionen verwendet werden.

 
Valentina Da Rold

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Author

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Leave a Reply

Your email address will not be published. Required fields are marked *

Archive