tag:blogger.com,1999:blog-36429538435287516642024-03-06T09:23:34.503+01:00Stefan Diener - Software developmentstefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-3642953843528751664.post-55414072052835480342017-06-16T10:31:00.003+02:002017-06-29T12:58:00.780+02:00Erste Gehversuche mit KotlinMoved to Google+: <a href="https://plus.google.com/+StefanDiener222/posts/Srug9CvmBTm">https://plus.google.com/+StefanDiener222/posts/Srug9CvmBTm</a><br />
<ul>
</ul>
stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-8591488460655613632017-06-02T15:58:00.002+02:002017-06-29T12:57:33.073+02:00Kotlin in ActionMoved to Google+: <a href="https://plus.google.com/+StefanDiener222/posts/aUsYYNr58fv">https://plus.google.com/+StefanDiener222/posts/aUsYYNr58fv</a><br />
<br />stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-54479224034401864812012-10-14T10:59:00.001+02:002012-10-14T11:00:34.802+02:00Lessons in App Building<a href="https://plus.google.com/u/0/112320456900086587872/posts/WA646CqubF8" target="_blank">Lessons in App Building (from Entrepreneur August 2012)</a>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-23157701913135890442012-10-01T17:27:00.002+02:002022-03-03T07:08:24.685+01:00Android: Screen Densities, Sizes, Configurations, and Icon Sizes<h3>
1. Definitions</h3>
<ul>
<li> <b>resolution</b> = number of pixels available in the display, scale-independent pixel = <b>sp</b></li>
<li> <b>density</b> = how many pixels appear within a constant area of the display, dots per inch = <b>dpi</b></li>
<li> <b>size</b> = amount of physical space available for displaying an interface, screen's diagonal, <b>inch</b></li>
<li> <b>density-independent pixel</b> = virtual pixel that is independent of the screen density, <b>dp</b></li>
</ul>
<br />
<h3>
2. Density Classes</h3>
<table border="1" cellpadding="5">
<tbody>
<tr><th>Class</th><th>Name</th><th>Density</th><th>Factor</th><th>Drawable Folder</th><th>Comment</th></tr>
<tr><td>ldpi</td><td>low density</td><td>120 dpi</td><td>sp = 3/4 * dp</td><td>drawable-ldpi</td><td></td></tr>
<tr><td>mdpi</td><td>medium density</td><td>160 dpi</td><td>sp = dp</td><td>drawable-mdpi OR drawable</td><td>baseline size, example: 320x480 (sp or dp)</td></tr>
<tr><td>hdpi</td><td>high density</td><td>240 dpi</td><td>sp = 1.5 x dp</td><td>drawable-hdpi</td><td>example: 480x800 sp = 320x533 dp</td></tr>
<tr><td>xhdpi</td><td>extra high density</td><td>320 dpi</td><td>sp = 2 x dp</td><td>drawable-xhdpi</td><td></td></tr>
<tr><td>xxhdpi</td><td>extra extra high density</td><td>480 dpi</td><td>sp = 3 x dp</td><td>drawable-xxhdpi</td><td></td></tr>
<tr><td>xxxhdpi</td><td>extra extra extra high density</td><td>640 dpi</td><td>sp = 4 x dp</td><td>drawable-xxxhdpi</td><td></td></tr>
</tbody></table>
<br />
<h3>
3. Icon Sizes (full / content)</h3>
<table border="1" cellpadding="5">
<tbody>
<tr><th>Density</th><th>Launcher</th><th>Menu</th><th>Action Bar</th><th>Status Bar and Notification</th><th>Tab</th><th>Pop-up Dialog and List View</th><th>Small and Contextual</th></tr>
<tr><td>ldpi</td><td>36x36 px</td><td>36x36 / 24x24 px</td><td>24x24 / 18x18 px</td><td>18x18 / 16x16 px</td><td>24x24 / 22x22 px</td><td>24x24 px</td><td>12x12 / 9x9 px</td></tr>
<tr><td>mdpi</td><td>48x48 px</td><td>48x48 / 32x32 px</td><td>32x32 / 24x24 px</td><td>24x24 / 22x22 px</td><td>32x32 / 28x28 px</td><td>32x32 px</td><td>16x16 / 12x12 px</td></tr>
<tr><td>hdpi</td><td>72x72 px</td><td>72x72 / 48x48 px</td><td>48x48 / 36x36 px</td><td>36x36 / 33x33 px</td><td>48x48 / 42x42 px</td><td>48x48 px</td><td>24x24 / 18x18 px</td></tr>
<tr><td>xhdpi</td><td>96x96 px</td><td>96x96 / 64x64 px</td><td>64x64 / 48x48 px</td><td>48x48 / 44x44 px</td><td>64x64 / 56x56 px</td><td>64x64 px</td><td>32x32 / 24x24 px</td></tr>
<tr><td>xxhdpi</td><td>144x144 px</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td></tr>
<tr><td>xxxhdpi</td><td>192x192 px</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td><td>(1)</td></tr>
</tbody></table>
<ul>
<li>(1) Google documentation says: "Applications should not generally worry about this density; relying on XHIGH graphics being scaled up to it should be sufficient for almost all cases." </li>
<li>Launcher icons for Android Market: 512x512 px.</li>
</ul>
<br />
<h3>
4. Screen Size Classes</h3>
<table border="1" cellpadding="5">
<tbody>
<tr><th>Class</th><th>Size in dp</th><th>Layout Folder</th><th>Examples</th><th>Comment</th></tr>
<tr><td>small</td><td>426x320 dp</td><td>layout-small</td><td>typical phone screen (240x320 ldpi, 320x480 mdpi, etc.)</td><td></td></tr>
<tr><td>normal</td><td>470x320 dp</td><td>layout-normal OR layout</td><td>typical phone screen (480x800 hdpi)</td><td>baseline size</td></tr>
<tr><td>large</td><td>640x480 dp</td><td>layout-large</td><td>tweener tablet like the Streak (480x800 mdpi), 7" tablet (600x1024 mdpi)</td><td></td></tr>
<tr><td>xlarge</td><td>960x720 dp</td><td>layout-xlarge</td><td>10" tablet (720x1280 mdpi, 800x1280 mdpi, etc.)</td><td></td></tr>
</tbody></table>
<ul>
<li> valid for Android 3.1 and older</li>
<li> for Android 3.2 and newer see: <a href="http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a></li>
</ul>
<br />
<h3>
5. Example Screen Configurations</h3>
<table border="1" cellpadding="5">
<tbody>
<tr><th>Screen Size</th><th>Low density (120), <i>ldpi</i></th><th>Medium density (160), <i>mdpi</i></th><th>High density (240), <i>hdpi</i></th><th>Extra high density (320), <i>xhdpi</i></th></tr>
<tr><td>small</td><td>QVGA (240x320)</td><td></td><td>480x640</td><td></td></tr>
<tr><td>normal</td><td>WQVGA400 (240x400)<br />
WQVGA432 (240x432)</td><td>HVGA (320x480)</td><td>WVGA800 (480x800)<br />
WVGA854 (480x854)<br />
600x1024</td><td>640x960</td></tr>
<tr><td>large</td><td>WVGA800 (480x800)<sup>(2)</sup><br />
WVGA854 (480x854)<sup>(2)</sup></td><td>WVGA800 (480x800)<sup>(1)</sup><br />
WVGA854 (480x854)<sup>(1)</sup><br />
600x1024</td><td></td><td></td></tr>
<tr><td>xlarge</td><td>1024x600</td><td>WXGA (1280x800)<sup>(3)</sup><br />
1024x768<br />
1280x768</td><td>1536x1152<br />
1920x1152<br />
1920x1200</td><td>2048x1536<br />
2560x1536<br />
2560x1600</td></tr>
</tbody></table>
<ul>
<li> (1) To emulate this configuration, specify a custom density of 160 when creating an Android Virtual Device that uses a WVGA800 or WVGA854 skin.</li>
<li> (2) To emulate this configuration, specify a custom density of 120 when creating an Android Virtual Device that uses a WVGA800 or WVGA854 skin.</li>
<li> (3) This skin is available with the Android 3.0 platform.</li>
</ul>
<br />
<h3>
6. Screen Orientation</h3>
<table border="1" cellpadding="5">
<tbody>
<tr><th>Orientation</th><th>Name</th><th>Layout Folder, Example</th></tr>
<tr><td>port</td><td>portrait</td><td>layout-port-large</td></tr>
<tr><td>land</td><td>landscape</td><td>layout-land-normal OR layout-land</td></tr>
</tbody></table>
<br />
<h3>
7. Best Practices</h3>
<ol>
<li> Use <tt>wrap_content</tt>, <tt>match_parent</tt>, or dp units when specifying dimensions in an XML layout file.
<ul>
<li> except for defining text sizes: sp (scaling depends on user setting)</li>
<li>Note: <tt>fill_parent</tt> is deprecated since API level 8.</li>
</ul>
</li>
<li> Do not use hard coded pixel values in your application code.</li>
<li> Do not use <tt>AbsoluteLayout</tt>.
<ul>
<li> deprecated since Android 1.5</li>
<li> alternative: <tt>RelativeLayout</tt>
</li>
</ul>
</li>
<li> Supply alternative bitmap drawables for different screen densities.</li>
<li>Provide a launcher icon for xxhdpi, but no other icons. </li>
</ol>
<br />
<h3>
8. References</h3>
<ul>
<li> <a href="http://android-developers.blogspot.de/2011/07/new-tools-for-managing-screen-sizes.html">New Tools For Managing Screen Sizes</a>, Android Developers Blog</li>
<li> <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple Screens</a>, Android Developers Guide</li>
<li> <a href="http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>, Android Developers Guide</li>
<li> <a href="http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources">Providing Alternative Resources</a>, Android Developers Guide</li>
<li> <a href="http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch">How Android Finds the Best-matching Resource</a>, Android Developers Guide</li>
<li> <a href="http://developer.android.com/design/index.html">Android Design</a></li>
<li> <a href="http://developer.android.com/design/style/iconography.html">Iconography</a>, Android Design</li>
<li> <a href="http://developer.android.com/training/multiscreen/index.html">Designing for Multiple Screens</a>, Android Developers Training</li>
<li> <a href="http://developer.android.com/about/dashboards/index.html">Platform Versions</a>, Android Developers Device Dashboard</li>
<li> <a href="https://plus.google.com/118292708268361843293/posts/ePQya3KsTjW">Nick Butcher: Nexus 10 launcher icons</a></li>
<li> <a href="http://blog.blundell-apps.com/list-of-android-devices-with-pixel-density-buckets/">List of Android Devices with pixel density buckets</a></li>
</ul>
<br />stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com3tag:blogger.com,1999:blog-3642953843528751664.post-25203861468167259682012-05-25T17:14:00.000+02:002012-05-28T16:58:37.157+02:00Google Retail Store<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimOY6uupZZUSmHNz3BudIuTFkQfGq33aKSA7dDHS6iros_kklDZJAZ21rwPhA8ioMfCdmECJyQ_Fti6iUERAvbc-Fc7KxkYdmPWFfHym6k9aGfSj6JvGhs4BkpE49ZHdiOjhlNegHignjA/s1600/20120506_1_Google_Buildung44.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
The Google Retail Store is located on the Google Campus in Mountain View at 2000 Charleston Road. The store is NOT open to the public, it's for Googlers and their guests only. No tailgating. No cash accepted, credit cards and Google Wallet only.<br />
<br />
WGS84 coordinates: N37.422722 W122.088223<br />
<br />
If you cannot find a Googler to invite you, watch the video instead (thanks to asypta):<br />
<a href="http://www.youtube.com/watch?v=17VHr6rsPAw">http://www.youtube.com/watch?v=17VHr6rsPAw</a><br />
<br />
Some more pictures of the store: <a href="http://mithun.com/projects/project_detail/technologycompany_store/" target="_blank">http://mithun.com/projects/project_detail/technologycompany_store/</a><br />
<br />
When you visit the Google Campus, don't miss the Android sculptures in front of Building 44, at 1625 Charleston Road.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimOY6uupZZUSmHNz3BudIuTFkQfGq33aKSA7dDHS6iros_kklDZJAZ21rwPhA8ioMfCdmECJyQ_Fti6iUERAvbc-Fc7KxkYdmPWFfHym6k9aGfSj6JvGhs4BkpE49ZHdiOjhlNegHignjA/s1600/20120506_1_Google_Buildung44.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimOY6uupZZUSmHNz3BudIuTFkQfGq33aKSA7dDHS6iros_kklDZJAZ21rwPhA8ioMfCdmECJyQ_Fti6iUERAvbc-Fc7KxkYdmPWFfHym6k9aGfSj6JvGhs4BkpE49ZHdiOjhlNegHignjA/s400/20120506_1_Google_Buildung44.JPG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Google Building 44</td></tr>
</tbody></table>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-21168297067584395662012-01-30T19:07:00.002+01:002012-01-30T19:10:00.843+01:00Android Lint und Jenkins / HudsonUm die Warnungen von Android Lint in Jenkins (oder Hudson, wenn man mag) anzuzeigen, ist ein wenig Konfigurationsaufwand notwendig, siehe hier:<br /><a href="http://stackoverflow.com/questions/8745949/display-android-lint-results-in-jenkins">http://stackoverflow.com/questions/8745949/display-android-lint-results-in-jenkins</a>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-63861073210121579552011-12-05T19:13:00.001+01:002011-12-05T19:14:50.776+01:00Probleme beim Bauen von Android-Projekten unter Ubuntu?Dann könnte dieser Artikel sehr hilfreich sein:<br /><a href="http://polywogsys.livejournal.com/286952.html">http://polywogsys.livejournal.com/286952.html</a>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-47247838917680167522011-02-05T17:00:00.003+01:002011-02-05T17:08:15.976+01:00Clean Code Developer: 3. Gelber Grad - Zusammenfassung<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRQlMcJDmoNaqOYNL76I7u37I-Kqh1QEbfe1-y5PE-AYsvt-lCDqy20M4MXDBUmKDUXRdH99yjdVg8RPPcG_4LwjWEVq2Jvj6lppcg7wqjYzo2HJt11HLiDxy0EYDL3bG4qdYEmfEDJxCu/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRQlMcJDmoNaqOYNL76I7u37I-Kqh1QEbfe1-y5PE-AYsvt-lCDqy20M4MXDBUmKDUXRdH99yjdVg8RPPcG_4LwjWEVq2Jvj6lppcg7wqjYzo2HJt11HLiDxy0EYDL3bG4qdYEmfEDJxCu/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5570236106968140178" border="0" /></a>Also, dann auf zum dritten Grad...<br /><br /><span style="font-weight: bold;font-size:130%;" >1. Prinzipien</span><br /><br /><span style="font-size:130%;">1.1 Interface Segregation Principle</span><br /><br /><i>Warum? Leistungsbeschreibungen, die unabhängig von einer konkreten Erfüllung sind, machen unabhängig.</i><br /> <ul><li> Interfaces sollten möglichst klein sein, um unnötige Kopplung zu vermeiden.</li> <li> Interfaces sollten nur Dinge enthalten, die wirklich eng zusammen gehören (hohe Kohäsion).</li> <li> Ziel: möglichst geringe Kopplung ziwschen den Komponenten</li></ul><span style="font-size:130%;">1.2 Dependency Inversion Principle</span><br /><br /><i>Warum? Punktgenaues Testen setzt Isolation von Klassen voraus. Isolation entsteht, wenn Klassen keine Abhängigkeiten von Implementationen mehr enthalten – weder zur Laufzeit, noch zur Übersetzungszeit. Konkrete Abhängigkeiten sollten deshalb so spät wie möglich entschieden werden. Am besten zur Laufzeit.</i><br /><ul><li> High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von Interfaces.</li> <li> Interfaces sollen nicht von Details abhängig sein, sondern Details von Interfaces.</li> <li> Mindestanforderung im 3. Grad: Abhängigkeiten über Konstruktoren injizieren</li></ul><span style="font-size:130%;">1.3 Liskov Substitution Principle</span><br /><br /><i>Warum? Wer mit Erben zu tun hat, möchte keine Überraschungen erleben, wenn er mit Erblassern vertraut ist.</i><br /><ul><li> Kernaussage: Subtypen müssen sich so verhalten wie ihr Basistyp</li> <li> allgemeiner: ein Subtyp darf die Funktionalität eines Basistyps lediglich erweitern, aber nicht einschänken</li> <li> Empfehlung: über Vererbung genau nachdenken<br /> <ul><li> siehe <i>Favor Composition over Inheritance (FCoI)</i>, <a href="http://stefan222devel.blogspot.com/2010/04/clean-code-developer-1-roter-grad.html" target="_blank">roter Grad</a></li> <li> bei Vererbung über Verhalten nachdenken, nicht nur über Struktur</li> </ul></li></ul><span style="font-size:130%;">1.4 Principle of Least Astonishment</span><br /><br /><i>Warum? Wenn sich eine Komponente überraschenderweise anders verhält als erwartet, wird ihre Anwendung unnötig kompliziert und fehleranfällig.</i><br /><ul><li> Software sollte überraschungsarm implementiert sein. Jede Überraschung stellt eine Unterbrechung dar und stört den kreativen Prozess der Softwareentwicklung.</li> <li> Die testgetriebene Entwicklung fördert überraschungsarme Schnittstellen.</li></ul><span style="font-size:130%;">1.5 Information Hiding Principle</span><br /><br /><i>Warum? Durch das Verbergen von Details in einer Schnittstelle werden die Abhängigkeiten reduziert.</i><br /><ul><li> Je mehr Details von außen sichtbar sind, desto höher ist die Kopplung zwischen der Klasse und ihren Verwendern.</li> <li> Benutzen die Verwender einer Klasse erstmal ein Detail, wird es schwerer, dieses Detail zu verändern.</li></ul><span style="font-weight: bold;font-size:130%;" >2. Praktiken</span><br /><br /><span style="font-size:130%;">2.1 Automatisierte Unit-Tests</span><br /><br /><i>Warum? Nur automatisierte Tests werden auch wirklich konsequent ausgeführt. Je punktgenauer sie Code testen, desto besser.</i><br /><ul><li> Regressionstests, um Korrektheit von Änderungen sicherzustellen und Angst vor Änderungen zu nehmen</li> <li> Automatisierung notwendig, da händisch nicht praktikabel</li> <li> Automatisierte Tests sparen Zeit und nehmen Angst.</li></ul><span style="font-size:130%;">2.2 Mockups (Testattrappen)</span><br /><br /><i>Warum? Ohne Attrappen keine einfach kontrollierbaren Tests.</i><br /><ul><li> Will man eine Komponente isoliert testen, müssen die Abhängigkeiten zu anderen Komponenten abgetrennt werden.</li> <li> Beim Isolieren werden sogenannte Mockups anstelle der echten Komponenten verwendet.</li> <li> andere Bezeichnungen für Attrappen: Stub, Dummy, Fake (teilweise mit <a href="http://martinfowler.com/articles/mocksArentStubs.html" target="_blank">unterschiedlichen Funktionsweisen</a>)</li></ul><span style="font-size:130%;">2.3 Code Coverage Analyse</span><br /><br /><i>Warum? Traue nur Tests, von denen du weißt, dass sie auch wirklich das Testareal abdecken.</i><br /><ul><li> Unit Tests sollten nach Möglichkeit alle Pfade durch unseren Code abdecken.</li> <li> Die Code Coverage Analyse dient dazu, Bereiche im Code aufzudecken, die noch nicht während der automatisierten Tests ausgeführt werden.</li> <li> Mögliche Metriken:<br /> <ul><li> C0-Überdeckung = Anweisungsüberdeckung</li> <li> C1-Überdeckung = Entscheidungs- / Zweigüberdeckung</li> </ul></li> <li> Ziel: theoretisch 100% Überdeckung, praktisch mehr als 90% Überdeckung</li></ul><span style="font-size:130%;">2.4 Teilnahme an Fachveranstaltungen</span><br /><br /><i>Warum? Am besten lernen wir von anderen und in Gemeinschaft.</i><br /><ul><li> Gedankenaustausch, Diskussionen, Erfahrungen austauschen, "über den Tellerrand blicken"</li> <li> z.B. regionale User Groups, überregionale Entwicklerkonferenzen</li></ul><span style="font-size:130%;">2.5 Komplexe Refaktorisierungen</span><br /><br /><i>Warum? Es ist nicht möglich, Code direkt in der ultimativen Form zu schreiben.</i><br /><ul><li> Erweiterung zum <a href="http://stefan222devel.blogspot.com/2010/04/clean-code-developer-1-roter-grad.html" target="_blank">roten Grad</a></li> <li> unbedingte Voraussetzung: automatisierte Tests</li></ul>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-5119187592611921962011-02-02T17:03:00.003+01:002011-02-02T17:10:20.574+01:00Clean Code Developer: 2. Oranger Grad - Erfahrungen<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy17Oxi5z6CHWJ0d9UjlZJkmUBNTWov82znokoGzpJLwxEZ7akXlgOaLXHhospfatTcMt-R4E2PLvAqCd_wjAv3SiM5qyKDew1Ou_0fM9Cy2Mn4-UBkWTQyt7pbS4w6jADnyaJVoWgO0m7/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy17Oxi5z6CHWJ0d9UjlZJkmUBNTWov82znokoGzpJLwxEZ7akXlgOaLXHhospfatTcMt-R4E2PLvAqCd_wjAv3SiM5qyKDew1Ou_0fM9Cy2Mn4-UBkWTQyt7pbS4w6jADnyaJVoWgO0m7/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5569123633023331954" border="0" /></a>Puhhh, der orange Grad hat sich sehr in die Länge gezogen. Nicht etwa weil ich ständig das Armband auf die andere Seite hätte wechseln müssen, sondern eher weil ich so wenig zum Programmieren gekommen bin. Zum Jahresende 2010 war's dann endlich geschafft und schon Anfang Februar 2011 komme ich dazu, den Blog nachzuziehen. Eine Zusammenfassung der Prinzipien und Praktiken sind in meinem <a href="http://stefan222devel.blogspot.com/2010/06/clean-code-developer-2-oranger-grad.html">Post vom 07. Juni 2010</a> zu finden. Hier meine Erfahrungen und Meinungen...<br /><br /><span style="font-weight: bold;font-size:130%;" >3. Ergebnisse</span><br /><span style="font-size:130%;">3.1 Single Level of Abstraction (SLA)</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Beachte ich meist "aus dem Gefühl heraus". Dieses Prinzip muss ich in Zukunft noch mehr verinnerlichen.</li><li>Erkenntnisse:<br /><ul><li> Eine manuelle Überprüfung, ob dieses Prinzip eingehalten wurde, ist sehr mühselig. Eine automatische Überprüfung ist unmöglich.</li><li> Man sollte beim Lesen einer Methode auf sein Bauchgefühl hören und bei Bedarf dann genauer hinsehen, ob SLA eingehalten wurde.<br /></li></ul></li></ul><span style="font-size:130%;">3.2 Single Responsibility Principle (SRP)</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Im Tagesgeschäft beachte ich diese Regel. Immer, wenn ich neue Funktionalität zu einer Klasse hinzufüge, frage ich mich vorher, ob dies noch zur Aufgabe der Klasse gehört oder nicht.</li><li>Erkenntnisse:<br /><ul><li> Natürlich ist man manchmal versucht, noch eine "Kleinigkeit" zu einer Klasse hinzuzufügen, aber hier muss man Disziplin wahren...</li></ul></li></ul><span style="font-size:130%;">3.3 Separation of Concerns (SoC)</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Ich achte insgesamt stärker auf die Einhaltung von SoC. Manchmal ist es nicht einfach, die verschiedenen Belange sauber zu trennen, so dass ich in berechtigten Fällen durchaus der pragmatischeren Lösung den Vorzug gebe.</li><li>Erkenntnisse:<br /><ul><li> Die <a href="http://de.wikipedia.org/wiki/Aspektorientierte_Programmierung" target="_blank">Aspektorientierte Programmierung</a> scheint hier das Mittel der Wahl zu sein.</li><li> Meine persönlichen Erfahrungen mit der AOP waren bisher allerdings eher ernüchternd bis frustrierend. Die Integration in die Eclipse IDE funktionierte nicht richtig und das Zusammenspiel mit RCP bzw. OSGi ist ein einziger Alptraum. Natürlich gibt's da haufenweise tolle Präsentationen von smarten Consultants zu dem Thema, aber ich halte die Kombination RCP / OSGi / AOP im Moment nicht für praxistauglich.</li></ul></li></ul><span style="font-size:130%;">3.4 Source Code Konventionen</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Code-Konventionen sind vorhanden und werden seit längerer Zeit schon angewendet. Es existiert ein schriftliches Regelwerk plus Konfigurationen für Checkstyle und PMD. Beide Tools werden sowohl in der Eclipse IDE, als auch im <i>Nightly Build</i> ausgeführt.</li></ul><span style="font-size:130%;">3.5 Issue Tracking</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Wird seit längerem bereits eingesetzt und hat sich ohne Frage bewährt.</li><li>Tools:<br /><ul><li> früher Mantis, <a href="http://www.mantisbt.org/" target="_blank">http://www.mantisbt.org/</a></li><li> aktuell Trac, <a href="http://trac.edgewall.org/" target="_blank">http://trac.edgewall.org/</a></li><li> und die Tracker der <a href="http://www.sourceforge.net/" target="_blank">SourceForge</a>-Projekte</li></ul></li></ul><span style="font-size:130%;">3.6 Automatisierte Integrationstests</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Automatisierte Integrationstest sind nur wenige vorhanden. Die Integrations- und Unit-Tests werden aktuell in den <i>Nightly Build</i> integriert.</li><li>Tools:<br /><ul><li> Hudson, <a href="http://hudson-ci.org/" target="_blank">http://hudson-ci.org/</a></li><li> JUnit, <a href="http://www.junit.org/" target="_blank">http://www.junit.org/</a></li><li> Ant, <a href="http://ant.apache.org/" target="_blank">http://ant.apache.org/</a></li><li> Eclipse Test Framework (ETF), <a href="http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.test/testframework.html?view=co" target="_blank">http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.test/testframework.html?view=co</a></li><li> PDE Test Utilities, <a href="http://www.eclipse.org/articles/Article-PDEJUnitAntAutomation/index.html#PDE_Test_Utilities" target="_blank">http://www.eclipse.org/articles/Article-PDEJUnitAntAutomation/index.html#PDE_Test_Utilities</a></li></ul></li><li>Erkenntnisse:<br /><ul><li> Seit <a href="http://www.eclipse.org/helios/" target="_blank">Eclipse Helios</a> wird JUnit 4 vom automatischen PDE-Build unterstützt.</li></ul></li></ul><span style="font-size:130%;">3.7 Lesen, Lesen, Lesen</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Vom Java-Magazin und Eclipse-Magazin lese ich jede Ausgabe, Blogs nur bei Bedarf und Fachbücher max. 2 pro Jahr. Mehr ist zeitlich leider nicht drin.</li></ul><span style="font-size:130%;">3.8 Reviews</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Pair-Reviews sind bei mir nicht möglich. Direkt vor jedem Commit führe ich immer einen Review meines eigenen Codes durch, was sich sehr bewährt hat.</li></ul>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-84516136140698374012011-01-28T17:07:00.006+01:002011-01-28T17:30:40.933+01:00Zurück von der OOP 2011<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL5l1-NFy8-pu2018NIRH0tWFGc48fJP17koN4nlvNO-XxY-CSzswGA0KF9NDdm60CEYGfop_CGKxc9vY7OXTFs50F99KHvV81TeFSvR33vXT5gaedf4VRCre-E5JbOEmXWDAAmrp-KggA/s1600/startteaser_oop2011.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 220px; height: 220px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL5l1-NFy8-pu2018NIRH0tWFGc48fJP17koN4nlvNO-XxY-CSzswGA0KF9NDdm60CEYGfop_CGKxc9vY7OXTFs50F99KHvV81TeFSvR33vXT5gaedf4VRCre-E5JbOEmXWDAAmrp-KggA/s400/startteaser_oop2011.jpg" alt="" id="BLOGGER_PHOTO_ID_5567269828463306018" border="0" /></a>Wow, nun ist sie leider schon wieder vorbei, die OOP 2011. Es wurde diesmal ein tolles Programm geboten, inklusive einige lebender Legenden, wie z.B. <a href="http://de.wikipedia.org/wiki/Erich_Gamma">Erich Gamma</a>, <a href="http://www.martinfowler.com/">Martin Fowler</a>, <a href="http://www.systemsguild.com/tdm.htm">Tom DeMarco</a> und <a href="http://www.omnisophie.com/">Gunter Dueck</a>. Spitze!stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-28728068849263907482010-06-07T19:14:00.004+02:002010-06-09T15:11:00.869+02:00Clean Code Developer: 2. Oranger Grad - Zusammenfassung<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi38CDI81UMJj0EocZvsu3A1UND8qjXu0RUZXtULAkFOmrFBLJEUWhbr92JZiIMXqTOTAt3fUF0TL_1X_qexjEgczG3CGH4d9bGakaPSkXGINeN3p3ftk-oE__9pYsxtHT-J75OgBp22AxL/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi38CDI81UMJj0EocZvsu3A1UND8qjXu0RUZXtULAkFOmrFBLJEUWhbr92JZiIMXqTOTAt3fUF0TL_1X_qexjEgczG3CGH4d9bGakaPSkXGINeN3p3ftk-oE__9pYsxtHT-J75OgBp22AxL/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5480081410251458466" border="0" /></a>Also, dann auf zum zweiten Grad...<br /><br /><span style="font-weight: bold;font-size:130%;" >1. Prinzipien</span><br /><span style="font-size:130%;">1.1 Single Level of Abstraction (SLA)</span><br /><br /><i>Warum? Die Einhaltung eines Abstraktionsniveaus fördert die Lesbarkeit.</i><br /><ul><li>Variablenzuweisung = niedrigstes Abstraktionsniveau, Methodenaufrufe = höhere Abstraktionsniveaus, API-Aufrufe = sehr hohes Level</li><li>Innerhalb einer Methode sollte nur ein Abstraktionsniveau verwendet werden, damit der Code gut lesbar und leicht zu verstehen ist.</li></ul><span style="font-size:130%;">1.2 Single Responsibility Principle (SRP)</span><br /><br /><i>Warum? Fokus erleichtert das Verständnis. Eine Klasse mit genau einer Aufgabe ist verständlicher als ein Gemischtwarenladen.</i><br /><ul><li>Eine Klasse sollte nur einen Grund für Änderungen haben. Folglich übernimmt eine Klasse genau eine Aufgabe.</li><li>Verletzung des <i>Single Responsibility Principles</i> führt zu Kopplung und erhöhter Komplexität</li></ul><span style="font-size:130%;">1.3 Separation of Concerns (SoC)</span><br /><br /><i>Warum? Wenn eine Codeeinheit keine klare Aufgabe hat ist es schwer sie zu verstehen, sie anzuwenden und sie ggf. zu korrigieren oder zu erweitern.</i><br /><ul><li>Concerns (Belange) stehen orthogonal zueinander und zur Hauptfunktionalität, z.B. Tracing, Logging, Transaktionalität, Caching</li><li>Concerns in verschiedene Code-Einheiten trennen, im Einklang mit dem <i>Single Responsibility Principle</i>, z.B. DB-Zugriffe von Geschäftslogik trennen</li><li>SoC führt zu loser Kopplung, hoher Kohäsion und gut testbaren Komponenten</li></ul><span style="font-size:130%;">1.4 Source Code Konventionen</span><br /><br /><i>Warum? Code wird häufiger gelesen als geschrieben. Daher sind Konventionen wichtig die ein schnelles Lesen und Erfassen des Codes unterstützen.</i><br /><ul><li>Namensregeln: <i>Warum? Ohne Namensregeln muss man sich wieder und wieder auf den Stil einzelner Entwickler einstimmen.</i></li><li>Richtig kommentieren: <i>Warum? Unnötige oder gar falsche Kommentare halten beim Lesen auf. Der Code sollte so klar und deutlich sein dass er möglichst ohne Kommentare auskommt.</i></li></ul><span style="font-weight: bold;font-size:130%;" >2. Praktiken</span><br /><span style="font-size:130%;">2.1 Issue Tracking</span><br /><br /><i>Warum? Nur, was man aufschreibt, vergisst man nicht und kann man effektiv delegieren und verfolgen.</i><br /><ul><li>Nichts geht verloren, alle Punkte können priorisiert und sortiert werden.</li><li>Tools:<br /><ul><li>Mantis, <a href="http://www.mantisbt.org/" target="_blank">http://www.mantisbt.org/</a></li> <li>Trac, <a href="http://trac.edgewall.org/" target="_blank">http://trac.edgewall.org/</a></li> <li>Bugzilla, <a href="http://www.bugzilla.org/" target="_blank">http://www.bugzilla.org/</a></li> <li>JIRA, <a href="http://www.atlassian.com/software/jira/" target="_blank">http://www.atlassian.com/software/jira/</a></li> <li>weitere...<br /></li></ul></li></ul><span style="font-size:130%;">2.2 Automatisierte Integrationstests</span><br /><br /><i>Warum? Integrationstests stellen sicher dass der Code tut was er soll. Diese wiederkehrende Tätigkeit nicht zu automatisieren wäre Zeitverschwendung.</i><br /><ul><li>Regressionstests, um Korrektheit von Änderungen sicherzustellen und Angst vor Änderungen zu nehmen</li><li>Automatisierung notwendig, da händisch nicht praktikabel</li><li>Integrationstests oder noch besser Unit Tests durchführen (fernes Ziel: Test Driven Development)</li></ul><span style="font-size:130%;">2.3 Lesen, Lesen, Lesen</span><br /><br /><i>Warum? Lesen bildet!</i><br /><ul><li>Ziel: immer den neuesten Stand der Entwicklung und der Techniken beobachten</li><li>Vorschlag: mindestens 6 Fachbücher pro Jahr plus Fachzeitschriften und Blogs regelmäßig lesen</li></ul><span style="font-size:130%;">2.4 Reviews</span><br /><br /><i>Warum? Vier Augen sehen mehr als zwei. Wenn der eine Entwickler dem anderen seinen Code erklärt, tauchen meist Details auf, die bislang nicht bedacht wurden.</i><br /><ul><li>als kontinuierlicher Prozess beim Pair Programming und/oder</li><li>als eigenständiger Prozessschritt beim Code Review</li></ul>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-29141852211975726522010-06-07T18:58:00.004+02:002010-06-07T19:29:50.753+02:00Clean Code Developer: 1. Roter Grad - Erfahrungen<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxAdR8XFmNepMg44wY_9BQRVPXAdAas-9xJxlgFdOFTmdDuyZ60cJWvfxuwIpjPJYGO_HfCcm5Js-Sz8iBcSc83MOPb6YqTQVV_mfOCBxoODfpGjuW4ri4VuhZgPGiuD1yvfq9N5QwbNc-/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxAdR8XFmNepMg44wY_9BQRVPXAdAas-9xJxlgFdOFTmdDuyZ60cJWvfxuwIpjPJYGO_HfCcm5Js-Sz8iBcSc83MOPb6YqTQVV_mfOCBxoODfpGjuW4ri4VuhZgPGiuD1yvfq9N5QwbNc-/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5480077427507552834" border="0" /></a>Meine 21 Tage im roten Grad sind heute zu Ende gegangen. Eine Zusammenfassung der Prinzipien und Praktiken sind in meinem <a href="http://stefan222devel.blogspot.com/2010/04/clean-code-developer-1-roter-grad.html">Post vom 13. April 2010</a> zu finden. Hier meine Erfahrungen und Meinungen...<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">3. Ergebnisse</span></span><br /><span style="font-size:130%;">3.1. Don't Repeat Yourself (DRY)</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Ich achte insgesamt stärker auf Copy&Paste. Wenn ich Code-Passagen kopieren möchte, überlege ich immer erst, ob sich das Kopieren nicht sinnvoll vermeiden lässt. Alternativen:<br /><ul><li>Code in gemeinsam benutzte Methode einpacken,</li> <li>Code in gemeinsam benutzte Hilfsklasse extrahieren,</li> <li>beide Code-Abschnitte zusammenfassen (Original und Kopie-Ziel).</li></ul></li><li>Tools: Zur automatischen Prüfung von DRY kommen zwei Tools in Frage:<br /><ul><li>CPD als Teil von PMD, <a href="http://pmd.sourceforge.net/cpd.html" target="_blank">http://pmd.sourceforge.net/cpd.html</a></li> <li>Checkstyle, Regel "StrictDuplicateCode", <a href="http://checkstyle.sourceforge.net/" target="_blank">http://checkstyle.sourceforge.net/</a></li></ul></li><li>Erkenntnisse:<br /><ul><li>Checkstyle-Regel "StrictDuplicateCode": Das Limit muss auf mindestens 24 Zeilen hochgesetzt werden (Default: 12 Zeilen), um keine Warnungen wegen des Copyright-Headers im Projekt <i><a href="http://www.lunarcp.de/">LunaRCP</a></i> zu bekommen. Folgende Dinge schränken jedoch die Benutzbarkeit stark ein:<br /> <ul><li>Javadoc-Zeilen werden nicht ignoriert.</li> <li>Es sind keine definierten Ausschlüsse möglich, wie z.B. bei PMD.</li> <li>Die Prüfung ist nicht zuverlässig. Teilweise werden Code-Passagen auch nach Änderungen noch als dupliziert angezeigt. "Rebuild All" konnte das Problem nicht lösen.</li> </ul></li> <li>Die Checkstyle-Regel "StrictDuplicateCode" wurde nach der Durchführung einiger Code-Verbesserungen wieder deaktiviert. Aber auch CPD bringt hier keine besseren (brauchbareren) Ergebnisse. Der automatisierte Einsatz im <i>Nightly Build</i> macht aus meiner Sicht derzeit keinen Sinn.</li></ul></li></ul><span style="font-size:130%;">3.2. Keep it simple, stupid (KISS)</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Ich liebe KISS! Und ich halte nicht viel von Lösungen, die unnötig kompliziert sind und z.B. Erweiterungspunkte auf Vorrat vorsehen, nur weil man sie ja vielleicht irgendwann in ferner Zukunft mal brauchen könnte.</li></ul><span style="font-size:130%;">3.3. Vorsicht vor Optimierungen!</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Optimierungen führe ich grundsätzlich nur durch, wenn offensichtlich Bedarf besteht. Ich mag keine "Optimierung auf Vorrat". Zu jeder Optimierungsaktion gehört ein vorheriges CPU- und/oder Memory-Profiling.</li></ul><span style="font-size:130%;">3.4. Favour Composition over Inheritance (FCoI)</span><br /><ul><li>Status: <b>gelb</b></li><li>Meine Meinung: Dieses Prinzip habe ich während des roten Grades nur selten angewandt, was aber sehr an den bearbeiteten Aufgabenstellungen lag (sehr wenig Neuentwicklungen). Dieses Prinzip muss ich in Zukunft noch mehr verinnerlichen.</li></ul><span style="font-size:130%;">3.5. Die Pfadfinderregel beachten</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Im Tagesgeschäft beachte ich die Pfadfinderregel. Immer, wenn eine Code-Passage "komisch" aussieht, d.h. einen "smell" hat, verbessere ich den Code. Im roten Grad habe ich verstärkt auf DRY, KISS und FCoI geachtet.</li></ul><span style="font-size:130%;">3.6. Root cause analysis</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Diese Regel beachte ich im Normalfall. Die Suche nach der wirklichen Ursache kostet langfristig gesehen viel weniger Zeit als die andauernden Workarounds.</li></ul><span style="font-size:130%;">3.7. Ein Versionskontrollsystem einsetzen</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: <a href="http://subversion.apache.org/" target="_blank">Subversion</a> ist seit längerem im Einsatz, inkl. der Verwendung von Tags und Branches.</li></ul><span style="font-size:130%;">3.8. Erste Refaktorisierungsmuster anwenden</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Verwende ich seit Ewigkeiten. Die am meisten verwendeten Refaktorisierungen der Eclipse IDE sind bei mir: "Methode extrahieren", "Klasse extrahieren", "Umbenennen", "Verschieben", "Konstante extrahieren", "Methoden-Signatur verändern".</li></ul><span style="font-size:130%;">3.9. Täglich reflektieren</span><br /><ul><li>Status: <b>grün</b></li><li>Meine Meinung: Die tägliche Reflektion über die getane Arbeit musste ich mir erst angewöhnen. Ich sehe sie mittlerweile als ein gutes Mittel an, um sich direkt vor dem Feierabend nochmal zu fragen, was man heute alles erledigt hat und welche Punkte eventuell noch offen sind. Die offenen Punkte trage ich in meine persönliche To-Do-Liste für den nächsten Tag ein, damit ich mir die Dinge nicht merken muss (d.h. nicht in den Feierabend mit nach Hause nehme) und nichts vergesse.</li></ul>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-40185415927418073872010-05-30T14:59:00.003+02:002010-05-30T15:02:31.665+02:0010+1 things they never teach in college about programming10+1 Dinge, die man nicht an der Uni oder FH lernt: <a href="http://www.dzone.com/links/r/101_things_they_never_teach_in_college_about_prog.html">http://www.dzone.com/links/r/101_things_they_never_teach_in_college_about_prog.html</a><br /><br />Ja, so isses...stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-79480954524169104482010-05-30T10:00:00.004+02:002010-05-30T10:08:24.465+02:00Neuer Artikel im Eclipse-Magazin<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMyMjvvDsge_ILVEBiVmoclEDGb3dfqjA1_jhMN662YPFRFKns497Z_DlHkx43Mrt7tlO7DdkgqLyNQHqi-5VM6HILC9vyTD8wrNk7-zyAKcj7Ekp8p8pNpYePdNHsBAPn9QhblwE19ErU/s1600/thumb4bfe2f0d8c2c8.png"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 100px; height: 141px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMyMjvvDsge_ILVEBiVmoclEDGb3dfqjA1_jhMN662YPFRFKns497Z_DlHkx43Mrt7tlO7DdkgqLyNQHqi-5VM6HILC9vyTD8wrNk7-zyAKcj7Ekp8p8pNpYePdNHsBAPn9QhblwE19ErU/s400/thumb4bfe2f0d8c2c8.png" alt="" id="BLOGGER_PHOTO_ID_5476970691601368434" border="0" /></a>Im aktuellen <a href="http://it-republik.de/jaxenter/eclipse-magazin-ausgaben/Quo-vadis-Eclipse-000397.html">Eclipse-Magazin (4.2010)</a> ist mein zweiter Artikel zum Projekt <a href="http://www.lunarcp.de"><span style="font-style: italic;">LunaRCP</span></a> erschienen: <i>"Baumkunde für Einsteiger. Navigationsbäume mit LunaRCP erstellen".<br /></i><br />BTW, den ersten Artikel hatte ich in Zusammenarbeit mit <a href="http://www.manfred-novotny.de/">Manfred Novotny</a> geschrieben. Er war bereits im <a href="http://it-republik.de/jaxenter/eclipse-magazin-ausgaben/On-The-Road-to-Eclipse-4.0-000332.html">Eclipse-Magazin 1.2010</a> erschienen: <i>"Persistenzlego. Hibernate-Integration mit Eclipse RCP"</i>.stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-64181630015547222522010-04-27T18:53:00.002+02:002010-04-27T18:55:07.697+02:00Clean Code Developer: Armbänder<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjiEirlBZWaw7MGdUZg4j7-b5tc0lGW1XZREWeNTTTF9JI0zTzVyMIf96iRGgxMx-b1Mr9oLCQfNJb1ak5_EcQsCFP4y9gknWf7gHKBaSzowfBzZr4-Mr17YS33a3QKTeqr2TVHTVrzJD0/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjiEirlBZWaw7MGdUZg4j7-b5tc0lGW1XZREWeNTTTF9JI0zTzVyMIf96iRGgxMx-b1Mr9oLCQfNJb1ak5_EcQsCFP4y9gknWf7gHKBaSzowfBzZr4-Mr17YS33a3QKTeqr2TVHTVrzJD0/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5464861763698095090" border="0" /></a><br />Super, jetzt sind sie endlich da, die CCD-Armbänder. Bestellt am 1. April (kein Scherz!) und schon geliefert am 23. April.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimA6WnE89fuw3GIkwObazD1oetMq75bjzJKEO3KQJJHqH9YtlWrWas6dgdwfWAHVBoebDJKPoWs3eN_LyPWXmQc-lPqxQ1YUgxbJ1vOvMmwBI4E7Ki86cy4i1yW2Vt_dPHo5hOuoSorLdL/s1600/P4230035_small.JPG"><img style="cursor: pointer; width: 300px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimA6WnE89fuw3GIkwObazD1oetMq75bjzJKEO3KQJJHqH9YtlWrWas6dgdwfWAHVBoebDJKPoWs3eN_LyPWXmQc-lPqxQ1YUgxbJ1vOvMmwBI4E7Ki86cy4i1yW2Vt_dPHo5hOuoSorLdL/s400/P4230035_small.JPG" alt="" id="BLOGGER_PHOTO_ID_5464861688819252834" border="0" /></a>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-65208291751814242962010-04-13T18:25:00.002+02:002010-04-13T18:43:32.447+02:00Clean Code Developer: 1. Roter Grad - Zusammenfasung<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aT23wavqO8V77d_iR8b0zOr5kPURHej-QRaecU1jvIaYbEo0ActDhYUGYtgoG84cyXbz_GeF8GLY4Bm61ZqIfCq5QRCOsV4JmMs8DCgOj7cxswNyJQ8oPtEvNfTWifC3nxtcK4ZdTvIz/s1600/CleanCodeDeveloper.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aT23wavqO8V77d_iR8b0zOr5kPURHej-QRaecU1jvIaYbEo0ActDhYUGYtgoG84cyXbz_GeF8GLY4Bm61ZqIfCq5QRCOsV4JmMs8DCgOj7cxswNyJQ8oPtEvNfTWifC3nxtcK4ZdTvIz/s400/CleanCodeDeveloper.gif" alt="" id="BLOGGER_PHOTO_ID_5459659424713564722" border="0" /></a>"Mit dem roten Grad beginnt der Weg des Clean Code Developers. Ab hier gilt es, einen ersten Teil des CCD Wertesystems in die tägliche Arbeit einzubringen und immer wieder zu üben." Dann wollen wir mal starten...<br /><br /><span style="font-weight: bold;font-size:130%;" >1. Prinzipien</span><br /><span style="font-size:130%;">1.1. Don't Repeat Yourself (DRY)</span><br /><br /><i>"Warum? Jede Doppelung von Code oder auch nur Handgriffen leistet Inkonsistenzen und Fehlern Vorschub."</i><br /><ul><li>Copy&Paste ist ein weit verbreitetes Anti-Pattern.</li><li>Ziel: doppelten Code und andere Artefakte erkennen und</li><li>Wiederholungen durch Refaktorisierungen entfernen (sofern nichts dagegen spricht).</li><li>Tools:</li><ul><li>CPD als Teil von PMD, <a href="http://pmd.sourceforge.net/cpd.html">http://pmd.sourceforge.net/cpd.html</a></li><li>Checkstyle, Regel "StrictDuplicateCode", <a href="http://checkstyle.sourceforge.net/">http://checkstyle.sourceforge.net/</a><br /></li></ul></ul><span style="font-size:130%;">1.2. Keep it simple, stupid (KISS)</span><br /><br /><i>"Warum? Wer mehr tut als das Einfachste, lässt den Kunden warten und macht die Lösung unnötig kompliziert."</i><br /><ul><li><a href="http://de.wikipedia.org/wiki/Einstein">Einstein</a>: "Alles sollte so einfach wie möglich gemacht werden, aber nicht einfacher."</li><li>Eine einfache, klare, leicht verständliche Lösung sollte immer bevorzugt werden.</li><li>Praxis: Reviews und Pair Programming.<br /></li></ul><span style="font-size:130%;">1.3. Vorsicht vor Optimierungen!</span><br /><br /><i>"Warum? Optimierungen kosten immer viel Aufwand. Wer Vorsicht walten lässt, spart oft wertvolle Ressourcen für das, was dem Kunden wirklich nützt."</i><br /><ul><li><a href="http://de.wikipedia.org/wiki/Michael_Anthony_Jackson">M.A. Jackson</a>: Rules of Optimization:</li><ul><li>Rule 1: Don't do it.</li><li>Rule 2 (for experts only): Don't do it yet.</li></ul><li>Verständlichkeit und Evolvierbarkeit vor (minimalen) Performance-Optimierungen.</li><li>Optimierungen nur, wenn vom Kunden gefordert, vom Entwickler zweimal überlegt und mit Profiler-Analyse<br /></li></ul><span style="font-size:130%;">1.4. Favour Composition over Inheritance (FCoI)</span><br /><br /><i>"Warum? Komposition fördert die lose Kopplung und die Testbarkeit eines Systems und ist oft flexibler."</i><br /><ul><li><a href="http://de.wikipedia.org/wiki/Viererbande_%28Softwareentwicklung%29">Gang of Four</a>: "Because inheritance exposes a subclass to details of its parent's implementation, it's often said that 'inheritance breaks encapsulation'."</li><li>Vererbung: white box, Subklasse abhängig von Elternklasse</li><li>Komposition: black box, klare Schnittstelle, bessere Entkopplung, leichtere Austauschbarkeit<br /></li></ul><span style="font-weight: bold;font-size:130%;" >2. Praktiken</span><br /><span style="font-size:130%;">2.1. Die Pfadfinderregel beachten</span><br /><br /><i>"Warum? Jede Beschäftigung mit einem Gegenstand macht ihn zumindest ein kleinwenig besser. Ganz ohne bürokratische Planung. Fundament und Graswurzelansatz für mehr Qualität."</i><br /><ul><li>Pfadfinderregel: "Hinterlasse einen Ort immer in einem besseren Zustand als du ihn vorgefunden hast."</li><li>Nach getaner Arbeit stimmt der Code mit dem Clean Code Development Wertesystem mehr überein als vorher.</li><li>Anti-Pattern: Broken-Windows-Theorie (eine zerbrochene Fensterscheibe führt später zu völliger Verwahrlosung)<br /></li></ul><span style="font-size:130%;">2.2. Root cause analysis</span><br /><br /><i>"Warum? Symptome behandeln bringt vielleicht schnell eine Linderung - langfristig kostet es aber mehr Aufwand. Wer stattdessen unter die Oberfläche von Problemen schaut, arbeitet am Ende effktiver."</i><br /><ul><li>Immer nach der Ursache eines Problems suchen.</li><li>Bei Kenntnis des Wurzelproblems ist die Bereinigung meist weniger aufwändig als eine Symptomkur.<br /></li></ul><span style="font-size:130%;">2.3. Ein Versionskontrollsystem einsetzen</span><br /><br /><i>"Warum? Angst vor Beschädigung eines 'running system' lähmt die Softwareentwicklung. Mit einer Versionsverwaltung ist solche Angst unbegründet. Die Entwicklung kann schnell und mutig voranschreiten."</i><br /><ul><li>Kein Kommentar!</li><li>Tools:</li><ul><li>Subversion, <a href="http://subversion.apache.org/">http://subversion.apache.org/</a></li><li>TortoiseSVN, <a href="http://tortoisesvn.tigris.org/">http://tortoisesvn.tigris.org/</a><br /></li></ul></ul><span style="font-size:130%;">2.4. Erste Refaktorisierungsmuster anwenden</span><br /><br /><i>"Warum? Code verbessern ist leichter, wenn man typische Verbesserungshandgriffe kennt. Ihre Anwendungsszenarien machen sensibel für Schwachpunkte im eigenen Code. Als anerkannte Muster stärken sie den Mut, sie anzuwenden."</i><br /><ul><li>vgl. Buch von <a href="http://de.wikipedia.org/wiki/Martin_Fowler">Martin Fowler</a></li><li>Refaktorisierungen für roten Grad: "Methode extrahieren" und "Umbenennen"</li><li>Tool: Eclipse for RCP/Plug-in Developers, <a href="http://www.eclipse.org/">http://www.eclipse.org/</a><br /></li></ul><span style="font-size:130%;">2.5. Täglich reflektieren</span><br /><br /><i>"Warum? Keine Verbesserung, kein Fortschritt, kein Lernen ohne Reflexion. Aber nur wenn Reflexion auch eingeplant wird, findet sie unter dem Druck des Tagesgeschäftes auch statt."</i><br /><ul><li>Persönliche Entwicklung durch kleinschrittige Planung und Reflexion nach jedem Schritt.</li><li>Die Arbeit so einteilen, dass sie aus Aufgaben besteht, die an einem Arbeitstag zu bewältigen sind.</li><li>Die Arbeit nicht mit in den Feierabend tragen.</li></ul>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-1826269281091838902010-02-22T16:47:00.002+01:002010-02-22T16:51:32.104+01:00Clean Code Developer: 0. Schwarzer Grad<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpXGwG9oikMB15LXLf0GiN0zTqJtYlX-NC7ovtJJ_q5KvJpceLLCPCtguxzDghVOZWXPg4U3c7sm1OevHLteWmZ9Zl4G5iZcXjAXBa0c_duCIfmUsYRcQWupKYYKfl3ZxYS6uYXve8St6R/s1600-h/dotnetpro+ccd+stempel2+almost+half+size+banner.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 234px; height: 102px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpXGwG9oikMB15LXLf0GiN0zTqJtYlX-NC7ovtJJ_q5KvJpceLLCPCtguxzDghVOZWXPg4U3c7sm1OevHLteWmZ9Zl4G5iZcXjAXBa0c_duCIfmUsYRcQWupKYYKfl3ZxYS6uYXve8St6R/s400/dotnetpro+ccd+stempel2+almost+half+size+banner.gif" alt="" id="BLOGGER_PHOTO_ID_5441095727359422738" border="0" /></a><a href="http://www.manfred-novotny.de/">Manfred Novotny</a> hatte mich im Januar auf diese tolle Homepage aufmerksam gemacht: <a href="http://clean-code-developer.de/">Clean Code Developer</a>. Ich kann nur sagen: eine <span style="font-weight: bold;">Offenbarung</span>! Endlich eine klare Ansage, was Professionalität in der Software-Entwicklung bedeutet / bedeuten kann / bedeuten könnte (je nach persönlichem Standpunkt). Ein nachvollziehbares und praktisch anwendbares Wertesystem für jeden Software-Entwickler. Obendrein wird eine Sammlung von <span style="font-weight: bold;">Prinzipien und Praktiken</span> angeboten, die in verschiedenen Stufen (<span style="font-style: italic;">"Graden"</span>) der Entwicklung zum "Clean Code Developer" erlernt und verinnerlicht werden können.<br /><br />Ich finde das Ganze eine echt tolle Sache und habe deshalb beschlossen, mich ebenfalls auf den Weg zum "Clean Code Developer" zu machen. Gemäß den CCD-Graden befinde ich mich nun also im <a href="http://clean-code-developer.de/wiki/CcdSchwarzerGrad">"Schwarzen Grad"</a>. Derzeit stehen dem Übergang zum <a href="http://clean-code-developer.de/wiki/CcdRoterGrad">"Roten Grad"</a> noch einige administrative Aufgaben im Weg, die meine Zeit beanspruchen. Ich werde dann später für jeden CCD-Grad meine persönlichen Erfahrungen hier im Blog festhalten.stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-35883114147356742332010-01-11T16:51:00.002+01:002010-01-11T17:00:10.990+01:00How to convert a Maven pom.xml into an Ivy ivy.xml fileIf you're using <a href="http://maven.apache.org/">Maven</a> just for resolving dependencies, <a href="http://ant.apache.org/ivy/">Ivy</a> might be a good alternative for you. You may convert your <span style="font-style: italic;">pom.xml</span> into an <span style="font-style: italic;">ivy.xml</span> file using the following <a href="http://ant.apache.org/">Ant</a> script:<pre><br /><project name="convertPomToIvy" basedir="." default="convert"<br /> xmlns:ivy="antlib:fr.jayasoft.ivy.ant"<br /> xmlns:ac="antlib:net.sf.antcontrib"><br /><br /> <path id="antlib.classpath"><br /> <fileset dir="C:/Program Files/apache-ivy-2.1.0" includes="*.jar"/><br /> <fileset dir="C:/Program Files/apache-ivy-2.1.0/lib" includes="*.jar"/><br /> </path><br /><br /> <taskdef uri="antlib:fr.jayasoft.ivy.ant"<br /> resource="fr/jayasoft/ivy/ant/antlib.xml"<br /> classpathref="antlib.classpath"<br /> loaderref="antlib.classpath.loader"/><br /><br /> <target name="convert"><br /> <ivy:convertpom pomFile="pom.xml" ivyFile="ivy.xml" /><br /> </target><br /></project><br /></pre><br />Please note that you may want to adjust the paths to the Ivy JAR files.stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com2tag:blogger.com,1999:blog-3642953843528751664.post-60232780594270010202009-11-16T15:32:00.002+01:002009-11-16T15:35:06.099+01:00Ranking: Popularität von ProgrammiersprachenEin sehr bekanntes Ranking zur Popularität von Programmiersprachen wird von der Firma Tiobe erstellt: <a href="http://www.tiobe.com/index.php/tiobe_index">http://www.tiobe.com/index.php/tiobe_index</a>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-77397441825021985532009-11-13T07:21:00.005+01:002009-11-13T07:25:33.756+01:00Zurück von der W-JAX 2009<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVlesbNnCMpVXpuyDV82Xajsy-FwCG_bK2SdQW-sQ35Xd0k4kLX4RVKq8m-ixPtIIJv-JR2RxX-8Ei305GojY40wNoFgwJKkT-BINYyny1x8kU5PsMPS7eP6tDWOh_ZVqGA02WB5FB_BKJ/s1600-h/wjax2009.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 100px; height: 100px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVlesbNnCMpVXpuyDV82Xajsy-FwCG_bK2SdQW-sQ35Xd0k4kLX4RVKq8m-ixPtIIJv-JR2RxX-8Ei305GojY40wNoFgwJKkT-BINYyny1x8kU5PsMPS7eP6tDWOh_ZVqGA02WB5FB_BKJ/s400/wjax2009.png" alt="" id="BLOGGER_PHOTO_ID_5403470212640429538" border="0" /></a>Die W-JAX 2009 in München war wirklich toll! Vielen Dank an die Organisatoren, Speaker und alle Besucher! Bis zum nächsten Jahr...stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-73501036826610275022009-02-09T17:17:00.003+01:002009-02-09T17:22:29.131+01:00Implementing the equals() MethodThis short article contains the recent facts for implementing the <span style="font-family:courier new;">equals()</span> method of a class. If you are interested in the full explanation of the details, please take a look at the article from <a href="http://www.angelikalanger.com/Articles/EffectiveJava/01.Equals-Part1/01.Equals1.html">Angelika Langer: Implementing the equals() Method - Part 1</a> (german only, sorry).<br /><br />This is the basic implementation for a class that is directly derived from <span style="font-family:courier new;">java.lang.Object</span>:<br /><pre>public boolean equals(final Object object) {<br /> if (this == object) {<br /> return true;<br /> }<br /><br /> if (object == null) {<br /> return false;<br /> }<br /><br /> if (getClass() != object.getClass()) {<br /> return false;<br /> }<br /><br /> // TODO compare all fields of this class<br /> return true;<br />}</pre>This is the basic implementation for a class that is <span style="font-weight: bold;">NOT</span> directly derived from <span style="font-family:courier new;">java.lang.Object</span>:<br /><pre>public boolean equals(final Object object) {<br /> if (this == object) {<br /> return true;<br /> }<br /><br /> if (!super.equals(object)) {<br /> return false;<br /> }<br /><br /> // TODO compare all fields of this class<br /> return true;<br />}<br /></pre>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-56298299658265773732009-01-18T09:49:00.003+01:002009-01-18T10:18:01.778+01:00Tutorial: Export a sample RCP application using Spring, Spring Dynamic Modules for OSGi Service Platforms and AgileRCPIn this article you will learn how to export an RCP application that makes use of <a href="http://www.springframework.org/">Spring</a>, <a href="http://www.springframework.org/osgi">Spring-DM</a> and <a href="http://www.sourceforge.net/projects/agilercp/">AgileRCP</a>. The article uses the example from the past tutorial about RCP / Spring / Spring-DM / AgileRCP (see <a href="http://stefan222devel.blogspot.com/2008/08/tutorial-sample-rcp-application-using_31.html">part 1</a>, <a href="http://stefan222devel.blogspot.com/2008/09/tutorial-sample-rcp-application-using.html">part 2</a> and <a href="http://stefan222devel.blogspot.com/2008/09/tutorial-sample-rcp-application-using_03.html">part 3</a>). Please note that the example code has changed slightly, see the downloadable source code archive at the end of this article.<br /><br /><ol><li>Create a feature that contains all plug-ins:</li><ul><li>New -> Other... -> Plug-in Development / Feature Project</li><li>Choose a proper project name, e.g. "org.digitalcure.hellospring.feature"</li><li>Initialize from the plug-ins list</li><li>Select the following plugins:</li><ul><li>org.agilercp.ui</li><li>org.agilercp.ui.dialog</li><li>org.agilercp.util</li><li>org.apache.commons.logging</li><li>org.digitalcure.hellospring.app</li><li>org.digitalcure.hellospring.common</li><li>org.digitalcure.hellospring.service</li><li>org.springframework.bundle.osgi.core</li><li>org.springframework.bundle.osgi.extender</li><li>org.springframework.bundle.osgi.io</li><li>org.springframework.bundle.spring</li></ul><li>Finish the wizard. An editor for the file <span style="font-family:courier new;">fragment.xml</span> will be opened.<br /></li></ul><li>Add the current plug-in versions:<ul><li>Switch to the Plug-ins tab.</li><li>Select all plug-ins and press the button "Versions...".</li><li>Select "Copy versions from plug-ins and fragments manifests" and finish the dialog.</li><li>Save the feature file.</li></ul></li><li>Configure the product to use features:<ul><li>Open the product file (plug-in "org.digitalcure.hellospring.app", file <span style="font-family:courier new;">HelloSpringApp.product</span>).</li><li>Overview tab: The product configuration is based on: features</li><li>Configuration tab: Press the button "Add..." and select our newly created feature.</li><li>Press "Add..." once again and add the feature "org.eclipse.rcp".</li><li>Save the product file.</li></ul></li><li>Export the product (1<span style="font-size:85%;">st</span> try):<ul><li>File -> Export... -> Plug-in Development / Eclipse product</li><li>Configuration: Press the "Browse..." button, expand the plug-in "org.digitalcure.hellospring.app" and select the file <span style="font-family: courier new;">HelloSpringApp.product</span>.</li><li>Root directory: <span style="font-family: courier new;">HelloSpring</span></li><li>Synchronize before exporting: yes</li><li>Destination: Select "Directory" and select a proper folder to export the product to.</li><li>Finish the dialog. Eclipse should export the product without errors.</li></ul></li><li>Run the exported product.<ul><li>Use a file browser (e.g. Windows Explorer) to navigate to your export directory and run the product (e.g. named "eclipse.exe").</li><li>The application will be displayed after a short delay, but there is an error message instead of the expected table.</li><li>First of all: Don't panic! The error is caused by the lazy startup of the plug-ins. Spring-DM is unable to create a proper <span style="font-family: courier new;">ApplicationContext</span> and so the application is unable to instrument Spring.</li></ul></li><li>Add a configuration file to the application plug-in:<ul><li>However, the exported product is very useful for us, because it ontains a default configuration file. Copy the file <span style="font-family: courier new;">config.ini</span> from the "configuration" folder and paste it into the root folder of the application plug-in.</li><li>Edit the build properties of the application plug-in and add the file <span style="font-family: courier new;">config.ini</span> to the binary build.</li><li>Open <span style="font-family: courier new;">config.ini</span> inside the Eclipse IDE.</li><li>Edit the line for the property "osgi.bundles" in the following way:<br /><br /><span style="font-family: courier new;">osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.update.configurator@3:start,org.eclipse.core.runtime@start,org.agilercp.ui@start,org.digitalcure.hellospring.app@start,org.digitalcure.hellospring.common@start,org.digitalcure.hellospring.service@start,org.springframework.bundle.osgi.extender@start</span><br /><br /></li></ul></li><li>Use the configuration file in the product:<ul><li>Open the product definition file and switch to the Configuration tab. Take a look at the section "Configuration File".</li><li>Choose the tab for your operating system.</li><li>Select "Use an existing config.ini file".</li><li>Press the button "Browse..." and select the newly created configuration file.</li><li>Save the product definition file.</li></ul></li><li>Export the product (2<span style="font-size:85%;">nd</span> try). Just the same as the 1<span style="font-size:85%;">st</span> try.</li><li>Run the exported product:<ul><li>Same procedure as described above.</li><li>The application will be displayed, including the expected table. That's it!</li></ul></li></ol>You may download the source code of the tutorial from <a href="http://www.schwafel.de/source/Spring_AgileRCP_Tutorial4.zip">here</a>.stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com0tag:blogger.com,1999:blog-3642953843528751664.post-75183868351255196792008-11-20T17:20:00.005+01:002008-11-20T18:50:07.641+01:00Tutorial: How to create a remote OSGi serviceIn this article you will learn how to create a remote OSGi service from a "local" OSGi service using <a href="http://r-osgi.sourceforge.net/">R-OSGi</a>. The OSGi service for an user manager is published by the <span style="font-family: courier new;">Activator</span> of the service bundle:<br /><pre>public class Activator implements BundleActivator {<br /> public void start(final BundleContext context) throws Exception {<br /> context.registerService(IUserManager.class.getName(), new UserManager(), null);<br /> System.out.println("Service registered.");<br /> }<br /><br /> public void stop(final BundleContext context) throws Exception {}<br />}<br /></pre>The <span style="font-family: courier new;">Activator</span> of the application bundle uses the service:<br /><pre>public class Activator implements BundleActivator {<br /> public void start(final BundleContext context) throws Exception {<br /> final ServiceReference serviceRef = context.getServiceReference(IUserManager.class.getName());<br /> if (serviceRef == null) {<br /> System.out.println("Service not found!");<br /> } else {<br /> final IUserManager userManager = (IUserManager) context.getService(serviceRef);<br /><br /> try {<br /> System.out.println("All user names:");<br /> final List<String> names = userManager.getUserNames();<br /> for (final String name : names) {<br /> System.out.println("Name = " + name);<br /> }<br /> } finally {<br /> context.ungetService(serviceRef);<br /> }<br /> }<br /> }<br /><br /> public void stop(final BundleContext context) throws Exception {}<br />}<br /></pre>Now you have to verify that <a href="http://r-osgi.sourceforge.net/">R-OSGi</a> is installed on your local Eclipse. Activate the view "Plug-ins" and search for a bundle named <span style="font-family: courier new;">ch.ethz.iks.r_osgi.remote</span>. If it is already there, you may skip the following installation procedure.<br /><br />The easiest way to install <a href="http://r-osgi.sourceforge.net/">R-OSGi</a> into your Eclipse is to install the <a href="http://www.eclipse.org/ecf/">Eclipse Communication Framework (ECF)</a>. Use one of the following update sites:<br /><ul><li>Eclipse 3.4: <a href="http://download.eclipse.org/rt/ecf/2.0/3.4/updateSite/site.xml">http://download.eclipse.org/rt/ecf/2.0/3.4/updateSite/site.xml</a></li><li>Eclipse 3.3: <a href="http://download.eclipse.org/rt/ecf/2.0/updateSite">http://download.eclipse.org/rt/ecf/2.0/updateSite</a><br /></li></ul>After the download of the plug-ins, their installation and the restart of the Eclipse IDE the R-OSGi bundle will be available in the "Plug-ins" view.<br /><br />First, you have to add the bundle <span style="font-family: courier new;">ch.ethz.iks.r_osgi.remote</span> to the list of required plug-ins. Do this for both the application and the service bundle. Then you have to mark the published OSGi service as remote service (inside the <span style="font-family: courier new;">Activator</span> of the service bundle):<br /><pre> public void start(final BundleContext context) throws Exception {<br /> final Hashtable properties = new Hashtable();<br /> properties.put(RemoteOSGiService.R_OSGi_REGISTRATION, Boolean.TRUE);<br /> context.registerService(IUserManager.class.getName(), new UserManager(), properties);<br /> System.out.println("Service registered.");<br /> }<br /></pre>That was easy! Using the remote service requires a little bit more code. Instead of getting the user manager service directly from the service registry, you have to get the R-OSGi service from the service registry. Then you have to query the R-OSGi service for the remote user manager services. The code inside the <span style="font-family: courier new;">Activator</span> of the application bundle looks like this:<br /><pre> public void start(final BundleContext context) throws Exception {<br /> final ServiceReference serviceRef = context.getServiceReference(RemoteOSGiService.class.getName());<br /> if (serviceRef == null) {<br /> System.out.println("R-OSGi service not found!");<br /> } else {<br /> final RemoteOSGiService remote = (RemoteOSGiService) context.getService(serviceRef);<br /> try {<br /> remote.connect(new URI("r-osgi://205.207.25.9:9278"));<br /><br /> final RemoteServiceReference[] references = remote.getRemoteServiceReferences(<br /> new URI("r-osgi://205.207.25.9:9278"), IUserManager.class.getName(), null);<br /> if (references == null) {<br /> System.out.println("Service not found!");<br /> } else {<br /> final IUserManager userManager = (IUserManager) remote.getRemoteService(references[0]);<br /><br /> System.out.println("All user names:");<br /> final List<String> names = userManager.getUserNames();<br /> for (final String name : names) {<br /> System.out.println("Name = " + name);<br /> }<br /> }<br /> } finally {<br /> context.ungetService(serviceRef);<br /> }<br /> }<br /> }<br /></pre>Now you should test the remote OSGi service. Create a run configuration for the service and run it. Then create a run configuration for the application and run it. Depending on your user manager implementation you should see something like this (Console of the application):<br /><pre>osgi> All user names:<br />Name = Charly<br />Name = Dennis<br />Name = Ed<br /></pre>You may download the source code from <a href="http://www.schwafel.de/source/Remote_OSGi_Tutorial.zip">here</a>.stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com3tag:blogger.com,1999:blog-3642953843528751664.post-15978147405452212472008-09-03T17:25:00.004+02:002008-11-20T17:23:00.623+01:00Tutorial: Sample RCP application using Spring, Spring Dynamic Modules for OSGi Service Platforms and AgileRCP (3/3)<span style="font-family:georgia;">In the first two parts of the tutorial you have learned how to use Spring beans as OSGi services (see <a href="http://stefan222devel.blogspot.com/2008/08/tutorial-sample-rcp-application-using_31.html">part 1</a> and <a href="http://stefan222devel.blogspot.com/2008/09/tutorial-sample-rcp-application-using.html">part 2</a>). You have used the <span style="font-family:courier new;">ApplicationContextTracker</span> of <a href="http://www.sourceforge.net/projects/agilercp/">AgileRCP</a> to access <a href="http://www.springframework.org/">Spring</a>'s <span style="font-family:courier new;">ApplicationContext</span>. The third part of the tutorial will show you how to use Eclipse RCP Extensions in interaction with Spring beans. <a href="http://www.sourceforge.net/projects/agilercp/">AgileRCP</a> offers a convenient way to do this without the hassle of the direct use of the <span style="font-family:courier new;">ApplicationContextTracker.</span><br /><ol style="font-family: georgia;"><li>Create a new interface for a user view:<br /><ul><li>New -> Interface</li><li>Name: <span style="font-family:courier new;">IUserView</span></li><li>Extended Interfaces: <span style="font-family:courier new;">org.agilercp.ui.IView</span>, <span style="font-family:courier new;">org.agilercp.ui.view.IWorkbenchPartView</span></li></ul></li><br /><li>Add a method for setting a list of user names:<br /><pre> void setUserNames(final List<String> names);</pre></li><li>The interface is not compile clean, because some packages are missing. Add the following packages to the list of imported packages (<span style="font-family:courier new;">MANIFEST.MF</span>, Dependencies tab):<br /><ul><li><span style="font-family:courier new;">org.agilercp.ui</span></li><li><span style="font-family:courier new;">org.agilercp.ui.dialog</span></li><li><span style="font-family:courier new;">org.agilercp.ui.view</span></li><li><span style="font-family:courier new;">org.agilercp.ui.workbench</span></li><li><span style="font-family:courier new;">org.agilercp.util.log</span></li></ul></li><br /><li>Edit the view of the application (<span style="font-family:courier new;">View.java):<br /></span><ul><span style="font-family:courier new;"><li>The view extends <span style="font-family:courier new;">DefaultViewParta</span> (from AgileRCP) instead of <span style="font-family:courier new;">ViewPart</span>.</li><li>The view implements the interface <span style="font-family:courier new;">IUserView.</span></li><li>The table viewer displays a list of user names.</li><li>This list will be set from outside.</li></span></ul><span style="font-family:courier new;"></span><pre><span style="font-family:courier new;">public class View extends DefaultViewPart implements IUserView {<br /> public static final String ID = "org.digitalcure.hellospring.app.view";<br /><br /> private TableViewer tableViewer;<br /><br /> @Override<br /> protected void doCreatePartControl(final Composite parent) {<br /> final Composite composite = new Composite(parent, SWT.NONE);<br /> composite.setLayout((new GridLayout(1, false)));<br /> composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));<br /><br /> tableViewer = new TableViewer(composite, SWT.FULL_SELECTION | SWT.BORDER);<br /> tableViewer.getTable().setHeaderVisible(true);<br /> tableViewer.getTable().setLinesVisible(true);<br /> tableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));<br /><br /> final TableColumn firstNameColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);<br /> firstNameColumn.setText("Name");<br /> firstNameColumn.setWidth(100);<br /><br /> tableViewer.setContentProvider(new ArrayContentProvider());<br /> tableViewer.setLabelProvider(new UserTableLabelProvider());<br /> }<br /><br /> @Override<br /> public void setFocus() {<br /> tableViewer.getTable().setFocus();<br /> }<br /><br /> public void setUserNames(final List<String> names) {<br /> tableViewer.setInput(names);<br /> }<br /><br /> private class UserTableLabelProvider extends LabelProvider implements ITableLabelProvider {<br /> public Image getColumnImage(final Object element, final int columnIndex) {<br /> return null;<br /> }<br /><br /> public String getColumnText(final Object element, final int columnIndex) {<br /> if (!(element instanceof String)) {<br /> throw new IllegalArgumentException("The given object must be a string!");<br /> }<br /><br /> return (String) element;<br /> }<br /> }<br />}</span></pre><span style="font-family:courier new;"></span></li><li>Edit the <span style="font-family:courier new;">plugin.xml</span> file:<br /><ul><li>Go to the Extensions tab, expand the node "org.eclipse.ui.views" and select "View (view)".</li><li>Change the class to: <span style="font-family:courier new;">org.agilercp.ui.workbench.WorkbenchPartFactory</span></li></ul></li><br /><li>The <span style="font-family:courier new;">WorkbenchPartFactory</span> implementation will create an instance of a Spring bean with the ID of the view (<span style="font-family:courier new;">org.digitalcure.hellospring.app.view</span>). The Spring bean has to implement the interface <span style="font-family:courier new;">org.agilercp.ui.IPresenter</span>. So now you have to create a new class for the presenter:<br /><ul><li>New -> Class</li><li>Name: <span style="font-family:courier new;">UserPresenter</span></li><li>Superclass: <span style="font-family:courier new;">org.agilercp.ui.DefaultPresenter</span></li></ul></li><br /><li>You have to specify the type of the presented view:<br /><pre>public class UserPresenter extends DefaultPresenter<IUserView> { ... }</pre></li><li>Add a member for the user manager to the user presenter class and a constructor that provides both the user manager and the user view:<br /><pre> private final IUserManager userManager;<br /><br /> public UserPresenter(final IUserView view, final IUserManager userManager) {<br /> super(view);<br /> this.userManager = userManager;<br /> }</pre></li><li>Override the <span style="font-family:courier new;">handleViewCreated(...)</span> method and initialize the view with the list of user names:<br /><pre> @Override<br /> protected void handleViewCreated(final IUserView view) {<br /> super.handleViewCreated(view);<br /> getView().setUserNames(userManager.getUserNames());<br /> }</pre></li><li>Edit the Spring configuration file <span style="font-family:courier new;">bundle-context.xml</span> and add a Spring bean for the user presenter:<br /><pre> <bean name="org.digitalcure.hellospring.app.view" class="org.digitalcure.hellospring.app.UserPresenter"><br /> <constructor-arg><br /> <bean class="org.digitalcure.hellospring.app.View" /><br /> </constructor-arg><br /> <constructor-arg ref="userManagerService" /><br /> </bean></pre></li><li>The source code modifications are finished, so you have to modify the product configuration file "HelloSpringApp.product". Go to the Configuration tab and press "Add Required Plug-ins".</li><br /><li>Open the Run Configuration and press "Add Required Bundles".</li><br /><li>Press "Run" to run the application. The list inside the application window should display the user names now.</li></ol><span style="font-family:georgia;">You may download the source code of the tutorial <a href="http://www.schwafel.de/source/Spring_AgileRCP_Tutorial.zip">from here</a>.</span><br /><br /></span>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com1tag:blogger.com,1999:blog-3642953843528751664.post-2660235399855955772008-09-01T16:39:00.003+02:002008-09-01T16:50:00.540+02:00Tutorial: Sample RCP application using Spring, Spring Dynamic Modules for OSGi Service Platforms and AgileRCP (2/3)<span style="font-family:georgia;">In this tutorial you will extend the sample application of the <a href="http://stefan222devel.blogspot.com/2008/08/tutorial-sample-rcp-application-using_31.html">first tutorial part</a>. You will add another plug-in that provides a new user manager. You will learn how to declare Spring beans as OSGi services and use them in other plug-ins. This is possible without any modification of the original source code.</span><br /><ol style="font-family: georgia;"><li>Create a new plug-in project for the user manager service:<br /><ul><li>New -> Other... -> Plug-in Development / Plug-in Project</li><li>Choose a proper project name, e.g. "org.digitalcure.hellospring.service"</li><li>Generate an activator: yes, This plug-in will make contributions to the UI: no, Would you like to create a rich client application? no</li><li>Create a plug-in using one of the templates: no</li></ul></li><br /><li>Edit the <span style="font-family:courier new;">MANIFEST.MF</span> file and import the package "org.digitalcure.hellospring.common" (Dependencies tab).</li><br /><li>Create an implementation of a user manager. Create a new class inside the "org.digitalcure.hellospring.service" package:<br /><ul><li>New -> Class</li><li>Choose a class name: <span style="font-family:courier new;">ExtendedUserManager</span></li><li>Interfaces: <span style="font-family:courier new;">org.digitalcure.hellospring.common.IUserManager</span></li></ul></li><br /><li>Implement the <span style="font-family:courier new;">getUserNames()</span> method, so that it returns three names, e.g.:<br /><pre>public List<String> getUserNames() {<br /> final List<String> list = new ArrayList<String>(3);<br /> list.add("Charly");<br /> list.add("Dennis");<br /> list.add("Ed");<br /> return list;<br />}</pre></li><li>Now you are ready to create the Spring configuration files. Create a folder named "spring" inside the <span style="font-family:courier new;">META-INF</span> folder.</li><br /><li>Create two XML files inside the "spring" folder:<br /><ul><li><span style="font-family:courier new;">bundle-context.xml</span></li><li><span style="font-family:courier new;">bundle-context-osgi.xml</span></li></ul></li><br /><li><span style="font-family:courier new;">bundle-context.xml</span>: Create a Spring bean for the user manager:<br /><pre><?xml version="1.0" encoding="UTF-8"?><br /><beans xmlns="http://www.springframework.org/schema/beans"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:schemaLocation="http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><br /><br /><bean id="extendedUserManager" class="org.digitalcure.hellospring.service.ExtendedUserManager" /><br /></beans></pre></li><li><span style="font-family:courier new;">bundle-context-osgi.xml</span>: Export the user manager bean as OSGi service:<br /><pre><?xml version="1.0" encoding="UTF-8"?><br /><beans:beans<br /> xmlns="http://www.springframework.org/schema/osgi"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xmlns:beans="http://www.springframework.org/schema/beans"<br /> xsi:schemaLocation="http://www.springframework.org/schema/osgi<br /> http://www.springframework.org/schema/osgi/spring-osgi.xsd<br /> http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans.xsd"><br /><br /><service id="extendedUserManagerService" ref="extendedUserManager"<br /> interface="org.digitalcure.hellospring.common.IUserManager" /><br /></beans:beans></pre></li><li>Add Spring support to the "service" project: Open the context menu for the project and select "Spring Tools" -> "Add Spring Project Nature". The project itself will be marked with a "S" in the upper right corner of the project icon.</li><br /><li>Open the Properties dialog of the project. Go to "Spring" -> "Beans Support" and add the two XML files of the "spring" folder. After closing the dialog, both XML files will be marked with an "S", plus the Java file "ExtendedUserManager.java".</li><br /><li>Switch back to the first project (the "app" project). Now you have to configure the first user manager (default user manager) as service. You have to edit the Spring configuration files of the project.</li><br /><li><span style="font-family:courier new;">bundle-context-osgi.xml</span>: Export the user manager bean as OSGi service:<br /><pre><?xml version="1.0" encoding="UTF-8"?><br /><beans:beans<br /> xmlns="http://www.springframework.org/schema/osgi"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xmlns:beans="http://www.springframework.org/schema/beans"<br /> xsi:schemaLocation="http://www.springframework.org/schema/osgi<br /> http://www.springframework.org/schema/osgi/spring-osgi.xsd<br /> http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans.xsd"><br /><br /><service id="defaultUserManagerService" ref="defaultUserManager"<br /> interface="org.digitalcure.hellospring.common.IUserManager" /><br /></beans:beans></pre></li><li><span style="font-family:courier new;">bundle-context.xml</span>: Import an user manager service:<br /><pre><osgi:reference id="userManagerService" interface="org.digitalcure.hellospring.common.IUserManager" /></pre></li><li><span style="font-family:courier new;">bundle-context.xml</span>: Use the user manager service for the action:<br /><pre><bean id="listUserAction" class="org.digitalcure.hellospring.app.ListUserAction" ><br /><property name="userManager" ref="userManagerService" /><br /></bean></pre></li><li>Edit the product configuration file "HelloSpringApp.product" and add the "service" plug-in to the list of plug-ins (Configuration tab).</li><br /><li>Edit the Run Configuration. Add the "service" plug-in to the list of plug-ins.</li><br /><li>Run the application. Take care of the logger messages in the Console view. When the application frame appears, select the menu item "File" -> "List Users". You should see a list of user names in the Console view.</li><br /><li>Please note that the user managers of both plug-ins ("app" and "service") are available as OSGi services. You may control the ranking of the services by adding the "ranking" attribute to the service definition.</li><br /><li>"app" plug-in, <span style="font-family:courier new;">bundle-context-osgi.xml</span>:<br /><pre><service id="defaultUserManagerService" ref="defaultUserManager"<br /> interface="org.digitalcure.hellospring.common.IUserManager" ranking="5" /></pre></li><li>"service" plug-in, <span style="font-family:courier new;">bundle-context-osgi.xml</span>:<br /><pre><service id="extendedUserManagerService" ref="extendedUserManager"<br /> interface="org.digitalcure.hellospring.common.IUserManager" ranking="7" /></pre></li><li>Run the application once again and see what names are printed. You may now modify the ranking of the user manager service of the "service" plug-in to 3 and run the application again. You should see other names printed in the Console view.</li></ol><span style="font-family:georgia;">You may download the source code of the tutorial <a href="http://www.schwafel.de/source/Spring_AgileRCP_Tutorial.zip">from here</a>.</span>stefan222http://www.blogger.com/profile/08154541330426030666noreply@blogger.com2