<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Beiträge von Aleksandar Palic - Mobile USTP MKL</title>
	<atom:link href="https://mobile.fhstp.ac.at/author/dm131523/feed/" rel="self" type="application/rss+xml" />
	<link>https://mobile.fhstp.ac.at/author/dm131523/</link>
	<description>Die &#34;Mobile Forschungsgruppe&#34; der USTP, sie  sammelt hier alles zu den Themen Design, UX und Entwicklung mobiler Applikationen</description>
	<lastBuildDate>Sun, 12 Oct 2014 17:34:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://mobile.fhstp.ac.at/wp-content/uploads/2025/03/icon-120x120.webp</url>
	<title>Beiträge von Aleksandar Palic - Mobile USTP MKL</title>
	<link>https://mobile.fhstp.ac.at/author/dm131523/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Gatherer: der erst Test</title>
		<link>https://mobile.fhstp.ac.at/tests/gatherer-der-erst-test/</link>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Mon, 13 Oct 2014 08:47:01 +0000</pubDate>
				<category><![CDATA[Tests]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[Gatherer]]></category>
		<category><![CDATA[Test]]></category>
		<category><![CDATA[Usability]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4653</guid>

					<description><![CDATA[<p>Seit dem letzten Semester ist viel Zeit vergangen. Aus Sommer wurde Herbst und aus Kiwano wurde Gatherer. Gatherer soll ein Name sein, der auch zum Produkt passt. “gatherer” kommt aus dem Englischen und bedeutet Sammler und “to gather” bedeutet sammeln. Genau das, soll Gatherer auch tun. Menschen auf einfache und effektive Art zusammen bringen. Aufgrund <a class="read-more" href="https://mobile.fhstp.ac.at/tests/gatherer-der-erst-test/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/tests/gatherer-der-erst-test/">Gatherer: der erst Test</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Seit dem letzten Semester ist viel Zeit vergangen. Aus Sommer wurde Herbst und aus Kiwano wurde Gatherer. Gatherer soll ein Name sein, der auch zum Produkt passt. “gatherer” kommt aus dem Englischen und bedeutet Sammler und “to gather” bedeutet sammeln. Genau das, soll Gatherer auch tun. Menschen auf einfache und effektive Art zusammen bringen. Aufgrund des neuen Namens muss ein komplettes Rebranding vorgenommen werden. Dabei wollten wir gleich auch das bisherige User Interface überarbeiten.</p>
<p><span id="more-4653"></span></p>
<p>Am 8. Oktober 2014 haben wir daher mit acht Studienkollegen einen kurzen Usability-Test durchgeführt, um unseren iOS Prototyp zu testen. Dieser umfasste zu diesem Zeitpunkt neun Screens, die einen Event-Erstellungsprozess abbilden.</p>
<p>Der Test hat viele Erkenntnisse zu Tage gebracht. Einerseits wurden einige Bugs gefunden. Beispielsweise ist die App an manchen Stellen abgestürzt. Das was uns aber besonders wichtig war, waren Usability-, UX- oder Verständnis-Probleme.</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8200.jpg"><img fetchpriority="high" decoding="async" class="aligncenter size-medium wp-image-4658" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8200-300x225.jpg" alt="Gatherer Usability Test" width="300" height="225" /></a></p>
<p><b>Probleme</b></p>
<p><b>Desiree Zottl Problem</b><br />
Nach dem Login, kamen die User auf den Start-Screen, welcher zu diesem Zeitpunkt nicht sehr viel zeigt, bis auf eine Box mit dem User-Profil und einem Button. Vier von acht Probanden, haben sich hier sehr gewundert, dass sie Desiree Zottl sind.</p>
<p><b>Start-Screen leitet auf keine Aktion hin</b><br />
Auf dem Start-Screen waren viele User ein wenig verloren. Ohne den Hinweis, dass sie bitte jetzt ein neues Event anlegen sollen, hätte kaum jemand den grünen Button gefunden.</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8204.png"><img decoding="async" class="aligncenter wp-image-4655 size-medium" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8204-200x300.png" alt="Gatherer - Startscreen" width="200" height="300" /></a></p>
<p><b>Durch Tastatur wichtige Funktion abgeschnitten</b><br />
Beim Lösen mancher Aufgaben hatten die Probanden Probleme wichtige Funktionen zu erwischen, da sie durch die Tastatur oder Suchergebnisse abgeschnitten oder nicht erreichbar waren.</p>
<p><b>Switch unklar</b><br />
Beim Hinzufügen eines Termins zu einem Event kann mit einem Switch zwischen ganztägigen und zeitabhängigen Terminen gewechselt werden. Hier war für einige Probanden unklar, ob der Switch gerade aktiv ist oder nicht.</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8207.png"><img decoding="async" class="aligncenter wp-image-4656 size-medium" title="Gatherer - WANN" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/10/IMG_8207-200x300.png" alt="Gatherer - WANN" width="200" height="300" /></a></p>
<p><b>Buttons teilweise zu klein</b><br />
Einige der Buttons sind zu klein und mussten von den Testperson oft mehrmals gedrückt werden, bevor die Funktion ausgeführt wurde. Dies hat natürlich Verwirrung gestiftet, weil die Testpersonen den Eindruck hatten, dass etwas nicht funktioniert hat.</p>
<p><b>Pflichtfelder hervorheben</b><br />
In einigen Fällen war es für die Probanden unklar, welche Felder ausgefüllt werden müssen und welche nicht. Es ist auch nicht eindeutig, ab wann ein Event ausreichend ausgefüllt ist, um es speichern zu können.</p>
<p><b>Viele Schritte</b><br />
Einige Probanden haben angemerkt, dass es eventuell mühsam ist so viele Schritten durchlaufen zu müssen, wenn man die App oft nützt.</p>
<p><b>Zum Ausfüllen Extra-Klick notwendig</b><br />
Bei den meisten Screens muss zuerst ein Plus-Button gedrückt werden, bevor die Felder ausgefüllt werden können. Ein Proband hat angemerkt, dass das eigentlich nicht notwendig ist und Zeit verbraucht.</p>
<p><b>Verwirrende Navigation bei Zusammenfassung</b><br />
Tippt man von der Zusammenfassung auf einen der Bereiche, springt man quasi wieder zurück und muss dann alle folgenden Schritte erneut durchlaufen. Das hat bei einigen Probanden für Verwirrung gesorgt.</p>
<p><b>Lösungen</b></p>
<p><b>Start-Screen</b><br />
Da der Start-Screen beim ersten Aufruf sehr leer ist soll er in Zukunft von Anfang an mehr dazu einladen neue Events anzulegen. Auch wollen wir eventuell auf das Anlagen eines Profils für Gatherer verzichten.</p>
<p><b>Wo zu Was</b><br />
Um die Anzahl der Schritte bis zum Beenden des Erstellungsprozesses zu reduzieren und Events zu vereinfachen wird der “Wo”-Screen wegfallen und als einfaches Textfeld in den “Was”-Screen wandern.</p>
<p><b>Unklarheiten aufräumen</b><br />
Einige Dinge, waren nicht zu 100% klar bei den Usern, die wollen wir in nächster Zeit versuchen auszuräumen.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/tests/gatherer-der-erst-test/">Gatherer: der erst Test</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>codefront.io</title>
		<link>https://mobile.fhstp.ac.at/allgemein/codefront-io/</link>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Wed, 28 May 2014 11:29:50 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[codefront]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Konferenz]]></category>
		<category><![CDATA[Linz]]></category>
		<category><![CDATA[Sass]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4492</guid>

					<description><![CDATA[<p>Acht Studierende der Masterklasse Mobiles Internet des Studiengangs Digitale Medientechnologien besuchten gemeinsam mit Grischa Schmiedl und Kerstin Blumenstein am 10. Mai 2014 die Front-End Developement Konferenz codefront.io. In der nicht weit von St. Pölten entfernten Johannes Kepler Universität in Linz fanden den ganzen Tag parallel in vier Hörsälen Vorträge zu verschiedensten Themen statt. Die Themen der <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/codefront-io/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/codefront-io/">codefront.io</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Acht Studierende der Masterklasse Mobiles Internet des Studiengangs Digitale Medientechnologien besuchten gemeinsam mit Grischa Schmiedl und Kerstin Blumenstein am 10. Mai 2014 die Front-End Developement Konferenz codefront.io. In der nicht weit von St. Pölten entfernten Johannes Kepler Universität in Linz fanden den ganzen Tag parallel in vier Hörsälen Vorträge zu verschiedensten Themen statt.</p>
<p><span id="more-4492"></span></p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10312600_793285870695973_4846584541707797059_n.jpg"><img loading="lazy" decoding="async" class="aligncenter wp-image-4495 size-medium" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10312600_793285870695973_4846584541707797059_n-300x225.jpg" alt="10312600_793285870695973_4846584541707797059_n" width="300" height="225" /></a></p>
<p>Die Themen der Konferenz waren sehr vielfältig. Das Spektrum reichte von Entwickler-Themen wie Angular JS und weiteren JavaScript Vorträgen über Responsive Web Design und SASS bis hin zu User Interface Design und Daten Visualisierung. Dadurch konnte sich jede/r die interessantesten Themen heraussuchen.</p>
<p>Einer der spannendsten Vorträge war der des Gründers des bekannten Smashing Magazine, Vitaly Friedman (Twitter: @smashingmag), über Responsive Web Design. Der Talk mit dem Titel &#8220;Real-Life Responsive Web Design&#8221; deckte sehr viele wichtige Aspekte ab, die heutzutage für die Erstellung von flexiblen Web-Projekten wichtig sind.</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10253922_793285817362645_2829413033242432445_n.jpg"><img loading="lazy" decoding="async" class="aligncenter wp-image-4494 size-medium" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10253922_793285817362645_2829413033242432445_n-300x225.jpg" alt="10253922_793285817362645_2829413033242432445_n" width="300" height="225" /></a></p>
<p>Auch sehr spannend war der Vortrag von Monica Dinculescu (Twitter: @notwaldorf). Sie arbeitet bei Google an der Entwicklung des eigenen Browsers Chrome und sprach über sechs Tricks, wie Google seine Chrome User glücklich macht. Damit gab sie einen spannenden Einblick hinter die Kulissen der Arbeit von Google.</p>
<p>Die Designer/innen und Entwickler/innen der Masterklasse Mobiles Internet konnten sehr viel aus den verschiedenen Vorträgen mitnehmen und werden auch bei der nächsten Konferenz in Österreich wieder dabei sein.</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10178088_565304850255008_7360456056746908306_n.jpg"><img loading="lazy" decoding="async" class="aligncenter wp-image-4493 size-medium" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/05/10178088_565304850255008_7360456056746908306_n-300x225.jpg" alt="10178088_565304850255008_7360456056746908306_n" width="300" height="225" /></a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/codefront-io/">codefront.io</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Job Queues mit Redis</title>
		<link>https://mobile.fhstp.ac.at/development/job-queues-mit-redis/</link>
					<comments>https://mobile.fhstp.ac.at/development/job-queues-mit-redis/#comments</comments>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Sun, 11 May 2014 19:49:54 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[asynchronous]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[queue]]></category>
		<category><![CDATA[redis]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4463</guid>

					<description><![CDATA[<p>Wer hat schon einmal ein einfaches E-Mail aus seiner Web-Applikation heraus verschickt? Wahrscheinlich jeder. Denkt beispielsweise an das klassische Registrierungsmail mit dem Bestätigungstoken. Der User Registriert sich und bekommt ein E-Mail in dem ein spezieller Token ist mit dem er sich freischalten kann. Perfekt. Doch was genau kann man hier falsch machen und wieso sollte <a class="read-more" href="https://mobile.fhstp.ac.at/development/job-queues-mit-redis/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/job-queues-mit-redis/">Job Queues mit Redis</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Wer hat schon einmal ein einfaches E-Mail aus seiner Web-Applikation heraus verschickt? Wahrscheinlich jeder. Denkt beispielsweise an das klassische Registrierungsmail mit dem Bestätigungstoken. Der User Registriert sich und bekommt ein E-Mail in dem ein spezieller Token ist mit dem er sich freischalten kann. Perfekt. Doch was genau kann man hier falsch machen und wieso sollte man sich um Job Queues Gedanken machen?<br />
<span id="more-4463"></span></p>
<h2>Queues</h2>
<p>Nun, viele Entwickler implementieren diesen E-Mail verschick-Prozess direkt in den ersten Response. Was folgt? Der Response dauert länger. Das Script führt nicht nur die eigenen Operationen durch, rendert das Template, sondern muss zusätzlich eine SMTP Verbindung öffnen und ein E-Mail verschicken. Das kann mit unter zu sehr nervigen Reaktionen bei den Usern führen, vor allem wenn es um keine banale Registrierung sondern eine komplexere Firmen Web-Applikation handelt die beispielsweise E-Mails verschickt wenn man zu einem bestimmten Projekt Issue einen Kommentar abgibt.<br />
Der Schlüssel hier sind Job Queues. Einfach gesagt lagert man spezielle Funktionalitäten absichtlich aus um Responses weiterhin schnell abwickeln zu lassen. Man &#8220;ent-blockt&#8221; sozusagen das System bzw. den Response und Redis hilft uns hier sehr gut weiter.</p>
<h2>Redis</h2>
<p>Redis selbst ist ein einfacher Key-Value Store und betitelt sich selbst oft als &#8220;data structure server&#8221; da in den einzelnen Value Feldern nicht nur gewöhnliche Zeichen gespeichert werden können, sondern auch komplexe hashes, listen oder sortierte sets. Die zwei größten Vorteile von Redis sind 1. die Schnelligkeit (auf Grund des einfachen Aufbaus) und 2. das Event Handling. Man kann beispielsweise auf einen gewissen Kanal horchen und wird informiert falls neue Daten reinkommen und kann dementsprechend reagieren.</p>
<h2>Node.js</h2>
<p>Node ist ein großer Haufen toller Sachen, aber grob Zusammengefasst ist Node ein Wrapper um die V8 von Google (JavaScript Interpreter) mit zusätzlichen Libraries (z.B. FileSystem, HTTP uvm.) und bringt somit JavaScript auf die Server-Seite. Es gibt bereits viele gute Redis Packages die uns die Verbindung zum Redis Server erleichtern, sucht man jedoch etwas genauer findet man sogar schon Libraries die uns genau unseren Job abnehmen. Eine dieser Libraries ist <a href="https://github.com/learnboost/kue">Kue</a>.</p>
<h2>Dig in!</h2>
<p>Ich werde nicht darauf eingehen wie man ein Node Projekt startet oder <a href="https://github.com/learnboost/kue">Kue</a> als Dependency integriert, denn das kann man sich auf den jeweiligen Repositories gut dokumentiert ansehen. Wie erstellt man nun asynchrone jobs?<br />
Man bindet zuerst die notwendigen Libraries ein:</p>
<pre class="brush: jscript; title: ; notranslate">
// email job module - job-email.js
var kue = require('kue')
  , jobs = kue.createQueue();
</pre>
<p>Danach erstellt man die Funktion die uns einen Job generiert:</p>
<pre class="brush: jscript; title: ; notranslate">
/**
 * email =&gt; {
 *   to: &quot;foo@email.com&quot;,
 *   from: &quot;bar@email.com&quot;,
 *   subject: &quot;Some Subject&quot;,
 *   message: &quot;Hello World!&quot;
 * }
 */
function newEmailJob (email) {
  var job = jobs.create('new email', email);
  job
    .on('complete', function () {
      console.log('Email', job.id, 'with subject', job.data.subject, 'is done!');
    })
    .on('failed', function () {
      console.log('Email', job.id, 'with subject', job.data.subject, 'has failed!');
    });
  job.save();
}
</pre>
<p>Zuerst wird die Funktions `jobs.create()` verwendet um einen Job zu generieren. Dabei werden Typ des Jobs und ein Objekt mit den Daten übergeben. Als nächstes werden über die `jobs.on()` Funktion 2 Events mit Callbacks gespeichert, damit die Library weiß was sie Ausführen soll falls der Job fehlerfrei abgearbeitet wurde oder ein Fehler eingetreten ist.</p>
<p>Als nächstes rufen wir die Funktion `jobs.process()` auf und übergeben das eigentliche Callback zum bearbeiten des Jobs bzw. verschicken des E-Mails.</p>
<pre class="brush: jscript; title: ; notranslate">
jobs.process('new email', 20, function (job, done) {
 // email versenden ...
 // email objekt liegt in job.data ...
 // ...

 done &amp;&amp; done();
});
</pre>
<p>Normalerweise wird von Kue nur ein Job auf einmal ausgeführt, das ist bei großen Jobs vielleicht auch sinnvoll, doch beim E-Mails verschicken können wir hier die maximale Anzahl an zu-bearbeitenden Jobs z.B. auf 20 setzen. Das heißt hier werden gleichzeitig 20 Queue Einträge vom Typ E-Mail aus Redis auf einmal rausgenommen und bearbeitet. Node.js ist hier ganz gut darin.</p>
<p>Zu guter letzt müssen wir unsere Funktion nur mehr aufrufen:</p>
<pre class="brush: jscript; title: ; notranslate">
newEmailJob({ to: &quot;...&quot;, from: &quot;...&quot;, ... });
</pre>
<p>Unter der Haube wird dabei das E-Mail Objekt in Redis gespeichert, zeitgleich hört `jobs.process()` aber auch auf Änderungen in der E-Mail Collection und führt daraufhin für jeden neuen Eintrag die selbst-definierte Callback Funktion aus (nämlich das E-Mail versenden). Sobald dies geschehen ist wird der Eintrag auch wieder aus Redis rausgelöscht. Wer genaueres wissen möchte und seine Queue beispielsweise in einer anderen Sprache implementieren möchte kann sich hier wieder passende Libraries suchen oder sich direkt die <a href="http://redis.io/topics/pubsub">PUB/SUB Methoden für Redis</a> ansehen.</p>
<h2>Summary</h2>
<p>Queues können für allerlei Abarbeitungen verwendet werden um Requests im Web nicht zu blockieren. Redis ist genau hier ein sehr gutes Tool dafür. Läuft man beispielsweise auch noch auf PHP und hat ein blockierendes I/O System sind Queues umso wichtiger.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/job-queues-mit-redis/">Job Queues mit Redis</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/development/job-queues-mit-redis/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Teil 1: Sails.js Einführung in das Backend MVC Framework</title>
		<link>https://mobile.fhstp.ac.at/development/teil-1-sails-js-einfuehrung-das-backend-mvc-framework/</link>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Thu, 23 Jan 2014 18:48:17 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Sails.js]]></category>
		<category><![CDATA[Socket.io]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=3891</guid>

					<description><![CDATA[<p>Serverseitiges JavaScript ist seit einer Weile in aller Munde und genau das hat sich Mike McNeill zunutze gemacht um ein full-stack Framework zu erschaffen, welches nun ja, eben &#8220;mehr&#8221; kann und &#8220;weniger&#8221; verlangt. Es basiert auf dem MVC Muster und ist an Ruby on Rails angelehnt. Warum Sails.js jedoch wirklich glänzt und wieso entwickeln von <a class="read-more" href="https://mobile.fhstp.ac.at/development/teil-1-sails-js-einfuehrung-das-backend-mvc-framework/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/teil-1-sails-js-einfuehrung-das-backend-mvc-framework/">Teil 1: Sails.js Einführung in das Backend MVC Framework</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Serverseitiges JavaScript ist seit einer Weile in aller Munde und genau das hat sich Mike McNeill zunutze gemacht um ein full-stack Framework zu erschaffen, welches nun ja, eben &#8220;mehr&#8221; kann und &#8220;weniger&#8221; verlangt. Es basiert auf dem MVC Muster und ist an Ruby on Rails angelehnt. Warum Sails.js jedoch wirklich glänzt und wieso entwickeln von skalierbaren, service orientierten APIs noch nie zuvor einfacher war, soll dieser Artikel beschreiben.</p>
<p><span id="more-3891"></span></p>
<p>Sails.js baut auf dem Express.js Web Framework auf und erweitert dieses um genau die Funktionalitäten wofür es für eine komplexe Backend Applikation zu schlank ist.</p>
<h1>Waterline ORM</h1>
<p>Mike McNeill hat nicht nur Sails entworfen, sondern auch Waterline.js, einen schlanken Datenbank agnostischen O/R Mapper der von Sails direkt verwendet wird. Waterline ist deshalb so praktisch weil es funktioniert, egal welche Datenbank man verwendet. Waterline&#8217;s Data Access Layer funktioniert über sogenannte Adapter, die man pro Datenbanksystem erstellen und konfigurieren kann. Genau genommen gibt es sogar einen vorintegrierten Filesystem Adapter der Models auf dem Filesystem abspeichert. Über GitHub findet man bereits Adapter für die verschiedensten relationalen und objektorientierten Datenbanksysteme wie MySQL oder MongoDB und schlimmstenfalls schreibt man den Adapter einfach selbst.</p>
<pre class="brush: jscript; title: ; notranslate">
// config/adapters.js
module.exports.adapters = {
  'default': 'mysql',

  disk: {
    module: 'sails-disk'
  },

  mysql: {
    module: 'sails-mysql',
    host: 'YOUR_MYSQL_SERVER_HOSTNAME_OR_IP_ADDRESS',
    user: 'YOUR_MYSQL_USER',
    password: 'YOUR_MYSQL_PASSWORD',
    database: 'YOUR_MYSQL_DB'
  }
}
</pre>
<h1>Models and Lifecycle Callbacks</h1>
<p>Models funktionieren in Sails.js genauso wie in jedem anderem MVC Framework. Es wird ein Entity erstellt, welches die Attribute beschreibt. Einziger Unterschied: Das Model ist zwar ein Objekt, die Attributswerte sind jedoch keine nativen Datentypen aus der Scriptsprache sondern Strings und werden dann pro Adapter anders für das Datenbanksystem gemappt. Dadurch ist auch keine zusätzliche Annotation für das ORM notwendig.</p>
<pre class="brush: jscript; title: ; notranslate">
// models/person.js
module.exports = {
  attributes: {
    firstName: 'STRING',
    lastName: 'STRING',
    age: {
      type: 'INTEGER',
      max: 150,
      required: true
    },
    emailAddress: {
      type: 'email', // Email type will get validated by the ORM
      required: true
    }
  },
  beforeCreate: function () {
     // ...
  }
};
</pre>
<p>Models in Sails.js werden außerdem von Waterline validiert, dazu gibt es eine Liste an Typen die man sich in der Sails Dokumentation ansehen kann. Weiters ist es möglich Lifecycle Callbacks zu implementieren, das sind Funktionen die an bestimmten Zeitpunkten automatisch aufgerufen werden und auf die man wie bei Delegates reagieren kann. Typische Callback Funktionen wären:</p>
<pre class="brush: jscript; title: ; notranslate">
- beforeCreate / *fn(values, cb)*
- afterCreate / *fn(newlyInsertedRecord, cb)*
- beforeUpdate / *fn(valuesToUpdate, cb)*
- afterUpdate / *fn(updatedRecord, cb)*
- beforeDestroy / *fn(criteria, cb)*
- afterDestroy / *fn(cb)*
</pre>
<h1>RESTfull JSON API in 5 seconds</h1>
<p>Sails erstellt zu jedem Model eine bereits fertig funktionierende json-basierte REST Api. Das bedeutet dass man sich überhaupt nicht mehr um eine REST Library kümmern muss, oder mühsam alle CRUD Funktionen mit den passenden HTTP Methoden implementieren muss. Die Magie dahinter steckt in den sogenannten Controller Blueprints &#8211; sprich Blaupausen &#8211; die man in der controller.js Konfiguration sehen kann.</p>
<p>Eine nette Einführung in die REST Features von Sails.js und eine Demo der Blueprints findet man hier:<br />
<a href="https://www.youtube.com/watch?v=GK-tFvpIR7c" target="_blank">https://www.youtube.com/watch?v=GK-tFvpIR7c</a></p>
<h1>Blueprints for Actions</h1>
<p>Schaltet man die `action` blueprints ein so erstellt Sails automatisch alle Routen für die entsprechenden Controller actions. Sprich die `sayHi` action vom Controller `Person` würde über `http://localhost:1337/person/sayHi` erreichbar sein. Das ist soweit noch nichts neues, das bieten sogar die meisten Frameworks bereits out-of-the-box an. Zusätzlich erstellen die `action` blueprints aber auch Routen für alle 4 HTTP Methoden (GET, POST, PUT, DELETE) und binden sie an jede Action Methode. Dadurch kann man in der Action bequem auf den Methodentyp abfragen und zusätzlich differenzieren. Zusätzlich bekommt jede Action einen optionalen `id` Parameter.</p>
<pre class="brush: jscript; title: ; notranslate">
GET     /email/send/:id?
POST    /email/send/:id?
PUT     /email/send/:id?
DELETE  /email/send/:id?
</pre>
<h1>Blueprints for REST</h1>
<p>Etwas interessanteres sind beispielsweise die `rest` blueprints. Diese erstellen wie bereits oben angedeutet unter der Haube alle 4 CRUD Methoden mit den dazugehörigen Routen. Das ist in vielen Fällen sehr praktisch und erleichtert einem viel mühsame Arbeit, zumal diese Actions und Routen für jedes Model automatisch generiert werden. Das bedeutet also, dass Sails hier bereits folgende Bindings unternimmt:</p>
<pre class="brush: jscript; title: ; notranslate">
GET      /person           -&gt; PersonController.findAll
GET      /person/:id?      -&gt; PersonController.find
POST     /person           -&gt; PersonController.create
PUT      /person/:id       -&gt; PersonController.update
DELETE   /person/:id       -&gt; PersonController.destroy
</pre>
<h1>Blueprints for Shortcuts</h1>
<p>Die dritte Möglichkeit ist mehr oder weniger eine weitere Beschleunigung und ermöglicht es, falls aktiviert, dass Sails für alle CRUD Methoden GET Routen anlegt und an die Actions bindet. Das bedeutet also, dass man alleinig über die Browserleiste alle 4 CRUD Methoden aufrufen kann. Das ist zwar sehr praktisch fürs Testing, da man keine Forms, Javascript oder sonstige REST Client Plugins braucht um die Methoden aufzurufen, aber Sails unterstreicht hier stark dass es aus Sicherheitsgründen für den Production Bereich deaktiviert werden sollte. Shortcuts würden folgendes ausschließlich über GET möglich machen:</p>
<pre class="brush: jscript; title: ; notranslate">
GET      /person/create?name=&amp;age=      -&gt; PersonController.create
GET      /person/:id/update?name=&amp;age=  -&gt; PersonController.update
GET      /person/delete/:id             -&gt; PersonController.destroy
</pre>
<h1>Socket.io, Boom!</h1>
<p>Sails.js verwendet für alle asynchronen Requests Socket.io und somit eine flexible Library mit vielen Fallbacks. Socket.io wird dabei von Sails.js gewrappt und ist am Client sowie am Server bereits fertig implementiert. Keine Handshakes, keine manuellen Verbindungen vom Client aus, alles out-of-the-box. Es ist also nicht mehr notwendig AJAX calls z.B. per jQuery zu machen, man nimmt einfach die globale `socket` Variable am Client und ruft einfach die Route am Server auf, die die Ressource liefern soll.</p>
<pre class="brush: jscript; title: ; notranslate">
// json von allen personen abrufen
socket.get('/person', function (err, data) {
    // ...
});
</pre>
<h1>Assets love Grunt</h1>
<p>Sails.js nutzt Grunt um einige Tätigkeiten zu automatisieren. Beispielsweise werden über Grunt alle neuen bzw. veränderten Assets vollautomatisch vom internen Assets Ordner in den öffentlich zugänglichen kopiert. Dabei kann man Grunt weiterkonfigurieren und CSS Präprozessoren einbetten, welche sobald sich beispielsweise eine SASS Datei verändert hat, diese direkt parst und in den public Assets Ordner verschiebt. Eine weitere Funktionalität ist die automatische Minifizierung sobald man den Modus auf Production wechselt. Sails.js nimmt dabei alle Assets her, minifiziert sie und linkt sie automatisch zurück ins Layout.</p>
<h1>Multiple Template Engines</h1>
<p>Ein sehr praktisches Feature ist die einfache Änderung von Templating Engines in Sails.js. Man kann entweder bei der Erstellung des Projekts über den `sails new projectname &#8211;template=engine` Befehl oder nachträglich über die Konfiguration die Template Engine definieren. Sails unterstützt dabei eine riesige Anzahl an Engines wie z.B.: underscore, hogan, haml, dust, swig, ejs, toffee, walrus, &amp; whiskers, wobei ejs die standards templating engine ist. Es ist allerdings wichtig zu wissen, dass nach einer Änderung eventuell das Grunt File upzudaten ist, da sonst die Assets nicht richtig kopiert werden und der Server bei jeder Client Datei Änderung neugestartet werden müsste.</p>
<h1>Integrated Async.js</h1>
<p>Um der Callback Hell zu entkommen, welche bei stark event gesteuerten Segmenten in einer Applikation enstehen können, implementiert Sails.js bereits Async.js out-of-the-box. Async.js verfügt über ein paar sehr praktische Methoden um Callbacks parallel oder seriell ausführen zu können. Im Sonderfall kann man sogar Async.js selbst entscheiden lassen, welches Callback zuerst aufgerufen wurde. Ein einfaches Beispiel für eine serielle, statt üblicherweise verschachtelte Abwicklung:</p>
<pre class="brush: jscript; title: ; notranslate">
var gameId = 7;

// normal
Game.find(gameId).done(function (err, game) {
   Reviews.findAllByGameId(game.id).done(function (err, reviews) {
      // &#x5B;object] game
      // &#x5B;object] reviews
   });
});

// with async.js
async.seriel({
  game: Game.find(gameId).done, // callback 1
  reviews: Review.findAllByGameId(gameId).done // callback 2
}, function (err, results) {
  // &#x5B;object] results.game
  // &#x5B;object] results.reviews
});
</pre>
<h1>Fazit</h1>
<p>Sails.js ist meiner Meinung `das` Beispiel schlechthin wie viel Potential in Node.js steckt. Zudem ist Sails.js gerade noch in Kinderschuhen und soll mit Version 0.10 nun auch Datenbank Relationen mit HAS_ONE, BELONGS_TO etc. mappen können. Die integrierten Blueprints für eine API sind unvorstellbar mächtig und die Integration von Socket.io macht das ganze zum Kinderspiel. Ich lege jedem Web Developer Sails.js ans Herz, der sich nach jahrelangen Krämpfen von PHP trennen möchte und ein Projekt sucht um sich mit Node anzufreunden. Das Entwickeln mit JavaScript auf sowohl Client als auch Serverseite mit den teilweise gleichen globalen Objekten ist sehr bequem. Wer PHP für seine Applikation weiterverwenden will und Sails.js als einfache API für seine Projekte nutzen möchte ist auf jeden Fall auch im richtigen Boot, denn einfacher geht es kaum.</p>
<p>Stay tuned für Teil 2 &#8211; die Kombination von Client und Serverseite mit Backbone und Sails von Desireé Zottl.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/teil-1-sails-js-einfuehrung-das-backend-mvc-framework/">Teil 1: Sails.js Einführung in das Backend MVC Framework</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Unwind Segues To The Rescue</title>
		<link>https://mobile.fhstp.ac.at/development/unwind-segues-rescue/</link>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Fri, 17 Jan 2014 09:52:04 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Native App]]></category>
		<category><![CDATA[Segues]]></category>
		<category><![CDATA[Unwind Segues]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=3756</guid>

					<description><![CDATA[<p>Beschäftigt man sich als iOS Anfänger etwas länger mit dem Storyboard vom Xcode so stößt man schon bald auf einige Fragen. Wer schon einmal versucht hat einen Back Button programmatisch zu erstellen (sprich ohne NavigationController der einem den Button und die Animation abnimmt) musste bereits selbst herausfinden wie er die Animation zurück bewerkstelligt. Eine sehr <a class="read-more" href="https://mobile.fhstp.ac.at/development/unwind-segues-rescue/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/unwind-segues-rescue/">Unwind Segues To The Rescue</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Beschäftigt man sich als iOS Anfänger etwas länger mit dem Storyboard vom Xcode so stößt man schon bald auf einige Fragen. Wer schon einmal versucht hat einen Back Button programmatisch zu erstellen (sprich ohne NavigationController der einem den Button und die Animation abnimmt) musste bereits selbst herausfinden wie er die Animation zurück bewerkstelligt. Eine sehr bequeme Lösung ist hier der Einsatz von sogenannten &#8220;Unwind&#8221; Segues.</p>
<p><span id="more-3756"></span></p>
<p>Unwind Segues ermöglichen es zu vorherigen ViewControllern zurückzuwechseln. Ein entscheidender Vorteil ist zudem, dass nicht nur auf den direkten ViewController davor sondern irgendeinen vorherigen zurück gewechselt werden kann. Xcode ermittelt dabei die Animationsart die für das Hinkommen zum Controller verwendet wurde und nimmt davon die umgekehrte Animation. Ich habe für diesen Artikel bereits 4 verschiedene ViewController vorbereitet und sie mit einer modal-Segue miteinander verbunden.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3762" alt="Unwind Segues 1" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/01/Bildschirmfoto-2014-01-17-um-10.02.40.png" width="620" height="243" /></p>
<p>Einzige Vorraussetzung ist, dass der Ziel-ViewController zu dem man zurück möchte eine spezielle Action definiert welche eine Unwind Segue als Parameter bekommt. Das sieht dann beispielsweise so aus:</p>
<pre class="brush: cpp; title: ; notranslate">
@implementation ViewController

- (void)viewDidLoad {
  &#x5B;super viewDidLoad]
  // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
  &#x5B;super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (IBAction)unwindToWhiteViewController:(UIStoryboardSegue *)segue {}

@end
</pre>
<p>Das tolle an dieser Funktion ist, dass sie ähnlich funktioniert wie `prepareForSegue`. Das bedeutet, dass in der Funktion alles ausgeführt wird bevor die eigentliche Segue Animation gestartet wird. Man könnte hier also sehr wohl über die Segue den Source ViewController ermitteln und abfragen ob es überhaupt der erwünschte ist (falls mehrere View Controller zurück zum ersten führen). Weiters hat man hier eine Schnittstelle und kann über den Source ViewController die Properties ermitteln falls Daten übergeben werden sollen.</p>
<pre class="brush: cpp; title: ; notranslate">
- (IBAction)unwindToWhiteViewController:(UIStoryboardSegue *)segue {

  UIViewController* sourceViewController = unwindSegue.sourceViewController;

  if (&#x5B;sourceViewController isKindOfClass:&#x5B;OrangeViewController class]])
  {
    NSLog(@&quot;I'm coming from Orange!&quot;);
  }
  else if (&#x5B;sourceViewController isKindOfClass:&#x5B;GreenViewController class]])
  {
    NSLog(@&quot;I'm coming from Green!&quot;);
  }

}
</pre>
<p>Hat man die Funktion bereits implementiert, muss man nur noch den Button auf das Exit Symbol vom Quell ViewController ziehen. In diesem Fall möchten wir vom Grünen ViewController zurück zum Weißen.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3777" alt="Unwind Segues 2" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/01/segue2.png" width="620" height="233" /></p>
<p>Danach sollte ein kleines Popup erscheinen und die alle definierten Unwind Actions anzeigen. Wenn man alles richtig gemacht hat sollte hier also die Unwind Segue aufscheinen.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3782" alt="Unwind Segues 3" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/01/segue3.png" width="495" height="134" /></p>
<p>Das wars auch schon! Zusätzlich kann man die Segue auch im Document Outline markieren und ihr im Attributes Inspector einen Identifier geben. Das hat den Vorteil, dass man die Segue danach auch progammatisch triggern kann wenn man möchte.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/unwind-segues-rescue/">Unwind Segues To The Rescue</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Business Applications mit Node.js und Express</title>
		<link>https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/</link>
					<comments>https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/#comments</comments>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Wed, 06 Nov 2013 20:15:06 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Express.js]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=3358</guid>

					<description><![CDATA[<p>Hat man in Node.js eine größere Web Applikation in Planung, wird man sich früher oder später um die Applikationsarchitektur kümmern müssen. Für Node gibt es hierfür das Express Framework, welches dem Entwickler beispielsweise den Umgang mit Requests/Responses oder dem Routing erleichtert, jedoch ist die Standardarchitektur einer Express App in manchen Fällen etwas zu schlank. Dieser <a class="read-more" href="https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/">Business Applications mit Node.js und Express</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Hat man in Node.js eine größere Web Applikation in Planung, wird man sich früher oder später um die Applikationsarchitektur kümmern müssen. Für Node gibt es hierfür das Express Framework, welches dem Entwickler beispielsweise den Umgang mit Requests/Responses oder dem Routing erleichtert, jedoch ist die Standardarchitektur einer Express App in manchen Fällen etwas zu schlank. Dieser Artikel zeigt, wie man die von Express.js generierte Standardstruktur sinnvoll erweitern und die Applikation durch Komponenten wie Controller oder Models ergänzen kann.</p>
<p><span id="more-3358"></span></p>
<h3>Installieren von Express</h3>
<p>Installiert man Express.js als globales Modul über `npm install -g express` kann man mit `express express-skeleton` ein Skeleton &#8211; sprich eine automatische Ordnerstruktur für die Applikation erstellen. Diese sieht wie folgt aus:</p>
<pre class="brush: jscript; title: ; notranslate">
   - app.js
   - package.json
   + public
        + images
        + javascripts
        + stylesheets
             - style.css
   + routes
        - index.js
        - user.js
   + views
        - index.jade
        - layout.jade
</pre>
<p>Man erkennt schnell, dass bis zur Implementierung des MVC Musters noch ein wenig Arbeit erforderlich ist. Express vermischt hier das Routing direkt mit dem Controller Pattern, in dem es die Routes direkt in `app.js` anführt und dort auf die reinen Controller-Actions verweist.</p>
<pre class="brush: jscript; title: ; notranslate">
// app.js
app.get('/', routes.index);

// routes/index.js
exports.index = function(req, res) {
   res.render('index', { title: 'Express' });
};
</pre>
<h3>Applikationskonfiguration</h3>
<p>Um die Applikation etwas flexibler zu machen, werden wir vorerst in Rootebene des Projekts einen neuen `config` Ordner erstellen und eine Datei namens `app.js` anlegen. Diese Datei wird unsere allgemeine Applikationskonfiguration beinhalten. Klassisch sind Sprache und ein CSRF Token falls man das Session Modul von Express verwendet. Das Modul besteht aus einem einfachen Objekt:</p>
<pre class="brush: jscript; title: ; notranslate">
// config/app.js
module.exports = {
   language: 'en',
   session: {
      secret: 'mySessionSecret123'
   }
   // other configuration ...
}
</pre>
<p>Importiert wird die Konfiguration einfach per:</p>
<pre class="brush: jscript; title: ; notranslate">
// app.js
var config = require('./config/app.js');
</pre>
<h3>Controller und Routing</h3>
<p>Die erste sinnvolle Erweiterung wäre es die Routes im `routes` Verzeichnis in Controller umzuwandeln, welche einfach dem JavaScript Konstruktor und Modul Pattern folgen. Man könnte den Controller auch als Objekt implementieren, der entscheidende Vorteil einer Funktion ist jedoch die Kapselung und die Möglichkeit andere Objekte über die Funktionsparameter zu injizieren. Im ersten Schritt benennen wir also das `routes` Verzeichnis in `controllers` um und bearbeiten die `index.js` wie folgt:</p>
<pre class="brush: jscript; title: ; notranslate">
// controllers/index.js
module.exports = function () {
   // possible attributes or requires ...

   return {
      rootAction: function (req, res) {
         res.render('index', { title: 'Express Advanced' });
      }
   };
}
</pre>
<p>Der erste signifikante Vorteil hier ist, dass Attribute definiert werden können, die nur dem Controller zugeordnet sind. Hier können Konfigurationen oder beispielsweise ORM EntitiyManager geladen und initialisiert werden. Dem Controller können außerdem, wie bereits beschrieben, per Dependency Injection Objekte direkt in die (jetzt gerade leeren) Funktionsparameter injiziert werden.</p>
<p>Nun wäre es an der Reihe die Routendefinitionen aus der `app.js` in eine Routen-Konfigurationsdatei outzusourcen. Wir erstellen also in unserem `config` Ordner eine `routes.js` Datei. Diese Datei beinhaltet nun alle unsere Routes, welche auf unsere Controller verweisen:</p>
<pre class="brush: jscript; title: ; notranslate">
// config/routes.js
module.exports = function () {
   // get required controllers
   var controller = {
      'index': require('../controllers/index.js')()
   };

   // define routes
   app.get('/', controller.index.rootAction);
   app.get('/blog', controller.index.blogAction);
   app.get('/login', controller.index.loginAction);
   app.post('/login', controller.index.checkLoginAction)
};
</pre>
<p>In der `app.js` importiert man die Konfigurationsdatei mit den Routes einfach mit:</p>
<pre class="brush: jscript; title: ; notranslate">
// app.js
require('./config/routes.js')();
</pre>
<h3>Models und Entities</h3>
<p>Applikationslogik landet überlicherweise im Business- bzw. Domänenlayer und nicht im Controller selbst. Aus diesem Grund erstellen wir einen `models` Ordner in unserer Rootebene des Projekts. Darin erstellen wir direkt ein Unterverzeichnis namens `entities`, welches unsere Entitäten beinhalten wird. Solche Entitäten bilden unsere Domänenobjekte bzw. Datenbanktabellen in &#8220;Objektform&#8221; ab. Alle anderen Implementierungen der Logik landen direkt im `models` Verzeichnis. Ein solches Domänenobjekt könnte folgendermaßen aussehen:</p>
<pre class="brush: jscript; title: ; notranslate">
// models/entities/user.js
module.exports = function (/* possible EM or DAO injection */) {
   // EM or DAO ...

   return function () {
      // private attributes
      var _id = null,
          _username = null,
          _password = null;

      // constructor
      (function construct() {
          // ...
      }());

      // private methods
      function privateMethod () {}

      // return public object with public functions
      return {
         // typical getter for all attributes
         getPropertyObject: function () {
            return {
               id: _id,
               username: _username,
               password: _password
            };
         },
         setPropertyObject: function (propertyObject) {
            _id = propertyObject.id;
            _username = propertyObject.username;
            _password = propertyObject.password;
         },
         loadUser: function (username, password) {
            // use DAO with ORM or implement manually
         },
         persistUser: function () {
            // use DAO with ORM or implement manually
         }
      };
   };
}
</pre>
<p>Wie man am obigen Code erkennen kann, ist es ganz einfach ein Domänenobjekt/Entity zu erstellen. Auffallend ist hier, dass das Model extra noch einmal in einer Funktion gewrappt ist, welche dann zurückgegeben wird. Vorteil dieser Implementierung ist ein eigener Scope für Entity Managers oder Data Access Objects, da diese normalerweise nicht als Attribute des Models abgebildet werden sollten. Objekte von diesem Model können dann ganz bequem aus einem Controller erstellt werden:</p>
<pre class="brush: jscript; title: ; notranslate">
// controllers/index.js
module.exports = function (/* EM or DAO */) {
   // require model
   var User = require('../models/entities/user.js')(/* EM or DAO */);

   return {
      // ...
      checkLoginAction: function (req, res) {
         var usernameGiven = req.body.username,
             passwordGiven = req.body.password;

         var user = new User();
         user.loadUser(usernameGiven, passwordGiven);
      }
   };
};
</pre>
<h3>Views mit Underscore</h3>
<p>Wer mit Jade als Templateengine nicht zufrieden ist, kann auch jede andere verwenden, die mit Express kompatibel ist. Für mich hat die Templateengine von Underscore gewonnen, da ich normale HTML Dateien als Views verwenden kann und dort meine minimale Logik integrieren kann. Wer ebenfalls Underscore verwenden will, muss seine `package.json` Datei um zwei Module erweitern, 1. Underscore und 2. Consolidate (wird benötigt um Underscore in Express zu integrieren):</p>
<pre class="brush: jscript; title: ; notranslate">
// package.json
{
   &quot;name&quot;: &quot;myApp&quot;,
   &quot;version&quot;: &quot;0.0.1&quot;,
   &quot;private&quot;: true,
   &quot;scripts&quot;: {
      &quot;start&quot;: &quot;node app.js&quot;
   },
   &quot;dependencies&quot;: {
      &quot;express&quot;: &quot;3.4.0&quot;,
      &quot;underscore&quot;: &quot;*&quot;,
      &quot;consolidate&quot;: &quot;*&quot;
   }
}
</pre>
<p>Danach sollte man nochmal `npm install` ausführen, um die Node Module, die noch fehlen, nachzuinstallieren (in diesem Fall Underscore und Consolidate). In der `app.js` muss man danach lediglich noch die View Engine updaten:</p>
<pre class="brush: jscript; title: ; notranslate">
// app.js
var cons = require('consolidate');

app.engine('html', cons.underscore);
app.set('view engine', 'html');
</pre>
<h3>Fazit</h3>
<p>Express liefert ein sehr schlankes und umfangreiches Framework für Web Applikationen. Man kann mit Leichtigkeit Requests und Reponses bearbeiten, Routen definieren, Sessions und Cookies verwalten und vieles mehr. Durch die Flexibilität des Frameworks ist es auch sehr einfach zu erweitern. Express zwingt den Entwickler nicht sich an die Struktur zu halten, sondern erlaubt die Funktionen in eigenen, neuen und erweiterten Architekturen einzusetzen.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/">Business Applications mit Node.js und Express</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/development/business-applications-mit-node-js-und-express/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Ghost &#8211; Open Source Blogging leicht gemacht</title>
		<link>https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/</link>
					<comments>https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/#comments</comments>
		
		<dc:creator><![CDATA[Aleksandar Palic]]></dc:creator>
		<pubDate>Fri, 18 Oct 2013 09:19:28 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Blogging]]></category>
		<category><![CDATA[mobile web]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=3133</guid>

					<description><![CDATA[<p>Diesen Montag startete das von vielen sehnlichst erwartete Ghost auf http://ghost.org/. Doch was genau ist Ghost und warum ist es nicht für jeden geeignet? Ghost ist eine mobile-freundliche Open Source Blogging Platform und spezialisiert sich laut Homepage einzig auf &#8220;Publishing&#8221;. Es ist auf Grund des offenen Quellcodes von jedem sehr einfach anzupassen und zu erweitern, sei <a class="read-more" href="https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/">Ghost &#8211; Open Source Blogging leicht gemacht</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Diesen Montag startete das von vielen sehnlichst erwartete Ghost auf <a title="Ghost" href="http://ghost.org/">http://ghost.org/</a>. Doch was genau ist Ghost und warum ist es nicht für jeden geeignet?</p>
<p>Ghost ist eine mobile-freundliche Open Source Blogging Platform und spezialisiert sich laut Homepage einzig auf &#8220;Publishing&#8221;. Es ist auf Grund des offenen Quellcodes von jedem sehr einfach anzupassen und zu erweitern, sei es beim Erstellen von Themes oder gar zusätzlichen Featuremodulen.</p>
<p><span id="more-3133"></span>Was Ghost jedoch wirklich ausmacht, ist das Konzentrieren auf das Bloggen selbst. Der Macher von Ghost, John O&#8217;Nolan, war selbst langjähriger Programmierer bei WordPress und gibt im Introduction Video an, WordPress wäre nicht mehr eine reine Blogging Software, sondern habe sich in den letzten Jahren stark geändert und wäre demnach mehr zu einem CMS für voll-funktionierende Homepages geworden. Ghost jedoch ist anders &#8211; mit Ghost sollen sich Autoren nur kurz mit der Konfiguration befassen und sich dann endgültig und ausschließlich dem Schreiben von Artikeln widmen können.</p>
<p>Einziges Manko: Ghost ist ein Node App und läuft somit nur auf Servern, die Node.js installiert haben. Dieses Problem sieht anfangs kleiner aus als es ist, denn die meisten Web Hoster bieten hauptsächlich PHP an. Sogar Ruby musste sich auf Grund der geringen Anfrage seinen Platz bei den Hostern erkämpfen. Da die Popularität von Node.js jedoch rasant steigt, ist es wohl nur eine Frage der Zeit, bis mehr Web Hoster anfangen Node.js Interpreter auf ihren Plattformen anzubieten. Abhilfe schafft hier beispielweise ein virtueller Server, auf welchem Programme wie PHP oder Node.js selbstständig und frei installiert werden können &#8211; allerdings muss man für diese etwas tiefer in die Geldbörse greifen.</p>
<p>&nbsp;</p>
<p>The post <a href="https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/">Ghost &#8211; Open Source Blogging leicht gemacht</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/news/ghost-open-source-blogging-leicht-gemacht/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
