Blog: Latest Entries (15):


Frameworks schreiben.. aber richtig

In meinen 11 Jahren habe ich schon einige Frameworks geschrieben. Ich mag Frameworks und lieb es so etwas zu entwickeln. Aber Frameworks sind schwer richtig zu entwickeln. Die meisten Framework-Entwicklungen Enden ohne etwas Brauchbares in der Hand zu halten. 50% der Frameworks, die ich im Laufe der Zeit geschrieben habe waren einfach Schrott.
Neben diesen gibt es dann die, die am Ende nutzlos sind. Das kann damit zusammen hängen, dass die Vorteile und die Arbeitszeitersparnis einfach nicht eintreten. Die wirklich brauchbaren kann ich an paar Fingern abzählen. Aber auch viele große Frameworks haben ihre Probleme, es ist also kein Problem was nur die Arbeit einzelner Entwickler oder kleiner Gruppen betrifft. Ein gutes Beispiel für so ein Framework ist JavaFX 1.x. Viele Ideen, viel Arbeit wurde investiert und am Ende wollte es niemand verwenden. JSF 1.x war auch noch weit davon entfernt wirklich rund zu laufen bei der Entwicklung und zeigte oft Unzulänglichkeiten. Allein dass mit Tomahawk alle möglichen HTML-Tags wie DIV nochmal für JSF implementiert wurden, weil es kaum möglich war JSF und HTML sinnvoll zu mischen.
Aber das Scheitern großer Frameworks soll hier gar nicht das Thema sein. Es soll darum gehen, wie man es richtig macht bzw. wie man weniger falsch macht.

Ich hatte vor einiger Zeit APF2 (annonyme php framework 2) angefangen. Es sollte alles richtig machen was ich bei aoop falsch gemacht hatte. Es sollte nicht der Content direkt raus geschrieben werden beim Funktionsaufruf. Es war so nicht möglich über den Content-Bereich aus den Title zu ändern und so war auch die Möglichkeit nicht da einen Titel eines Blog-Post zu setzen, wenn man den BLog-Post geladen hatte, weil dann der HTML-Head schon gesendet worden war.

Es sollte ein richtiges Routing haben, um so zum Zend Framework 2 aufschließen zu können. Damit sollte SEO einfacher werden, weil nicht alles auf die index.php ging.

APF2 ist tot. Es fehlte einfach viel was aoop schon hatte, denn ein unvollständiges Framework ist sinnlos und aoop zu "reparieren" ging schneller als gedacht. Alles komplett neu und besser zu machen braucht viel Zeit und man kann es nicht alles besser machen und dabei kompatibel bleiben. ZF1 zu ZF2, JSF 1.x zu JSF 2.x, AngularJS 1.x zu AngularJS 2.x.. JavaFX. Ein Framework neu zu schreiben lohnt sich nur wenn man auch etwas komplett neues damit entwickeln will. Das Framework nur neu zuschreiben und die darauf basierende Anwendung portieren zu wollen endet eigentlich immer damit dass man die Anwendung auch fast komplett neu schreibt. Man hat ja damals nichts auf Hinsicht eines neuen noch nicht existenten entwickelt. Deswegen werden alte Framework Versionen auch ewig weiter gepflegt, weil das Portieren auf ein komplett neues Konzept nicht so einfach möglich ist, weil man sich eben auf das alte Konzept eingelassen hat und sich daran orientiert hat bei der Entwicklung.

Also der erste Punkte: Man muss für die Zukunft etwas neues machen und nicht versuchen alte Sachen zu reparieren. Eine neue Version ist auch ein neues Framework.

Auch die Frage, ob es in einem bestimmten Bereich wirklich ein noch ein weiteres Framework braucht, dass wieder nur Nuancen anders macht. Ja.. die Konzepte sind alle sehr ähnlich, die meisten kommen bei den selben Problemen zu den selben Lösungen. Es gibt viele Lösungen aber nur wenig gute und man ist nicht so genial, dass nicht auch viele andere zu der Lösung kommen. Außerdem ist man durch viele bekannte Konzept schon so geprägt, dass man diese auch aufgreifen wird. MVC und MVVM... am Ende kann
man noch so viel nachdenken.. die Konzepte sind schon gut. MVC, MVC2 oder MVVM sind auch sehr ähnlich und oft ist es auch Interpretation ob nicht eines der Konzepte, dass andere schon vorweg genommen hat und es nur nicht in der Masse erkannt wurde.
Würde ich heute noch cJS neu entwickeln? Nein. Es funktioniert echt toll und als ich vor paar Tagen mp4togif.com doch mal wieder erweitert habe, ging es einfach, schnell und problemlos. Aber AngularJS kann das auch alles und noch mehr und gerade das Handling von Arrays "item.name for item in items tracking by item.id".. so eine kleine Sache macht es für mich so toll. Das Wichtigste ist aber, dass AngularJS aktiv und mit soviel Man-Power weiter entwickelt wird, wie ich es nicht neben bei leisten könnte. Ich entwickle aoop aktiv weiter. Das ist schon viel Arbeit.

Also Punkt Nummer 2: Wenn man nicht die Zeit hat es durch gehend weiter zu entwickeln, sollte man es lassen und eines von jemanden verwenden, der oder besser die die Zeit investieren. Also auch mal an die Framework Entwickler denken und diese auch bei Gelegenheit etwas unterstützen. Denn die geben ihre Arbeit meistens kostenlos ab und sparen uns damit so viel Zeit, die wir wieder in etwas investieren, mit dem wir Geld machen oder es jedenfalls hoffen mal Geld zu machen :-)

Aber was ist, wenn es kein anderes Framework gibt, das das macht was ich brauche? Dann sollte man versuchen möglichst viele Leute zu finden, die es verwenden und somit den Bedarf schaffen, Zeit zu investieren. Gerade in Teams mit einem eigenen Framework (bei mir war es eins um XML-Templates in PDFs umzuwandeln, man also kein iText lernen musste sondern HTML und CSS reichte) muss es sich wirklich durch setzen. Wenn man nicht den Rückhalt hat, wird jede investierte Zeit als verschwendete Zeit gesehen.
Wenn man HTML + CSS Templating für ein Team entwickelt, dass zum großen Teil nie mehr als Java-Code und dort nur SWT für GUI gesehen hat, hat man schon einmal einen schlechten Start. Wenn das Framework dann besonders schnell entwickelt wurde, an einigen Stellen noch Probleme hat und nicht besonders schnell ist, hat es es sehr schwer sich jemals wieder von diesem Ruf zu erholen.
CSS ist teilweise etwas undurchsichtig und wenn sich dann Entwickler nicht merken können ob # nun sich auf eine Id oder eine Class bezieht, hat das Framework einfach keine Chance.

Damit wäre Punkt 3: Das Framework muss von den Entwicklern benutzt werden können. Wenn man nur ein Framework für sich selbst schreibt, scheint dieses egal zu sein, aber man weiß nie, ob nicht doch jemand anderes mal ein Projekt von einem übernehmen wird. Wenn man in einem festen Team arbeiten, muss man sich nach dem Wissen und den Vorlieben des Teams richten, damit das Framework angenommen wird.

Wenn wir nun ein neues Projekt mit einem Framework beginnen wollen, wollen wir nicht erst einmal viel Doku lesen oder einrichten müssen. Wir wollen (ich gehe mal vom Webbereich aus) das Framework deployen, es aufrufen und eine kleine Seite sehen. Vielleicht weißt das Framework einen nochauf eine fehlende Datenbank-Verbindung hin. Was wir an sich nicht machen wollen ist, den Server erstmal umständlich konfigurieren zu müssen. Erstmal die Config des Tomcats oder Apaches ändern zu müssen nervt. Wenn wir aber nun das Framework an sich zum Laufen bekommen haben, wollen wir unsere Anwendung anfangen zu entwickeln. ZF2 braucht gefühlt sehr viel Konfiguration und es müssen viele Dateien angelegt werden. Die Modul-Klasse, das Mapping des Namespaces, das Laden der Config-Dateien, was man alles in PHP umsetzen muss. Als Anfänger hat man sehr damit zu kämpfen, wil man oft auch nicht genau weiß, in welcher der Dateien nun was noch mal stand. Default-Werte sind unbekannt und die endlose Verschachtelung der Arrays ist
alles andere als übersichtlich.
Ich habe ein SWT-Framework erlebt wo man erst einmal 5 Klassen ableiten musste, mindestens 6 Methoden überschreiben sollte, die aber auch nicht abstract waren und man sowie so noch alle möglichen Pfade und Klassen an den richtigen stellen anpassen musste. Das war schon keine Konfiguration mehr sondern wirkliches Ändern und Anpassen von elementaren Code-Teilen.
Ein Update auf eine aktuellere Version des Frameworks,war also auch kein einfaches Kopieren von Dateien sondern man musste wieder den Code anpassen und hoffen, dass es immer noch die selben Stellen waren, wo es zu ändern war.

Punkt 4: Die Installation sollte an sich lauffähig sein und das Anlegen eines eigenen Moduls oder ähnlichen sollte über eine einzige Datei möglich sein. Diese Datei sollte kein Programm-Code sein und deutlich strukturiert sein. Auch Default-Werte sollten immer vorhanden sein, falls man einen Wert nicht in der Config setzt.

Und gleich Punkt 5 dazu: Wenn man ein Update macht sollte man die Dateien einfach kopieren können ohne eine der Dateien ändern zu müssen oder Angst haben zu müssen die momentane Config ausversehen wieder mit der mitgelieferten Default-Config zu überschreiben. Am besten ist ein zentrales Verzeichnis für die Config und dass ohne Inhalt einfach auf die default-Config zurück springt.

Fazit: Wenn man diese Punkte beachtet, steigen die Chancen, dass das eigene Framework brauchbar ist und auch von anderen Entwicklern angenommen wird. Zusätzlich sollte das Framework natürlich gut, schnell und möglichst fehlerfrei sein. Aber meistens scheitert das eigene Framework einfach daran, dass man zu wenig Zeit investiert, nur auf den momentanen eigenen Bedarf hin entwickelt und sich zu wenig Gedanken macht wie man selbst oder andere beim nächsten Projekt damit einen möglichst einfachen und entspannten Einstieg haben.

Virtualhost im Apache einrichten

Wenn man lokal entwickelt muss man sich oft eine Subdomain für "localhost" einrichten. Das ZF und ZF2 sind am liebsten so installiert und Folders in einer Domain funktionieren nicht immer ganz so gut. Außerdem kann man dann so einfach alles auf die produktive Domain kopiren ohne die htaccess anpassen zu müssen.

So etwas einzurichten ist auch ganz einfach. Es geht in der httpd.conf oder man richtet sich die extra/httpd-vhost.conf ein.


<VirtualHost *:80>
DocumentRoot "C:/workspaces/php/projectXYZ"
ServerName xyz.localhost
ServerAlias www.xyz.localhost
<Directory "C:/workspaces/php/projectXYZ">
DirectoryIndex index.php
AllowOverride All
Require all granted
</Directory>
</VirtualHost>


Mit AllowOverride erlaubt man das Verwenden von Rewrites

Erster Test mit PHP7

heute habe ich meinen ersten Test mit PHP 7 durch geführt. 1&1 ist so nett und bietet für jeden schon an PHP 7.0RC3 einzustellen. Ich hab mir eine Subdomain angelegt und diese auf PHP 7 konfiguriert. Ich wollte mal sehen, ob mein System mit PHP 7 läuft oder ich noch etwas ändern muss. Bis jetzt lief meine Homepage produktiv mit PHP 5.5 und wurde mit 5.6 entwickelt. Bei PHP7 fallen ein paar Altlasten weg, die man eigentlich schon vor Jahren hätte mal anpassen sollen. Das hatte ich vor paar Wochen gemacht:


  • Die alten Konstruktoren durch __construct() ersetzen. Ich weiß nicht warum die alten nicht mehr untersützt werden sollen in Java funktioniert die Art und Weise super und auch mit PHP hatte ich keine Probleme.. ist aber eben jetzt anders

  • Die alten msyql-Function sind nun nicht mehr dabei. Aber dafür gibt es noch die mysqli-Funktionen (auch in Form von Klassen für OOP). Da alles in einer Klasse gekapselt war, bedeutete das nur die Klasse zu kopieren und an jedes "mysql" ein "i" ran zuhängen. Also in 2 Minuten erledigt. Selbst ein automatisches Replace über alle Dateien hätte funktioniert.



Mehr hatte ich nicht geändert und es lief unter 5.6 alles sehr schnell und stabil. Dann folgte der Test auf PHP 7.. und es lauft. Gefühlt ist es immer noch stabil und schnell. Performance-Messungen habe ich noch nicht gemacht, aber werde in den nächsten 1-2 Wochen wohl mal welche nachreichen.

Fazit
Ich glaube es wird kaum bis wenige Probleme beim Wechsel geben, wenn der Code strukturiert ist und nicht seit 10 Jahren nicht mehr angefasst wurde. Das "Problem" mit den mysql-Funktionen klingt schlimmer als es ist bei alten Legacy-Code wo die DB-Queries wild im Sourcecode verteilt sind. Ein Replace und es ist erledigt, das Schlimmste was passieren kann ist das man ein paar Kommentare mit umbenennt. Also keine Angst haben und einfach mal ausprobieren.

bbcode-image

Ein guter Arbeits-PC

Wie sieht eigentlich der fast perfekte Arbeits-PC für einen Webentwickler aus? Webentwicklung kann jetzt auch relativ weitreichend sein, aber ich meine jetzt So etwas wie PHP, JSF, HTML5, viel JavaScript und auch viel UX und GUI-Design. JSF läuft zwar auch gut auf einem Websphere oder Wildfly. Aber diese brauchen vom ganzen Workflow bei der Entwicklung sehr viel Leistung. Bei JEE ist der schnellste PC gerade immer gut genug. Eine Eclipse-Instanz mit 15 Projekten, Maven, JBoss und einer VM mit Oracle kann so gut wie jeden Rechner auslasten, wenn Erstmal der Gesamt Workspace neugebaut wird und die Projekte deployed werden.

Aber auch gerade für kleine Side-Projects braucht man so etwas nicht und auch bei den meisten normalen Projekten wo man nur MySQL, PHP oder einen Tomcat hat, reicht viel weniger. Aber ein paar Dinge sind sehr wichtig.

Stabiles und schnelles LAN
Es gibt nicht schlimmeres als nicht funktionierendes LAN. Denn wenn es nicht funktioniert, ist genau der Zeitpunkt wo man ubedingt im Internet eine sehr wichtige Kleinigkeit nach gucken muss, die man schon mal gemacht hat, aber einen nicht mehr 100%ig klar ist wie man es damals gemacht hat und wo das andere Projekt und de Code gerade geblieben sind.
Auch das Kopieren von Daten auf Server oder das Exportieren oder Importieren von Datenbank-Beständen ist mit einem guten und stabilen Netzwerk sehr viel angenehmer. Wlan ist meistens langsam, instabil und bei mehreren aktiven Geräten gleichzeitig, macht es schnell keinen Spaß mehr damit zu arbeiten. Für Tablet und mal zum Surfen mit dem Notebook oder ein Video streamen (wo der Anbieter behauptet es wäre Full HD..) reicht Wlan immer. Aber wenn man mal einen Eclipse-Workspace von 1,5GB darüber kopieren wollte, weiß man wo die Grenzen liegen.

Ein schnell startender Rechner
Auch wenn man bei der Arbeit die Zeiterfassung nicht erst mit gestarteten Windows hat und somit jede Minute dann Zeit ist, die einem nicht als Arbeitszeit angerechnet wird, sind endlose Startzeiten einfach nur nervig. Wer mal mit NT 4.0 gearbeitet hat und eine SCSI-Karte eingebaut hatte kann sich sicher gut daran erinnern. >1 Minute Startzeit sind viel. Besonders nervig wird es mit serverseitig gespeicherten Profilen und langsamen Netzwerken. Einloggen und dann nochmal 2-3 Minuten warten bis der Desktop zu sehen ist und auch sich erste Dinge anklicken lassen.
Ich hatte mal einen älteren WinXP Rechner mit Eclipse, JBoss, SQL-Developer, Firefox, Thunderbird.. 5-6 Minuten bis man die ersten Zeichen Code schreiben konnte waren nicht selten. Wenn Antivir noch aktiv wurde, würde es noch schlimmer.
Also eine SSD oder eine gute Festplatte sorgt schon mal für einen entspannten Einstieg in die Arbeit und sorgt dafür, dass der Mitarbeiter gleich schon zu Anfang vollkommen entnervt vor seinem PC sitzt.
Und eben schnelles LAN, falls was von einem Server geladen werden soll.

CPU-Kerne.. viele
Heute muss man beim Entwickeln viel parallel laufen lassen. Auch wenn die Software selbst nicht viel mit Threads arbeitet (was aber heute fast schon eine Ausnahme ist und eher daran liegt, dass zu wenig zu tun ist für einen zweiten Thread) sind viel Kerne nicht verkehrt. Die vielen Kernedürfen dann auch gerne langsamer sein. Privat komme ich mit 2x L5335 Xeons mit je 4 Kernen super zurecht, während der i7 bei der arbeit mit nur 4 Kernen an einigen Punkten an seine Grenzen kam. Gerade wenn die VM mit der Oracle DB 2 Kerne bekam und auch 4GB der 16GB reservierte. Dann noch eine MySQL-DB ein Tomcat und dazu eine Eclipse-Instanz oder auch mal zwei. Privat mit 8 Kernen und 24GB ist es immer die Festplatte, die am Ende das Problem ist aber nie wirklich der Rest.
Also gute CPUs mit vielen Kernen und viel RAM. Man kann von beiden nie genug haben. Für reine PHP Entwicklung oder HTML5 reicht natürlich oft schon 8GB und ein i5 aus. Aber auch hier sollte dann wenigstens das Mainboard gut genug sein um die Leistung von beiden gut genug auszuspielen.

Gute Monitore
Gerade im Webbereich hat man viel mit Grafik und Farben zu tun. 2x EIZO Flexscan S2411W sind echt super. Ein günstiger Samsung ist gar nichts dagegen. Gut für die Augen, weil alles super erkennen kann und die Farben und Kontraste deutlich sind. Teuer. Ja.. aber zwei Moitore sind fast schon Grundvoraussetzung. Einer für die IDE der andere für den Webbrowser zum Testen und Referenzen und Hilfen suchen. FullHD oder 1920x1200 dürfen es heute schon sein. Mehr ist nicht verkehrt aber auch nicht wirklich nötig. Aber auch gebrauchte alte wie ein Acer... oder ein Fujitsu .... sind noch immer sehr gut zu gebrauchen. Neu muss nicht immer besser sein.. wenn die Farben und die Qualität stimmen.

bbcode-image
Eizo Nanao S2411W-BK

Datensicherung
Nicht wirklich ein Teil des PCs aber für das angenehme Arbeiten sehr wichtig. Auch wenn man es nie braucht.. zu wissen, dass die Daten gesichert wurden beruhigt einen sehr. GIT, SVN.. damit man im Notfall auf eine alter Version zurück springen kann.. auch wenn man es nie wirklich macht. Aber bei der Nachforschung doch immer sehr hilfreich.
Auch privat sollte man seine Daten immer mal sichern. Sehr gut funktioniert ein BluRay-Brenner oder eine einfache externe Festplatte. Es muss nicht immer eine "echte" externe Festplatte sein. Ein einfaches Gehäuse und eine gute (gebrauchte) 3,5 Zoll Festplatte sind oft günstiger und dazu noch zuverlässiger als eine 2,5 Festplatte für den selben Preis und man ist sich sicher was für eine Festplatte verbaut und man diese im Notfall ohne Probleme auch intern oder in einem anderen Gehäuse betreiben kann.

Die Geräuschkulisse
Auch wenn man es im normalen Arbeitsalltag kaum wahr nimmt... viele PCs sind doch sehr laut. Wenn man dann mal Abends im Dunkeln vor dem PC sitzt, nichts weiter an hat und keine Musik hört und versucht konzentriert einen Blog-Eintrag zu schreiben, merkt man erst wie laut ein PC wirklich ist. Am Ende sind es immer die Lüfter die den Krach machen.
Festplatten werden schnell angehalten bei modernen Systemen und beim Schreiben in einem Text-Editor wie Notepad++ liegt sowie so alles im Arbeitsspeicher.
Nach viel herum probieren und testen sind die PCs hier jetzt sehr leise bzw meiner relativ leise.

Der AMD FX 4300 läuft selbst unter viel Last wie bei Witcher 3 sehr leise und ist kaum hörbar.

Das kam aber erst nachdem er mit diesen beiden Teilen aus gerüstet wurde und eine Radeon HD7950 spendiert bekam. Mehr Leistung bei weniger Strom bedeutet eben auch, das weniger gekühlt werden muss und weniger Krach bei gleicher Leistung heraus kommt.

bbcode-image
be quiet BK009 Pure Rock

bbcode-image
BeQuiet Silent Wings Pure 120x120x25

Mein Hauptrechner läuft noch mit 2 alten 80mm Thermaltake Lüftern, die aber mal in nächster Zeit durch 2 von BeQuiet! ausgetauscht werden sollen. 2 BeQuiet-Lüfter laufen schon auf 2 2HE Kühlkörpern und kühlen wirklich super und leise.

An den Körper denken
Was man auf keinen Fall vernachlässigen sollte ist der Körper. Nacken, Rücken, Handgelenke und Augen. Ein guter Monitor schont die Augen. Wenn er auf der richtigen Höhe eingestellt ist und man einen guten Stuhl hat schont es den Nacken und den Rücken. Hände und Gelenke schont man mit der richtigen Tastatur und Maus. Nach vielen Versuchen bin ich bei einer Cherry-Tastatur und einer Razer Imperator Maus gelandet. Roccat Kone ist auch eine gute Maus. Bei einer Dell verkrampfte die Hand schon nach 30 Minuten und auch die günstigen von Logitech sind teilweise verbesserungswürdig wenn man viele Stunden damit arbeitet. Meine Erfahrung für mich hat gezeigt, dass ich doch gerne eine etwas größere und schwerere Maus habe. Auch mag ich keine flachen Tasten auf Tastaturen. Notebook Tastaturen sind für mich ein Graus (halb hohe Tasten auf einer anderen Cherry gehen aber ich hätte doch lieber auch dort eine mit hohen Tasten). Aber das muss jeder mit Zeit für sich selbst heraus finden, was einem gefällt und was gut für einen ist. Wenn man dann etwas gefunden hat darf es auch gerne etwas mehr kosten, weil lieber mal 50 Euro mehr ausgeben als eine Sehnenscheidenentzündung und Monate lange Behandlungen oder dauernd Kopfschmerzen wegen dem Nacken, weil der Monitor falsch/zu hoch ausgerichtet ist und sich nicht richtig verstellen läßt.

bbcode-image
Razer Imperator

bbcode-image
Cherry G83-6105 LUNDE-2

Auch wenn es teilweise Gamer-Hardware ist, ist diese wirklich für alle gut, die lange am PC sitzen und auch intensiv mit den Geräten arbeiten. Es kam mir zu Erst komisch vor mit einer Gamer-Maus zu arbeiten aber eine meiner ersten Fragen bei meinem neuen Arbeitgeber war, ob ich diese winzige Funkmaus von Logitech gegen meine Imperator austauschen könnte. Es war gleich ein ganz anderes Gefühl die wieder benutzen zu können.

Windows 10 Virtuelle Desktops

Die virtuellen Desktops in Windows 10 sind doch eine praktische Sache. Gerade wenn man zuhause abends nebenbei auch mal etwas produktives machen möchte. Dann kann man die üblichen Dinge die man sonst so offen hat auf den ersten Desktop legen und IDE, SourceTree und die Firefox Instanz zum Testen auf den zweiten.
So kann man auch ohne Probleme in Facebook einen Chat haben und muss nicht umständlich immer zwischen Fenstern und Tabs wechseln.

Einfach und schnell zwischen den Desktops wechselt man mit Win+Ctrl+(links|rechte). Es ist auf jeden Fall sehr viel schneller als zwei Fenster wieder nach vorne zu holen, wenn man gerade etwas anderes gemacht hat oder sich durch die offenen Tabs im Browser zu suchen bis man wieder die zwei richtigen gefunden hat, die man brauchte.

Auch für Kinder und Jugendliche, die gerade Hausaufgaben machen (sollen) eröffnen sich damit ganz neue Möglichkeiten.

PHP Annotation-based Validator

Mein erster Prototyp für einen Validator in PHP der mit Annotationen arbeitet. Über ReflectionClass kann ich mir dann die Properties holen und dann mit getDocComments() mir die Annotationen auslesen.


<html>
<body>
<?php
$anno="@validate{type:,range:,regex:}";


function validateValue($value,$annotation){
$result=true;
$annotation=preg_replace("/^.*\@validate\{(.+)}.*$/Uis","$1",$annotation);
$parts=preg_split("/,/",$annotation);
foreach($parts as $part){
$check=preg_split("/:/",$part);
$key=$check[0];
if($key=="notnull" && $value==null){
$result=false;
}
else if($key=='type'){
$condition=$check[1];
if($condition=='int' && !is_int($value)){
$result=false;
}
else if($condition=='float' && !is_float($value)){
$result=false;
}
else if($condition=='array' && !is_array($value)){
$result=false;
}
}
else if($key=='regex'){
$result=preg_match($check[1],$value);
}
else if($key=='range'){
$range=preg_split("/~/",$check[1]);
if($value>$range[1] || $value<$range[0]){
$result=false;
}
}
else if($key=='countrange'){
$range=preg_split("/~/",$check[1]);
if(count($value)>$range[1] || count($value)<$range[0]){
$result=false;
}
}
else if($key=='lengthrange'){
$range=preg_split("/~/",$check[1]);
if(strlen($value)>$range[1] || strlen($value)<$range[0]){
$result=false;
}
}

if(!$result){
return $result;
}
}
return $result;
}

echo "Test notnull(failed): ".validateValue(null,"@validate{notnull}")."<br/>";
echo "Test notnull (ok): ".validateValue("test","@validate{notnull}")."<br/>";
echo "Test regex (failed): ".validateValue("ein komischer test","@validate{regex:/komischerer/}")."<br/>";
echo "Test regex (ok): ".validateValue("ein komischer test","@validate{regex:/komischer/}")."<br/>";
echo "Test type (failed): ".validateValue("test","@validate{type:array}")."<br/>";
echo "Test type (ok): ".validateValue(array("1","2"),"@validate{type:array}")."<br/>";
echo "Test range (failed): ".validateValue(3,"@validate{range:4~12}")."<br/>";
echo "Test range (ok): ".validateValue(6,"@validate{range:4~12}")."<br/>";
echo "Test lengthrange (failed): ".validateValue("123","@validate{lengthrange:4~12}")."<br/>";
echo "Test lengthrange (ok): ".validateValue("123456","@validate{lengthrange:4~12}")."<br/>";
?>
</body>
</html>

Angular und native Forms

Wer mal eine <select> mit Angular gefüllt hat, kennt das Phenomen, dass die Ids nicht im Value der Option stehen sondern über Angular später gesetzt werden sollen. Wenn man mit ng-model arbeitet ist das auch alles kein Problem. Nur wenn man das <select> klassisch über eine Form submiten möchte kommt es zu Problemen.


ng-options="item.id as item.name for item in items"


Was hilft ist das hier


ng-options="item.name for item in items track by item.id"


Damit wird nicht mehr der Index des Arrays verwendet sondern wirklich die Id aus dem Objekt.

REST und ZF1

Auch im ZF1 ist es sehr einfach einen REST-Service zu implementieren.


public function restAction(){
$this->getHelper('Layout')->disableLayout();
$this->getHelper('ViewRenderer')->setNoRender();
$this->getResponse()->setHeader(
'Content-Type', 'application/json; charset=UTF-8'
);

$data=............;

echo json_encode($data);
return;
}


Man muss nur das Layout und den ViewRenderer deaktivieren und schon kann man sein Response ganz nach Belieben gestalten. Das Vorgehen über das Response als return Wert im Zend Framework 2 finde ich aber insgesamt klarer und strukturierter als die Art und Weise um ZF1.

PHP und Profiling

Irgendwann kommt der Zeitpunkt, da ist eine Anwendung langsam. Es liegt nicht am Datenbankserver oder der Netzwerkanbindung oder der Auslastung des Servers. Es liegt einfach ganz allein daran, dass die Anwendung langsam ist.
Oft findet man einige Dinge von selbst heraus. Aber oft ist man einfach überfragt in welchen Teilen der Anwendung die Zeit verloren geht. Was braucht lange? Werden einige Dinge unnötig oft aufgerufen? Zu viele Dateisystem-Zugriffe?

Hier hilft dann nur noch ein Profiling der Anwendung. Profiling ist einfach die Anwendung eine Zeit lang zu überwachen und zu protokollieren, wie viel Zeit in der Zeit auf welche Methoden oder Funktionen verwendet wird.
Das alleine sagt natürlich erstmal nicht wo Probleme vorhanden sind. Deswegen halte ich die Idee ein separate Team solche Performance-TEst durch zu führen und zu analysieren für nicht ganz so zielführend. Denn manchmal brauchen einige Methoden viel Zeit. Da man Zeit sowie so meistens nur in Verhältnis der Methoden zu einander betrachtet muss man wissen was schnell sein soll und was langsam sein sollte oder darf.
Ich hatte mal bei Bouncy Dolphin das Problem, dass alles an sich ganz schnell lief, aber beim Profiling auf eine Methode fast 40% der Zeit ging, die nur den aktuellen Punktestand auf das Canvas zeichnete. Nach viel hin und her Probieren kopierte ich den Inhalt eines Canvas mit dem Punktestand auf das Haupt-Canvas. Das Canvas mit dem Punktestand wurde nur neu gezeichnet wenn sich der Punktestand auch änderte. Danach verbrauchte die Methode nur nach 15%. Also war es schneller das gesamte Canvas zu kopieren als eine oder zwei Ziffern zeichnen zu lassen.
document.getElementById["aaaaa"].value=score verursacht z.B. auch extrem hohe Kosten. Also immer alle wichtigen Elemente in Variablen halten und nicht jedesmal neu im Document suchen!

Wärend man in Java extrem mächtige Tools wie VisualVM hat und der Profilier des Firefox oder Chrome einem bei JavaScript Problem sehr gut hilft, ist die Situation bei PHP etwas umständlicher. Zwar kann man so gut wie immer XDebug verwenden, aber so einfaches Remote-Profiling wie mit VisualVM ist da nicht zu machen.
Aber da man meistens sowie so lokal auf dem eigenen PC entwickelt und testet, reicht es die Daten in eine Datei schreiben zu lassen und diese dann mit Hilfe eines Programms zu analysieren.


xdebug.profiler_enable=1
xdebug.profiler_output_dir=C:/test/profile


PHPStorm bringt ein entsprechendes Tool mit.

Aber ich habe bis jetzt WinCacheGrind verwendet. Damit ließen sich nach etwas Einarbeitung dann schnell heraus finden, wo die Zeit verloren ging und welche Methoden wie oft aufgerufen wurden.
Der Class-Loader durchsuchte das System-Verzeichnis zu oft, weil an der Stelle nicht richtig geprüft wurde, ob die Klasse schon bekannt war. So konnte ich die Ladezeit einer Seite in meinem Framework am Ende nach vielen solcher Probleme von 160ms auf ungefähr 80ms senken. Viel Caching kam auch noch dazu und das Vermeiden von Zugriffen auf das Dateisystem.

Aber es gibt noch andere Profiler als XDebug für PHP. Hier findet man eine gute Übersicht:
PHP Profiler im Vergleich

Ich hab schön öfters gehört, dass solche Test und das Profiling ans Ende der Entwicklung gehören und man so etwas nur macht wenn man keine andere Wahl hat. Aber am Ende findet man viele Fehler dabei und ich halte es für falsch nicht schon am Anfang zu testen ob eine Anwendung auch später mit vielen produktiven Daten noch performant laufen wird. Denn am Ende sind grundlegende Fehler in der Architektur schwerer und auf wendiger zu beheben als am Anfang oder in der Mitte der Entwicklung.
Nachträglich an einzelnen Stellen Caching einzubauen ist auch nicht so gut wie von Anfang an ein allgemeinen Caching-Mechanismus zu entwerfen, der an allen relevanten Stellen automatisch greift.
Deswegen sollte man auch schon ganz am Anfang immer mal einen Profiler mitlaufen lassen und gucken, ob alles so läuft wie man es sich dachte.

Kundendaten zum Testen und Datenschutz

Manchmal gibt es ja Probleme die man nur mit produktiven Daten nachgestellt bekommt. Oder man hat keine gute Möglichkeit vielDaten zu erzeugen um Test mit vielen realistischen Daten durch zu führen. Dann hilft oft eine Kopie der Datenbank des produktivenSystems.
Nur echte Kunden-Daten auf einer Entwickler-Workstation liegen zu haben, ist nicht wirklich toll. Der Datenschutz und so.

Hier hilft es die Datenbank in einer VM zu betreiben und einfach die gesamte VM zu verschlüsseln. Man muss nichts an der Workstationändern und hat trotzdem eine gute Sicherheit für die Daten.

Bei VirtualBox muss man nur das Erweiterungs-Pack downloaden und schon kann man dort eine gesamte VM verschlüsseln.

bbcode-image


bbcode-image

Bild mit JavaScript und Canvas in SW

Ein einfaches Code-Beispiel um mit JavaScript ein Bild in ein schwarz-weiß Bild umzuwandeln. Läuft schnell und ist relativ unkompliziert einzubauen.


if(this.color=="bw"){
var idata=ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height);
var data=idata.data;
for(var i=0;i<data.length;i+=4){
var grayValue=data*0.3+data[i+1]*0.59+data[i+2]*0.11;

data=grayValue;
data[i+1]=grayValue;
data[i+2]=grayValue;
//dont change alpha value [i+4]
}
ctx.putImageData(idata,0,0);
}

JavaScript Frameworks und ihre Verbreitung

Ich heute letztens über diesen Artikel auf diesen Blog-Eintrag über die Nutzung und Verbreitung von JavaScript-Frameworks gestolpert.

Da es ja eigentlich um Web Frontend-Tools geht fehlt mir dabei etwas eine Übersicht zu den CSS-Frameworks, da diese doch schon sehr oft verwendet werden. Bootstrap, Foundation und UIKit hätten mich dabei sehr interessiert. Ich würde jetzt spontan vermuten,dass Bootstrap deutlich vorne liegen würde.

Bei den JavaScript Frameworks bin ich aber der Meinung, dass z.B. Frameworks wie AngularJS und jQuery eher schlecht mit einander zu vergleichen sind. jQuery arbeite auf einem viel nähren Level am DOM und AngluarJS durch sein Templating und Databinding auf einem eher höheren Level angesiedelt ist. Wenn man viel mit dem DOM arbeitet ist jQuery natürlich sehr von Vorteil. Bei AngularJS muss man dann öfters auf eigene Direktiven zurück greifen.

Wenn man schnell Prototypen mit grundlegenden Funktionen und paar Dummy-Daten bauen will ist AngularJS aber sehr viel besser. Man muss meistens nur das HTML-Layout um die AngularJS eigenen Attribute ergänzen und hat dann schon nach wenigen Minuten gefüllte Listen und Selects. Gerade bei Listen und Selects spielt AngularJS seine Vorteile, dann mit ein ng-repeat oder ng-options ist in wenigen Sekunden zuschreiben, wärend das Erzeugen und Befüllen und Hinzufügen von Options und LIs sehr viel aufwendiger ist.
So hat man sehr viel schneller etwas wo man meistens dann am Ende nur noch die AJAX-Request ergänzen muss um richtige Daten anstelle der Dummy-Daten zu haben.

Wenn ich aber Klick-Koordinaten in einem DIV oder einem CANVAS berechnen möchte und mit der Metrik der Elemente arbeite, dann ist natürlich jQuery die erste Wahl.

Bei den Frameworks wird also einfach zu viel einfach zusammen geworfen und in Konkurrenz gesetzt was nie konkurrieren wollte oder sich eher noch perfekt ergänzen kann. Es gibt Artikel darüber wie AngularJS und React.js. Google und Facebook zusammen kann toll sein.

Bei den Module Bundlers kann ich nur zustimmen, dass die eine tolle Sache sind und ich bei meinem cJS auch RequireJS als Möglichkeit eingebaut Controller zu laden. Aber auch ist selbst benutze es irgendwie nie. Bei großen Anwendungen ist es bestimmt toll und eine Art JS-Class-Loader. Aber bei kleinen Anwendungen mit 6 Controllern ist das einfache einbinden irgendwie übersichtlicher.
Aber an sich sind die toll und man sollte sie viel öfter verwenden. Leider werden alle Controller am Anfang direkt instanziert. Ideal wäre es wenn der Controller erst geladen wird, wenn er das erste mal auch wirklich angesprochen wird. Also die Bindings auch erst erstellt werden, wenn diese das erste mal in Aktion kommen.
So ein Framework würde sicher viel Speicher sparen.

PHP Annotations und Reflections

Mit Hilfe der Reflections-Klassen in PHP sit es auch z.B. möglich sich einen JSON-Encoder zubauen, der nicht verlangt, dass alle Attribute der Klasse public sein müssen. Ähnlich wie in Java kann man hier auch auf private Attribute ohne Probleme zugreifen wenn man dieses setzt:


$prop->setAccessible(true);


Wenn man dann noch neben den skalaren Typen eine extra Behandlung für Array-Inhalte und Objekte einbaut, kann man sich ganz einfach einen rekursiven JSON-Encoder bauen, der auch mit normalen Beans mit Gettern und Settern zurecht kommt und man keine zusätzlichen DTOs mehr extra anlegen muss.


class XWJSONConverter{
public function __construct(){

}

public function convert($value,$level=0,$name=null,$firstInLine=true,$result=""){
$opening=false;
if($level==0 && $name!=null){
$result.="{";
$opening=true;
}
if(is_scalar($value)){
if(!$firstInLine){
$result.= ",";
}
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= json_encode($value);
}
else if(is_array($value)){
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= "[";
$i=0;
foreach($value as $val){
$result=$this->convert($val,$level+1,null,$i==0,$result);
$i++;
}
$result.= "]";
}
else if(is_object($value)){
if(!$firstInLine){
$result.= ",";
}
if($name!=null){
$result.= '"'.$name.'":';
}
$result.= "{";
$ref=new ReflectionClass(get_class($value));
$props=$ref->getProperties();
$cnt=count($props);
for($i=0;$i<$cnt;$i++){
$prop=$props[$i];

$doc=trim($prop->getDocComment());
if(!preg_match("/@json_transient/i",$doc)){
$prop->setAccessible(true);
$name=$prop->getName();
if($prop->isPrivate() || $prop->isProtected()){
$name=preg_replace("/^_/","",$name);
}
$result=$this->convert($prop->getValue($value),$level+1,$name,$i==0,$result);
}
}
$result.= "}";
}
else if(is_null($value)){
if (!$firstInLine) {
$result .= ',';
}
if ($name != null) {
$result .= '"' . $name . '":';
}
$result .= 'null';
}

if($opening){
$result.="}";
}
return $result;
}
}


Ein Decoder war mir jetzt nciht wirklich wichtig, da in meinen Anwendungsfällen PHP eigetnlich immer nur JSON für REST-APIs generiert und auf JavaScript-Seite, das decodieren in eine Objekt-Struktur ohne Probleme dann wieder möglich ist. Da sind private und public nicht mehr wichtig.

Was hier noch interessant sein könnte ist mein Versuch mit Annotations in PHP zu arbeiten. Wenn man verhindern will, dass ein Attribute mit nach JSON encodiert wird, kann man das damit verhindern:


class Test{
private $toJSON="ok";
/**
* @json_transient
*/
private $notToJSON="ne";
}


Damit wird im JSON-String nur das erste Attribute auftauchen.

Zurück aus Schweden

bbcode-image


Ship It: A Practical Guide to Successful Software Projects

Ein wirklich gutes Buch. Der Vorteil ist, dass Kapitel so geschrieben sind, dass man auch mal welche überspringen kann. Zum Beispiel das Kaptiel über Sourcecode Management Systeme wie SVN oder CVS werden heute kaum noch jemanden neues zeigen können.

Auf die Zusammenfassungen am Ende der Kaptiel und des gesamten Buches sind toll. Es gibt Listen wie es laufen sollte, wie man es verbessern kann und welche Anzeichen dafür sprechen, dass Verbesserungsbedarf besteht.

Ich fand das Kapitel über Daily-Meetings und "The List", also priorisierte Todo-Listen wirklich gut und sie gaben mir neue Denkanstöße. Ich werde mal versuchen Daily-Meetings in meinen Arbneitstag einzubringen und umzusetzten.. mal sehen was mein Chef dazu sagt :-)

Ich kann jedem Entwickler, Projektleiter und Kontakt-Person, die mit einem der beiden erst genannten für einen Kunden Kontakt halten muss empfehlen.
Denn wenn der Kunde die Probleme der Entwickler versteht und der Entwickler die Probleme der Kunden (etwas technisches zu Formulieren und Zeiten abschätzen zu können), dann kann man viele Missverständnisse schon mal vermeiden. Und dieses Buch ist einfach formuliert mit Reallife-Beispielen und könnte als neutraler Dritter zwischen beiden Seiten einen gemeinsamen Konsens vermitteln.

REST und Zend Framework 2

REST mit dem Zend Framework 2 soll ganz einfach gehen. Geht es auch. Bestimmt gibt es viele verschiedene Möglichkeiten, aber diese scheint erstmal ganz gut zu funktionieren. Den XWJSONConverter hatte ich shcon in einem vorherigen Blog-Post vorgestellt. Man kann natürlich auch JSON:encode aus dem ZF2 verwenden oder json_encode().


class IndexController extends AbstractRestfulController{
private function _getResponseWithHeader(){
$response = $this->getResponse();
$response->getHeaders()
//make can accessed by *
->addHeaderLine('Access-Control-Allow-Origin','*')
//set allow methods
->addHeaderLine('Access-Control-Allow-Methods','POST PUT DELETE GET')
//change content-type
->addHeaderLine('Content-Type', 'application/json; charset=utf-8');

return $response;
}

private function _createJSONResponse($obj){
$json=new XWJSONConverter();
$response = $this->_getResponseWithHeader()->setContent($json->encode($obj));
return $response;
}

public function indexAction(){
$entity=$this->getServiceManager()->get("entityDAO")->load(1);
return $this->_createJSONResponse($entity);
}
}

Older posts:

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?