<?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/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>DaRaFF&#039;s Blog</title>
	<atom:link href="http://daraff.ch/feed/" rel="self" type="application/rss+xml" />
	<link>http://daraff.ch</link>
	<description>Gedanken über Themen, die mich beschäftigen</description>
	<lastBuildDate>Thu, 16 May 2013 05:55:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Lessons Learned @ NZZ – Teil 5 – Refactoring von Fat Controllern</title>
		<link>http://daraff.ch/2013/05/lessons-learned-nzz-teil-5-refactoring-von-fat-controllern/</link>
		<comments>http://daraff.ch/2013/05/lessons-learned-nzz-teil-5-refactoring-von-fat-controllern/#comments</comments>
		<pubDate>Thu, 16 May 2013 05:55:43 +0000</pubDate>
		<dc:creator>DaRaFF</dc:creator>
				<category><![CDATA[Architektur / Design]]></category>

		<guid isPermaLink="false">http://daraff.ch/?p=1794</guid>
		<description><![CDATA[This entry is part 5 of 5 in the series Lessons Learned @ NZZIm letzten Teil der Serie habe ich ja beschrieben, was ein (Symfony2)-Controller tun sollte bzw. was meine Erkenntnisse bezüglich fat Controllern ist. Ein Artikel auf test.ical.ly gibt ein paar &#8230; <a href="http://daraff.ch/2013/05/lessons-learned-nzz-teil-5-refactoring-von-fat-controllern/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">This entry is part 5 of 5 in the series <a href="http://daraff.ch/series/lessons-learned-nzz/" class="series-148" title="Lessons Learned @ NZZ">Lessons Learned @ NZZ</a></div><p>Im <a title="Lessons Learned @ NZZ – Teil 4 – Symfony2 Controller" href="http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/">letzten Teil der Serie</a> habe ich ja beschrieben, was ein (Symfony2)-Controller tun sollte bzw. was meine Erkenntnisse bezüglich fat Controllern ist. Ein <a title="4 simple tips to avoid fat controller" href="http://www.testically.org/2013/01/15/4-simple-tips-to-avoid-fat-controllers/ ">Artikel</a> auf <a href="http://test.ical.ly">test.ical.ly</a> gibt ein paar gute Tips, wie man fat Controller verhindern kann.</p>
<p>Was kann man nun tun, wenn man riesige Controller hat (aus was für Gründen auch immer) und diese wieder in schlanke, verständliche, lesbare Controller refactoren will? Ich beschreibe nun eine Vorgehensweise, welche sich für mich schon einige Male bezahlt gemacht hat. Vielleicht könnt ihr auch davon profitieren.</p>
<h1>Code studieren und grob verstehen?</h1>
<p>Als ersten Schritt muss man versuchen im groben zu verstehen, was der Controller macht.</p>
<ul>
<li><span style="line-height: 16px;">Was für Logik beinhaltet der Controller?</span></li>
<li>Welche Services / Klassen werden verwendet?</li>
<li>Welche Daten werden für die HTML / JSON / XML Response aufbereitet?</li>
<li>Welche Templates werden mit den Daten befüllt?</li>
</ul>
<h1>Funktionale Tests schreiben</h1>
<p>Falls noch keine Tests vorhanden sind, sollte unbedingt versucht werden, die Controller mit funktionalen Tests abzudecken, um für das Refactoring Sicherheit zu gewinnen. Man soll schliesslich ohne Bedenken/Angst das Refactoring durchführen können. Da aktuell der Code wahrscheinlich sehr verdrahtet und abhängig voneinander ist, sind funktionale Tests die richtige Wahl. Ausserdem kann man mit funktionalen Tests auch viel Code mit verhältnismässig wenigen Tests abdecken.</p>
<h1>Auslagern in kleine private Methoden</h1>
<p>Nachdem die Tests geschrieben sind, kann man mit dem Auslagern des Controller-Codes in kleine private Methoden beginnen. Die privaten Methoden verbleiben hierbei noch im Controller, werden aber später in andere Klassen ausgelagert. Man sollte einfach kleine zusammenhängende Code-Blöcke finden und gute Funktionsnamen vergeben.</p>
<p>Ich empfehle ausserdem, dass die Code-Blöcke strikte in Integrations- oder Operations-Funktionen unterteilt werden. Der <a href="http://blog.ralfw.de/2013/04/software-fraktal-funktionale.html">Blogpost</a> von Ralf Westphal hat mich sehr beeindruckt und ist für mich ein sehr schlüssiges Vorgehen.</p>
<p>Während des Auslagerns, findet man eventuell noch weitere Testfälle, welche man dann natürlich ergänzen sollte. Ausserdem wird einem auch immer mehr klar, was der Code eigentlich genau alles tut/kann.</p>
<h1>Klassendesign erstellen</h1>
<p>Nachdem man nun viele kleine Methoden hat, sollte man Papier und Stift zur Hand nehmen und Klassen identifizieren, in welche die Methoden verschoben werden können. Es muss kein perfektes UML sein, eine einfach Skizze mit Kästchen und Pfeilen reicht schon. Man sollte einfach ein Gefühl für die neue Struktur erhalten. Ausserdem lohnt es sich eigentlich immer, wenn man das neue Klassendesign mit einem zweiten Entwickler kurz durchgeht/bespricht. Normalerweise kommt da immer wertvoller Input zurück.</p>
<h1>Refactoring in die neuen Klassen</h1>
<p>In diesem Schritt werden die Methoden in die vorher neu gebildeten Klassen verschoben. Währen dem Refactoring kann es gut sein, dass noch weitere Klassen dazu kommen oder auch wegfallen. Man sollte das ganze so lange weiterführen, bis man das Gefühl hat, dass die Methoden am richtigen Ort sind. Natürlich sollte man jeweils nach einigen kleinen Refactorings die Tests wieder laufen lassen, um zu prüfen, ob der Code noch das tut, was er vorher schon getan hat.</p>
<h1>Codereview eines Entwicklers</h1>
<p>Als letzten Schritt empfehle ich, dass der Code nochmals von einem anderen Entwickler angeschaut wird. Er soll vor allem darauf achten, ob er den Code versteht und falls eine Modifikation nötig wäre, das auch tun könnte, ohne den Code stundenlang studieren zu müssen.</p>
<h1>Feedback erwünscht</h1>
<p>Da dies ein sehr subjektives Vorgehen ist, würde mich Euer Feedback freuen.</p>
<ul>
<li>Sind das sinnvolle Schritte? Zu viel, zu wenig?</li>
<li>Wie packt ihr (Controller)-Refactorings normalerweise an?</li>
</ul>
<p>&nbsp;</p>
<div id="socialshareprivacy_4f282e4a8e94c0bf7fac8e36d102fb18"></div>
			<script type="text/javascript">
			(function($){
				var options = {"info_link":"http:\/\/www.heise.de\/ct\/artikel\/2-Klicks-fuer-mehr-Datenschutz-1333879.html","txt_help":"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i<\/em>.","settings_perma":"Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:","cookie_path":"\/","cookie_expire":365,"cookie_domain":"","css_path":"http:\/\/daraff.chsocialshareprivacy.css","services":{"facebook":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_facebook.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_fb_off":"nicht mit Facebook verbunden","txt_fb_on":"mit Facebook verbunden","display_name":"Facebook","referrer_track":"","language":"de_DE"},"twitter":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_twitter.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_twitter_off":"nicht mit Twitter verbunden","txt_twitter_on":"mit Twitter verbunden","display_name":"Twitter","referrer_track":"","tweet_text":""},"gplus":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_gplus.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_gplus_off":"nicht mit Google+ verbunden","txt_gplus_on":"mit Google+ verbunden","display_name":"Google+","referrer_track":"","language":"de"}}};
				options.cookie_domain = document.location.host;
				options.uri = 'http://daraff.ch/2013/05/lessons-learned-nzz-teil-5-refactoring-von-fat-controllern/'
				$(document).ready(function(){
					$('#socialshareprivacy_4f282e4a8e94c0bf7fac8e36d102fb18').socialSharePrivacy(options);
				});
			})(jQuery);
			</script>
		<!-- end wp-socialshareprivacy --> <p><a href="http://daraff.ch/?flattrss_redirect&amp;id=1794&amp;md5=4ccb671525b1bee8f31042f322b3e498" title="Flattr" target="_blank"><img src="http://daraff.ch/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://daraff.ch/2013/05/lessons-learned-nzz-teil-5-refactoring-von-fat-controllern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=30420&amp;popout=1&amp;url=http%3A%2F%2Fdaraff.ch%2F2013%2F05%2Flessons-learned-nzz-teil-5-refactoring-von-fat-controllern%2F&amp;language=de_DE&amp;category=text&amp;title=Lessons+Learned+%40+NZZ+%E2%80%93+Teil+5+%E2%80%93+Refactoring+von+Fat+Controllern&amp;description=This+entry+is+part+5+of+5+in+the+series+Lessons+Learned+%40+NZZIm+letzten+Teil+der+Serie+habe+ich+ja+beschrieben%2C+was+ein+%28Symfony2%29-Controller+tun+sollte+bzw.+was+meine...&amp;tags=blog" type="text/html" />

		<series:name><![CDATA[Lessons Learned @ NZZ]]></series:name>
	</item>
		<item>
		<title>Lessons Learned @ NZZ &#8211; Teil 4 &#8211; Symfony2 Controller</title>
		<link>http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/</link>
		<comments>http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/#comments</comments>
		<pubDate>Sat, 01 Dec 2012 12:25:41 +0000</pubDate>
		<dc:creator>DaRaFF</dc:creator>
				<category><![CDATA[Architektur / Design]]></category>

		<guid isPermaLink="false">http://daraff.ch/?p=1780</guid>
		<description><![CDATA[This entry is part 4 of 5 in the series Lessons Learned @ NZZBeruflich arbeite ich momentan intensiv mit Symfony2. Wir hatten in den letzten 1,5 Jahren im Team immer wieder grosse Meinungsunterschiede, welchen Ansatz man für Symfony2 Controller wählen &#8230; <a href="http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">This entry is part 4 of 5 in the series <a href="http://daraff.ch/series/lessons-learned-nzz/" class="series-148" title="Lessons Learned @ NZZ">Lessons Learned @ NZZ</a></div><p>Beruflich arbeite ich momentan intensiv mit Symfony2. Wir hatten in den letzten 1,5 Jahren im Team immer wieder grosse Meinungsunterschiede, welchen Ansatz man für Symfony2 Controller wählen soll.</p>
<ul>
<li>Direkt vom Symfony2 Controller erben?</li>
<li>Die Controller als Services aufsetzen und alle benötigten Services per Dependency Injection übergeben?</li>
<li>Die Controller als Services instanzieren und nur den Container per Dependency Injection übergeben und die Services aus dem Container laden?</li>
</ul>
<p>Es gibt für alle 3 Positionen pro&#8217;s und kontra&#8217;s. Einige von unseren Argumenten, waren aber geprägt von der bereits bestehenden Umgebung/Applikation. Eigentlich sollte man aber von einer idealen Umgebung ausgehen und überlegen, was das beste ist und erst dann auf die bestehende Situation adaptieren.</p>
<h1>Was ist die Aufgabe eines Controllers?</h1>
<p>Als erstes sollte man verstehen, was die Aufgabe eines Controllers in der Webentwicklung ist.</p>
<ol>
<li>Request zu einem Modelrequest konvertieren</li>
<li>Anfrage an Model</li>
<li>Fehlerhandling</li>
<li>Korrekte View auswählen</li>
<li>Model an View weiterleiten</li>
</ol>
<p>Wie man hier schön sehen kann, macht ein Controller nicht sehr viel. Er sollte also möglichst klein sein und nur die ihm zugetragenen Aufgaben erledigen (Idealerweise zwischen 10-20 Zeilen Code).</p>
<h1>Unsere Controller und unsere Argumente</h1>
<p>Wir hatten <strong>fat Controller</strong>, was bedeutet, wir haben alles mögliche in die Controller gepackt (ja, ich weiss, das ist nicht gut). Natürlich war die Situation wieder einmal dem Termindruck geschuldet und wie es halt so ist, wenn einmal ein gewisses Design da ist, dann macht man halt das gleiche, wie der Kollege vorher.</p>
<h3>Vom Symfony2 Controller vererben, Services aus Container beziehen</h3>
<ul>
<li>+ Es ist so offiziell in der Doku</li>
<li>+ Symfony2 Controller bietet bereits viele nützliche Funktionen und Services an</li>
<li>- Es kann zu schlechtem Design führen, weil jederzeit irgendwo irgendwelche Services aus dem Container geladen werden könnten</li>
</ul>
<h3>Controller als Service + Services als Dependency Injection</h3>
<ul>
<li>+ Man weiss schon im Konstruktor, welche Services verwendet werden.</li>
<li>+ Es besteht nicht die Gefahr, dass irgendwo im Verlaufe des Controllers über den Container nicht existierende oder fehlerhafte Services verwendet werden</li>
<li>+ Man hat Code Completion in der IDE</li>
</ul>
<h1>Erkenntnisse</h1>
<p>Ich hoffe jetzt mal, dass die Argumente im vorherigen Abschnitt Sinn für Euch machen. Es gibt sicher noch mehr. Einige der Argumente entstanden aber nur, weil wir im Controller das <a title="Single Responsibility Principle" href="http://de.wikipedia.org/wiki/Single-Responsibility-Prinzip">Single Responsibility Principle</a> verletzten. Uns war nicht wirklich bewusst (bzw. wir haben nicht lange genug darüber nachgedacht), was ein Controller genau zu tun hat. Dadurch entstanden interessante aber <strong>falsche</strong> Argumente.</p>
<p>Wir haben uns nun dazu entschieden, <strong>von den Symfony2 Controllern zu vererben</strong> und die <strong>Controller</strong> sollten als Faustregel <strong>nicht länger als 20 Zeilen</strong> beinhalten. Jetzt kann man die Argumente, die für den Controller als Service sprechen leicht entkräften.</p>
<blockquote><p>Es kann zu schlechtem Design führen, weil jederzeit irgendwo irgendwelche Services aus dem Container geladen werden könnten.<br />
Man weiss schon im Konstruktor, welche Services verwendet werden.</p></blockquote>
<p>Weil die Methoden jetzt klein sind, müssen generell nur wenige Services geladen werden, der Code ist/bleibt übersichtlich.</p>
<blockquote><p>Es besteht nicht die Gefahr, dass irgendwo im Verlaufe des Controllers über den Container nicht existierende oder fehlerhafte Services verwendet werden.</p></blockquote>
<p>Ok, die Gefahr besteht immer noch, aber mit funktionalen Tests und dem wenigen Code ist dies sehr einfach zu verhindern. In der vorherigen Situation mit riesen Controllern, war es echt heavy gute Funktionale Tests zu schreiben.</p>
<blockquote><p>Man hat Code Completion in der IDE</p></blockquote>
<p>Durch die kurzen Methoden, ist dies nicht mehr wirklich relevant.</p>
<h1>Was nun mit unseren Fat Controllern?</h1>
<p>Das klingt ja alles schön und gut, wenn man auf der grünen Wiese beginnt, aber was machen wir nun mit unseren bestehenden Controllern?</p>
<p>Refactoring, refactoring, refactoring. Uns bleibt nichts anderes übrig, als Schritt für Schritt Aufgaben im Controller Code zu identifieren und in Serviceklassen auszulagern.</p>
<p>Entscheidend ist, dass alle die gleiche Vorstellung davon haben, wie der Code bzw. die Controller in Zukunft aussehen sollen und jeder ein kleines Stück dazu beitragen kann.</p>
<p><strong>Quellen</strong></p>
<ul>
<li><a title="Controller Responsibilities" href="http://www.beberlei.de/talks/symfony-rest/#10 ">Controller Responsibilities</a></li>
<li><a title="Don't pull your dependencies" href="http://www.testically.org/2012/11/28/dont-pull-your-dependencies/">Don&#8217;t pull your dependencies</a></li>
<li><a href="http://symfony.com/doc/2.0/book/controller.html">Symfony2-doc Controller</a></li>
</ul>
<p>&nbsp;</p>
<div id="socialshareprivacy_9e8944dae6fd7af8c9d7b008a3532279"></div>
			<script type="text/javascript">
			(function($){
				var options = {"info_link":"http:\/\/www.heise.de\/ct\/artikel\/2-Klicks-fuer-mehr-Datenschutz-1333879.html","txt_help":"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i<\/em>.","settings_perma":"Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:","cookie_path":"\/","cookie_expire":365,"cookie_domain":"","css_path":"http:\/\/daraff.chsocialshareprivacy.css","services":{"facebook":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_facebook.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_fb_off":"nicht mit Facebook verbunden","txt_fb_on":"mit Facebook verbunden","display_name":"Facebook","referrer_track":"","language":"de_DE"},"twitter":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_twitter.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_twitter_off":"nicht mit Twitter verbunden","txt_twitter_on":"mit Twitter verbunden","display_name":"Twitter","referrer_track":"","tweet_text":""},"gplus":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_gplus.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_gplus_off":"nicht mit Google+ verbunden","txt_gplus_on":"mit Google+ verbunden","display_name":"Google+","referrer_track":"","language":"de"}}};
				options.cookie_domain = document.location.host;
				options.uri = 'http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/'
				$(document).ready(function(){
					$('#socialshareprivacy_9e8944dae6fd7af8c9d7b008a3532279').socialSharePrivacy(options);
				});
			})(jQuery);
			</script>
		<!-- end wp-socialshareprivacy --> <p><a href="http://daraff.ch/?flattrss_redirect&amp;id=1780&amp;md5=68ea31367754f8b3f0a3c7a856278a9e" title="Flattr" target="_blank"><img src="http://daraff.ch/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://daraff.ch/2012/12/lessons-learned-nzz-teil-4-symfony2-controller/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=30420&amp;popout=1&amp;url=http%3A%2F%2Fdaraff.ch%2F2012%2F12%2Flessons-learned-nzz-teil-4-symfony2-controller%2F&amp;language=de_DE&amp;category=text&amp;title=Lessons+Learned+%40+NZZ+%26%238211%3B+Teil+4+%26%238211%3B+Symfony2+Controller&amp;description=This+entry+is+part+4+of+5+in+the+series+Lessons+Learned+%40+NZZBeruflich+arbeite+ich+momentan+intensiv+mit+Symfony2.+Wir+hatten+in+den+letzten+1%2C5+Jahren+im+Team+immer...&amp;tags=blog" type="text/html" />

		<series:name><![CDATA[Lessons Learned @ NZZ]]></series:name>
	</item>
		<item>
		<title>Typische Beispielinstallation für einen PHP Webdeveloper auf Ubuntu</title>
		<link>http://daraff.ch/2012/11/typische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu/</link>
		<comments>http://daraff.ch/2012/11/typische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu/#comments</comments>
		<pubDate>Sat, 03 Nov 2012 11:55:04 +0000</pubDate>
		<dc:creator>DaRaFF</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://daraff.ch/?p=1764</guid>
		<description><![CDATA[Seit geraumer Zeit arbeite ich intensiv als PHP Webentwickler mit Ubuntu. Immer wieder mal kommt es vor, dass ich eine neue Maschine aufsetzen muss (seit für Heimarbeit oder weil ein Laptop seinen Dienst versagt hat&#8230;). Es kommt auch vor, dass &#8230; <a href="http://daraff.ch/2012/11/typische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Seit geraumer Zeit arbeite ich intensiv als PHP Webentwickler mit Ubuntu. Immer wieder mal kommt es vor, dass ich eine neue Maschine aufsetzen muss (seit für Heimarbeit oder weil ein Laptop seinen Dienst versagt hat&#8230;).</p>
<p>Es kommt auch vor, dass ich immer wieder mal gefragt werde, wie man am besten ein bestimmtes Tool wie z.B. PHPUnit auf seiner Entwicklermaschine installiert.</p>
<p>Ich habe mich darum entschieden, einen typischen Installationsstack für einen PHP Entwickler auf Ubuntu als Beispiel zu posten.</p>
<p>Natürlich bin ich für Feedback oder Verbesserungsvorschläge immer offen.</p>
<p>Beispielinstallation: <a href="https://gist.github.com/3995789">https://gist.github.com/3995789</a></p>
<div id="socialshareprivacy_83f2374ef34be436236affea0c2d95eb"></div>
			<script type="text/javascript">
			(function($){
				var options = {"info_link":"http:\/\/www.heise.de\/ct\/artikel\/2-Klicks-fuer-mehr-Datenschutz-1333879.html","txt_help":"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i<\/em>.","settings_perma":"Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:","cookie_path":"\/","cookie_expire":365,"cookie_domain":"","css_path":"http:\/\/daraff.chsocialshareprivacy.css","services":{"facebook":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_facebook.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_fb_off":"nicht mit Facebook verbunden","txt_fb_on":"mit Facebook verbunden","display_name":"Facebook","referrer_track":"","language":"de_DE"},"twitter":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_twitter.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_twitter_off":"nicht mit Twitter verbunden","txt_twitter_on":"mit Twitter verbunden","display_name":"Twitter","referrer_track":"","tweet_text":""},"gplus":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_gplus.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_gplus_off":"nicht mit Google+ verbunden","txt_gplus_on":"mit Google+ verbunden","display_name":"Google+","referrer_track":"","language":"de"}}};
				options.cookie_domain = document.location.host;
				options.uri = 'http://daraff.ch/2012/11/typische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu/'
				$(document).ready(function(){
					$('#socialshareprivacy_83f2374ef34be436236affea0c2d95eb').socialSharePrivacy(options);
				});
			})(jQuery);
			</script>
		<!-- end wp-socialshareprivacy --> <p><a href="http://daraff.ch/?flattrss_redirect&amp;id=1764&amp;md5=5f773dd23a51ff1cd32d62d29cc7e18f" title="Flattr" target="_blank"><img src="http://daraff.ch/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://daraff.ch/2012/11/typische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=30420&amp;popout=1&amp;url=http%3A%2F%2Fdaraff.ch%2F2012%2F11%2Ftypische-beispielinstallation-fur-einen-php-webdeveloper-auf-ubuntu%2F&amp;language=de_DE&amp;category=text&amp;title=Typische+Beispielinstallation+f%C3%BCr+einen+PHP+Webdeveloper+auf+Ubuntu&amp;description=Seit+geraumer+Zeit+arbeite+ich+intensiv+als+PHP+Webentwickler+mit+Ubuntu.+Immer+wieder+mal+kommt+es+vor%2C+dass+ich+eine+neue+Maschine+aufsetzen+muss+%28seit+f%C3%BCr+Heimarbeit+oder+weil+ein...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Lessons Learned @ NZZ &#8211; Teil3 &#8211; Code Reviews</title>
		<link>http://daraff.ch/2012/03/lessons-learned-nzz-teil3-code-reviews/</link>
		<comments>http://daraff.ch/2012/03/lessons-learned-nzz-teil3-code-reviews/#comments</comments>
		<pubDate>Mon, 19 Mar 2012 19:25:31 +0000</pubDate>
		<dc:creator>DaRaFF</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Qualität]]></category>
		<category><![CDATA[code review]]></category>
		<category><![CDATA[software qualität]]></category>

		<guid isPermaLink="false">http://daraff.ch/?p=1749</guid>
		<description><![CDATA[This entry is part 3 of 5 in the series Lessons Learned @ NZZHeute möchte ich über das Thema Code Reviews berichten. Vorgeschichte In der NZZ haben wir Ende des letzten Jahres unsere Code Repositories in Richtung Github gezügelt. Weil &#8230; <a href="http://daraff.ch/2012/03/lessons-learned-nzz-teil3-code-reviews/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">This entry is part 3 of 5 in the series <a href="http://daraff.ch/series/lessons-learned-nzz/" class="series-148" title="Lessons Learned @ NZZ">Lessons Learned @ NZZ</a></div><p>Heute möchte ich über das Thema Code Reviews berichten.</p>
<h1>Vorgeschichte</h1>
<p>In der NZZ haben wir Ende des letzten Jahres unsere Code Repositories in Richtung Github gezügelt. Weil das Entwicklerteam in kurzer Zeit sehr stark gewachsen ist, mussten wir Wege finden, die Codequalität auf einem hohen Stand zu etablieren. Dies haben wir mit Code Reviews und <a href="http://help.github.com/send-pull-requests/">Pull Requests</a> auf Github versucht.</p>
<h1>Der Prozess</h1>
<p>Ein neues Feature/Bugfix wird in einem neuen Branch, vorzugsweise mittels Pairprogramming, entwickelt. Sind der/die Entwickler der Meinung, dass Feature sei fertig, wird auf Github ein so genannter Pull Request eröffnet. Ein Pull Request zeigt die Unterschiede zwischen 2 Branches an (z.B. zwischen dem develop und dem feature Branch). Der Reviewer (Auch ein Entwickler, aber keiner der das Feature implementiert hat), macht nun folgende Dinge.</p>
<ul>
<li>Unittests durchlaufen lassen</li>
<li>Stylechecks durchlaufen lassen</li>
<li>Reviewen der Differenzen vom Pull Request</li>
<li>Feedback auf der Github Plattform bezüglich Mängeln</li>
</ul>
<p>Ist alles ok, integriert der Reviewer den Code in den develop Branch. Gibt es Mängel, sind die Entwickler wieder in der Pflicht und müssen die Mängel beheben. Dieses Ping Pong Spiel geht so lange weiter, bis der Reviewer der Meinung ist, dass alles ok ist.</p>
<h1>Fazit</h1>
<p>Als wir die Idee mit den Codereviews auf Github hatten, dachten wir, dass dies eine Verbesserung der Codequalität bringen könnte.</p>
<p>Der Effekt war aber deutlich grösser als erwartet. Die Qualität hat sich massiv gesteigert und die Knowhowverteilung ist auch besser geworden, da nun immer 2-3 Leute den Code kennen.</p>
<p>Da ich selber auch Reviewer bin, kann ich folgende Dinge dazu sagen:</p>
<ul>
<li>Code-Reviews haben sehr positive Auswirkungen auf die innere Qualität eines Projektes</li>
<li>Code reviewen ist sehr streng/anspruchsvoll</li>
<li>Entwickler lernen sehr viel aus den Feedbacks</li>
<li>Als Reviewer lernt man selber auch sehr viel dazu</li>
<li>Knowhow verteilt sich noch besser</li>
<li>Checkstylefehler, schlechte Variablennamen usw. sind einfach zu finden. Softwaredesignfehler sind aber sehr schwierig auszumachen und werden häufig zu wenig genau unter die Lupe genommen</li>
<li>Wenn man es seriös macht, benötigen Code Reviews sehr viel Zeit. Wenn man also unter Zeitdruck ist, leidet häufig auch die Qualität der Reviews</li>
</ul>
<p>&nbsp;</p>
<p>Was denkt Ihr über Code Reviews? Sind diese sinnvoll und wenn ja, warum? Oder sind sie nur Arbeitsbeschaffung?</p>
<p>&nbsp;</p>
<div id="socialshareprivacy_ea3f889f7ad04a5659ee98c812344a9b"></div>
			<script type="text/javascript">
			(function($){
				var options = {"info_link":"http:\/\/www.heise.de\/ct\/artikel\/2-Klicks-fuer-mehr-Datenschutz-1333879.html","txt_help":"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i<\/em>.","settings_perma":"Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:","cookie_path":"\/","cookie_expire":365,"cookie_domain":"","css_path":"http:\/\/daraff.chsocialshareprivacy.css","services":{"facebook":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_facebook.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_fb_off":"nicht mit Facebook verbunden","txt_fb_on":"mit Facebook verbunden","display_name":"Facebook","referrer_track":"","language":"de_DE"},"twitter":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_twitter.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_twitter_off":"nicht mit Twitter verbunden","txt_twitter_on":"mit Twitter verbunden","display_name":"Twitter","referrer_track":"","tweet_text":""},"gplus":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_gplus.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_gplus_off":"nicht mit Google+ verbunden","txt_gplus_on":"mit Google+ verbunden","display_name":"Google+","referrer_track":"","language":"de"}}};
				options.cookie_domain = document.location.host;
				options.uri = 'http://daraff.ch/2012/03/lessons-learned-nzz-teil3-code-reviews/'
				$(document).ready(function(){
					$('#socialshareprivacy_ea3f889f7ad04a5659ee98c812344a9b').socialSharePrivacy(options);
				});
			})(jQuery);
			</script>
		<!-- end wp-socialshareprivacy --> <p><a href="http://daraff.ch/?flattrss_redirect&amp;id=1749&amp;md5=5f706f093b9d85102f3bf45a02e98ba6" title="Flattr" target="_blank"><img src="http://daraff.ch/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://daraff.ch/2012/03/lessons-learned-nzz-teil3-code-reviews/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=30420&amp;popout=1&amp;url=http%3A%2F%2Fdaraff.ch%2F2012%2F03%2Flessons-learned-nzz-teil3-code-reviews%2F&amp;language=de_DE&amp;category=text&amp;title=Lessons+Learned+%40+NZZ+%26%238211%3B+Teil3+%26%238211%3B+Code+Reviews&amp;description=This+entry+is+part+3+of+5+in+the+series+Lessons+Learned+%40+NZZHeute+m%C3%B6chte+ich+%C3%BCber+das+Thema+Code+Reviews+berichten.+Vorgeschichte+In+der+NZZ+haben+wir+Ende+des...&amp;tags=code+review%2Csoftware+qualit%C3%A4t%2Cblog" type="text/html" />

		<series:name><![CDATA[Lessons Learned @ NZZ]]></series:name>
	</item>
		<item>
		<title>Lessons Learned @ NZZ &#8211; Teil2 &#8211; Distributed SCRUM Teams</title>
		<link>http://daraff.ch/2012/03/lessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams/</link>
		<comments>http://daraff.ch/2012/03/lessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams/#comments</comments>
		<pubDate>Fri, 02 Mar 2012 17:31:30 +0000</pubDate>
		<dc:creator>DaRaFF</dc:creator>
				<category><![CDATA[Softwareengineering]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[distributed teams]]></category>
		<category><![CDATA[scrum]]></category>

		<guid isPermaLink="false">http://daraff.ch/?p=1739</guid>
		<description><![CDATA[This entry is part 2 of 5 in the series Lessons Learned @ NZZWie ich schon im letzten Artikel erwähnt habe, sind wir aktuell 3 SCRUM Teams und haben diese auch in sehr kurzer Zeit von 4 auf 18 Entwickler &#8230; <a href="http://daraff.ch/2012/03/lessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">This entry is part 2 of 5 in the series <a href="http://daraff.ch/series/lessons-learned-nzz/" class="series-148" title="Lessons Learned @ NZZ">Lessons Learned @ NZZ</a></div><p>Wie ich schon im letzten Artikel erwähnt habe, sind wir aktuell 3 SCRUM Teams und haben diese auch in sehr kurzer Zeit von 4 auf 18 Entwickler hochgefahren (ca. 6 Monate).</p>
<p>Am Anfang gab es eine kurze Kennenlernphase zwischen den einzelnen Personen. Wir waren am gleichen Ort und arbeiteten zusammen. Danach wurden die Teams aufgeteilt und auf die Projekte losgelassen. Relativ schnell war die Kommunikation zwischen den Teams eher rar. Jedes Team hatte seine eigene Philosophie von Design, Standards usw. und über kurz oder lang, gab es kleinere Probleme. Man beschwerte sich, warum jemand das so gelöst hat und nicht so, wie es im eigenen Team geregelt war.</p>
<p>Wir versuchten also einen neuen Ansatz. Die zwei Teams aus Zürich und der Ukraine wurde gemischt, um die Kommunikation zwischen den beiden Standorten zu verbessern. Das Team von Liip, haben wir so belassen, weil es ein externer Partner ist.</p>
<p>Neu besuchen wir uns regelmässig. Leute von Kiev arbeiten 1-3 Wochen bei uns und umgekehrt. Auch die Leute vom Liip Team, arbeiten regelmässig in der NZZ.</p>
<p>Dieser Ansatz hat die Kommunikation zwischen den Teams extrem verbessert. Man versteht sich besser, man fühlt sich verbundener. Natürlich gibt es nach wie vor Problemchen, aber diese sind lange nicht mehr so gross wie vorher.</p>
<p>Was denkt ihr von dieser Lösung? Gibt es noch bessere Ansätze? Sollte man verteilte Teams generell versuchen zu vermeiden?</p>
<p>Ich bin gespannt auf eure Meinung.</p>
<div id="socialshareprivacy_9fa87f1fbbe17e5400116a2a27221b7f"></div>
			<script type="text/javascript">
			(function($){
				var options = {"info_link":"http:\/\/www.heise.de\/ct\/artikel\/2-Klicks-fuer-mehr-Datenschutz-1333879.html","txt_help":"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i<\/em>.","settings_perma":"Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:","cookie_path":"\/","cookie_expire":365,"cookie_domain":"","css_path":"http:\/\/daraff.chsocialshareprivacy.css","services":{"facebook":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_facebook.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_fb_off":"nicht mit Facebook verbunden","txt_fb_on":"mit Facebook verbunden","display_name":"Facebook","referrer_track":"","language":"de_DE"},"twitter":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_twitter.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_twitter_off":"nicht mit Twitter verbunden","txt_twitter_on":"mit Twitter verbunden","display_name":"Twitter","referrer_track":"","tweet_text":""},"gplus":{"status":"on","dummy_img":"http:\/\/daraff.chimages\/dummy_gplus.png","txt_info":"2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i<\/em>.","txt_gplus_off":"nicht mit Google+ verbunden","txt_gplus_on":"mit Google+ verbunden","display_name":"Google+","referrer_track":"","language":"de"}}};
				options.cookie_domain = document.location.host;
				options.uri = 'http://daraff.ch/2012/03/lessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams/'
				$(document).ready(function(){
					$('#socialshareprivacy_9fa87f1fbbe17e5400116a2a27221b7f').socialSharePrivacy(options);
				});
			})(jQuery);
			</script>
		<!-- end wp-socialshareprivacy --> <p><a href="http://daraff.ch/?flattrss_redirect&amp;id=1739&amp;md5=b4364bb503771cddd528972d927eb13d" title="Flattr" target="_blank"><img src="http://daraff.ch/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://daraff.ch/2012/03/lessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=30420&amp;popout=1&amp;url=http%3A%2F%2Fdaraff.ch%2F2012%2F03%2Flessons-learned-nzz-teil2-zusammenarbeit-von-distributed-scrum-teams%2F&amp;language=de_DE&amp;category=text&amp;title=Lessons+Learned+%40+NZZ+%26%238211%3B+Teil2+%26%238211%3B+Distributed+SCRUM+Teams&amp;description=This+entry+is+part+2+of+5+in+the+series+Lessons+Learned+%40+NZZWie+ich+schon+im+letzten+Artikel+erw%C3%A4hnt+habe%2C+sind+wir+aktuell+3+SCRUM+Teams+und+haben+diese...&amp;tags=agile%2Cdistributed+teams%2Cscrum%2Cblog" type="text/html" />

		<series:name><![CDATA[Lessons Learned @ NZZ]]></series:name>
	</item>
	</channel>
</rss>
