Blog: Latest Entries (15):


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);
}
}

Warum Spalten-Prefixes nicht immer gut sind

Lange Zeit habe ich auch immer bei Columns von Datenbank-Tabellen immer ein Prefix verwendet. Die Tabelle TESTS hatte dann z.B. die Spalte TEST_ID. Daran ist ja auch erstmal nichts verkehrt. Probleme gab es mit Oracle und der Beschränkung auf 30 Zeichen für den Spaltennamen in einigen Fällen.


$entity->setId($data["TEST_ID"]);


Der Code oben funktioniert auch super, wenn man jedes Value "per Hand" in das Object schreibt.

Wenn wir aber nun ein automatisches Mapping über Annotationen nutzen kann es in einigen Fällen schnell umständlich werden.
Wenn wir keine Ableitung und Vererbung benutzen, ist auch hier kein Problem zu erwarten. Wenn wir aber eine Basic-Klasse verwenden, von der alle anderen Klassen ableiten, haben wir schnell ein Problem, weil wir in der Basic-Klasse in den Annotationen einen Platzhalter für den Prefix verwenden müssten. Ohne Prefix geht es hier sehr viel einfacher.


/**
* @dbcolumn=ID
*/
private $id=0;



/**
* @dbcolumn={prefix}_ID
*/
private $id=0;


Deswegen sollten Prefixe nur bei FKs verwendet werden, um ein automatisches Mapping unkompliziert nutzen zu können. Wenn man es jetzt nicht nutzt, will man es später vielleicht und kann dann jetzt schon alles so bauen, um später keine Probleme zu bekommen. Platzhalter funktionieren natürlich auch.. gehen aber zur Lasten der Performance.

TXT2Links-Update

Früher war es nur möglich URL zu finden, die am Anfang einer Zeile standen und die Zeile für sich allein hatten. Das war für einfache Listen vollkommen ausreichend. Nun wurde es so erweitert, dass auch URLs innerhalb eines Textes gefunden werden könnten. Man kann nun also eine *.txt-Datei laden und die Web-App versucht alle enthaltenen Links zu finden und darzustellen.

CSS Frameworks

In der letzten Zeit habe ich mit CSS-Frameworks zu tun gehabt. Bootstrap, Foundation und UIKit. Mit Bootstrap hatte ich ja schon etwas länger Kontakt. Foundation jetzt so 3 Wochen und UIKit 2 Tage. Bootstrap gefällt mir von der standard Optik aber immer noch am Besten. Bei UIKit gefallen mir die mitgelieferten Icons. Foundation macht was es soll, aber sieht mir an einigen Stellen doch zu sehr nach plain-HTML aus und die Dokumentation sagt mir am wenigsten von den Dreien zu.

Aber am Ende machen doch alle drei genau das Selbe und das auch sehr ähnliche Weise. Was ich mit dem einen hinbekomme, kann ich ohne große Probleme auch mit den anderen erledigen. Oft muss man nur die CSS-Class's austauschen.

Ob man nun soviele ähnliche Frameworks braucht lasse ich mal dahin gestellt und versuche erstmal für mich heraus zu finden, welches ich nun als primäres verwenden sollte.

Microsoft Lumia 640

Viele haben ja etwas gegen die Lumias... ich mag aber mein Lumia 640.

Kamera ist gut. Der Akku hält extrem lange und raus nehmbar ist. Oberfläche lässt sich wirklich gut bedienen und ist schnell. Auch alle wichtigen Apps sind vorhanden. Endlose Versorgung mit Updates. Selbst alte Lumia 1020 bekommen immer noch alle Windows Updates.

Und im Gegensatz zu meinen alten Smartphones mit Bada 2.0 oder Firefox OS kann ich jetzt meinen Eltern auch von Unterwegs aus helfen dank des Teamviewer-Clients.

bbcode-image

bbcode-image


Also ich kann die Lumias nur empfehlen! (Das Lumia 1020 hat eine wirklich geniale Kamera)

bbcode-image
Microsoft Lumia 640


jQuery einfaches DataBinding

Es muss nicht immer AngularJS sein, um ein einiger Massen automatisches Databinding zu haben. Auch mit jQuery kann sich schnell kleine Lösungen basteln. Hier wir eine Liste von Items aus gegeben (<ul><li>...), die <li>'s sind per Drag and Drop sortiertbar und werden später wieder eingelesen und die Items der Reihenfolge der <li>'s entsprechend sortiert. Das wird schon ganz klassisch über die DOM-Elemente gemacht. Aber ich hatte keine Lust darauf auch die Checkboxen dannausdem <li> über das DOM zusuchen und auszulesen.

Hier zeigen sich die Vorteile von Closures mal wieder. Wenn man eine CheckBox ändert wird sofort über das onChange-Event getriggert auch das Feld des Objekts im Array angepasst. Ohne das Array oder DOM-Elemente durchlaufen zu müssen. Alles ganz automatisch.


//bind checkbox to item.visible of the current item
var func=function(item){
return function(){
item.visible=!item.visible;
}
};
check.change(func(items[j]));


Ich kann immer noch nicht verstehen, wie manche JavaScript-Entwickler ohne Closures auskommen und einige.. wenige.. ok.. einer.. sogar mal meinte Closures bräuchte man überhaupt und man komme immer gut ohne aus.

Older posts:

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