<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8264982132165404360</atom:id><lastBuildDate>Mon, 07 Oct 2024 04:27:04 +0000</lastBuildDate><category>Micro-Pattern-Trilogie</category><category>MPT</category><category>MVP</category><category>Model-View-Presenter</category><category>Presenter First</category><category>Projekte</category><category>C#</category><category>CML</category><category>Caller-Mediator-Listener</category><category>1. MPT Beispiel</category><category>Atomix</category><category>Gedanken</category><category>Project Jessica</category><category>TFR</category><category>Transmitter-Frequency-Receiver</category><category>Allgemeines</category><category>CPS</category><category>Client-Provider-Server</category><category>Flow-Design</category><category>General</category><category>Neuigkeiten</category><category>OOP Kritik</category><category>Project Talisa</category><category>RAD-Tool</category><category>Ankündigung</category><category>DI</category><category>DIY-DI</category><category>Datenverwaltung</category><category>Dependency Injection</category><category>OOP</category><category>Paradigmen</category><category>Parser</category><category>Vorbereitung</category><category>Vorstellung</category><category>dynamic controls</category><category>dynamic views</category><category>dynamische Ansichten</category><category>dynamische Controls</category><title>Der Sachsen-Coder</title><description>OMG ... noch so&#39;n Programmier-Blog ^_^</description><link>http://sachsencoder.blogspot.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-1808924119056070609</guid><pubDate>Mon, 10 Sep 2012 21:57:00 +0000</pubDate><atom:updated>2012-09-10T23:57:25.458+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Allgemeines</category><category domain="http://www.blogger.com/atom/ns#">Flow-Design</category><category domain="http://www.blogger.com/atom/ns#">Gedanken</category><category domain="http://www.blogger.com/atom/ns#">OOP</category><category domain="http://www.blogger.com/atom/ns#">Project Talisa</category><title>OOP und Flow Design sind wie Yin und Yang</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Yin_yang.svg/200px-Yin_yang.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Yin_yang.svg/200px-Yin_yang.svg.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Je mehr ich in meinen Projekten Flow Design mithilfe der Event Based Components anwende, umso mehr stelle ich fest, dass auch die konventionelle Objektorientierte Programmierung sehr gut in das Konzept passt.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Das merke ich gerade besonders bei meinem &lt;a href=&quot;http://sachsencoder.blogspot.de/search/label/Project%20Talisa&quot; target=&quot;_blank&quot;&gt;&quot;Talisa&quot; Projekt&lt;/a&gt;. Seit einigen Tagen bastle ich intensiv an der Parser-Funktionalität.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
Im Groben funktioniert das ja so, dass man drüben eine Zeichenkette reinsteckt und am anderen Ende kommt ein vollständiger abstrakter Syntaxbaum heraus. Sich das als Flow vorzustellen, ist eine Wohltat für die Hirnzellen. Und so habe ich das auch aufgebaut. Bis ich an den Punkt kam, als es darum ging, die Token-Liste zu parsen. Das ist alles andere als trivial, wenn man es ordentlich machen will.&lt;/div&gt;
&lt;div&gt;
Natürlich wollte ich das auch erst pur im Flow Design Stil angehen. Aber als ich begann, einen kleinen Plan zu schmieden, wie ich das am Besten umsetze (&lt;i&gt;&quot;Also erst müsste es dort hin fließen, dann kommt das dort hinein, dann ... Mist, da brauche ich wieder shared state, dann geht das wieder dort hin ... oh Gott!&quot;&lt;/i&gt;), resignierte das Hirn schnell, indem es zu verstehen gab: &lt;i&gt;&quot;Boa, nee ... das ist doch nicht Dein Ernst, oder?! Das ist voll kompliziert, darüber nachzudenken! OOP fühlt sich hier viel besser an!&quot;&lt;/i&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Tatsächlich hatte ich auf Anhieb eine bessere Vorstellung von einer Lösung im OOP-Stil. Zwar noch nicht konkret, aber ich wusste, wie ich meine sogenannte &quot;FlowPattern&quot;-Komponente am liebsten verwenden möchte. &lt;a href=&quot;https://github.com/SachsenCoder/Talisa/blob/bef9dba5873db530d83de8530545597abf7c073f/Source/Talisa.Core/Create_Flow_Ast.cs&quot; target=&quot;_blank&quot;&gt;Aber diese OOP-Komponente steckt völlig isoliert in meiner Flow-Komponente mit der Bezeichnung &quot;Create_Flow_Ast&quot;&lt;/a&gt;. (Der verlinkte Quellcode ist noch völlig Work-In-Progress. Wie gesagt, ich bastle gerade noch am Parser.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Ich hatte auch schon des öfteren vergessen, dass ich mich in einer einzelnen Flow-Komponente befinde, aufgrund der Isolierung. ;-)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Wann verwende ich(!) Flow Design und wann OOP?&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
Ja, die Betonung liegt hier auf &quot;ich&quot;, weil es bei anderen Entwicklern wieder ganz anders sein kann. Die Liste kann aber als grobe Orientierung dienen, falls man noch nicht so das Gefühl dafür hat.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Flow Design:&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Beliebige rohe Daten müssen in abstrakte Datenstrukturen gebracht werden. Und dies kann in mehreren Etappen erfolgen.&lt;/li&gt;
&lt;li&gt;Man verwendet Closed-Source Komponenten oder fremden Code. Den sollte man sauber in eine Flow-Komponente stecken.&lt;/li&gt;
&lt;li&gt;Man kann sich sehr gut vorstellen, bestimmte Bereiche seines Codes asynchron ablaufen zu lassen.&amp;nbsp;➜ Diese Komponenten sollten in isolierte Flow Einheiten gesteckt werden!&lt;/li&gt;
&lt;li&gt;Es geht allgemein um Threads und asynchrone Verarbeitung?&amp;nbsp;➜ Flow, Flow, Flow und nochmal Flow! Ich kann das nicht oft genug betonen, weil Threads echt fies sein können. Ich bin schon oft ein Opfer von ihnen geworden. (So verrückt kann man gar nicht immer denken, welche Schlupflöcher diese &quot;Biester&quot; immer wieder finden. *g*)&lt;br /&gt;Daher: Jegliche Funktionalität von Threads getrennt halten. Threads isoliert halten und nur durch Flow-Eingänge und -Ausgänge an die zu erledigenden Aufgaben führen!&lt;/li&gt;
&lt;li&gt;Wann immer man vor seinem geistigen Auge einen Flow erkennen kann. Wenn das Lösen eines Problems durch Flow Design geradezu natürlich und einfach erscheint ... wenn das Nachdenken nicht sonderlich anstrengt, sondern im Gegenteil, es einen regelrecht mitreißt! Warum dann seine Zeit und Energie mit OOP verschwenden?&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;b&gt;OOP:&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Die Verarbeitung ist komplexer und lässt sich eher umständlich und unübersichtlich als Flow beschreiben.&lt;/li&gt;
&lt;li&gt;Die Lösung für ein Problem ist in sich geschlossen, untrennbar und atomar. Warum soll man hier auf OOP verzichten?&lt;/li&gt;
&lt;li&gt;Man hat etwas Hierarchisches, was irgendwie verarbeitet werden will.&lt;/li&gt;
&lt;li&gt;Die Usability (aus Entwicklersicht) kann durch Verwenden von OOP deutlich verbessert werden. (Siehe mein &quot;FlowPattern&quot;-Beispiel von oben.)&lt;/li&gt;
&lt;li&gt;Es ist nicht beabsichtigt bzw. nicht sinnvoll, Funktionalitäten innerhalb der Komponente asynchron ablaufen zu lassen. (Wieder mein &quot;FlowPattern&quot; als Beispiel: Es ist weder sinnvoll, noch beabsichtigt, irgendwelche Threads &lt;u&gt;innerhalb&lt;/u&gt; dieser Komponente hantieren zu lassen. Das wäre mehr als gefährlich!) Somit kann man getrost OOP nutzen, wenn ein gegebenes Problem dadurch leichter zu lösen ist.&lt;/li&gt;
&lt;li&gt;Wann immer man vor seinem geistigen Auge eine Interaktion von Objekten erkennen kann. Wenn das Lösen eines Problems durch OOP geradezu natürlich und einfach erscheint ... wenn das Nachdenken nicht sonderlich anstrengt, sondern im Gegenteil, es einen regelrecht mitreißt! Warum dann seine Zeit und Energie mit Flow Design verschwenden?&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Abschließend noch einige Zitate von Bruce Lee, die man auf die Essenz dieses Beitrags gut projizieren kann:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;i&gt;&quot;An der Kampfkunst ist nichts Geheimnisvolles. Nimm die Dinge wie sie sind: Schlage, wenn du schlagen mußt, tritt, wenn du treten mußt.&quot;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;i&gt;&quot;Der leichte Weg ist auch der richtige Weg.&quot;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;i&gt;&quot;Meine Bewegungen sind einfach, direkt und nicht-klassisch.&quot;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;i&gt;Bildquelle &quot;Yin Yang&quot;: &lt;a href=&quot;http://de.wikipedia.org/w/index.php?title=Datei:Yin_yang.svg&amp;amp;filetimestamp=20120227235200&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;;&lt;br /&gt;Zitatquelle:&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;a href=&quot;http://www.bruce-lee-jeet-kune-do.de/bruce-lee/zitate.html&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;http://www.bruce-lee-jeet-kune-do.de/bruce-lee/zitate.html&lt;/span&gt;&lt;/i&gt;&lt;/a&gt;&lt;/div&gt;
</description><link>http://sachsencoder.blogspot.com/2012/09/oop-und-flow-design-sind-wie-yin-und.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-6682571963826974313</guid><pubDate>Mon, 27 Aug 2012 18:42:00 +0000</pubDate><atom:updated>2012-08-27T20:42:53.954+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Project Talisa</category><category domain="http://www.blogger.com/atom/ns#">Projekte</category><title>Project Talisa</title><description>&lt;i&gt;&lt;b&gt;Eines vorweg:&lt;/b&gt; &lt;a href=&quot;http://sachsencoder.blogspot.de/search/label/Project%20Jessica&quot; target=&quot;_blank&quot;&gt;Project Jessica&lt;/a&gt; ist nicht tot! Es liegt vorerst nur auf Eis.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Project Talisa?&lt;/span&gt;&lt;br /&gt;
Hierbei handelt es sich um den Versuch, eine IDE für Flow Design orientierte Software zu erstellen.&lt;br /&gt;
Die Basis bzw. der gemeinsame Nenner wird die &quot;&lt;a href=&quot;http://blog.ralfw.de/2011/10/skalierbare-softwarebausteine-teil-2.html&quot; target=&quot;_blank&quot;&gt;Flow-Beschreibungssprache&lt;/a&gt;&quot; von Ralf Westphal sein.&lt;br /&gt;
&lt;br /&gt;
Eine konkrete Idee, wo die Reise hingehen wird, habe ich aber noch nicht direkt. Es wird sich entwickeln.&lt;br /&gt;
Aber was mir so vorschwebt, sind automatisch generierte Diagramme und Quellcode Dateien.&lt;br /&gt;
Importieren von Quellcode Dateien soll später auch mal möglich sein. Und natürlich auch das direkte Bearbeiten des Flows im Diagramm.&lt;br /&gt;
Eine art Simulationsmodus schwebt mir da auch noch vor. Eventuell sogar eine Flow Analyse oder so.&lt;br /&gt;
&lt;br /&gt;
Am Ende will ich mit der IDE meinem Ziel näher kommen, Software zu modellieren. (Bitte nicht mit UML Modellierung verwechseln! Das ist zu sehr vorbelastet und man denkt dabei an &quot;umständlich&quot; und &quot;kompliziert&quot;. Man sollte eher an das Modellieren von 3D Grafik Modellen denken. *g*)&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Was ich bei dem Projekt anders machen will, als bei Jessica&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Weniger faseln, sondern mehr coden!&lt;/b&gt; Ich schreibe zwar auch sehr gerne (zu gerne sogar), aber davon entsteht leider keine Software. Das ärgert mich zwar selber, aber ich muss da Prioritäten setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Es gibt nix Perfektes!&lt;/b&gt; Der Tatsache muss ich einfach immer wieder ins Auge blicken! Ich will es nicht wahr haben, aber so ist es. Ich will immer alles perfekt machen, aber das lähmt ungemein. Die Gedanken kreisen ständig um Kleinigkeiten. Man kommt sich vor, als ob man versucht Ort und Impuls von Quantenteilchen gleichzeitig bestimmen zu wollen. Aber es funktioniert nicht.&lt;br /&gt;
In der Softwareentwicklung ist es das Selbe. Man kann zwar versuchen, ein Optimum zu erreichen, aber man wird immer irgendwelche Kompromisse eingehen (müssen), die einfach &quot;hässlich&quot; sind.&lt;br /&gt;
Und so werde ich mich auch nicht zu sehr damit belasten, eine Perfektion zu erreichen. Wie es wird, so wird es. Hauptsache, es gibt was Funktionierendes. Das bringt mich zum nächsten Punkt ...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ship early and often!&lt;/b&gt; Mal sehen, ob ich das einhalten kann. (Hier spielen ja auch die Faktoren &quot;Zeit&quot; und &quot;Motivation&quot; eine Rolle.)&lt;br /&gt;
Man kann das aber auch so an vielen Open Source Projekten beobachten. Erfolgreich sind die Projekte, wo es schnell vorwärts geht. Auch diese Projekte sind oft weit weg von &quot;Perfekt&quot;, aber man kann die Evolution erkennen. Da ist was in Bewegung und man weiß, dass man für das nächste Release nicht erst ein Jahr warten muss. Um das zu erreichen, muss man bereit sein, die Illusion der Perfektion hinter sich zu lassen.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Wird gefrickelt? Schon möglich.&lt;/b&gt;&amp;nbsp;Das heißt, es gibt keinen direkten Plan, wie ich bei dem Projekt vorgehe. Es ist auch möglich, dass ich eventuell das Rad neu erfinde, weil ich eine gewisse Technologie noch nicht verstanden habe und es in meinen Augen einfach schneller geht, wenn ich es für meine Bedürfnisse selbst implementiere.&lt;br /&gt;
&lt;br /&gt;
Kurzum: Ich will auch für mich persönlich schnell Features haben, die ich produktiv nutzen kann. Zudem sehe ich das Projekt als Experiment, wie eine neu IDE aussehen könnte und was für Möglichkeiten realisierbar sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Warum der Name &quot;Talisa&quot;?&lt;/span&gt;&lt;br /&gt;
Aus dem selben Grund, wie ich das andere Projekt &quot;Jessica&quot; genannt habe. Ein Name, wie z.B. Flow(er)IDE oder sowas, klingt irgendwie abgedroschen und hat man irgendwie schon mal gehört. Ein einfacher femininer Name passt. Wer will, kann ja bei der Google Bildersuche mal nach Talisa suchen. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bleibt eigentlich nur noch zu sagen, dass man &lt;a href=&quot;https://github.com/SachsenCoder/Talisa&quot; target=&quot;_blank&quot;&gt;das Projekt bei GitHub findet&lt;/a&gt;.&lt;br /&gt;
(Dank &quot;&lt;a href=&quot;http://windows.github.com/&quot; target=&quot;_blank&quot;&gt;GitHub for Windows&lt;/a&gt;&quot; habe ich Git nun auch halbwegs im Griff. *g*)&lt;br /&gt;
&lt;br /&gt;
Tja, dann guck mer mal. ;-)</description><link>http://sachsencoder.blogspot.com/2012/08/project-talisa_27.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4191137768402741661</guid><pubDate>Sun, 05 Feb 2012 18:18:00 +0000</pubDate><atom:updated>2012-02-05T19:18:31.491+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Datenverwaltung</category><category domain="http://www.blogger.com/atom/ns#">Project Jessica</category><category domain="http://www.blogger.com/atom/ns#">Projekte</category><title>Project Jessica - Datenverwaltung</title><description>Ein wesentlicher Aspekt der Software wird die Datenverwaltung sein.&lt;br /&gt;
Ich habe lange überlegt, ob ich eine fertige Datenbanklösung nehme oder etwas Eigenes entwerfe, was exakt auf meine Bedürfnisse zugeschnitten ist.&lt;br /&gt;
Mir wurde empfohlen, vielleicht besser eine bestehende dokumentenorientierte Datenbanklösung zu verwenden. &lt;a href=&quot;http://www.mongodb.org/&quot; target=&quot;_blank&quot;&gt;MongoDB&lt;/a&gt; wirkte auf mich erstmal sehr attraktiv und ausgereift. Aber dieses Datenbanksystem bringt standardmäßig ca. 65 MB auf die Waage. Da stehen noch keine Nutzerdaten drin. Das ist der gewöhnliche Overhead.&lt;br /&gt;
Das ist mir ein bisschen schwergewichtig.&lt;br /&gt;
Ich hatte mich auch mal umgesehen, was es sonst noch so für &lt;a href=&quot;http://nosql-database.org/&quot; target=&quot;_blank&quot;&gt;NoSQL-Datenbanken&lt;/a&gt; gibt. Da gibt es ja enorm viele. Stichprobenartig habe ich mir auch mal die ein oder andere genauer angesehen. Da hat jede so ihre Vor- und Nachteile. Die eine ist kommerziell, die andere vom Background her zu kompliziert, zu schwergewichtig, hat keine offizielle .NET-API, oder, oder, oder.&lt;br /&gt;
Ich möchte damit nicht die Leistung der Datenbankentwickler schmälern, die da sehr viel Zeit und Know-How investiert haben. Ich brauche aber eher was Einfaches, speziell Zugeschnittenes, ohne generischen full fledged Datenbank-Wrapper.&lt;br /&gt;
&lt;br /&gt;
Eine Kleinigkeit hatte ich nämlich vergessen zu erwähnen: Jessica soll keine umfangreiche Installation erfordern oder sich ins System einnisten, um zu funktionieren. Sie soll portabel sein.&lt;br /&gt;
Entpacken ... ausführen ... glücklich sein! ^_^&lt;br /&gt;
&lt;br /&gt;
Alle relevanten Daten, die sie im Laufe ihres Lebens anlegen muss, landen in einem einfachen Unterverzeichnis direkt neben &quot;ihr&quot;.&lt;br /&gt;
Das hat, wie ich finde, mehrere Vorteile:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Man weiß, wo sich die Daten befinden.&lt;/b&gt; Oft ist es schwierig, bei anderer Bildverwaltungssoftware, den Ort der erzeugten Daten zu lokalisieren. (Vielleicht befinden sie sich im AppData-Verzeichnis oder doch woanders?!)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Man kann leichter experimentieren.&lt;/b&gt; So benennt man nur den Datenordner um, startet die Software neu und sie verhält sich so, als würde sie zum allerersten mal gestartet. Danach könnte man diesen &quot;Testordner&quot; wieder löschen ... nennt den anderen Ordner wieder so wie vorher ... startet Jessica und alles ist so, als wäre nie etwas gewesen.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Es sind ganz einfach vollständige Backups möglich.&lt;/b&gt; Das ergibt sich auch durch den zweiten Punkt.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bilder und Software zusammen mitnehmen.&lt;/b&gt; Zum Beispiel, wenn man auf einer externen Festplatte seine ganzen Bilder hat, könnte man dort auch die Jessica inklusive ihrer Daten drauf kopieren. Woanders könnte man dann die Bilder problemlos mit der voll eingerichteten Software betrachten, vorführen oder organisieren.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Solche Dinge, wie die Sache mit den Backups oder so, kann man auch direkt in die Software integrieren. Auf lange Sicht soll sie sehr DAU-freundlich sein.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Nun zur eigentlichen Datenverwaltung:&lt;/div&gt;
&lt;div&gt;
Ich versuche die Sache pragmatisch anzugehen. Ich möchte in erster Linie (Medien)-Dateien verwalten. Punkt.&lt;/div&gt;
&lt;div&gt;
Jede Datei besitzt ja von Haus aus einen Dateiname. Diese Datei kann auch noch in einem Ordner liegen. Zusätzlich gibt es zu jeder Datei mögliche Tags bzw. Schlagworte.&lt;/div&gt;
&lt;div&gt;
(Klar, diverse Medienformate haben noch viel mehr Metadaten zu bieten. Aber die interessieren mich am Anfang eher weniger, weil ich ja kein Profi-Fotograf bin. Wenn aber die Software soweit ist, dass sie z.B. nach Tags exakt filtern kann, werden auch noch andere Metadaten hinzukommen.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Es gilt also erstmal strikte Komplexitätsreduktion und Fokus auf das Wesentliche:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Dateinamen&lt;/li&gt;
&lt;li&gt;Dateinamenerweiterungen&lt;/li&gt;
&lt;li&gt;Ordnernamen&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Nach diesen Dingen soll am Anfang gesucht werden können. Das wäre dann so ähnlich, wie es bei Picasa der Fall ist.&lt;br /&gt;
&lt;br /&gt;
Nun habe ich mich die letzten Tage (bzw. Wochen) immerzu mit diesem Aspekt gedanklich auseinandergesetzt. Ich habe recherchiert und bin dabei immer wieder auf &lt;a href=&quot;http://de.wikipedia.org/wiki/B-Tree&quot; target=&quot;_blank&quot;&gt;B-Trees&lt;/a&gt; gestoßen. Diese Struktur scheint sich bei Datenbanken durchgesetzt zu haben. Eine &lt;a href=&quot;http://bplusdotnet.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;Implementation für C#&lt;/a&gt; habe ich auch gefunden.&lt;br /&gt;
&lt;br /&gt;
Es gibt aber noch eine Sache, die mich doch sehr beschäftigt:&lt;br /&gt;
Wie kann man effizient nach Dateien oder allgemein nach Stichworten suchen? Wie organisiert man sowas strukturell?&lt;br /&gt;
Das Einfachste wäre ja, man sortiert sie alphabetisch. Das Problem ist aber, dass man im seltensten Fall eine Datei alphabetisch sucht. Man sucht ja eine Datei viel öfter nach ihrem ungefähren Wortlaut. Gerade, weil man nicht mehr genau weiß, wie sie hieß.&lt;br /&gt;
Also kann man IMHO nicht einfach alphabetisch sortieren und danach indizieren. Man müsste jeden Buchstabe von einem Dateiname indizieren.&lt;br /&gt;
Um das anschaulicher zu machen, habe ich einige Grafiken angefertigt, mit denen ich ein Beispielszenario durchgehe.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir mal an, es gibt ein Bild, welches &quot;Jessica&quot; heißt. (Der Einfachheit halber verzichte ich hier auf Dateiendungen.)&lt;br /&gt;
Schematisch dargestellt, teilt sich der Name in folgende Buchstaben auf:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifoQZW6jo2QzVJgMEm8m5rGwd9_eX9KMIebHjE6_NTIliPP7nzmXyLAcewDVZGiFRmuhhzxbQGgNLRdZ56NgYHRSacBOeu-WMXq0ppO_I_uGfu8kCI1IjjzL_gqIVhJxxLVP7MjreFMNiN/s1600/Search_Tree.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;56&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifoQZW6jo2QzVJgMEm8m5rGwd9_eX9KMIebHjE6_NTIliPP7nzmXyLAcewDVZGiFRmuhhzxbQGgNLRdZ56NgYHRSacBOeu-WMXq0ppO_I_uGfu8kCI1IjjzL_gqIVhJxxLVP7MjreFMNiN/s400/Search_Tree.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Jeden Buchstabe würde ich einzeln indizieren, sodass jeder Buchstabe auf die Datei verweist.&lt;br /&gt;
Hierzu müssen aber redundante Buchstaben entfernt und eine alphabetische Ordnung hergestellt werden. Wie ich mir das vorstelle, sieht man im nächsten Bild in der obersten Reihe:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAM1Y7Sy2QufAz8xgqganCyT7O3IH9yXzj59Ozbzq9veNl-PBn5oFwoLKlbIUkJBPhyphenhyphenzujphHg-pcccppE_OCgbI8JKBC71aFmUIBE0b_YEGEJ3BovwetnAKJk7MQokhc3kvy7qhohXWrY/s1600/Search_Tree_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAM1Y7Sy2QufAz8xgqganCyT7O3IH9yXzj59Ozbzq9veNl-PBn5oFwoLKlbIUkJBPhyphenhyphenzujphHg-pcccppE_OCgbI8JKBC71aFmUIBE0b_YEGEJ3BovwetnAKJk7MQokhc3kvy7qhohXWrY/s400/Search_Tree_2.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Die oberste Reihe kann man sich wie eine Liste bzw. wie ein Dictionary vorstellen. In einem Suchfeld könnte ich einen der Buchstaben aus der obersten Reihe eingeben und bekäme als Suchergebnis mindestens auch die &quot;Jessica&quot;-Datei angeboten.&lt;br /&gt;
An jedem Buchstabe aus der obersten Reihe könnte wieder eine Liste oder eine Graph-Struktur hängen. In der Struktur sind dann wieder Buchstaben hinterlegt, welche auf die &quot;Jessica&quot;-Datei verweisen.&lt;br /&gt;
Die Pfeile geben eine valide Buchstabenfolge wieder, mit der man die &quot;Jessica&quot;-Datei finden kann.&lt;br /&gt;
Gebe ich also &quot;&lt;b&gt;ICA&lt;/b&gt;&quot; in das Suchfeld ein, bekomme ich als logische Konsequenz die &quot;Jess&lt;b&gt;ica&lt;/b&gt;&quot;-Datei angezeigt, weil diese Buchstaben in der Reihenfolge im Dateiname vorkommen.&lt;br /&gt;
Würde ich aber &quot;&lt;b&gt;ICAB&lt;/b&gt;&quot; eingeben, so bekäme ich die Datei nicht angezeigt, weil diese Buchstabenfolge nicht im Name vorkommt. Nach dem Knoten &quot;&lt;b&gt;A&lt;/b&gt;&quot; kommt nix mehr. Beim Buchstabe &quot;&lt;b&gt;S&lt;/b&gt;&quot; gibt es zwei mögliche Wege, bedingt durch das doppelte Auftreten dieses Buchstaben im Name.&lt;br /&gt;
&lt;br /&gt;
Wie sieht das Ganze aus, wenn ein Dateiname hinzukommt? Um das ganze interessanter zu machen, habe ich einen Name gewählt, der sich mit &quot;Jessica&quot; überschneidet. Die andere Datei heißt &quot;Jennifer&quot;.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_FGCMnhT4h2LT8vvSQIlS9OH-891dSRJTJq1y8WfMMrkTJPLbWTrBjPzDwYSS5BrRDmm42wbsArv6gzfm115bG-Qza90pNYYDeMQXXEicx_TkYyisi_-EoHx051i4bxJ70-sugluVNeBD/s1600/Search_Tree_.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;50&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_FGCMnhT4h2LT8vvSQIlS9OH-891dSRJTJq1y8WfMMrkTJPLbWTrBjPzDwYSS5BrRDmm42wbsArv6gzfm115bG-Qza90pNYYDeMQXXEicx_TkYyisi_-EoHx051i4bxJ70-sugluVNeBD/s400/Search_Tree_.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Zur besseren Unterscheidung sind die Knoten von &quot;Jennifer&quot; blau.&lt;br /&gt;
Das folgende Bild zeigt die alphabetische Anordnung aller Knoten inklusive der Knoten von &quot;Jessica&quot;:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgveKDwycCw29hqoKkt-osE3nt5HFF8dfPJFhaQdy7SfwWFAtFCjLrFI1GuKjF5Rq-GazYVa9g7ydXgLimW9tpGQKtnbjbsDDNVTchMVJRi2IdgmA6DVmKd8Mjmsee3-a9N5Q57iGGF8smj/s1600/Search_Tree_3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;211&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgveKDwycCw29hqoKkt-osE3nt5HFF8dfPJFhaQdy7SfwWFAtFCjLrFI1GuKjF5Rq-GazYVa9g7ydXgLimW9tpGQKtnbjbsDDNVTchMVJRi2IdgmA6DVmKd8Mjmsee3-a9N5Q57iGGF8smj/s400/Search_Tree_3.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Das Gebilde sieht schon interessanter aus. Buchstaben, welche beide Namen gemeinsam haben, habe ich anders eingefärbt, um sie besser hervorzuheben.&lt;br /&gt;
Nun ist der Graph schon bei zwei Namen so umfangreich geworden. Logisch! Gerade am Anfang würde er immer stark anwachsen, weil es sehr wahrscheinlich ist, dass es bestimmte Buchstaben- und Zeichenkombinationen noch nicht gibt. Das Wachstum wird sich aber abschwächen, je mehr Dateinamen es gibt. Pro Knoten wird es dann nur mehr Indexverweise geben. Das Auffinden einer beliebigen Datei sollte aber verhältnismäßig schnell gehen. In dem obigen Beispiel müsste man im schlechtesten Fall 3 Buchstaben eingeben, um eine Datei eindeutig zu finden. Im besten Fall reicht ein Buchstabe. Ein Knoten referenziert aber immer eine exakte Indexmenge. Das heißt, die Resultate könnten sofort abgerufen werden. Das würde sicher erstmal viel Redundanz verursachen. Aber vielleicht ließe sich da später noch was optimieren.&lt;br /&gt;
Eine Möglichkeit fiele mir schon ein. In dem obigen Beispiel bräuchte man nur 3 getrennte Index-Cluster und nicht für jeden Knoten einen eigenen.&lt;br /&gt;
&lt;br /&gt;
Ich hätte zumindest keine Idee, wie man sonst effizient nach bestimmten Dateien anhand von Wortfragmenten suchen will.&lt;br /&gt;
Ich müsste das einfach mal in der Praxis ausprobieren und dann sehen, ob mir das überhaupt Vorteile bringt.&lt;br /&gt;
Vielleicht habe ich mich auch komplett in eine Sackgasse verrannt. Erst recht, weil ich schon zu lange über diese Problematik nachdenke und dadurch noch nix umgesetzt habe.&lt;br /&gt;
&lt;br /&gt;
Vielleicht sollte ich mich mit diesem Aspekt der Datenverwaltung noch gar nicht heiß machen. Ob ich am Ende eine eigene Verwaltung implementiere oder doch ein bestehendes Datenbanksystem verwende, kann im Grunde noch offen bleiben. Die Architektur soll auf jeden Fall so aufgebaut sein, dass dieser Aspekt jederzeit ausgetauscht werden kann.&lt;br /&gt;
&lt;br /&gt;
Strategisch günstiger wird es sein, wenn ich das Projekt von ganz oben beginne: beim User Interface.&lt;br /&gt;
Vor allem hätte man dadurch schon am Anfang sichtbare Fortschritte. Wenn dann erst mal das Gefühl für die Usability da ist, wächst der Rest so allmählich hinein.&lt;br /&gt;
&lt;br /&gt;
Als nächstes werde ich also erstmal Mockups skizzieren, wie ich mir das GUI vorstelle. Dann habe ich auch ein Gerüst, wenn ich das in XAML kodiere. Ein Mockup ist schnell mal verworfen oder verändert.&lt;br /&gt;
&lt;br /&gt;
Bis dann.&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;-chrome-auto-translate-plugin-dialog&quot; style=&quot;background-attachment: initial !important; background-clip: initial !important; background-color: transparent !important; background-image: initial !important; background-origin: initial !important; display: none; left: 0px; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; opacity: 1 !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important; position: absolute !important; text-align: left !important; top: 0px; z-index: 999999 !important;&quot;&gt;
&lt;div style=&quot;-webkit-border-radius: 10px !important; background-color: #363636 !important; background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #000), color-stop(50%, #363636), color-stop(100%, #000)); border-color: #000000 !important; border-width: 0px !important; color: #fafafa !important; font-size: 16px !important; max-width: 300px !important; opacity: 0.8 !important; overflow: visible !important; padding: 8px !important; text-align: left !important; z-index: 999999 !important;&quot;&gt;
&lt;div class=&quot;translate&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;additional&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img onclick=&quot;document.location.href=&#39;http://translate.google.com/&#39;;&quot; src=&quot;http://www.google.com/uds/css/small-logo.png&quot; style=&quot;-webkit-border-radius: 20px; background-color: rgba(200, 200, 200, 0.3) !important; cursor: pointer !important; margin: 0 !important; padding: 3px 5px 0 !important; position: absolute !important; right: 1px !important; top: -20px !important; z-index: -1 !important;&quot; /&gt;&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2012/02/project-jessica-datenverwaltung.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifoQZW6jo2QzVJgMEm8m5rGwd9_eX9KMIebHjE6_NTIliPP7nzmXyLAcewDVZGiFRmuhhzxbQGgNLRdZ56NgYHRSacBOeu-WMXq0ppO_I_uGfu8kCI1IjjzL_gqIVhJxxLVP7MjreFMNiN/s72-c/Search_Tree.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4004847245005086936</guid><pubDate>Sun, 22 Jan 2012 16:06:00 +0000</pubDate><atom:updated>2012-01-22T17:06:42.030+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Project Jessica</category><category domain="http://www.blogger.com/atom/ns#">Projekte</category><category domain="http://www.blogger.com/atom/ns#">Vorbereitung</category><title>Project Jessica - Vorbereitung</title><description>&lt;span style=&quot;font-size: large;&quot;&gt;Wie wird die Versionierung aussehen?&lt;/span&gt;&lt;br /&gt;
Ist das &quot;Big Picture&quot; nach meinem Empfinden erreicht, bekommt Jessica die Version 1.0.&lt;br /&gt;
Die Schritte dahin werden in Iterationen zerlegt. Und Iterationen werden in Slices zerlegt.&lt;br /&gt;
&lt;br /&gt;
Angenommen, es gibt die Version 0.3.2, dann heißt das, es ist die 3. Iteration mit dem 2. Slice auf den Weg zum &quot;Big Picture&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Definition &quot;Iteration&quot;&lt;/b&gt;&lt;br /&gt;
Eine Iteration beinhaltet eine Funktionalität, mit der man schon etwas Sinnvolles anfangen kann. &quot;Sinnvoll&quot; ist natürlich relativ. Im Falle von Jessica ist der erste Schritt insofern sinnvoll, weil ich ein oder mehrere Ordner importieren kann und mir ALLE gefundenen Bilder angezeigt werden können, bzw ich durchscrollen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Definition &quot;Slice&quot;&lt;/b&gt;&lt;br /&gt;
Ein Slice ist ein kleines Häppchen auf den Weg zur ersten sinnvollen Funktionalität. Nur für sich genommen ist ein Slice nicht sinnvoll. Um beim obigen Beispiel zu bleiben, ist es nicht sinnig, wenn ich einen Ordner importieren könnte, aber es würde nix angezeigt werden.&lt;br /&gt;
Aber der Slice ist wichtig, um die Komplexität aus Entwicklersicht zu reduzieren und um die Motivation zu erhalten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie viele Iterationen oder Slices es geben wird, steht noch nicht fest. Das hängt von der Komplexität des angestrebten Features ab.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Das Repository&lt;/span&gt;&lt;br /&gt;
Vorgestern habe ich das Git-Repository bei GitHub eingerichtet.&lt;br /&gt;
Man findet es dort:&amp;nbsp;&lt;a href=&quot;https://github.com/SachsenCoder/Jessica&quot;&gt;https://github.com/SachsenCoder/Jessica&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Mit der Schritt-für-Schritt-Anleitung von GitHub war das Einrichten sehr einfach. Ich hatte nur lokal ein kleines Problem mit der &quot;Git Bash&quot;, weil die Konsole kein UTF-8 darstellen wollte. (Mein Nachname hat ja das &quot;ö&quot; an zweiter Stelle.)&lt;br /&gt;
Naja, ich habe mich dann für die &lt;a href=&quot;http://code.google.com/p/gitextensions/&quot; target=&quot;_blank&quot;&gt;Git Extensions&lt;/a&gt; entschieden. Das Tool nutzte ich auch sonst ganz gerne für meine lokalen Repositories. Damit war das UTF-8 Problem auch gelöst. ^^&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Wie geht es weiter?&lt;/span&gt;&lt;br /&gt;
Gestern hatte ich die echte Jessica vektorisiert:&amp;nbsp;&lt;a href=&quot;http://fav.me/d4n56c4&quot;&gt;http://fav.me/d4n56c4&lt;/a&gt;&lt;br /&gt;
(Sowas brauchte ich auch mal wieder. Das hat was Entspannendes.)&lt;br /&gt;
&lt;br /&gt;
Als nächstes werde ich erstmal ein paar Spikes entwerfen. Das betrifft einmal das GUI und die &quot;Datenbank&quot;.&lt;br /&gt;
Datenbank deshalb in Anführungsstrichen, weil ich erstmal selber eine Idee testen will. Eine richtige universelle Datenbank wird das nicht und ist auch gar nicht beabsichtigt.&lt;br /&gt;
Wie ich mir das vorstelle, wird in einem weiteren Beitrag beschrieben.&lt;br /&gt;
Die Spikes werde ich auch in das Repository packen. Die gehören immerhin zur Entwicklung dazu. ;-)&lt;br /&gt;
&lt;br /&gt;
Bis dann! :-)&lt;br /&gt;
&lt;div id=&quot;-chrome-auto-translate-plugin-dialog&quot; style=&quot;background-attachment: initial !important; background-clip: initial !important; background-color: transparent !important; background-image: initial !important; background-origin: initial !important; display: none; left: 0px; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; opacity: 1 !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important; position: absolute !important; text-align: left !important; top: 0px; z-index: 999999 !important;&quot;&gt;
&lt;div style=&quot;-webkit-border-radius: 10px !important; background-color: #363636 !important; background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #000), color-stop(50%, #363636), color-stop(100%, #000)); border-color: #000000 !important; border-width: 0px !important; color: #fafafa !important; font-size: 16px !important; max-width: 300px !important; opacity: 0.8 !important; overflow: visible !important; padding: 8px !important; text-align: left !important; z-index: 999999 !important;&quot;&gt;
&lt;div class=&quot;translate&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;additional&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img onclick=&quot;document.location.href=&#39;http://translate.google.com/&#39;;&quot; src=&quot;http://www.google.com/uds/css/small-logo.png&quot; style=&quot;-webkit-border-radius: 20px; background-color: rgba(200, 200, 200, 0.3) !important; cursor: pointer !important; margin: 0 !important; padding: 3px 5px 0 !important; position: absolute !important; right: 1px !important; top: -20px !important; z-index: -1 !important;&quot; /&gt;&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2012/01/project-jessica-vorbereitung.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-59711933920585874</guid><pubDate>Thu, 19 Jan 2012 22:28:00 +0000</pubDate><atom:updated>2012-01-19T23:28:48.698+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Project Jessica</category><category domain="http://www.blogger.com/atom/ns#">Projekte</category><category domain="http://www.blogger.com/atom/ns#">Vorstellung</category><title>Project Jessica - Vorstellung</title><description>Ich muss mich jetzt quasi outen, da es sonst für Außenstehende keinen Sinn ergeben würde, weshalb gerade ich eine solche Software brauchen sollte.&lt;br /&gt;
&lt;br /&gt;
Ich besitze ca. 269 Tausend Mediendateien (Videoclips und Bilder zusammen) verteilt auf etwa 3.713 Ordnern mit fast 310 GB, kann mich nur schwer von einem Bild trennen, aber fotografiere selber so gut wie gar nicht.&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Die große Preisfrage:&lt;/u&gt;
&lt;br /&gt;
Wie komme ich zu so einer menge Material? Wer oder was bin ich? ;-)&lt;br /&gt;
&lt;br /&gt;
Ich glaube, ich bin ein Bildermessie oder sowas. Ich denke manchmal, dass das echt schon krankhaft ist.&lt;br /&gt;
So habe ich z.B. einen Ordner, wo nur Bilder von &lt;a href=&quot;http://www.deviantart.com/&quot; target=&quot;_blank&quot;&gt;deviantArt&lt;/a&gt; drin sind ... ca. 16 Tausend Bilder, rund 21,9 GB überwiegend High-Quality. Alles manuell runtergeladen. (Gott, wenn ich mir das mal auf der Zunge zergehen lasse. Die Tabs vom Google Chrome Browser haben da schon des öfteren den Geist aufgegeben, weil zu viele HQ Bilder gleichzeitig geöffnet waren. Und die Flash-Instanzen schlugen auch noch zu Buche. Ich glaube, der Chrome Browser selber ist da auch schon mal komplett abgeschmiert. *g*)&lt;br /&gt;
Oder meine Sammlung weiblicher Promis:&amp;nbsp;21.343 Dateien verteilt auf 448 Ordner (ca. 10,8 GB).&lt;br /&gt;
&lt;br /&gt;
Da bin ich natürlich scharf auf gute Bildverwaltungsprogramme, denn es werden sicher nicht weniger Bilder. Eher noch mehr.&lt;br /&gt;
So manches Tool kam mit der Menge gar nicht zurecht, weil das nur auf wenige Bilder ausgelegt war. (So in der Größenordnung von wenigen Hundert bis Tausend oder so. Also, was der Otto Normaluser so mit seiner Digicam produziert.)&lt;br /&gt;
Andere Tools brechen zusammen, wenn man mal um die 30 Tausend Bilder als Slideshow in zufälliger Reihenfolge abspielen lassen will. -.-&lt;br /&gt;
Oder beim Photoshop Elements Organizer: Das Tool machte Anfangs wirklich einen guten Eindruck. Mal um die Tausend Bilder in einen Katalog eingelesen. Ging ganz gut. Vor allem die Filtermöglichkeiten und die Smartalben hatten mich erstaunt. Sowas wollte ich schon immer mal haben. Also hatte ich es gewagt: Er sollte meinen ganzen Bestand einlesen. &quot;ACH DU SCHANDE! Was ist denn jetzt los?&quot; sagte ich so zu mir. Da hat der mir echt einen &lt;b&gt;modalen&lt;/b&gt;&amp;nbsp;Progressdialog angedreht, wo es nur die Möglichkeit zum Abbrechen gab. Naja, muss es eben so sein. Ich glaube, der war fast den halben bis dreiviertel Tag damit beschäftigt, die Medien einzulesen. Wäre ja alles nicht so schlimm gewesen, wenn er das im Hintergrund gemacht hätte. Als er denn dann endlich fertig war, hat er mir erstmal gesagt, was er alles nicht einlesen konnte. Das präsentierte er mir in einem winzigen Dialog in einer noch winzigeren Listbox, wo ich mir dann die fehlgeschlagenen Dateien ansehen konnte. Gut, vielleicht waren da wirklich ein paar Beschädigte dabei. Oder es handelte sich zum Teil auch um Zip-/Rar-Archive. Soviel ich noch weiß, hat er mal aufgrund der fehlerhaften Dateien den Vorgang mittendrin abgebrochen. Da hatte ich dann letztlich immer nur eine Hand voll Ordner gleichzeitig eingelesen. Das hat er einigermaßen verkraftet. Aber selbst der restliche Umgang mit der Datenmenge hat keinen Spaß gemacht. Immer wieder wurde man vom GUI abgehalten, etwas zu tun, weil es blockierte. Das war eine sehr grausige Software (für meine Bedürfnisse).&lt;br /&gt;
Tja, meine bisherigen Favoriten sind Picasa und die Windows Live Fotogalerie. Die kommen spielend mit großen Datenmengen klar. Aber denen mangelt es massiv an komfortablen Verwaltungsfunktionen, wie ich sie gerne hätte.&lt;br /&gt;
&lt;br /&gt;
Nun wollte ich eigentlich warten, bis diese Tools irgendwann mal Smartalben oder mächtige Filtermöglichkeiten haben. Aber da kann ich vielleicht noch lange warten. &lt;a href=&quot;http://www.google.com/moderator/#8/e=3f2ad&quot; target=&quot;_blank&quot;&gt;Entweder wollen das wirklich nicht viele Leute, oder sie wissen gar nicht, was Smartalben sind&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Nein, jetzt reicht&#39;s! Ich brauche die Features sehr bald. Ich will endlich mal Ordnung in meine Bild- und Videoclip-Bestände bringen!&lt;br /&gt;
Also gibt es nur eine Lösung: Selber machen!&lt;br /&gt;
Jene Software wird auf den Name &lt;b&gt;Jessica&lt;/b&gt; hören!&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;Jessica - Die Bildverwaltungssoftware für anspruchsvolle Sammler&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://i17.photobucket.com/albums/b90/hardensbabe06/jessica-alba.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://i17.photobucket.com/albums/b90/hardensbabe06/jessica-alba.jpg&quot; width=&quot;253&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Wird meine Software am Ende&lt;br /&gt;
auch mal so attraktiv sein,&lt;br /&gt;
wie die echte Jessica?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Warum gerade der Name &quot;Jessica&quot;?&lt;br /&gt;
Wenn ich den Name höre, muss ich unweigerlich an Jessica Alba denken. ^_^&lt;br /&gt;
Und das wird mir immer vor Augen halten, dass meine Software &quot;Jessica&quot; auch sexy und menschlich werden soll! Mit &quot;menschlich&quot; meine ich hier speziell die Mensch-Maschine-Interaktion. Software und Hardware sollten sich doch dem Menschen anpassen und nicht umgekehrt. Aber das werde ich im weiteren Verlauf noch genauer erläutern, was mir da so vorschwebt.&lt;br /&gt;
Generell werde ich versuchen, neue Pfade zu beschreiten. Ob mir das gelingen wird, weiß ich nicht. Aber die Vision ist an der Stelle wichtig und dass man darauf hin arbeitet. Warum sollte man sich mit weniger zufrieden geben? Was Microsoft, Apple, Google &amp;amp; Co. entwickeln, ist doch nicht das Ende der Fahnenstange an Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;u&gt;The Big Picture&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
OK, nun das &quot;Big Picture&quot;. Ich glaube, das kann man wörtlich nehmen, bei dem, was die Jessica am Ende alles können soll:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;100 Bilder? 100.000 Bilder? 1.000.000 Bilder oder noch mehr? ... Die Menge spielt für mich keine Rolle!&quot;&lt;/b&gt;&lt;br /&gt;
Es liegt auf der Hand, dass Jessica spielend mit beliebig vielen Bildern umgehen können soll. Das ist soweit nix Besonderes, denke ich. Ich denke mir, Picasa und die Windows Live Fotogalerie können das auch.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Was? Du suchst altmodische, statische Alben? Bei mir sind die Alben intelligent, dynamisch und beliebig kombinierbar!&quot;&lt;/b&gt;&lt;br /&gt;
Hier wird es schon interessanter. Das soll nämlich so ein Killer-Feature werden.&lt;br /&gt;
Es wird nach wie vor möglich sein, ein statisches Album anzulegen, wenn man denn unbedingt möchte. Aber bei der Jessica sollen solche Alben intern nur Smartalben mit einer fixen Bildermenge sein. Da wird es aus struktureller Sicht keinen Unterschied geben.&lt;br /&gt;
Aber die Stärken sollen sich erst offenbaren, wenn man die Bilder detailliert mit Tags beschrieben hat. Heutige Tools ermöglichen zwar auch, seine Bilder ausführlich zu taggen ... ja, man sagt sogar, je ausführlicher ein Bild getagged ist, desto besser findet man es wieder. Das hatte ich auch immer gedacht. Daher hatte ich damals auch begonnen, meine Bilder sehr ausführlich zu taggen.&lt;br /&gt;
Dann wollte ich natürlich mit den Filtermöglichkeiten spielen: Zeige mir die Bilder, welche Tag &quot;X&quot; haben, aber nicht Tag &quot;Y&quot; ... zusätzlich können hier noch Bilder reinfallen, welche Tag &quot;M&quot; haben, aber auf keinen Fall dürfen Bilder angezeigt werden, welche Tag &quot;P&quot; haben.&lt;br /&gt;
Bei sowas stößt man bei der gängigen Software schnell an seine Grenzen und ist dann sehr enttäuscht. Da nützen ja die ganzen detaillierten Tags nix, wenn ich nicht exakt das rausfiltern kann, was ich will.&lt;br /&gt;
&lt;br /&gt;
Die Smartalben sollen aber noch mehr können: Man soll vorher Filterregeln für die Smartalben festlegen können. (Soweit nix Besonderes.) Also z.B.: Enthält Tag &quot;X&quot;, aber nicht Tag &quot;Y&quot;. Dann soll es möglich sein, ein beliebiges Bild in dieses Album zu ziehen, woraufhin die Tags von dem Bild so angepasst werden, dass sie logisch in dieses Smartalbum passen. Das soll aber nur optional geschehen. Denn es kann ja auch die Möglichkeit geben, dass dieses Bild zur fixen Menge hinzugefügt werden soll. Vielleicht löse ich das so, dass da bei dem Smartalbum dann diese zwei Möglichkeiten aufblubbern, wenn man die Bilder darauf zieht.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Mit mir wirst du keine Tagging-Probleme mehr haben!&quot;&lt;/b&gt;&lt;br /&gt;
Neben normalen Tags soll es auch hierarchische Tags geben. Diese soll man so handhaben können, als würde man mit richtigen Ordnern arbeiten. Man soll somit Tags verschieben, kopieren und umbenennen können. Alles soll sich unmittelbar auf die Dateien übertragen, welche die betroffenen Tags besitzen.&lt;br /&gt;
Es soll auch möglich sein, bestehende Tags, die hierarchisch angeordnet sind, importieren zu können. Dabei soll das Trennzeichen keine Rolle spielen. Für hierarchische Tags nimmt ja heutzutage jede Software ein anderes Format. Die einen verwenden den Slash, die anderen den Backslash, wieder andere einen Bindestrich, etc.&lt;br /&gt;
Jessica soll mit jedem denkbaren Format umgehen können. Ebenso soll es möglich sein, in jedes beliebige Tag-Format zu exportieren. Denn, wenn ich einmal ein Bild getagged habe, möchte ich das nie wieder taggen müssen, nur weil eine andere Software mit dem Format nicht klar kommt.&lt;br /&gt;
Bei Bildern, wo man die Tags nicht direkt einbetten kann, werden sie extern abgelegt und verwaltet.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Im Vollbildmodus und bei den Slideshows bekommst du das zu sehen, was du wirklich willst und wie lange!&quot;&lt;/b&gt;&lt;br /&gt;
Es ist ja wirklich deprimierend. Es gibt so viele Bilder, welche selbst die Full-HD Auflösung locker übersteigen. Sieht man sie sich dann im Vollbildmodus an, hat man trotzdem nur zwei Möglichkeiten: Entweder so im Ganzen zu betrachten, oder rein zu zoomen und dann wie ein irrer hin und her zu scrollen, um den ein oder anderen Bereich in seiner vollen Detailtiefe zu sehen. Und beim nächsten mal geht das gleiche Spiel von vorne los.&lt;br /&gt;
Warum kann man die relevanten Bereiche des Bildes nicht markieren und speichern? Und wenn man beim nächsten mal wieder das Bild ansieht, kann man durch einfache Maus- oder Tastatureingaben die Bereiche sofort anspringen. Oder man baut sich so etwas wie eine Collage aus den verschiedenen Ansichten und kann diese ebenso einfach abrufen. Das alles wird nur als Projektionsinformation gespeichert und nicht als neues Bild.&lt;br /&gt;
Dann die Slideshows: Ich frage mich, warum die manchmal so wenige Optionen haben. Bei manchen Programmen gibt es eine Shuffle-Funktion, aber keine &quot;Endlos&quot;-Funktion. Oder umgekehrt. Bei Jessica soll es mindestens Beides geben. Und warum kann man das Intervall nicht für jedes Bild individuell setzen?&lt;br /&gt;
Mir schwebt da so eine art &quot;Aufnahme&quot;-Funktion vor. Während ich die Bilder manuell betrachte, soll einfach alles Mögliche aufgezeichnet werden. Verweildauer auf einem Bild ... Pan und Zoom, etc. Danach soll man auch noch die Möglichkeit haben, die &quot;Aufnahme&quot; zu bearbeiten, um uninteressante Stellen zu entfernen oder zu modifizieren. Und hinterher kann das dann als Slideshow wiedergegeben werden. Bei dem Ganzen werden immer nur Parameter gespeichert und keine richtigen Filme aufgenommen! Das ist mir wichtig, um keinen unnötigen Platz zu verschwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Du musst nicht warten, bis ich mit einer Aufgabe fertig bin, um weiter arbeiten zu können!&quot;&lt;/b&gt;&lt;br /&gt;
Das verstehe ich unter Performance einer Software!&lt;br /&gt;
Einen Algorithmus empfindet man doch nur dann als zu langsam, wenn man nicht eher weiter arbeiten kann, bis er durchgelaufen ist. Bei Jessica sollen bei langwierigen Operationen Previews und Platzhalter existieren, mit denen man aktiv weiter arbeiten kann, als wäre der Prozess schon abgeschlossen. Man stelle sich langwierige Kopieroperationen oder Dateimodifikationen vor. Sowas dauert eben lange. Aber es steht ja vorher fest, wie das Resultat aussehen soll. Nur die Durchführung dauert seine Zeit.&lt;br /&gt;
Was sicher auch langwierig sein kann, ist die Durchführung der Smartalben.&lt;br /&gt;
Wird die Software während eines langwierigen Prozesses geschlossen, wird beim nächsten Start fortgesetzt. So, wie das Picasa auch bei der Gesichtserkennung macht.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Ich kann auch Dinge rückgängig machen!&quot;&lt;/b&gt;&lt;br /&gt;
Es soll so etwas wie eine Undo-Funktion geben. Z.B., wenn man Bilder versehentlich ins falsche Album gezogen hat, soll man das wieder rückgängig machen können.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Ich hinterlasse einen menschlichen Eindruck!&quot;&lt;/b&gt;&lt;br /&gt;
Das Ziel soll es sein, sich dem Benutzer menschlich mitzuteilen. Das soll erreicht werden, indem weitgehend technische Begriffe vermieden werden. Sämtliche Mitteilungen sollen leger und ungezwungen wirken.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Und noch einige Kleinigkeiten ...&quot;&lt;/b&gt;&lt;br /&gt;
Videos sollen ebenso wie Bilder zu verwalten sein. Bei gif-Bildern sollte man die Animation abspielen können. (Auch keine Selbstverständlichkeit bei den ganze Programmen, die es da so gibt.)&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;u&gt;Herausforderungen und mögliche Schwierigkeiten&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
Wie schon erwähnt, handelt es sich bei dem &quot;Big Picture&quot; nur um eine sehr grobe Vorstellung von der endgültigen Software. Die meisten Dinge werden sich inkrementell entwickeln. Wenn dann so das typische Empfinden kommt, wie &quot;Cool wäre es, wenn [...] möglich wäre.&quot;, dann werde ich überlegen, dies einzubauen.&lt;br /&gt;
Eine Herausforderung werden sicher die ganzen grafischen Spielereien und insgesamt das User Interface werden. Aber ich vertraue hier mal voll und ganz auf die Möglichkeiten der WPF:&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;iframe frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://channel9.msdn.com/Blogs/AdamKinney/WPF-35-SP1-Graphics-with-David-Teitlebaum/player?w=512&amp;amp;h=288&quot; style=&quot;height: 288px; width: 512px;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
Das Longterm-Goal wird sein, dass ich beim User-Interface keinerlei Logik-Code in der Codebehind-Datei habe. Es soll ja am Ende alles strikt nach MVVM ausgerichtet sein.&lt;br /&gt;
&lt;br /&gt;
Schwierigkeiten könnte ich mir bei den Smartalben vorstellen und bei der ganzen Tagging-Problematik.&lt;br /&gt;
Ich werde womöglich auch keine typische Datenbank als Backend verwenden, da ich hier starke Performance-Probleme durch die Abfragen erwarte. (Es käme für mich, wenn überhaupt eine konventionelle Datenbank verwendet werden würde, nur SQLite in Frage, da man hier nix vorher installieren muss.)&lt;br /&gt;
Nein, ich werde mir selber ein System ausdenken, was für die Anforderungen genau zugeschnitten ist.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;u&gt;Der erste Schritt&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
... fängt erstmal klein an, um überhaupt eine Basis zu schaffen.&lt;br /&gt;
Am Anfang soll es möglich sein, einen (oder mehrere) Ordner mit Bildern zu wählen, welcher beim nächsten Programmstart automatisch geladen wird. Die erfassten Bilder sollen auch schon mal in einer Liste dargestellt werden. (Thumbnails werden zunächst noch nicht gespeichert. Die Bilder werden erstmal direkt geladen.)&lt;br /&gt;
Bei dem Schritt versuche ich auch schon ein bisschen das UI so halbwegs zu designen. (Von den Farben her und eventuell auch die Schriftart und Größe. Geplant ist auch ein sehr dezentes Hintergrundbild: &lt;a href=&quot;http://fav.me/d2e1eo8&quot;&gt;http://fav.me/d2e1eo8&lt;/a&gt;.&amp;nbsp;Dieses würde ich mit Inkscape &quot;abpausen&quot;, um schärfere Konturen zu haben. Mit der Erlaubnis des Urhebers würde ich das dann in meine Software einbauen. ;-))&lt;br /&gt;
&lt;br /&gt;
Probleme sehe ich hier eventuell bei dem Darstellen der Bilder. Ich habe da noch keine Vorstellung, wie die WPF mit sehr vielen Bildern intern umgeht. Unter Windows Forms hätte ich jedes Bild einfach manuell ausgelesen, direkt auf eine Oberfläche gezeichnet und das Bild dann wieder freigegeben.&lt;br /&gt;
Hier wird sich sowieso die Frage stellen, ob ich mein eigenes Steuerelement erzeuge, oder ein UserControl in Verbindung mit dem Image-Element besser ist.&lt;br /&gt;
&lt;br /&gt;
Nun ja, das muss ich dann mal sehen.&lt;br /&gt;
&lt;br /&gt;
Als nächstes käme dann die Vorbereitung des Projekts ...&lt;br /&gt;
&lt;div id=&quot;-chrome-auto-translate-plugin-dialog&quot; style=&quot;background-attachment: initial !important; background-clip: initial !important; background-color: transparent !important; background-image: initial !important; background-origin: initial !important; display: none; left: 0px; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; opacity: 1 !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important; position: absolute !important; text-align: left !important; top: 0px; z-index: 999999 !important;&quot;&gt;
&lt;div style=&quot;-webkit-border-radius: 10px !important; background-color: #363636 !important; background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #000), color-stop(50%, #363636), color-stop(100%, #000)); border-color: #000000 !important; border-width: 0px !important; color: #fafafa !important; font-size: 16px !important; max-width: 300px !important; opacity: 0.8 !important; overflow: visible !important; padding: 8px !important; text-align: left !important; z-index: 999999 !important;&quot;&gt;
&lt;div class=&quot;translate&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;additional&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img onclick=&quot;document.location.href=&#39;http://translate.google.com/&#39;;&quot; src=&quot;http://www.google.com/uds/css/small-logo.png&quot; style=&quot;-webkit-border-radius: 20px; background-color: rgba(200, 200, 200, 0.3) !important; cursor: pointer !important; margin: 0 !important; padding: 3px 5px 0 !important; position: absolute !important; right: 1px !important; top: -20px !important; z-index: -1 !important;&quot; /&gt;&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2012/01/project-jessica-vorstellung.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-5230285900673973106</guid><pubDate>Mon, 16 Jan 2012 23:03:00 +0000</pubDate><atom:updated>2012-01-17T00:03:08.187+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">General</category><category domain="http://www.blogger.com/atom/ns#">Projekte</category><title>Die Aufwärmphase vor der Projektvorstellung</title><description>Eigentlich hatte ich zwar im letzten Beitrag versprochen, dass ich als nächstes das erste Projekt vorstellen werde. Aber ich wollte erstmal noch meine Vorgehensweise bei allen kommenden Projekten erklären.&lt;br /&gt;
&lt;div&gt;
Mir kommt es ja auf Konsistenz an, die ich bei allen Projekten anstrebe.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Die Vorstellung der Projekte&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
Jedes Projekt wird nach folgendem Schema vorgestellt werden:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;The Big Picture&lt;/b&gt;&lt;br /&gt;Unter dieser Überschrift werde ich meine Vorstellung von der zu entwickelnden Software präsentieren. Was soll sie am Ende mindestens können? Was sind meine persönlichen &quot;must-have&quot;-Features? Es wird eben ein grober Überblick gegeben, um Appetit zu wecken. ;-)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Herausforderungen und mögliche Schwierigkeiten&lt;/b&gt;&lt;br /&gt;Jedes Projekt wird das ein oder andere Feature enthalten, was ich so noch nie zuvor implementiert habe. Das könnte also Schwierigkeiten machen oder eben sehr knifflig sein. Diese möglichen Stolpersteine werde ich hier aufzählen.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Der erste Schritt&lt;br /&gt;&lt;/b&gt;Jedes Projekt fängt erstmal klein an. Daher definiere ich unter diesem Punkt die Features der ersten Iteration.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Gemeinsamkeiten aller Projekte&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Sie tragen einen weiblichen Name. (Die Erklärung, weshalb das so ist, habe ich ja schon im letzten Beitrag geschrieben.)&lt;/li&gt;
&lt;li&gt;Die Root-Bezeichnung meiner Namespaces wird entweder die Initialen &lt;i&gt;CGO&lt;/i&gt; oder &lt;i&gt;SachsenCoder&lt;/i&gt; tragen.&lt;br /&gt;&lt;script src=&quot;https://gist.github.com/1622966.js?file=1.cs&quot;&gt;
&lt;/script&gt;&lt;br /&gt;Ich tendiere aber zu &lt;i&gt;SachsenCoder&lt;/i&gt;. Das erscheint mir weltweit eindeutiger zu sein.&lt;/li&gt;
&lt;li&gt;Die Projekte werde ich bei &lt;i&gt;github&lt;/i&gt; veröffentlichen. (Hoffentlich klappt das auch alles so. Ich habe bisher nur lokale Git-Repositories verwendet. *g*)&lt;br /&gt;Innerhalb der github-Umgebung werde ich primär alle Texte auf Englisch verfassen. Das macht sich besser, falls doch mal jemand an dem Projekt mitmachen will. So ist es dann wenigstens international verständlich. (Auch, wenn mein Englisch sicher nicht ganz so erstklassig ist. *g*)&lt;/li&gt;
&lt;li&gt;Alle Projekte werden als Basis .NET-Framework 4.0 verwenden.&lt;/li&gt;
&lt;li&gt;Die Sprache selber wird C# sein. (Das ist die einzige Sprache, dessen Syntax mir wirklich gut gefällt!)&lt;/li&gt;
&lt;li&gt;Alle Projekte werden im AppKata-Stil aufgezogen und nach der Spinning-Strategie angegangen. Das heißt, es gibt viele überschaubare Iterationen auf den Weg zum &lt;i&gt;Big Picture&lt;/i&gt; und darüber hinaus. Jede Iteration soll einen kleinen, aber echten Nutzen hervorbringen. Jede Iteration wird je nach Komplexität in unterschiedlich kleine Slices aufgeteilt, damit ich/man von den Anforderungen nicht gleich erschlagen wird und ein Problem zeitnah gelöst werden kann.&lt;br /&gt;Ich halte dieses Vorgehen für unerlässlich, um die Motivation aufrecht zu halten.&lt;/li&gt;
&lt;li&gt;Spätestens nach jeder Iteration (oder dem ein oder anderen Slice) werde ich öffentlich darüber reflektieren, wie es gelaufen ist. Stellten sich die voraussichtlichen Schwierigkeiten wirklich als Hürde heraus? Wenn ja, warum? Wenn nein, warum nicht? Ist die Motivation noch gegeben oder steuere ich auf eine Lustlosigkeit zu? Bin ich mit der entwickelten Lösung zu Frieden? Entspricht sie den gegebenen Anforderungen? Gibt es Möglichkeiten der Verbesserung? Kann ich diese Verbesserungen umsetzen oder komme ich da an eine Know-How-Barriere?&lt;br /&gt;Diese Art der Reflektion soll mir dabei helfen, die Sachen, die ich da entwickelt habe, nochmal bewusst zu machen. Es soll auch verhindern, dass ich in eine &quot;Frickel&quot;-Ebene abdrifte.&lt;/li&gt;
&lt;li&gt;Die Entwicklung wird weitgehend gebloggt werden. Das heißt, die Lösungsfindung mache ich quasi öffentlich. So, als wenn ich laut denke oder jemanden meinen Lösungsweg erkläre. (Sicher werden mir dabei auch selber eventuelle Denkfehler auffallen.) Zudem gibt es anderen die Möglichkeit, die Entwicklung von Anfang an nachzuvollziehen. (Kann ja sein, dass am Ende wirklich geile Tools dabei rauskommen. Dann ist es doch fantastisch, wenn gerade sowas verständlich dokumentiert ist. Das ist ja im Open-Source-Bereich nicht selbstverständlich.)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Unter&#39;m Strich soll die Entwicklung einen professionellen Charakter bekommen.&lt;/div&gt;
&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2012/01/die-aufwarmphase-vor-der.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4298579173004881501</guid><pubDate>Sun, 15 Jan 2012 23:31:00 +0000</pubDate><atom:updated>2012-01-16T00:31:38.631+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Flow-Design</category><category domain="http://www.blogger.com/atom/ns#">General</category><title>Endlich mal was auf die Beine stellen!</title><description>Mit der Überschrift möchte ich mir selbst einen mentalen Arschtritt verpassen. Es ist ja nun schon fast ein Jahr her, als ich meinen letzten Blog-Post veröffentlicht habe. Und so kann ich nicht gleich mit der Tür ins Haus fallen, sondern muss erstmal den Leser auf das Kommende einstimmen.&lt;br /&gt;
&lt;br /&gt;
Eigentlich habe ich noch viele Blog-Post-Entwürfe rumliegen, die alle davon handeln sollten, dass die Event-Based-Components doch nicht so prickelnd sind, wie man sie sich vorstellt.&lt;br /&gt;
Die Ironie daran ist eigentlich die, dass mir kaum ein ernsthafter Kritikpunkt einfallen wollte. Die einzige ernsthafte Kritik, die mir eingefallen ist, ist die schlechtere Code-Navigierbarkeit innerhalb von Visual Studio. (Z.B. beim Debuggen. &quot;Gehe zu Definition&quot; wird da nicht so schön funktionieren.)&lt;br /&gt;
Auch sollte man bei den EBC stehts eine visuelle Abbildung synchron zum Code mitführen. Da ist eben etwas Disziplin gefragt.&lt;br /&gt;
&lt;br /&gt;
Und das war es eigentlich auch schon. Alles andere sind eher gravierende Vorteile gegenüber den herkömmlichen Praktiken, die so in aller Munde sind. (Wenn man ehrlich zu sich selber ist, merkt man das auch.)&lt;br /&gt;
Ich stellte das bei meiner &quot;Micro-Pattern-Trilogie&quot; auch fest. Man konnte alles schön voneinander getrennt halten. Aber sie waren zu schwergewichtig und brachten zu viel Rauschen mit. Damit war das Ding für mich gestorben.&lt;br /&gt;
&lt;br /&gt;
Nun hat sich in der Zeit aber sehr viel getan. Die EBC sind sehr schlank, flexibel und aussagekräftiger geworden. EBC sind nun viel mehr ein Implementationsdetail. Der eigentliche Überbegriff für das Ganze heißt nun ganz einfach &quot;Flow-Design&quot;. Es ist einfach ein Paradigma, wie man ein Business-Problem ganz einfach angehen kann. Wie das am Ende in der Programmiersprache XYZ umgesetzt wird, spielt keine Rolle. Die Art, wie es am schönsten in C# umgesetzt werden kann, ist eben das, was sich EBC nennt. (Wobei das eigentlich keinen extra Name bräuchte. Zumal ja die heutigen EBC kaum noch was mit der Ursprungsdefinition zu tun haben.)&lt;br /&gt;
&lt;br /&gt;
Hierfür möchte ich noch zwei hervorragende Videos zu der neuen und erfrischenden Art der &quot;Flow-Based&quot;-Entwicklung vorstellen.&lt;br /&gt;
&lt;br /&gt;
Das erste Video hatte ich damals live mitverfolgt. Das fand ich besonders motivierend, weil die&amp;nbsp;&lt;b&gt;alte&lt;/b&gt;&amp;nbsp;EBC-Denke dort quasi gar nicht mehr auftaucht. Das zeigt sich besonders darin, dass es in der normalen Form keine Substantive mehr gibt. Es gibt also keine &quot;Täter&quot; mehr, wie z.B. einen &quot;UserRegistrator&quot; oder ähnliche abenteuerliche Gebilde, wo man letztlich nicht weiß, was er alles tut.&lt;br /&gt;
Stattdessen gibt es &quot;Tätigkeiten&quot;, also echte &quot;Funktionseinheiten&quot;. Eine Funktionseinheit könnte z.B. &quot;Register_User&quot; heißen. So benennt man dann z.B. auch die Klasse. Das ist das, was mir an dem neuen Konzept am Besten gefällt! Benennt man eine Klasse nach ihrer Funktion in der Verbform, ist definitiv klar, was sie tut. Im besten Fall tut sie nur diese eine Sache! Bei einem &quot;UserRegistrator&quot; weiß man leider nicht genau, was er alles tut. Da steckt die Funktionalität in einzelnen Methoden, welche eventuell weitreichende Abhängigkeiten haben, die gar nix mehr mit dem eigentlichen Kontext zu tun haben. Und das verleitet dazu, dass man Verantwortlichkeiten mischt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;225&quot; mozallowfullscreen=&quot;&quot; src=&quot;http://player.vimeo.com/video/25826340?title=0&amp;amp;byline=0&amp;amp;portrait=0&quot; webkitallowfullscreen=&quot;&quot; width=&quot;400&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
Das zweite Video zeigt quasi an einem praktischen Anwendungsfall, wie der Entwicklungsprozess mit &quot;Flow-Design&quot; aussieht. Hier kommt auch gut zur Geltung, dass ein &quot;Flow-Design&quot; wunderbar evolviert.
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;225&quot; mozallowfullscreen=&quot;&quot; src=&quot;http://player.vimeo.com/video/29660206?byline=0&amp;amp;portrait=0&amp;amp;color=cbbb9c&quot; webkitallowfullscreen=&quot;&quot; width=&quot;400&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Soviel erstmal zu der kleinen Einführung.&lt;br /&gt;
Um zum Ausgangspunkt zurückzukommen: Ich muss (und will) endlich mal ein privates Projekt auf die Beine stellen! Unter Zuhilfenahme von &quot;Flow-Design&quot;.&lt;br /&gt;
&lt;br /&gt;
Projektideen habe ich da mehr als genug:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ein Bildverwaltungsprogramm&lt;/b&gt;&lt;br /&gt;Das soll so in die Richtung wie Picasa oder die Windows Live Fotogalerie gehen. Aber mein Programm soll flexiblere und besser anpassbare Slideshows ermöglichen. Auch soll es mit sehr vielen Dateien mühelos umgehen können. (Das ist nicht immer selbstverständlich bei den Lösungen, die es da so gibt.) Aber das eigentliche Killerfeature sollen ja Smartalben sein! Die vermisse ich nach wie vor in Picasa und bei der Windows Live Fotogalerie. (Der Photoshop Elements Organizer bietet zwar Smartalben an, aber die kann man nicht schachteln.) Generell sollen alle erdenklichen Filtermöglichkeiten möglich sein ... beliebig komplex. Was die Software in erster Linie nicht bieten soll, sind diverse Social-Features und Bildbearbeitungsfunktionen. Gesichtserkennung ist auch erstmal nicht geplant. (Das sind aber Sachen, die per Flow-Design leicht nachrüstbar sein sollten.) Die Verwaltungsaspekte sollen hier im Vordergrund stehen.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Einen Editor und Player für interaktive Stories&lt;/b&gt;&lt;br /&gt;Sowas finde ich einfach &quot;nice to have&quot;. ;-)&lt;br /&gt;Ich stelle mir das so vor, dass man einfach beginnt, eine Geschichte zu schreiben. Und während dieses Vorgangs kann man dann intuitiv die dynamischen Aspekte der Storie festlegen. (Charaktere, Handlung, Interaktion, etc.) Man soll nicht schon vorher wissen müssen, was man alles braucht oder was dynamisch werden soll, wenn man eine solche Geschichte beginnt. Ein Tool, was so in die Richtung geht, aber in meinen Augen noch nicht so richtig den Punkt getroffen hat, ist z.B. &lt;a href=&quot;http://gimcrackd.com/etc/src/&quot; target=&quot;_blank&quot;&gt;Twine&lt;/a&gt;. Das fühlt sich noch zu sehr nach Scripting an. Und übersichtlich ist das bei komplexeren Stories auch nicht gerade. Oder wenn noch Variablen ins Spiel kommen. Oder wenn man seine Charaktere im Blick behalten will, etc.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ein Tool für einfachere Softwareentwicklung&lt;/b&gt;&lt;br /&gt;Davon träumt sicher jeder Softwareentwickler! ;-D&lt;br /&gt;Ehe ich da viel dazu erzähle ... ich denke da an eine Mischung aus &lt;a href=&quot;http://www.andrewbragdon.com/codebubbles_site.asp&quot; target=&quot;_blank&quot;&gt;Code Bubbles&lt;/a&gt; und &lt;a href=&quot;http://www.dsprobotics.com/flowstone.html&quot; target=&quot;_blank&quot;&gt;FlowStone&lt;/a&gt;. Quasi ein Softwaremodellierungstool.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Eine&amp;nbsp;&lt;a href=&quot;http://wuala.com/&quot; target=&quot;_blank&quot;&gt;Wuala&lt;/a&gt;-Alternative&lt;/b&gt;&lt;br /&gt;Denn Wuala unterstützt ja keinen Speichertausch mehr. :-(&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ein Automatisierungstool&lt;/b&gt;&lt;br /&gt;Ja, sowas Ähnliches wie &lt;a href=&quot;http://www.finalbuilder.com/&quot; target=&quot;_blank&quot;&gt;FinalBuilder&lt;/a&gt;. Nur nicht so Feature-Complete und universell wie dieses Tool derzeit zu sein scheint. Einfach ein Tooling, was meine kleinen Automatisierungsanforderungen komfortabel erfüllt. (Ein bisschen Templating, d.h. Platzhalter durch echte Werte ersetzen; Dateiverwaltungskram; Commandline-Tools ausführen; etc.) Das Tool könnte &quot;nebenbei&quot; entstehen. Je nachdem, welche Automatisierung ich gerade gebrauchen könnte.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Tja, an Ideen mangelt es nicht. Ich will aber realistisch sein: Das Softwareentwicklungstool und die Wuala-Alternative wird es voraussichtlich nicht (sofort?) geben. Das entwickelt man auch mit Flow-Design nicht mal eben so in der knappen Freizeit.&lt;/div&gt;
&lt;div&gt;
Bei den anderen Programmen sehe ich da aber schon realistische Ziele.&lt;/div&gt;
&lt;div&gt;
Was alle Programme (hoffentlich) gemeinsam haben werden, ist Folgendes:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Ein modernes, einfach zu handhabendes (G)UI. Heutzutage muss man wirklich keine hässlichen GUIs mehr hinnehmen oder einem User anbieten. Die Tools für Mac OS sehen immer so stylisch aus. Warum sollte das nur Mac OS exklusiv sein?&lt;/li&gt;
&lt;li&gt;Jedes Tool versuche ich penibel im Flow-Design-Stil zu entwickeln. Also erst der grafische Entwurf und dann der Code. (Das wird für mich eine disziplinarische Herausforderung werden, weil ich sonst alles gleich im Code entworfen habe.) Als Tool für die Diagramme werde ich hier &lt;a href=&quot;http://www.yworks.com/de/products_yed_about.html&quot; target=&quot;_blank&quot;&gt;yEd&lt;/a&gt; verwenden.&lt;/li&gt;
&lt;li&gt;Sie werden frei wie &quot;Freibier&quot; und sicher auch frei wie &quot;frei veränderbar&quot; sein. ;-)&lt;br /&gt;Ich verfolge kein finanzielles Interesse. Die Tools entwerfe ich, weil ich sie sehnlichst brauche. Ich will nicht länger warten, bis sie mal irgendjemand irgendwann programmiert. Und warum sollte ich die Tools am Ende nicht anderen zur Verfügung stellen?&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Was erwarte ich von dem Vorhaben?&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;In erster Linie, wie bereits erwähnt, brauche ich die Tools, weil mir die existierenden Lösungen nicht das bieten, was ich wirklich brauche. (Oder weil andere Lösungen zu komplex und/oder zu teuer sind.)&lt;/li&gt;
&lt;li&gt;Ich will meine Fähigkeiten als Entwickler ausbauen, sodass mir die Flow-Design-Methodik in Fleisch und Blut übergeht. Ich möchte nicht mehr in die alte OOP-Denke verfallen.&lt;/li&gt;
&lt;li&gt;Kann es für den Arbeitsmarkt bessere Referenzen geben, als selbst entwickelte Software inklusive Dokumentation von deren Entstehungsprozess?&lt;/li&gt;
&lt;li&gt;Ich möchte eben auch einfach mal in der Freizeit etwas Produktives machen. Bisher bin ich nur auf Arbeit wirklich produktiv und entwerfe Software. Aber da hat man eben immer den Zeitdruck; muss die Anforderungen so umsetzen, wie sie gefordert sind und die resultierenden Tools bringen einem selbst keinen Nutzen. Es ist eben irgendwie einfach nur Arbeit, die man macht. (Es macht zwar trotzdem Spaß, aber so richtig kann man sich irgendwie nicht entfalten.) Ich will einfach auch mal selber die Anforderungen definieren und Tools entwickeln, die mir persönlich sehr viel bringen. Und das ohne BWLer im Rücken, aus deren Sicht es ja keine Probleme gibt und alles &quot;straight forward&quot; ist. Ohne BWLer, für die Softwareentwicklung nur ein notwendiges, unberechenbares Übel in der Kostenkalkulation ist.&lt;/li&gt;
&lt;li&gt;Das Flow-Design verspricht eigentlich echte Wiederverwendbarkeit, da es nur Input- und Outputabhängigkeiten gibt. Ich hoffe, dass ich da auch viele Funktionseinheiten in anderen Projekten verwenden kann.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Was sind die persönlichen Herausforderungen und Risiken für mein Vorhaben?&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Durchhaltevermögen! Das ist definitiv die größte Herausforderung der ich mich stellen muss. Ich weiß schon jetzt, dass es sicher Phasen geben wird, wo ich mal definitiv keinen Bock haben werde, irgendwas zu programmieren. Ich denke, das ist aber ganz natürlich. Man ist schließlich kein Roboter. Ich hoffe nur, dass solch eine Phase nicht dauerhaft eines meiner Vorhaben zerstört!&lt;/li&gt;
&lt;li&gt;Durch meine hohen Anforderungen an die Usability werde ich endlich mal gezwungen, mich mit Drag &amp;amp; Drop, (dynamischen) Kontextmenüs und sonstigen GUI-Spielereien auseinanderzusetzen. Auch, was die prinzipielle Gestaltung der Oberfläche anbelangt. Da muss ich selber hartnäckig bleiben und darf mich nicht zu schnell mit einer ungewollten Lösung abfinden. Daher muss ich vorher penibel meine exakte Vorstellung dokumentieren und mich dran halten.&lt;/li&gt;
&lt;li&gt;Ich muss mir einheitliche Konventionen schaffen und mich penibel dran halten! Auf Arbeit ertappe ich mich oft, dass ich mit diesem Grundsatz breche. Oft aus Bequemlichkeit oder &lt;i&gt;Zeitdruck&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Was gibt es sonst noch zu wissen?&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Ein Framework zu benutzen, ist für mich ein notwendiges Übel, um schnell Resultate zu bekommen. Für mich gibt es im Entwicklungsprozess aber nix Schlimmeres, als vor Problemen zu stehen, die mit dem Framework zu tun haben. Die Probleme entstehen, weil man oft nicht genau weiß, wie man ein Framework richtig benutzt. Oder man steht vor einem merkwürdigen Verhalten, was man nicht versteht und nicht nachvollziehen kann. (Das ist die Bug- und Fehlerquelle Nummer eins.) Daher meide ich auch den exzessiven Gebrauch von Framework-Features, die ich nicht verstehe oder nachvollziehen kann. Da erfinde ich das Rad lieber neu und weiß dann wenigstens, wie es funktioniert. Das werde ich auch bei meinen Projekten so handhaben. Mit der Strategie bin ich bisher sehr gut gefahren. (Außerdem ist es DAS, was mir überhaupt am Programmieren gefällt: Wenn man mal selber etwas implementieren kann und es hinterher noch tadellos funktioniert.)&lt;/li&gt;
&lt;li&gt;Ich werde nach Möglichkeit offene Libraries für Programmteile verwenden, wo ich selber einfach nicht die Zeit oder das nötige Know-How habe, um eine solche Funktionalität selber zu implementieren. (Z.B. Gesichtserkennung oder sowas.)&lt;/li&gt;
&lt;li&gt;Um meine grafischen Fähigkeiten etwas zu schulen, werde ich mich dieser Quelle bedienen:&amp;nbsp;
&lt;a href=&quot;http://2dgameartforprogrammers.blogspot.com/&quot;&gt;http://2dgameartforprogrammers.blogspot.com/&lt;/a&gt;&lt;br /&gt;Da dreht sich zwar alles um Spielegrafik, aber gerade was die Shading-Grundlagen anbelangt, kann man das Wissen sicher auch universell für GUIs einsetzen.&lt;/li&gt;
&lt;li&gt;Die Codenamen meiner Projekte werden weibliche Vornamen tragen!&lt;br /&gt;Ich habe lange überlegt, wie ich meine Projekte nennen könnte. Zuerst dachte ich an Tierbezeichnungen. Aber fast jede Software trägt ja irgendwie eine Tierbezeichnung als Codename. (Ubuntu &amp;amp; Co. lässt grüßen. *g*)&lt;br /&gt;Davon will ich mich abgrenzen. Software ist in meinen Augen in jeder Hinsicht weiblich und nicht tierisch! ;-) Und vor allem möchte ich Namen für meine Software haben, die man sich auch gut merken und aussprechen kann. (Schließlich werden diese Namen ein Bestandteil des Namespaces. Da möchte ich keine cryptischen Bezeichnungen drin haben. *g*)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Im nächsten Beitrag werde ich dann sicher mein erstes Projekt vorstellen. Da bin ich selber sogar schon ganz gespannt drauf. :-D&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;-chrome-auto-translate-plugin-dialog&quot; style=&quot;background-attachment: initial !important; background-clip: initial !important; background-color: transparent !important; background-image: initial !important; background-origin: initial !important; display: none; left: 0px; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; opacity: 1 !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important; position: absolute !important; text-align: left !important; top: 0px; z-index: 999999 !important;&quot;&gt;
&lt;div style=&quot;-webkit-border-radius: 10px !important; background-color: #363636 !important; background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #000), color-stop(50%, #363636), color-stop(100%, #000)); border-color: #000000 !important; border-width: 0px !important; color: #fafafa !important; font-size: 16px !important; max-width: 300px !important; opacity: 0.8 !important; overflow: visible !important; padding: 8px !important; text-align: left !important; z-index: 999999 !important;&quot;&gt;
&lt;div class=&quot;translate&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;additional&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img onclick=&quot;document.location.href=&#39;http://translate.google.com/&#39;;&quot; src=&quot;http://www.google.com/uds/css/small-logo.png&quot; style=&quot;-webkit-border-radius: 20px; background-color: rgba(200, 200, 200, 0.3) !important; cursor: pointer !important; margin: 0 !important; padding: 3px 5px 0 !important; position: absolute !important; right: 1px !important; top: -20px !important; z-index: -1 !important;&quot; /&gt;&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2012/01/endlich-mal-was-auf-die-beine-stellen.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-1893155749786318465</guid><pubDate>Mon, 07 Feb 2011 22:57:00 +0000</pubDate><atom:updated>2011-02-07T23:57:21.095+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Gedanken</category><category domain="http://www.blogger.com/atom/ns#">OOP Kritik</category><category domain="http://www.blogger.com/atom/ns#">Paradigmen</category><title>Welches Paradigma passt zu Dir?</title><description>Im Internet werden ständig sinnlose und anstrengende Glaubenskriege geführt. Das fängt damit an, welches Betriebssystem besser ist und geht dann weiter, welcher Browser cooler ist.&lt;br /&gt;
Diese Diskussionen kennt sicher jeder zur Genüge.&lt;br /&gt;
&lt;br /&gt;
Nun müsste man meinen, dass wir als Softwareentwickler innerhalb unseres Bereiches vernünftiger wären. Tja, schön wär&#39;s. Da gibt es fast noch hitzigere Debatten, welche Sprache oder welches Paradigma besser ist.&lt;br /&gt;
Auch diese Diskussionen werden eher subjektiv, als objektiv geführt.&lt;br /&gt;
Man hört aber immer öfter heraus, man solle die Sprachen und Paradigmen wie Werkzeuge betrachten. Und so soll man eben immer das Werkzeug auswählen, welches zu einer bestimmten Problemstellung passt.&lt;br /&gt;
&lt;br /&gt;
Nun haben wir aber das große Glück, dass mittlerweile fast alle größeren bekannten Programmiersprachen Multiparadigmensprachen sind. Damit sollte sich die Wahl der &quot;richtigen&quot; Sprache beinahe erledigt haben. Oft liest man auch von den vernünftigeren Diskutanten, dass man die Sprache wählen soll, dessen Syntax einem besser gefällt. Soweit, so gut!&lt;br /&gt;
&lt;br /&gt;
Und wie ist das mit den Paradigmen? Da bleiben noch viele stur und möchten anderen gerne ihr eigenes bevorzugtes Paradigma aufdrängen. Der große Vorreiter unserer Zeit ist wohl die OOP. &quot;Denn alles andere ist ja out und von vorgestern!&quot;&lt;br /&gt;
Und leider wird einem dieses Paradigma wirklich oft aufgezwungen. Da braucht man sich nur mal die Bibliotheken rund um .NET oder Java anzugucken. Da geht wirklich nix mehr ohne OOP.&lt;br /&gt;
&lt;br /&gt;
Was ist aber, wenn man nicht immer objektorientiert denken kann bzw. will? Was ist, wenn einem dieses objektorientierte Zeug Komplexe bereitet oder gar Denkblockaden auslöst?&lt;br /&gt;
&lt;br /&gt;
Das klingt absurd? Sowas ist Unsinn? Der Softwareentwickler ist einfach nur zu dumm für OOP?&lt;br /&gt;
&lt;br /&gt;
Dann sind Linkshänder aus der Sicht eines Rechtshänders sicher auch nur zu dumm, um mit der rechten Hand zu schreiben. Sollen sie doch gefälligst lernen, mit der rechten Hand zu schreiben. Immerhin kann die Mehrheit der Menschen auch mit der rechten Hand schreiben.&lt;br /&gt;
Zum Glück wurde diese Einstellung aus den Köpfen der meisten Menschen verbannt. (Auch, wenn bis dahin viele Linkshänder zur Rechtshändigkeit gezwungen wurden. Ich wollte früher als Kind auch mit Links schreiben ... aber mit spiegelverkehrter Schrift. Ich sollte dann aber mit der rechten Hand schreiben ... was ich auch heute noch tue. Ob das meine geistige Entfaltung beeinträchtigt hat, kann ich nicht klar sagen. *g*)&lt;br /&gt;
&lt;br /&gt;
Warum ist das aber noch nicht in den Köpfen der Softwareentwickler angekommen?&lt;br /&gt;
Paradigmen werden immer noch wie Werkzeuge behandelt, die nur für ein bestimmtes Problem in Frage kommen und bei anderen wiederum nicht in Frage kommen (dürfen!).&lt;br /&gt;
&lt;br /&gt;
Gerade in der OOP wird mit Dogmen umher geworfen, wo man meinen könnte, man hat die zehn Gebote vor sich. Da gibt es dann sogar Kampagnen, wie z.B. die &quot;&lt;a href=&quot;http://www.antiifcampaign.com/&quot;&gt;Anti-If-Kampagne&lt;/a&gt;&quot;, wo ich in dem Moment nicht weiß, ob ich lachen oder weinen soll. Früher war das böse &quot;goto&quot; das Übel allen Übels und musste bekämpft werden. Oh, das hat man auch erfolgreich durchgesetzt! Oder traut sich heute noch jemand ein wohl überlegtes &quot;goto&quot; in seinen Quellcode zu setzen, wenn es dem besseren Verständnis oder gar der Performance dient? Das macht kaum noch jemand, weil viele Angst haben, als unfähig bezeichnet zu werden.&lt;br /&gt;
Und nun versucht man das Selbe mit dem &quot;if-then-else&quot;-Konstrukt. Denn es gibt ja dafür die heilige Polymorphie.&amp;nbsp;Und wer die nicht in seinem Programm verwendet, ist doch von vorgestern und unfähig.&lt;br /&gt;
&lt;br /&gt;
Aber ich schweife etwas ab.&lt;br /&gt;
&lt;br /&gt;
Der Punkt ist aber, dass man offenbar versucht, ein bestimmtes Paradigma zu DEM global gültigen Paradigma zu erheben. Dabei fragt aber keiner, ob man damit überhaupt zurecht kommt, oder nicht. (Gibt es überhaupt noch Frameworks, die nicht objektorientiert aufgebaut sind? Das ist eine ernsthafte Frage. Mir fällt da höchstens spontan die normale Win32-API ein.)&lt;br /&gt;
&lt;br /&gt;
Dazu möchte ich ein Zitat einstellen, was mir sehr gut gefallen und mich dazu veranlasst hat, diesen Beitrag zu schreiben. Es ist auf der Seite &quot;&lt;a href=&quot;http://www.cs.loyola.edu/~binkley/772/articles/oopbad.htm&quot;&gt;OOP Criticism&lt;/a&gt;&quot; unter der Überschrift &quot;One Mind Fits All?&quot; zu finden:&lt;br /&gt;
&lt;blockquote&gt;...I was always told that OO was an intuitive way of thinking. Although I develop daily in OO languages, I do find OO rather unintuitive (although I manage). ... If I analyze a problem, I draw tables not objects and classes, I think in tables, those are much more intuitive to me. Even when I program in OOP, I rely as much as possible on tables. ...it&#39;s nice to see that I&#39;m not the only one who &#39;thinks&#39; in tables. ...&lt;/blockquote&gt;Es geht doch am Ende genau darum: &lt;b&gt;Welches Paradigma passt zu Dir?&lt;/b&gt;&lt;br /&gt;
Einer denkt in Bildern, ein anderer in Tabellen und wieder ein anderer denkt in Wörtern oder etwas ganz Anderes.&lt;br /&gt;
&lt;br /&gt;
Vielleicht sollten wir in Zukunft diesbezüglich offener und toleranter sein.&lt;br /&gt;
Es gibt eben nicht DAS Paradigma. Es gibt auch nicht DAS Paradigma für ein bestimmtes Problem.&lt;br /&gt;
Es kann nur DAS Paradigma geben, was DU in einem bestimmten Kontext für richtig hältst und womit DU am Besten zurecht kommst.&lt;br /&gt;
&lt;br /&gt;
Wenn man in diesem Punkt die Freiheiten lässt, kann auch eine Entwicklung statt finden. Zum Einen kann man sich persönlich entwickeln, wenn man sein passendes Paradigma sucht. Zum Anderen kann man aber auch die Softwareentwicklung aktiv verändern.&amp;nbsp;(Vielleicht entstehen dadurch sogar noch ganz andere Paradigmen?!)&lt;br /&gt;
&lt;br /&gt;
Softwareentwicklung ist ein kreativer Prozess! Und Kreativität muss sich frei entfalten können! :-)</description><link>http://sachsencoder.blogspot.com/2011/02/welches-paradigma-passt-zu-dir.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4819390364390699740</guid><pubDate>Sat, 05 Feb 2011 22:49:00 +0000</pubDate><atom:updated>2011-02-05T23:49:05.791+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Gedanken</category><category domain="http://www.blogger.com/atom/ns#">OOP Kritik</category><title>Warum versucht man die Welt zu modellieren?</title><description>Inspiriert durch den letzten Beitrag von Ralf Westphal &quot;&lt;a href=&quot;http://ralfw.blogspot.com/2011/02/mehr-vom-selben-hilft-nicht-mehr.html&quot;&gt;Mehr vom Selben hilft nicht mehr&lt;/a&gt;&quot;, dachte ich mir, dass es durchaus sinnvoll sein kann, der Kernaussage noch mehr Ausdruck zu verleihen. Ganz im Sinne von &quot;Spread the word!&quot;&lt;br /&gt;
&lt;br /&gt;
Längere Zeit vorher beschäftigte ich mich auch mal mit Konzepten, wie z.B. &lt;a href=&quot;http://functional-programming.net/&quot;&gt;Funktionale Programmierung&lt;/a&gt; und &lt;a href=&quot;http://gamesfromwithin.com/data-oriented-design&quot;&gt;Data Oriented Design&lt;/a&gt;.&lt;br /&gt;
Und ich sagte so zu mir: &quot;Verdammt! Recht haben sie!&quot;&lt;br /&gt;
&lt;br /&gt;
Es geht seit der Erfindung des ersten Computers um Datenverarbeitung. Und das möglichst effizient und seiteneffektfrei!&lt;br /&gt;
&lt;br /&gt;
Warum ist das aber in Vergessenheit geraten? Haben wir schon lange den Boden unter den Füßen verloren?&lt;br /&gt;
Das kann man wohl annehmen. Dank &lt;i&gt;*hust*&lt;/i&gt; der Objektorientierten Programmierung (OOP) programmiert man nicht mehr, sondern modelliert nur noch. Es wird alles Erdenkliche in Klassen beschrieben und durch Objekte ins Leben gerufen. Ob das nun sinnvoll ist, oder nicht. Egal! &quot;OOP ist ja sooo geil und überhaupt kann man damit viel besser die Welt beschreiben.&quot;&lt;br /&gt;
Ja, man kann damit wunderbar die Welt beschreiben und modellieren. Damit wirbt zumindest jedes mir bekannte OOP-Buch.&lt;br /&gt;
Gerade, um den Leser für Vererbung zu begeistern, werden wirklich immer diese trivialen Beispiele, wie z.B. die Tierklassen, Autoklassen, Baumklassen, etc. aufgeführt.&lt;br /&gt;
Aber ganz ehrlich: Derartigen trivialen Nonsens habe ich bisher noch nie in meinen Softwareprojekten vorgefunden. In der Software-Realität gibt es eher &quot;Tierautos mit Blättern dran&quot;. Das liegt ganz einfach daran, dass man viele Dinge im Businessproblem nicht so einfach klassifizieren kann, wie es einen die OOP-Autoren gerne schmackhaft machen wollen. Objekte müssen miteinander interagieren und Daten austauschen, denn nur darum geht es letztlich wieder: um die Datenverarbeitung.&lt;br /&gt;
&lt;br /&gt;
Aber auch dafür hat sich die OOP-Gemeinde einige Konstrukte ausgedacht, die sich &lt;a href=&quot;http://www.philipphauer.de/study/se/design-pattern.php&quot;&gt;Entwurfsmuster&lt;/a&gt; &quot;schimpfen&quot;. Überhaupt wurde der Trend eingeleitet, man solle nicht mehr &quot;ableiten&quot; und &quot;vererben&quot;, sondern &quot;komponieren&quot;. Dies sei flexibler, sagt man. (Was ich auch nicht bestreiten will.)&lt;br /&gt;
&lt;br /&gt;
Doch sehe ich die Entwurfsmuster eher als Krücke. Nach dem Motto: Not macht erfinderisch.&lt;br /&gt;
Und, dass diese Entwurfsmuster nur ein Notnagel sein können, sieht man z.B. am &quot;Visitor Pattern&quot; oder dem &quot;State Pattern&quot;. Die mögen ja wunderbar funktionieren, aber den Quellcode darf man hinterher nicht verstehen, geschweige denn debuggen wollen.&lt;br /&gt;
&lt;br /&gt;
Tja, das hat alles nicht mehr den Eindruck, als wolle man Daten verarbeiten, sondern als wolle man geschickt mit einem Netzwerk aus Objekten um die Daten herumtanzen, ohne diese direkt zu berühren.&lt;br /&gt;
&lt;br /&gt;
Es denkt doch keiner mehr an den Prozessor und an den Speicher.&lt;br /&gt;
&lt;br /&gt;
Die OOP widerspricht immer noch der Arbeitsweise der gegenwärtigen Rechner. Denn im Rechner sind noch immer die Daten vom Code getrennt. Der Prozessor kennt keine Klassen, Objekte und erst recht keine Entwurfsmuster. Das wäre ja alles kein Problem, wenn die Zugriffszeiten auf den Arbeitsspeicher nicht den Prozessor unnötig ausbremsen würden.&lt;br /&gt;
&lt;br /&gt;
Ganz ehrlich: Ich würde kein Prozessor sein wollen, der ein OO Programm bewältigen muss. ;-)&lt;br /&gt;
&lt;br /&gt;
Warum versucht man also die Welt - das Businessproblem - in ein OO-Schema zu pressen, welches der Compiler wieder halbwegs entfrickeln (Code von Daten trennen) muss, damit es der Prozessor dann mehr schlecht als optimal lösen &quot;darf&quot;?&lt;br /&gt;
&lt;br /&gt;
Und wie man dem Beitrag von Ralf entnehmen kann, geben die OOP-Gurus zu verstehen, dass die Mehrheit nach so vielen Jahren noch immer nicht richtig OO programmieren kann.&lt;br /&gt;
&lt;br /&gt;
Ja, da muss man wirklich fragen, wessen Problem das ist? Ich brauche diese &quot;Religion&quot; OOP nicht wirklich, um meine Business-Probleme auf Arbeit zu lösen. Das habe ich jedoch leider eher spät gemerkt, weil ich auch auf den OOP-Zug aufgesprungen bin, der sehr gut beworben wurde. Hinterher fand ich die Codebasis aber trotzdem nicht schön. Vielmehr war alles so aufgeblasen und ich verlor den Überblick.&lt;br /&gt;
&lt;br /&gt;
Ich frage mich aber wirklich, warum die OOP-Gurus so hartnäckig an der Objektorientierung festhalten. Geht es dabei nur um das Modellieren der Welt?&lt;br /&gt;
Wäre es nicht sinnvoller, ein Paradigma zu wählen, welches dem Programmierer gleichermaßen entgegen kommt, wie der Hardware? Wenn man nicht mehr versuchen würde, die Business-Probleme 1:1 mit Objekten zu beschreiben, sondern die Probleme grundlegend abstrahieren würde, sodass diese einfacher zu fassen und für die Hardware optimal beherrschbar sind?&lt;br /&gt;
&lt;br /&gt;
Vielleicht hat man damals die Idee - den Code von den Daten getrennt zu halten - zu schnell verworfen. Denn gerade die Rechnerarchitektur zeigt uns doch, wie die Daten am besten verarbeitet werden können. Und solange sich die Architektur nicht ändert, ist es IMHO keine gute Idee, weiterhin die Daten mit dem Code zu mischen.&lt;br /&gt;
&lt;br /&gt;
Ich bin zumindest gespannt, wohin die Reise gehen wird. Spätestens mit den ersten Quantenrechnern dürfte sich noch so Einiges ändern. ;-)</description><link>http://sachsencoder.blogspot.com/2011/02/warum-versucht-man-die-welt-zu.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-2226680140902203083</guid><pubDate>Sat, 10 Jul 2010 22:13:00 +0000</pubDate><atom:updated>2010-07-11T00:13:51.671+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Dependency Injection</category><category domain="http://www.blogger.com/atom/ns#">DI</category><category domain="http://www.blogger.com/atom/ns#">DIY-DI</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><title>Ansichten ändern sich!</title><description>Es ist nun schon eine Weile her, als ich hier einen Beitrag geschrieben hatte. Ich nutzte die Zeit, um mit der MPT ein wenig Erfahrung zu sammeln. Dies tat ich mit einem Projekt auf Arbeit.&lt;br /&gt;
&lt;br /&gt;
Naja, es funktionierte schon alles so, wie ich mir das gedacht hatte. Jedes Objekt war im Grunde unabhängig voneinander und der Datenfluss geschah eher passiv. Eigentlich genau das, was ich wollte, oder?&lt;br /&gt;
Nun ja, nicht ganz.&lt;br /&gt;
So bereitete mir z.B. die Idee des Transmitters in einem Anwendungsfall ziemliche Probleme:&lt;br /&gt;
Nehmen wir an Objekt &lt;b&gt;A&lt;/b&gt; ist ein Transmitter für irgendeinen Wert &lt;b&gt;X&lt;/b&gt;.&lt;br /&gt;
Objekt &lt;b&gt;B&lt;/b&gt; und Objekt &lt;b&gt;C&lt;/b&gt;&amp;nbsp;empfangen diesen Wert &lt;b&gt;X&lt;/b&gt;.&lt;br /&gt;
Objekt &lt;b&gt;B&lt;/b&gt; fordert den Wert &lt;b&gt;X&lt;/b&gt; an. Diesen Wert bekommt Objekt &lt;b&gt;B&lt;/b&gt; von Objekt &lt;b&gt;A&lt;/b&gt;. Aber auch Objekt &lt;b&gt;C&lt;/b&gt; bekommt diesen Wert &lt;b&gt;X&lt;/b&gt;, weil es ja ebenfalls als Empfänger für diesen Wert registriert ist.&lt;br /&gt;
&lt;br /&gt;
Das scheint soweit OK zu sein, oder? In meinem Fall war dies aber nicht gewollt, weil das &lt;i&gt;unaufgeforderte Empfangen&lt;/i&gt; des Wertes &lt;b&gt;X&lt;/b&gt; eine Ereigniskette ausgelöst hat, die nicht hätte ausgelöst werden dürfen.&lt;br /&gt;
Also, wenn Objekt &lt;b&gt;A&lt;/b&gt; den Wert &lt;b&gt;X&lt;/b&gt; anfordert, darf ihn nicht Objekt &lt;b&gt;B&lt;/b&gt; bekommen. Und wenn Objekt &lt;b&gt;B&lt;/b&gt; den Wert &lt;b&gt;X&lt;/b&gt; anfordert, darf ihn nicht Objekt &lt;b&gt;A&lt;/b&gt; bekommen.&lt;br /&gt;
Das ist ein ziemliches Dilemma, welches einen schon mal verzweifeln lässt.&lt;br /&gt;
Meine erste Idee war es ja, bei den Objekten &lt;b&gt;A&lt;/b&gt; und &lt;b&gt;B&lt;/b&gt; eine Flag-Variable einzuführen, welche in der Empfangsroutine prüft, ob der Wert &lt;b&gt;X&lt;/b&gt; überhaupt angefordert wurde.&lt;br /&gt;
Doch das schlug ich mir schnell wieder aus den Kopf, denn so eine &quot;Prüfung&quot; verschmutzt die Businesslogik. Zudem wissen die Objekte gar nicht, was um sie herum geschieht. Diese Flag-Variable würde aber indirekt andeuten, dass dieses Objekt etwas über seine Umgebung weiß. Und das wäre schlecht!&lt;br /&gt;
&lt;br /&gt;
Ich überlegte lange, wie ich das Problem lösen könnte. Dann kam mir die Idee! Man könnte ja einfach ein Objekt dazwischen schalten, welches wie ein &lt;b&gt;Ventil&lt;/b&gt; funktioniert. Man schaltet es z.B. einfach zwischen Objekt &lt;b&gt;A&lt;/b&gt; und Objekt &lt;b&gt;B&lt;/b&gt;. Die Anforderung von Objekt &lt;b&gt;B&lt;/b&gt; geht durch das &quot;&lt;b&gt;Ventil&lt;/b&gt;&quot;. Dabei wird in dem &quot;&lt;b&gt;Ventil&lt;/b&gt;&quot; ein Flag gesetzt, welches den Empfang von Wert &lt;b&gt;X&lt;/b&gt; erlaubt. Es ist somit &quot;offen&quot;. Wenn dann der Wert kommt, wird der Wert an Objekt &lt;b&gt;B&lt;/b&gt; durchgereicht und das Ventil wird wieder geschlossen. Bei einem unaufgeforderten Empfang wird der Wert einfach abgewiesen und Objekt &lt;b&gt;B&lt;/b&gt; bekommt davon gar nix mit.&lt;br /&gt;
&lt;br /&gt;
Nachdem ich das so eingebaut hatte, funktionierte alles wieder problemlos. Die Ventile sorgten für den gewünschten Datenfluss und die Businesslogik hatte sich absolut nicht geändert. Genial!&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Unzufrieden, trotz entkoppelter Objekte&lt;/span&gt;&lt;br /&gt;
Die Anwendung funktionierte, aber mir war unwohl bei dem Gedanke, dass noch mehr Funktionen in die Software fließen sollten.&lt;br /&gt;
Wie kann das sein? Die Entkopplung sollte ja eigentlich das Gegenteil bewirken und Sicherheit bei der Implementation neuer Funktionen erzeugen. Ein Grund für die Unsicherheit war wohl auch das oben geschilderte Szenario.&lt;br /&gt;
Viel schlimmer war aber gerade die totale Isolierung der einzelnen Businessobjekte zueinander. Das heißt, ich konnte aus einem Objekt heraus nicht die Kommunikationsstrecke verfolgen.&lt;br /&gt;
Wollte ich also wissen, was passiert, wenn ich auf einen bestimmten Button klicke, so kam ich zwar zur entsprechenden Aufrufmethode, doch dann war da eine Sackgasse. Der Isolation sei &quot;Dank&quot;, stand da in den jeweiligen Methoden nur die Floskel &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Say.Carefully(MacheIrgendwasSinnvolles, this)&lt;/span&gt;&quot;.&lt;br /&gt;
&quot;Ach ja, toll! Und welches Objekt ist jetzt nochmal dafür zuständig, diese Sache auszuführen?&quot; fragte ich mich des öfteren.&lt;br /&gt;
Denn leider steht man hier wirklich in der Sackgasse. Man kann nicht einfach zur Definition von &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MacheIrgendwasSinnvolles&lt;/span&gt;&quot; springen, um den Programmfluss nachzuvollziehen. Das ist der Preis, den man für die Isolation bezahlt. Und der ist teuer!&lt;br /&gt;
Um also zu wissen, welches Objekt auf dieses Ereignis reagiert, muss man sich die Verdrahtung angucken. Gut, jetzt hat man das verantwortliche Objekt lokalisiert. Man geht in die Klasse und sucht sich die entsprechende Methode. Die Freude hält nicht lange an, denn in der Methode steht auf einmal der Aufruf &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Say.Carefully(INeedEinenBestimmtenWert, this)&lt;/span&gt;&quot;.&amp;nbsp;&quot;OMG!&quot;&lt;br /&gt;
Aber zum Glück ist es an der Stelle tatsächlich nicht wichtig, wo der Wert herkommt. Ich suche in der Klasse schnell die passende Receive-Methode und fahre mit der Programmverfolgung fort. In der Receive-Methode wird Business-Logik ausgeführt. Ein neuer Wert wird darin berechnet. (Um Missverständnissen vorzubeugen: Diese Werte sind natürlich auch Objekte. Es sind aber eben spezielle Value-Objekte und keine primitiven Datentypen! Ich bin auch dabei, mir abzugewöhnen, primitive Datentypen direkt zu transportieren, weil diese einfach nichts aussagen und zudem nicht erweiterbar sind.)&lt;br /&gt;
Weiter geht&#39;s: Am Ende dieser Methode steht dann also wieder &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Say.Carefully(SendNeuerWert, this)&lt;/span&gt;&quot;.&lt;br /&gt;
Jetzt geht das Geeier wieder los. &quot;Wer nimmt den Wert entgegen und was passiert damit?&quot;. Also wieder zurück und von &quot;oben&quot; drauf gucken, weil ja das Objekt für sich isoliert gewesen ist.&lt;br /&gt;
So geht das dann immer weiter. Besonders &quot;lustig&quot; wird es dann, wenn man wirklich einen Bug lokalisieren muss und die Zeit drängt. Da springt man hin und her ... hoch und runter. Wenn man Glück hat, findet man den Bug.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Eine gewisse Ordnung, und trotzdem Chaos&lt;/span&gt;&lt;br /&gt;
Alles hat im Grunde eine ordentliche Struktur, aber für mich ergibt sich ein Gefühl von Chaos, dass ich auf Dauer nicht zu bändigen vermag. Ursache dessen ist gerade diese Isolation der Objekte! Aus einem Objekt heraus kann ich nicht einfach auf den Programmfluss schließen. Und weil die Objekte äußerlich von nix abhängig sind (fehlende Konstruktorargumente), weiß ich ja nicht mal, ob diese Objekte überhaupt benötigt werden. Ist ein bestimmtes Objekt für einen bestimmten Vorgang unerlässlich? Vielleicht ja? Vielleicht nein? Welche Events von dem Objekt müssen verdrahtet werden, damit die Software funktioniert? Welche davon sind optional?&lt;br /&gt;
All das sagt das Objekt, von außen betrachtet, nicht aus.&lt;br /&gt;
Ich sehe mir bei einem Softwareprojekt nicht zuerst an, wie die Objekte verdrahtet sind. Der naive Ansatz, den ich immer verfolge, wenn ich wieder mal wissen will, wie etwas funktioniert, ist Folgender:&lt;br /&gt;
&lt;br /&gt;
Im Grunde haben alle meine Anwendungen ein quasi statisches Hauptformular. Dieses nehme ich mir her und im Entwurfsfenster sehe ich es dann mit all seinen Buttons usw. Wenn ich wissen will, welche Funktion sich hinter einem Button verbirgt, klicke ich doppelt drauf und springe in die entsprechende Routine. Bei der MPT beginnt dann jenes Szenario, welches ich oben dargestellt hatte.&lt;br /&gt;
Und DAS macht keinen Spaß! Das Formular ist zwar dadurch wunderbar entkoppelt, aber für sich gesehen ist es absolut sinnlos, weil es nix über die Funktionalität der Software aussagt. Nun kann man sich darüber streiten, ob man so beginnen sollte, eine Software zu lesen. Aber, hey! Eine User-Story beginnt schließlich so: &quot;Wenn ich auf den Button klicke, dann ...!&quot; Und dann beginnt die Business-Logik zu fließen. Aber bei der MPT fließt erstmal nix, sondern man kommt gerade an dieser Stelle zum Stillstand, wo es interessant wird. In meinen früheren Projekten ist an der Stelle tatsächlich die Story geflossen. (Auch wenn da in der Anfängerphase(!) eine furchtbare Struktur zum Vorschein kam und die Domänen häufig gemischt waren, wirkte diese weit weniger chaotisch, als die MPT! Denn man konnte wenigstens hintereinander weg dem Programmfluss folgen! Und das ist absolut wichtig, wenn man Software verstehen will!)&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Zurück zu den Wurzeln&lt;/span&gt;&lt;br /&gt;
Eine totale(!) Entkopplung, also Isolation von Objekten, mag ja auch ihre Vorteile haben. Aber mir hat sie in der Praxis das Verstehen meiner eigenen Software nur erschwert. Denn wie gesagt: Ich gucke in erster Linie nicht auf den &quot;Schaltplan&quot;, also danach, wie die Objekte miteinander verknüpft sind. Man hat schließlich immer noch Quellcode vor sich, den man wie eine Geschichte lesen können soll.&lt;br /&gt;
Das geht aber NICHT, wenn man hier nur isolierte Klassen vor sich hat.&lt;br /&gt;
So konnte das nicht weiter gehen! Immer dieses &quot;von Sackgasse zu Sackgasse&quot; springen machte absolut keinen Spaß!&lt;br /&gt;
Was würde also dagegen sprechen, Objekten wieder die gewohnte Abhängigkeit zu verleihen? Sie also miteinander lose(!) zu koppeln? Nix würde dagegen sprechen! Die lose Kopplung würde einen aber wieder zu einem lesbaren Programm verhelfen! Und das ist mir wichtiger, als auf biegen und brechen meine Klassen total zu entkoppeln. Das nützt mir nix, wenn ich die Software am Ende nicht vernünftig lesen kann. Schlimmer noch, wenn sich der Lesefluss so anfühlt, als ob ich von einer &quot;goto-Anweisung&quot; zur nächsten &quot;goto-Anweisung&quot; springe. Man nennt das &quot;Spaghetti-Code&quot;. Genauso fühlt sich aber auch das Nachvollziehen des MPT-Codes an!&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Dependency Injection neu entdeckt: DIY-DI&lt;/span&gt;&lt;br /&gt;
Dependency Injection (DI) ist mir nicht unbekannt. Durch &lt;a href=&quot;http://misko.hevery.com/&quot;&gt;Misko Hevery&lt;/a&gt;, einem regelrechten DI Enthusiasten, hatte ich die Thematik so richtig vertieft. Warum hatte ich aber das Prinzip der DI nicht weiter verfolgt? Im Grunde hatte mich die manuelle Objekterzeugung abgeschreckt. Sowas kann dann schon mal unübersichtlich und komplex werden.&amp;nbsp;Natürlich gibt es auch DI-Frameworks, welche einem die Arbeit abnehmen sollen.&lt;br /&gt;
Wenn ich aber eines hasse, dann sind es irgendwelche Frameworks, von denen man sich wieder abhängig macht. Frameworks, wo im Hintergrund irgendwas &quot;Magisches&quot; passiert, kann ich nicht leiden. Ich möchte in meinem Quellcode jede Kleinigkeit nachvollziehen können. Dass ich da beim .Net-Framework mit einem relativ hohen Abstraktionsgrad leben muss, ist mir da schon genug &quot;Magie&quot;. Da brauche ich nicht noch irgendein mysteriöses Framework, wo ich nicht weiß, was da im Detail passiert.&lt;br /&gt;
&lt;br /&gt;
Nun bin ich da aber vor kurzem bei Misko Heverys Blog auf einen Artikel gestoßen, der in mir wieder das Interesse für DI geweckt hat: &lt;a href=&quot;http://misko.hevery.com/2010/05/26/do-it-yourself-dependency-injection/&quot;&gt;Do it Yourself – Dependency Injection&lt;/a&gt;&amp;nbsp;(DIY-DI). (Der eigentliche &quot;Erfinder&quot; dieser Idee ist aber Chad Parry und sein originaler Beitrag befindet sich &lt;a href=&quot;http://blacksheep.parry.org/archives/diy-di&quot;&gt;dort&lt;/a&gt;.)&lt;br /&gt;
Als ich mir die Präsentation und das PDF dazu durchgelesen hatte, war mir schlagartig klar, dass ich meine Software zukünftig SO und nicht anders entwickeln möchte! Das ist genau das, was ich unter &lt;i&gt;sauberen Quellcode&lt;/i&gt; verstehe.&lt;br /&gt;
DI ist im objektorientierten Bereich nun mal ein probates Mittel, um Ordnung in seine Struktur zu bekommen. Wenn ein Objekt auf andere Objekte angewiesen ist, damit es funktionieren kann, sollte es dies doch äußerlich kenntlich machen. Das gibt eine gewisse Transparenz und zugleich eine enorme Sicherheit für den Programmierer. Man sieht sofort, mit welchen Objekten das Zielobjekt unmittelbar interagiert und man weiß, dass das Objekt voll funktionsfähig ist, wenn es die geforderten Objekte injiziert bekommt. (Zumindest sollte das so sein. Stichwort: &quot;&lt;a href=&quot;http://de.wikipedia.org/wiki/Law_of_Demeter&quot;&gt;Law of Demeter&lt;/a&gt;&quot;)&lt;br /&gt;
&lt;br /&gt;
So habe ich auf Arbeit damit begonnen, mein derzeitiges Projekt nach DIY-DI zu migrieren. Und mir bereitet es erstmals wieder Freude, Funktionalität hinzuzufügen.&lt;br /&gt;
So begann meine Überlegung: &quot;Das Business-Model benötigt kein User Interface, um zu funktionieren. Aber ein User Interface benötigt ein Business-Model, um zu funktionieren.&quot;&lt;br /&gt;
Das erscheint auch logisch. Spinnt man das noch eine Ebene weiter, so benötige ich als Benutzer das User Interface, um die Software bedienen zu können! Das ist Fakt!&lt;br /&gt;
Ich, als Mensch, bin ja auch nicht isoliert von meiner Umwelt. Die Umwelt ist zwar nicht abhängig von mir, aber ich von ihr. So brauche ich z.B. die Luft zum Atmen, usw.&lt;br /&gt;
&lt;br /&gt;
Um zur Software zurück zu kommen, injizierte ich also einen &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MainPresenter&lt;/span&gt;&quot; in meine &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MainForm&lt;/span&gt;&quot;. Und über den &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MainPresenter&lt;/span&gt;&quot; fordere ich nur die Dinge an, die für das User Interface von Belang sind. Der &quot;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MainPresenter&lt;/span&gt;&quot; ist von diversen Service-Objekten abhängig, die er benötigt, um die Anforderungen vom User Interface erfüllen zu können.&lt;br /&gt;
So hatte ich schon einige Funktionalitäten von der MPT-Architektur umgestellt.&amp;nbsp;Alles ist auf einmal so einfach nachvollziehbar geworden. Der Aufruf, &quot;Gehe zu Definition&quot; in Visual Studio, ist mir endlich wieder von Nutzen, weil ich mit dessen Hilfe wirklich hintereinander weg die komplette Aufrufhierarchie nachvollziehen kann.&lt;br /&gt;
&lt;br /&gt;
Das soll es erstmal soweit gewesen sein. Die totale Entkopplung ist für mich einfach nicht mehr attraktiv.</description><link>http://sachsencoder.blogspot.com/2010/07/ansichten-andern-sich.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-6915715470315258219</guid><pubDate>Mon, 31 May 2010 20:24:00 +0000</pubDate><atom:updated>2010-06-01T08:52:46.184+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><title>Mittelmänner bleiben, wie sie sind!</title><description>In meinem &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/05/die-mittelmanner-entwickeln-sich.html&quot;&gt;letzten Beitrag&lt;/a&gt; war ich ja völlig begeistert von der Idee, die Infrastruktur der Asynchronisation und Synchronisation in die Mittelmänner zu verschieben.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Davor will ich aber an dieser Stelle ausdrücklich abraten!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Ralf Westphal hatte mich davor gewarnt, die &quot;Vermittler&quot; mit mehr Aufgaben zu beladen, als sie eigentlich tun sollten. Und da hat er absolut Recht!&lt;br /&gt;
&lt;br /&gt;
Warum habe ich aber mit meiner Grundidee gebrochen und die Vermittler mit der Synch/Asynch-Angelegenheit belastet?&lt;br /&gt;
Ganz einfach: Ich hatte einen Denkfehler. *g*&lt;br /&gt;
&lt;br /&gt;
Ich hatte einfach zu kompliziert gedacht. Das möchte ich mal genauer erklären:&lt;br /&gt;
Mein Gedanke ging in die Richtung, wie es auf dem folgenden Bild dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNbzAwgqxyMSS3Wks6wOdzJtV9R3ZwyjEAWnhn7ltr-VquEFaAtDYzXPTapMuoJK8NBUV6ZwIjV0Y3Weqfl8RUhPt4ryS2Jyo6mdEctH0vqs9T02qEGKUbAkOEiBS1ujC9O2jI3aXL53H3/s1600/falsch.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;448&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNbzAwgqxyMSS3Wks6wOdzJtV9R3ZwyjEAWnhn7ltr-VquEFaAtDYzXPTapMuoJK8NBUV6ZwIjV0Y3Weqfl8RUhPt4ryS2Jyo6mdEctH0vqs9T02qEGKUbAkOEiBS1ujC9O2jI3aXL53H3/s640/falsch.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Für den Asynch/Synch Aspekt werden eigene Mittelmänner und Schnittstellen definiert. (Zum Vergrößern auf Bild klicken.)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
Meine Idee war es, für die Asynchronisation und Synchronisation auch entsprechend eigene Mittelmänner und Schnittstellen zu definieren. Das erschien mir aber viel zu unflexibel und zu aufwändig, weshalb ich mich für den unschönen Hack entschied, &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/05/die-mittelmanner-entwickeln-sich.html&quot;&gt;die Mittelmänner zu modifizieren&lt;/a&gt;. Zudem sah ich hierin schon fast das Todesurteil meiner MPT. Denn wenn ich mit der MPT nicht ebenso einfach solche flexiblen Konstrukte realisieren kann, wie es Ralf mit seinen EBCs &lt;a href=&quot;http://ralfw.blogspot.com/2010/02/verbindungsstucke-event-based.html&quot;&gt;dort&lt;/a&gt; gezeigt hat, so wäre die MPT schlicht unbrauchbar.&lt;br /&gt;
&lt;br /&gt;
Und ich war wirklich schon nahe dran, die MPT zu vergessen und mich den EBCs zuzuwenden.&lt;br /&gt;
&lt;br /&gt;
Nun, ich weiß nicht, warum ich erst letzten Freitag beim Autofahren auf die entscheidende Idee gekommen bin, welche die MPT ebenso flexibel macht, wie die EBCs. Dabei ist es im Nachhinein betrachtet schon fast peinlich, dass ich so umständlich gedacht habe.&lt;br /&gt;
&lt;br /&gt;
Die Lösung zum Problem zeigt die folgende Grafik:&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0qra5Bu9XflRAZr4DAsglbiwnJZhZFEh3FI21EdB2WuNhyphenhyphenpDdejGgXPZV-G35gw0Mnher4zHdopsJGdxRb9K_igwZBurX2c0SlJi3kYOVmT6mh4lNoytQuQRwucvNsJQHJihjQp8CG5E3/s1600/richtig.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;414&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0qra5Bu9XflRAZr4DAsglbiwnJZhZFEh3FI21EdB2WuNhyphenhyphenpDdejGgXPZV-G35gw0Mnher4zHdopsJGdxRb9K_igwZBurX2c0SlJi3kYOVmT6mh4lNoytQuQRwucvNsJQHJihjQp8CG5E3/s640/richtig.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Hier werden einfach die bestehenden Mittelmänner und Schnittstellen verwendet. (Zum Vergrößern auf Bild klicken.)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
Anstatt für die Asynch/Synch Aspekte eigene Mittelmänner und Schnittstellen zu implementieren, kann ich doch auch einfach die bestehenden Konstrukte verwenden. Denn die Asynch/Synch Modelle benötigen doch gar keine andere Signatur. Das heißt, es sind ja keine Adapter bzw. Translator, welche z.B. einen Text aufnehmen und eine Zahl zurückgeben. Oder die ein Trigger-Event aufnehmen und verschiedene konkrete Events auslösen.&lt;br /&gt;
Das war von Anfang an mein Denkfehler dabei.&lt;br /&gt;
Die Asynch/Synch Modelle sind doch in dem Falle einfach nur &quot;Repeater&quot;. Sie können doch gleichzeitig der &quot;Caller und Listener&quot; oder &quot;Transmitter und Receiver&quot; sein. Das verbietet niemand.&lt;br /&gt;
Und das beste hierbei ist eben wieder der Vorteil der konkreten Trennung der Objekte. Die &quot;MainForm&quot; und das &quot;BerechneModel&quot; wissen nix von einer asynchronen oder synchronen Verarbeitung. Für sie ist alles so, wie immer. Und das ist ja auch der Sinn und Zweck bei der MPT (und auch bei Ralfs EBCs)! Man soll die Infrastruktur der Anwendung verändern können, OHNE die bestehende Business-Logik auch nur minimal zu verändern.&lt;br /&gt;
Was mir bei dem zweiten Bild besonders gefällt, ist die kettenartige Struktur, die man dadurch erhält. Man könnte hier sogar beliebig viele Zwischenglieder einfügen, denn der Input und Output ist für die Endknoten immer der Selbe!&lt;br /&gt;
Die Asynchronisaton und Synchronisation spielt sich nur in den jeweiligen Modellen und nirgendwo anders ab!&lt;br /&gt;
Und DAS ist wirklich genial! ;-)&lt;br /&gt;
(Heute hatte ich das auf Arbeit auch gleich in meinem Projekt umgeändert. Und es funktionierte anstandslos.)&lt;br /&gt;
&lt;br /&gt;
Wie sieht nun der Quellcode dazu aus? Ich freue mich, sagen zu können, dass es fast so aussieht, wie bei &lt;a href=&quot;http://ralfw.blogspot.com/2010/05/asynchrone-kommunikation-mit-ebcs-statt.html&quot;&gt;Ralfs Asynch/Synch-Beispiel&lt;/a&gt;! :-)&lt;br /&gt;
&lt;br /&gt;
So wird das zusammengesteckt:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace NewAsyncTest
{
 static class Program
 {
  /// &amp;lt;summary&amp;gt;
  /// Der Haupteinstiegspunkt für die Anwendung.
  /// &amp;lt;/summary&amp;gt;
  [STAThread]
  static void Main()
  {
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);

   Form1 form1 = new Form1();
   BerechneModel berechneModel = new BerechneModel();
   Asynchronizer asynchronizer = new Asynchronizer();
   Synchronizer synchronizer = new Synchronizer();

   new BerechneMediator(
    form1,
    asynchronizer);

   new BerechneMediator(
    asynchronizer,
    berechneModel);

   new ErgebnisFrequency(
    berechneModel,
    synchronizer);

   new ErgebnisFrequency(
    synchronizer,
    form1);

   Application.Run(form1);
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
So sieht der Asynchronizer aus:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace NewAsyncTest
{
 public class Asynchronizer :
  IAmBerechneListener,
  IAmBerechneCaller
 {
  public void DoBerechne()
  {
   ThreadPool.QueueUserWorkItem(
    delegate
    {
     Say.Carefully(Berechne, this);
    });
  }

  public event EventHandler Berechne;
 }
}&lt;/pre&gt;&lt;br /&gt;
So sieht der Synchronizer aus:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Threading;

namespace NewAsyncTest
{
 public class Synchronizer :
  IAmErgebnisReceiver,
  IAmErgebnisTransmitter
 {
  private AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);

  int ergebnis;
  public void ReceiveErgebnis(int ergebnis)
  {
   asyncOp.Post(new SendOrPostCallback(
    delegate
    {
     this.ergebnis = ergebnis;
     Say.Carefully(SendErgebnis, this);
    }), null);
  }

  public event EventHandler SendErgebnis;

  public int ReturnErgebnis()
  {
   return ergebnis;
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Ein entsprechendes RAR-Archiv, mit dem Beispielprogramm, kann man sich auch wieder herunterladen: &lt;a href=&quot;http://docs.google.com/leaf?id=0B0p6jU6QiR9-ZWIxMDU5YzQtZTdhYS00ZGNkLWE2ODktNDIyZWU0NzA5NzIw&amp;amp;sort=name&amp;amp;layout=list&amp;amp;num=50&quot;&gt;KLICK&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Tja, keine Ahnung, aber beim Autofahren kamen mir bisher immer die besten Einfälle. *g*&lt;br /&gt;
&lt;br /&gt;
Ich werde wohl im nächsten Beitrag mal die MPT mit den EBCs vergleichen. (Wobei ich die EBCs nicht als &quot;Konkurrenz&quot; betrachte. Das erkläre ich aber, wenn es soweit ist.)</description><link>http://sachsencoder.blogspot.com/2010/05/mittelmanner-bleiben-wie-sie-sind.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNbzAwgqxyMSS3Wks6wOdzJtV9R3ZwyjEAWnhn7ltr-VquEFaAtDYzXPTapMuoJK8NBUV6ZwIjV0Y3Weqfl8RUhPt4ryS2Jyo6mdEctH0vqs9T02qEGKUbAkOEiBS1ujC9O2jI3aXL53H3/s72-c/falsch.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4752056964191932264</guid><pubDate>Tue, 11 May 2010 21:30:00 +0000</pubDate><atom:updated>2010-05-12T12:46:59.336+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><category domain="http://www.blogger.com/atom/ns#">Neuigkeiten</category><title>Die Mittelmänner entwickeln sich!</title><description>Ich bin ja so glücklich über das, was ich heute erreicht habe! Aber schön der Reihe nach:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Die Mittelmänner entwickeln sich weiter!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Wie kann man das verstehen? Ganz einfach: Weißt Du noch, als ich in meinen Präsentationen (z.B. &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/caller-mediator-listener-im-detail.html&quot;&gt;diese hier&lt;/a&gt;) gesagt habe, dass die Mittelmänner selber von Außen keine Zugriffsmöglichkeiten haben (sollen)?&lt;br /&gt;
Ich habe heute meine Meinung geändert! (Ich habe aber auch nie gesagt, dass die Micro-Pattern-Trilogie bereits vollendet ist.) ^_^&lt;br /&gt;
&lt;br /&gt;
Ich bin bei &lt;a href=&quot;http://www.blogger.com/profile/05225416366856069349&quot;&gt;Ralf Westphal&lt;/a&gt;s &lt;a href=&quot;http://ralfw.blogspot.com/&quot;&gt;Blog&lt;/a&gt; über diesen Beitrag gestolpert: &lt;a href=&quot;http://ralfw.blogspot.com/2010/05/asynchrone-kommunikation-mit-ebcs-statt.html&quot;&gt;Asynchrone Kommunikation mit EBCs statt “Async-Pattern”&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Ralf hat da absolut Recht, wenn er sagt, dass die Dinge, wie z.B. Threads, nix in der Businesslogik zu suchen haben! Ich hatte aber auch am Anfang den Fehler gemacht, als ich mal diesbezüglich experimentiert hatte. Ich hatte aber auch keine Idee, wie ich es denn am besten anders anstellen könnte.&lt;br /&gt;
&lt;br /&gt;
Und heute grübelte ich etwas über diesen Fakt nach. Die natürliche Trennung zwischen den Objekten stellen ja die Mittelmänner dar. Also ist es doch naheliegend, wenn man an diesem Connector festlegt, ob der Nachrichtenfluss asynchron oder synchron verlaufen soll und nicht in den Businessmodellen!&lt;br /&gt;
&lt;br /&gt;
Guter Stil ist es ja, wenn man ein Framework so entwirft, wie man es später auch auf einfache Weise verwenden möchte. So kam ich auf folgende Idee:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace NewAsyncTest
{
 static class Program
 {
  /// &amp;lt;summary&amp;gt;
  /// Der Haupteinstiegspunkt für die Anwendung.
  /// &amp;lt;/summary&amp;gt;
  [STAThread]
  static void Main()
  {
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);

   Form1 form1 = new Form1();
   BerechneModel berechneModel = new BerechneModel();

   new BerechneMediator(
    form1,
    berechneModel).Asynchronize();

   new ErgebnisFrequency(
    berechneModel,
    form1).Synchronize();

   Application.Run(form1);
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Hier nochmal die relevante Stelle:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; first-line: 21&quot;&gt;new BerechneMediator(
 form1,
 berechneModel).Asynchronize();

new ErgebnisFrequency(
 berechneModel,
 form1).Synchronize();&lt;/pre&gt;&lt;br /&gt;
Wie man sieht, haben die Mittelmänner nun doch noch öffentliche Methoden bekommen.&lt;br /&gt;
Die &quot;form1&quot; ist der Auslöser für den &quot;berechne&quot;-Vorgang. Das &quot;berechneModel&quot; führt die Berechnung durch. Je nachdem, wie umfangreich die Berechnung ist, kann dies eine gewisse Zeit dauern. Deshalb wollen wir diesen Vorgang asynchron durchführen. Das hat zur Folge, dass der Nutzer in der Zwischenzeit ungehindert weiter mit der Anwendung arbeiten kann.&lt;br /&gt;
&lt;br /&gt;
Wenn das &quot;berechneModel&quot; fertig ist, wird das Ergebnis einfach an die Form zurück gesendet. Aber Vorsicht! Es muss synchronisiert werden, weil die &quot;form1&quot; ein GUI ist. Tut man dies nicht, wird eine Exception geworfen!&lt;br /&gt;
Mit dem Methodenaufruf &quot;Synchronize&quot; ist das Thema aber schon gegessen.&lt;br /&gt;
So einfach kann die asynchrone/synchrone Nachrichtenverarbeitung sein. Und übersichtlich ist das ganze auch noch.&lt;br /&gt;
Ist das geil, oder ist das geil? ^_^&lt;br /&gt;
&lt;br /&gt;
Und wie sieht die Sache intern aus?&lt;br /&gt;
Der Übersichtlichkeit halber, zeige ich hier nur mal den &quot;BerechneMediator&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace NewAsyncTest
{
 public interface IAmBerechneCaller
 {
  event EventHandler Berechne;
 }

 public interface IAmBerechneListener
 {
  void Berechne();
 }

 public class BerechneMediator : Middleman
 {
  private readonly IAmBerechneCaller caller;
  private readonly IAmBerechneListener listener;

  public BerechneMediator(
   IAmBerechneCaller caller,
   IAmBerechneListener listener)
  {
   this.caller = caller;
   this.listener = listener;

   this.caller.Berechne += Do(caller_Berechne);
  }

  void caller_Berechne(object sender, EventArgs e)
  {
   listener.Berechne();
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Kein Witz! So sieht das wirklich aus. Mein Ziel war es ja, dass ich meine Pattern genauso weiterverwenden kann, wie ich es bisher getan habe.&lt;br /&gt;
Man sieht erst auf den zweiten Blick, was sich geändert hat. JEDER Mittelmann muss ab sofort von der abstrakten Klasse &quot;Middleman&quot; erben, wenn er die komfortablen synch/asynch Features nutzen will.&lt;br /&gt;
Wenn er diese geerbt hat, muss er beim Zuweisen des Event-Handlers die geschützte &quot;Do&quot;-Methode verwenden. Mehr ist hierbei absolut nicht zu tun.&lt;br /&gt;
&lt;br /&gt;
Sehen wir uns nun die abstrakte Basisklasse &quot;Middleman&quot; an. Denn nur dort befindet sich die gesamte Infrastruktur.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;

namespace NewAsyncTest
{
 public abstract class Middleman
 {
  private bool isAsynchronizer = false;
  private bool isSynchronizer = false;
  private AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);

  public void Asynchronize()
  {
   isSynchronizer = false;
   isAsynchronizer = true;
  }

  public void Synchronize()
  {
   isSynchronizer = true;
   isAsynchronizer = false;
  }

  public void NormalMode()
  {
   isSynchronizer = false;
   isAsynchronizer = false;
  }

  protected EventHandler Do(EventHandler customMethod)
  {
   return new EventHandler(
    delegate
    {
     if (isAsynchronizer)
     {
      ThreadPool.QueueUserWorkItem(delegate { customMethod(this, EventArgs.Empty); });
     }
     else if (isSynchronizer)
     {
      asyncOp.Post(new SendOrPostCallback(
       delegate
       {
        customMethod(this, EventArgs.Empty);
       }), null);
     }
     else
     {
      customMethod(this, EventArgs.Empty);
     }
    });
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Sieht kompliziert aus, ist es aber gar nicht. ;-)&lt;br /&gt;
Es sind die anonymen delegates, die das Ganze etwas wüst aussehen lassen. *lach*&lt;br /&gt;
Über die 3 öffentlichen Methoden werden lediglich Statusflags gesetzt. (Ja, es sind 3 und nicht 2 Methoden, weil ich noch eine Methode wollte, mit der ich die Flags wieder zurücksetzen kann.)&lt;br /&gt;
&lt;br /&gt;
In der geschützten &quot;Do&quot; Methode wird lediglich ein neuer EventHandler zurückgegeben. Und in diesem Handler steckt eine Kontrollanweisung, die einfach prüft, welche Rolle der &quot;Mittelmann&quot; im Moment spielt. Ist er ein &quot;Asynchronizer&quot;, wird die &quot;customMethod&quot; einfach in den ThreadPool gesteckt. Und nach mir die Sintflut. *g*&lt;br /&gt;
Ist er ein &quot;Synchronizer&quot;, wird die &quot;customMethod&quot; in die &quot;asyncOp&quot; gesteckt. (Dieses Ding sorgt voll automatisch dafür, dass ein beliebiger Thread mit dem GUI-Thread synchronisiert wird.)&lt;br /&gt;
Wenn er letztlich nix von Beiden ist, dann soll die &quot;customMethod&quot; ganz normal aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Und weil diese Prüfung bei JEDEM ausgelösten Event durchgeführt wird, könnte man quasi zur Laufzeit der Anwendung das Verhalten ändern.&lt;br /&gt;
&lt;br /&gt;
Also ich finde das richtig geil! Da hier in der grundlegenden Struktur absolut nicht viel geändert werden muss, habe ich das heute auch in sehr kurzer Zeit in meinem Softwareprojekt auf Arbeit aktualisiert. Da habe ich nämlich auch einen Task, der am besten asynchron ablaufen müsste. Das ist jetzt ein Kinderspiel! :-D&lt;br /&gt;
Es ist so geil! ^_^&lt;br /&gt;
&lt;br /&gt;
Das soll es auch schon gewesen sein.&lt;br /&gt;
Ich habe hier auch ein Visual Studio 2008 Projekt, wo Du das mal ausprobieren kannst: &lt;a href=&quot;http://docs.google.com/leaf?id=0B0p6jU6QiR9-ODJkYWY2MzAtNDNmNi00MjIzLTg5YTQtYWI2ZjEzNDdlNmVm&amp;amp;hl=de&quot;&gt;KLICK [rar-Archiv]&lt;/a&gt;</description><link>http://sachsencoder.blogspot.com/2010/05/die-mittelmanner-entwickeln-sich.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-832249488967269723</guid><pubDate>Tue, 11 May 2010 19:16:00 +0000</pubDate><atom:updated>2010-05-12T08:36:04.840+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">1. MPT Beispiel</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><title>1. MPT Beispiel - Teil 2</title><description>Nun kommt, &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/05/ich-mache-es-doch-anders.html&quot;&gt;wie vesprochen&lt;/a&gt;, der 2. Teil meines &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/1-mpt-beispiel-teil-1.html&quot;&gt;ersten MPT Beispiels&lt;/a&gt;.&lt;br /&gt;
Und ich bin direkt froh darüber, dass ich gerade in diesem Teil auf die &quot;Mittelmänner&quot; eingehe! Denn erst heute habe ich einen effektiven Weg gefunden, um ganz einfach die asynchrone und synchrone Nachrichtenverarbeitung zu verwenden. Dazu aber später mehr. (Das wird dann ein extra Beitrag werden.)&lt;br /&gt;
&lt;br /&gt;
Beim letzten Mal hatte ich ja gezeigt, wie einfach das Hauptfenster intern aufgebaut ist.&lt;br /&gt;
&lt;br /&gt;
Heute möchte ich zeigen, was die Komponenten zusammenhält:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Die Mittelmänner&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Hier kommt erstmal&amp;nbsp;wieder&amp;nbsp;das Listing des Quellcodes, den ich nachher ausführlicher erklären möchte:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2&quot;&gt;using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace PFDynamic
{
 static class Program
 {
  /// &amp;lt;summary&amp;gt;
  /// Der Haupteinstiegspunkt für die Anwendung.
  /// &amp;lt;/summary&amp;gt;
  [STAThread]
  static void Main()
  {
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);

   Form1 form1 = new Form1();
   AddTextViewModel addTextViewModel =
    new AddTextViewModel(
     new TextViewManager(
      form1));
   
   new AddTextViewMediator(
    form1,
    addTextViewModel);

   new TextViewFrequency(
    addTextViewModel,
    form1);

   Application.Run(form1);
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Ja, das ist auch schon alles.&lt;br /&gt;
Los geht&#39;s!&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; first-line: 18&quot;&gt;Form1 form1 = new Form1();
AddTextViewModel addTextViewModel =
 new AddTextViewModel(
  new TextViewManager(
   form1));&lt;/pre&gt;&lt;br /&gt;
Ich muss es gleich jetzt sagen: Was du in diesem Ausschnitt siehst, ist Mist! Es funktioniert zwar, aber es ist strukturell einfach nicht zumutbar, wenn du mit den Micro-Pattern entwickelst! Dass ich es so programmiert habe, lag eigentlich nur an zwei Faktoren:&lt;br /&gt;
1. wollte ich die Idee nur mal schnell testen, um zu sehen, ob das so funktioniert, wie ich es mir gedacht habe.&lt;br /&gt;
2. hing ich gedanklich doch noch sehr an dem originalen &quot;&lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/presenter-first-geniale-idee.html&quot;&gt;Presenter Fist&lt;/a&gt;&quot; Prinzip. Denn dort ist es gestattet, dass konkrete Objekte eigene Abhängigkeiten haben.&lt;br /&gt;
&lt;br /&gt;
Ich will dennoch erklären, was der Code zu bedeuten hat.&lt;br /&gt;
In Zeile 18 wird einfach nur das Hauptfenster erzeugt, ist aber noch nicht sichtbar.&lt;br /&gt;
In der nächsten Zeile wird das &quot;AddTextViewModel&quot; erzeugt. Dieses erwartet als Konstruktor-Argument ein Objekt, welches sich als &quot;IAmTextViewFactory&quot; bezeichnet. Der &quot;TextViewManager&quot; fungiert als diese &quot;IAmTextViewFactory&quot;.&lt;br /&gt;
Der &quot;TextViewManager&quot; erwartet ein Objekt, welches sich als &quot;IAmTextTransmitter&quot; bezeichnet. In diesem Falle ist ja das Hauptfenster eben dieser &quot;TextTransmitter&quot;.&lt;br /&gt;
Die Internas dieses Konstrukts zeige ich im nächsten Teil.&lt;br /&gt;
&lt;br /&gt;
Wie man sieht, ist sogar diese kleine Hierarchie nicht mehr leicht nachvollziehbar. Zudem sind die Objekte wieder miteinander gekoppelt und somit voneinander abhängig. Sowas geht echt gar nicht! Kein Objekt sollte von einem anderen Objekt abhängig sein ... ausgenommen, die &quot;Mittelmänner&quot;. Aber die haben selber keine Businesslogik, sondern sind nur für die Infrastruktur da.&lt;br /&gt;
&lt;br /&gt;
Der nächste Abschnitt:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; first-line: 24&quot;&gt;new AddTextViewMediator(
 form1,
 addTextViewModel);

new TextViewFrequency(
 addTextViewModel,
 form1);&lt;/pre&gt;&lt;br /&gt;
So sollte die gesamte Software zusammengesetzt sein! Das ist die saubere Anwendung vom MPT Konzept.&lt;br /&gt;
Die Mittelmänner können einfach in den &quot;Raum&quot; hinein erstellt werden.&lt;br /&gt;
&lt;br /&gt;
Sehen wir uns einfach mal an, wie die &quot;Mittelmänner&quot; im Inneren aussehen:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Der Mediator:&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace PFDynamic
{
 public class AddTextViewMediator
 {
  private readonly IAmAddTextViewCaller caller;
  private readonly IAmAddTextViewListener listener;

  public AddTextViewMediator(
   IAmAddTextViewCaller caller,
   IAmAddTextViewListener listener)
  {
   this.caller = caller;
   this.listener = listener;

   this.caller.AddTextView += new EventHandler(caller_AddTextView);
  }

  void caller_AddTextView(object sender, EventArgs e)
  {
   listener.DoAddTextView();
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
&lt;i&gt;Die Frequency:&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace PFDynamic
{
 public class TextViewFrequency
 {
  private readonly IAmTextViewTransmitter transmitter;
  private readonly IAmTextViewReceiver receiver;

  public TextViewFrequency(
   IAmTextViewTransmitter transmitter,
   IAmTextViewReceiver receiver)
  {
   this.transmitter = transmitter;
   this.receiver = receiver;

   this.transmitter.SendTextView += new EventHandler(transmitter_SendTextView);
  }

  void transmitter_SendTextView(object sender, EventArgs e)
  {
   receiver.ReceiveTextView(
    transmitter.ReturnTextView());
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Soviel gibt es da im Grunde nicht zu sagen, denke ich. Wer C# kann, sollte den Quellcode hier problemlos verstehen. Es ist im Grunde nur Wrapper-Code. Und diesen Code muss man bei jedem Triplet erstellen. Und das langweilt, weshalb hier unbedingt ein RAD-Tool her muss! ^_^&lt;br /&gt;
&lt;br /&gt;
Das soll es für diesen Beitrag gewesen sein.&lt;br /&gt;
&lt;br /&gt;
Jetzt schreibe ich gleich noch den nächsten Beitrag mit den Neuigkeiten, die sich in letzter Zeit bei dem MPT Konzept ergeben haben.&lt;br /&gt;
&lt;br /&gt;
Bis dann! :-)</description><link>http://sachsencoder.blogspot.com/2010/05/1-mpt-beispiel-teil-2.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-8629140690991396519</guid><pubDate>Mon, 10 May 2010 21:30:00 +0000</pubDate><atom:updated>2010-05-11T00:10:15.842+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">1. MPT Beispiel</category><category domain="http://www.blogger.com/atom/ns#">Allgemeines</category><category domain="http://www.blogger.com/atom/ns#">Ankündigung</category><category domain="http://www.blogger.com/atom/ns#">Atomix</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">RAD-Tool</category><title>Ich mache es doch anders ...</title><description>Vor ein paar Tagen hatte ich ja &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/05/was-gibt-es-neues.html&quot;&gt;geschrieben&lt;/a&gt;, dass die Fortsetzung des &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/1-mpt-beispiel-teil-1.html&quot;&gt;MPT-Beispiels&lt;/a&gt; etwas warten muss, weil ich das RAD-Tool aktiv entwickeln möchte.&lt;br /&gt;
Ich werde es aber doch so machen, dass ich erst noch das MPT-Beispiel komplett erkläre. Das ist so besser, weil dann erstmal eine Basis dafür existiert, wie die Sache in der Praxis aussieht.&lt;br /&gt;
&lt;br /&gt;
Umso spannender (ich hoffe es jedenfalls *g*) wird es dann nach dem Beispiel werden!&lt;br /&gt;
Ich habe nämlich vor, den Fortschritt des RAD-Tools per Video zu protokollieren. Es soll aber keine Schritt-für-Schritt Anleitung werden, sondern ich möchte nur kurz die Features vorstellen und erklären, wie diese funktionieren. Das werde ich sicher auch mal mit Diagrammen veranschaulichen.&lt;br /&gt;
In jedem Beitrag werde ich dann auch noch den Versions-Hash von dem entsprechenden &lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt;-Commit hinterlassen, damit man später irgendwann mal leicht nachvollziehen kann, zu welcher Version das Video gehört.&lt;br /&gt;
Ich denke, das ist mal was anderes.&lt;br /&gt;
Ich, persönlich, liebe es ja, zu verfolgen, wie eine Anwendung wächst und an Features gewinnt. (Das war z.B. auch ein Grund, weshalb ich schon möglichst zeitig zu Google Chrome gegriffen habe. Da waren ja, verglichen mit Firefox, noch kaum Features drin. Oder die Entwicklung von&amp;nbsp;&lt;a href=&quot;http://www.blender.org/&quot;&gt;Blender&lt;/a&gt; verfolge ich z.B. auch schon, seit es noch zu &quot;Not a Number&quot; gehörte. Ja, einer Anwendung beim Wachsen zuzusehen ist echt aufregend!)&lt;br /&gt;
&lt;br /&gt;
Momentan ist &quot;Atomix&quot; ja noch in einem sehr frühen (und nicht wirklich brauchbaren) Stadium. Aber es besitzt dennoch schon genug, um diesen ersten Iterationsschritt per Video vorzustellen. Ich kann z.B. Dateien laden und diese in einer Listbox anzeigen, welche sich in einem eigenen Toolfenster befindet. Über einen Menüpunkt kann ich dieses Fenster beliebig öffnen und schließen.&lt;br /&gt;
Das zeige und erkläre ich aber alles in dem Video genauer. Es ist aber alles unter Zuhilfenahme der MPT entstanden.&lt;br /&gt;
&quot;Atomix&quot; wird auch eher evolutionär wachsen. In der ersten Iteration werden die Features noch statisch bzw. spezifisch sein, um zunächst festzustellen, ob es so funktioniert. In der nächsten Iteration werden die Features dynamischen Charakter haben bzw. abstrakter sein. So ist es z.B. auch momentan bei der Dateiansicht. Sie befindet sich momentan im ersten Iterationsschritt. (Genaueres dazu später in dem Video.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Dann muss ich unbedingt noch etwas berichten!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Heute wurde ich von &lt;a href=&quot;http://www.blogger.com/profile/05225416366856069349&quot;&gt;Ralf Westphal&lt;/a&gt; per eMail kontaktiert und erhielt ein interessiertes Feedback. Er verwies mich auch auf seine Idee der sogenannten &quot;&lt;a href=&quot;http://ralfw.blogspot.com/search/label/Event-based%20Components&quot;&gt;Event-based Components&lt;/a&gt;&quot;. Unsere Ideen sind im Grunde identisch! Das heißt, wir beide streben ein Konzept an, womit man auf einfache Weise durch völlige Entkopplung der Aspekte seine Anwendung agil und flexibel entwickeln kann.&lt;br /&gt;
Man sollte sich seine Ideen dazu wirklich mal ansehen! Gerade seine Grafiken sind sehr anschaulich.&lt;br /&gt;
Was auf den ersten Blick auffällt, ist, dass er regen Gebrauch der neuen C# Features macht.&lt;br /&gt;
Ich halte mich dabei noch an die Version 2.0, weil ich auf Arbeit auch noch mit Visual Studio 2005 Professional auskommen muss. Und mein Konzept möchte ich in erster Linie für die Arbeit nutzen. Daher ist das etwas problematisch, mich zu sehr auf die neuen Features einzulassen. Man ist dann schnell davon verwöhnt.&lt;br /&gt;
(So brachte mich z.B. die erste richtige Konfrontation mit C# direkt von C++ ab. C/C++ fasse ich nicht mehr freiwillig an. Nur, wenn es wirklich sein muss.)&lt;br /&gt;
&lt;br /&gt;
Zudem bin ich überrascht, dass solche Ideen zur Abwechslung mal aus dem deutschsprachigen Raum kommen. Damit hätte ich absolut nicht gerechnet!&lt;br /&gt;
&lt;br /&gt;
Wir wollen auf alle Fälle weiterhin Kontakt halten und Ideen austauschen.&lt;br /&gt;
&lt;br /&gt;
Aber ich bin wirklich froh, dass es noch mehr Leute gibt, die sich über die Zukunft der Softwareentwicklung Gedanken machen! :-)</description><link>http://sachsencoder.blogspot.com/2010/05/ich-mache-es-doch-anders.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-2000605855343325783</guid><pubDate>Sat, 08 May 2010 21:16:00 +0000</pubDate><atom:updated>2010-05-09T11:17:35.764+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Atomix</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><category domain="http://www.blogger.com/atom/ns#">Parser</category><title>Das Rad neu erfinden? Nein!</title><description>Heute Früh, zwischen 2 und 3 Uhr bin ich plötzlich aufgewacht und konnte nicht mehr einschlafen. Ohne Witz!&lt;br /&gt;
Mir gingen die ganze Zeit Ideen für weitere Features meiner begonnenen &quot;Atomix&quot; Anwendung durch den Kopf. Sind die Ideen mit dem MPT Konzept umsetzbar? Die Gedankenexperimente gingen los und ich kam immer zu dem selben Ergebnis: Natürlich ist das umsetzbar! Unter Zuhilfenahme der MPT ist das sogar sehr einfach, da man sich ja keine Gedanken über die Objektabhängigkeiten machen muss. Man geht ja bei der Implementation einfach davon aus, dass man die benötigten Daten einfach von irgendwoher bekommt. Und dann nutzt man einfach diese Daten für sein gewünschtes Feature.&lt;br /&gt;
Früher habe ich mir eher den Kopf darüber zerbrochen, wie ich die Objekte am Besten miteinander verkopple, um zu dem gewünschten Feature zu kommen:&lt;br /&gt;
&lt;blockquote&gt;&lt;i&gt;Injiziere ich Objekt &quot;A&quot; in Objekt &quot;B&quot;, oder doch besser Objekt &quot;B&quot; in Objekt &quot;A&quot;? Und was ist, wenn ich in Objekt &quot;A&quot; nur einen Teil der Daten von Objekt &quot;B&quot; benötige? Vielleicht benötige ich nur einen bestimmten String von Objekt &quot;B&quot;? Weshalb also Objekt &quot;A&quot; vom kompletten Objekt &quot;B&quot; abhängig machen? Ich kann es aber auch nicht anders machen, weil ich z.B. den String irgendwann dynamisch zur Laufzeit benötige. Also muss ich es doch so machen.&lt;br /&gt;
Und wenn ich in Objekt &quot;B&quot; noch mit Objekt &quot;A&quot; hantieren will? [usw. usf.]&lt;/i&gt;&lt;/blockquote&gt;&lt;i&gt;&lt;/i&gt;Diese Überlegungen entfallen bei der MPT völlig, da hier im Grunde &lt;i&gt;alle&lt;/i&gt; Objekte auf der selben Ebene stehen. Und kein Objekt interessiert sich dafür, wo es seine Daten herbekommt oder wo seine eigenen Daten hingehen. Man benötigt eine bestimmte Datenstruktur für Irgendwas Bestimmtes? Passende Schnittstelle dafür implementieren und seine Idee fortsetzen.&lt;br /&gt;
&lt;br /&gt;
Dadurch sind massenhaft Features durch meinen Kopf gegangen. Das hat kaum ein Ende genommen. Echt schlimm, wenn man dabei durch nix gebremst wird ... höchstens seine eigene Fantasie. Und ehe ich mich versah, ging schon wieder die Sonne auf. *g*&lt;br /&gt;
&lt;br /&gt;
Aber dennoch kam ich an einen Punkt, der mich heute den ganzen Tag stark beschäftigt hat:&lt;br /&gt;
&lt;b&gt;&quot;Atomix&quot; wird auch Quellcode parsen müssen! Soll ich da anfangen, einen eigenen Parser zu entwickeln oder eine existierende Lösung suchen?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Ich dachte tatsächlich erst daran, einen eigenen Parser zu entwickeln. Schnell mal nach der offiziellen C# Spezifikation gegoogelt und den &lt;a href=&quot;http://www.ecma-international.org/publications/standards/Ecma-334.htm&quot;&gt;Standard ECMA-334&lt;/a&gt; gefunden. &quot;Rein geguckt und zam gezuckt!&quot;, wie es so schön heißt. ^_^&lt;br /&gt;
Dass C# komplex ist, ist klar. Aber dieses Dokument hat es schon in sich. Eben eine richtige Spezifikation.&lt;br /&gt;
&lt;br /&gt;
Ich hielt dennoch an dem Gedanke fest, einen eigenen Parser zu entwickeln. Aber mir fehlte ein bisschen der konkrete Ansatz, wie man sowas programmiert. Also nochmal gegoogelt und ich fand das: &quot;&lt;a href=&quot;http://blog.tcx.be/2007/05/writing-parser-overview.html&quot;&gt;Writing a parser: overview&lt;/a&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
Nun war die dort erfundene Beispielsprache ja recht einfach. Einfacher, als etwa C#. Und dennoch ist der Parser für jene einfache Sprache so komplex. Wie würde der erst bei C# aussehen? So einen Parser hat man jedenfalls nicht mal so eben nebenbei programmiert.&lt;br /&gt;
&lt;br /&gt;
Nun will ich ja im Grunde nur ein RAD-Tool entwickeln, welches mir ein bisschen Arbeit abnehmen soll. Und der dafür benötigte Parser ist da eher ein notwendiges Übel. Der soll bei der Entwicklung nicht mehr Aufmerksamkeit bekommen, als meine eigentliche Anwendung.&lt;br /&gt;
So kommen wir wieder auf die Überschrift dieses Beitrages zurück. Ist es notwendig, das Rad neu zu erfinden? Also in dem Falle, sicher nicht! Ich kenne mindestens ein Projekt, welches einen Parser verwendet, wie ich ihn benötige: &quot;&lt;a href=&quot;http://www.icsharpcode.net/OpenSource/SD/&quot;&gt;SharpDevelop&lt;/a&gt;&quot;.&lt;br /&gt;
Ich lud mir den Sourcecode von SharpDevelop runter und stöberte darin nach etwas, was &quot;Parser&quot; hieß. Ich hatte auch etwas gefunden, aber es war nicht direkt das, was ich erwartet hatte.&lt;br /&gt;
Also googelte ich nochmal, weil ich wissen wollte, wie man den Parser von SharpDevelop für eigene Projekte nutzen kann. Tatsächlich fand ich auch etwas: &quot;&lt;a href=&quot;http://wiki.sharpdevelop.net/NRefactory.ashx&quot;&gt;NRefactory&lt;/a&gt;&quot;.&lt;br /&gt;
Das sieht sehr vielversprechend aus und scheint einfach verwendbar zu sein. (Und wenn man einmal weiß, wonach man suchen muss, findet man es auch gleich im Quellcode von SharpDevelop wieder. *g*)&lt;br /&gt;
Ich fand auch noch eine Auflistung von verschiedenen Parsern bei Google: &quot;&lt;a href=&quot;http://stackoverflow.com/questions/81406/parser-for-c&quot;&gt;Parser for C#&lt;/a&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
Hmmm, dort fiel mir auch die &quot;&lt;a href=&quot;http://ccimetadata.codeplex.com/&quot;&gt;Common Compiler Infrastructure: Metadata API&lt;/a&gt;&quot; ins Auge. Das werde ich mir vielleicht auch mal näher ansehen.&lt;br /&gt;
Aber theoretisch dürfte für meine Zwecke die normale &quot;System.Reflection&quot; ausreichen. Mal gucken.&lt;br /&gt;
&lt;br /&gt;
Tja, nun hätte sich im Grunde die Sache mit dem Parser erledigt und ich kann mich wieder voll und ganz auf meine eigentliche Anwendung konzentrieren. :-)</description><link>http://sachsencoder.blogspot.com/2010/05/das-rad-neu-erfinden-nein.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-3682447524484189867</guid><pubDate>Wed, 05 May 2010 21:57:00 +0000</pubDate><atom:updated>2010-05-05T23:57:42.124+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Atomix</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><category domain="http://www.blogger.com/atom/ns#">Neuigkeiten</category><category domain="http://www.blogger.com/atom/ns#">RAD-Tool</category><title>Was gibt es Neues?</title><description>Zunächst mal: Keine Angst! Das MPT-Beispiel ist nicht in Vergessenheit geraten. Es muss jedoch erstmal etwas warten. (Warum, erkläre ich weiter unten.)&lt;br /&gt;
&lt;br /&gt;
Auf Arbeit habe ich momentan die Zeit, meine Softwareprojekte aufzuräumen. (Das heißt, ich nehme mir die Zeit einfach, wenn sonst nix zu tun ist. *g*) Und da dachte ich mir so, dass ich mein letztes (noch aktuelles) Projekt restrukturiere. Gerade, weil ich weiß, dass da später noch mehr Features implementiert werden sollen. Und bei der alten Struktur wäre das &quot;Frickeln&quot; vorprogrammiert. ;-)&lt;br /&gt;
&lt;br /&gt;
Also entschied ich mich, die eher frickelhafte (aber funktionale) Software in eine ordentliche &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/hypothese-die-micro-pattern-trilogie.html&quot;&gt;MPT&lt;/a&gt; umzuformen. Ganz einfach ist das nicht, da in der alten Struktur viele verschiedene Aspekte in einer einzigen Klasse zusammengefasst sind. Das Meiste von der Business-Logik sammelte sich leider in der GUI-Klasse an. (Wenn es schnell gehen soll und man noch den Überblick behält, kann man schon mal diesen Schritt wählen. Denn Merke: Der Kunde interessiert sich am Ende nur für das Tool und nicht über dessen interne Struktur. &lt;a href=&quot;http://haacked.com/archive/2005/05/31/ThereIsNoPerfectDesign.aspx&quot;&gt;There is no perfect Design!&lt;/a&gt;)&lt;br /&gt;
Aber man tut sich selber einen großen Gefallen, wenn man die Aspekte seiner Software voneinander trennt!&lt;br /&gt;
Tja, was soll ich sagen? Ich freue mich immer wieder, dass das MPT Konzept tatsächlich so funktioniert, wie ich es mir gedacht habe. Nebenbei entdecke ich Möglichkeiten, wie ich es noch optimieren kann, um mir etwas Arbeit abzunehmen und den Überblick zu behalten.&lt;br /&gt;
&lt;br /&gt;
Dabei kommen wir gleich zum nächsten Punkt: Es muss leichter fallen, Software mit dem MPT Konzept zu erstellen!&lt;br /&gt;
&lt;br /&gt;
Dafür muss unbedingt ein RAD-Tool her! Da es sowas für die MPT noch nicht gibt, ist mein Einsatz gefragt. *g*&lt;br /&gt;
Vergangenes Wochenende hatte ich schon mit der Entwicklung begonnen. Der Projektname lautet &quot;Atomix&quot;. (Der Name hat sich so ergeben, weil man mit dem Tool seine Software so erstellt, wie wenn man einzelne Atome miteinander verbindet.) Ich möchte mal kurz erklären, wie ich mir dieses Tool vorstelle:&lt;br /&gt;
Es soll von Anfang an mit dem MPT Konzept entwickelt werden. Ich möchte es so zeitig wie möglich produktiv einsetzen können. Das heißt also, die Features haben Vorrang und das Design kommt später. Es soll schließlich in erster Linie ein Werkzeug sein und seinen Zweck erfüllen. (Das Design sollte sich aber später leicht aufpeppen lassen. Der völligen Entkopplung sei Dank! *g*)&lt;br /&gt;
&lt;br /&gt;
Dieses Tool soll vorerst nicht die gewohnte Entwicklungsumgebung ersetzen, sondern diese ergänzen. (Aber nicht in Form eines Plug-Ins!)&lt;br /&gt;
Im Vordergrund steht die MPT-Struktur der zu entwickelnden Software. Aus diesem Grund wird diese in einer grafischen Form dargestellt werden. Wie man sich das ungefähr vorstellen kann, soll folgende Grafik zeigen:&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnJaGDvPQIw5cAEvKNT-4-Qx4SloqkTrYHc84dZtwIJeu0-Ov-R0EF49QDi9XDgoUA6IkbQQiTNzyTy7OF0dldqmj8Fmzy9y0UYdrGjeO1Rj6Z9XlfpW9smPP1W-C5fcXSBSOLtVaZAqz1/s1600/Model3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;321&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnJaGDvPQIw5cAEvKNT-4-Qx4SloqkTrYHc84dZtwIJeu0-Ov-R0EF49QDi9XDgoUA6IkbQQiTNzyTy7OF0dldqmj8Fmzy9y0UYdrGjeO1Rj6Z9XlfpW9smPP1W-C5fcXSBSOLtVaZAqz1/s640/Model3.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;So könnte die grafische Repräsentation mal aussehen.&lt;br /&gt;
(zum Vergrößern auf&#39;s Bild klicken)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
Dieses Diagramm hatte ich mit &lt;a href=&quot;http://www.yworks.com/de/products_yed_about.html&quot;&gt;yEd&lt;/a&gt; entworfen und zeigt den funktionalen Beginn meines ersten &quot;Atomix&quot;-Versuches. (Dies verfolge ich aber nicht weiter, weil ich mich hierbei noch zu sehr an der Idee des &quot;Presenter First&quot; orientiert hatte. Das heißt, hier haben die konkreten Objekte selber feste Abhängigkeiten. Man achte auf die zusammenhängenden weißen Objekte mit der dicken Linie. Das darf nicht sein, da es ein Stilbruch bei der MPT ist.)&lt;br /&gt;
&lt;br /&gt;
Was man aber gerade an diesem Diagramm sehr gut sehen kann, ist die organische Form, welche die Software letztlich hat. Sie ist nicht starr und steif, sondern anpassbar und flexibel.&lt;br /&gt;
&lt;br /&gt;
Bei meinem Tool steht also die Grafik im Mittelpunkt. Wenn man dann z.B. auf eines der Elemente klickt, soll ein Fenster aufpoppen, wo der zugehörige Quellcode drin steht. Dazu inspiriert hat mich der neue Ansatz der sogenannten &quot;&lt;a href=&quot;http://www.cs.brown.edu/people/acb/codebubbles_site.htm&quot;&gt;Code Bubbles&lt;/a&gt;&quot;.&lt;br /&gt;
Man soll dann nur den Quellcode sehen, der in dem Moment wirklich relevant ist.&lt;br /&gt;
Hinzufügen von neuen Triplets soll mit wenigen Mausklicks möglich sein. Dabei soll sich stehts der Quellcode automatisch mit anpassen. Die Grafik soll sich auch aktualisieren, wenn ich z.B. in Visual Studio den Quelltext ändere.&lt;br /&gt;
Die einzelnen Elemente sollen durch einfaches Drag &amp;amp; Drop austauschbar sein, sodass man seine Software im Grunde durch wenige Klicks verändern kann.&lt;br /&gt;
&lt;br /&gt;
Das sollen erstmal die groben Ideen sein, die mir spontan eingefallen sind.&lt;br /&gt;
Aber alles schön der Reihe nach. *g*&lt;br /&gt;
&lt;br /&gt;
Naja, und dafür muss erstmal die Fortsetzung von meinem &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/1-mpt-beispiel-teil-1.html&quot;&gt;MPT Beispiel&lt;/a&gt; etwas zurückstehen.</description><link>http://sachsencoder.blogspot.com/2010/05/was-gibt-es-neues.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnJaGDvPQIw5cAEvKNT-4-Qx4SloqkTrYHc84dZtwIJeu0-Ov-R0EF49QDi9XDgoUA6IkbQQiTNzyTy7OF0dldqmj8Fmzy9y0UYdrGjeO1Rj6Z9XlfpW9smPP1W-C5fcXSBSOLtVaZAqz1/s72-c/Model3.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-8649129740985375719</guid><pubDate>Sat, 24 Apr 2010 16:47:00 +0000</pubDate><atom:updated>2010-04-24T18:58:16.995+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">1. MPT Beispiel</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">Caller-Mediator-Listener</category><category domain="http://www.blogger.com/atom/ns#">CML</category><category domain="http://www.blogger.com/atom/ns#">dynamic controls</category><category domain="http://www.blogger.com/atom/ns#">dynamic views</category><category domain="http://www.blogger.com/atom/ns#">dynamische Ansichten</category><category domain="http://www.blogger.com/atom/ns#">dynamische Controls</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><category domain="http://www.blogger.com/atom/ns#">TFR</category><category domain="http://www.blogger.com/atom/ns#">Transmitter-Frequency-Receiver</category><title>1. MPT Beispiel - Teil 1</title><description>So, jetzt gibt es das erste praktische Beispiel zur &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/hypothese-die-micro-pattern-trilogie.html&quot;&gt;Micro-Pattern-Trilogie&lt;/a&gt;.&lt;br /&gt;
Ich hatte gründlich darüber nachgedacht, ob ich extra für jedes Triplet eine eigene kleine Anwendung entwickeln soll, oder nicht. Aber ich dachte mir so, für das &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/caller-mediator-listener-im-detail.html&quot;&gt;CML Triplet&lt;/a&gt; lohnt sich keine eigenständige Anwendung, weil es schlicht zu primitiv ist.&lt;br /&gt;
Ich hatte da aber schon mal etwas probiert, was vom Umfang her einem realistischen Beispiel würdig ist. Da kommt im Prinzip alles vor, außer des &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/client-provider-server-im-detail.html&quot;&gt;CPS Triplets&lt;/a&gt;. (Das ist aber nicht schlimm. Das kommt dann einfach ein anderes Mal dran.)&lt;br /&gt;
Weil Bilder bekanntlich mehr sagen, als tausend Worte, stelle ich die Anwendung einfach mal in einem kurzen Video vor:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;object height=&quot;505&quot; width=&quot;640&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/ckUcdN-xa_c&amp;hl=de_DE&amp;fs=1&amp;&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/ckUcdN-xa_c&amp;hl=de_DE&amp;fs=1&amp;&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;640&quot; height=&quot;505&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;
(Oh Gott! Da kommt man sich teilweise blöd vor, wenn man mit &#39;nem Mikrofon spricht. Naja, ich bin nicht so der Rede-Mensch. Aber irgendwie fetzt das trotzdem! Ich werde sicher noch mehr Videos dieser Art machen. Aber da wird dann etwas mehr los sein, als in diesem Video. *g*)&lt;br /&gt;
&lt;br /&gt;
Ja, wie du gesehen hast, wird es dynamisch. Das heißt, es werden zur Laufzeit neue Ansichten erzeugt, wobei jede einzelne Ansicht mithilfe des &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/transmitter-frequency-receiver-im.html&quot;&gt;TFR Triplets&lt;/a&gt; den aktuell eingegebenen Text erhält. Außerdem - und das war damals im Prinzip der eigentliche Grund für dieses kleine Programm - bekommt das Hauptformular die verschiedenen Ansichten auf die selbe Weise.&lt;br /&gt;
&lt;br /&gt;
Ich würde sagen, wir fangen mit dem einfachsten Teil der Software an. Das wäre in diesem Fall die Benutzeroberfläche, bzw. dessen Innenleben ... also der Quellcode.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2&quot;&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PFDynamic
{
 public partial class Form1 :
  Form,
  IAmTextTransmitter,
  IAmAddTextViewCaller,
  IAmTextViewReceiver
 {
  public Form1()
  {
   InitializeComponent();
  }

  public event EventHandler SendText;

  public string ReturnText()
  {
   return textBox1.Text;
  }

  private void textBox1_TextChanged(object sender, EventArgs e)
  {
   Say.Carefully(SendText, this);
  }

  private void button1_Click(object sender, EventArgs e)
  {
   Say.Carefully(AddTextView, this);
  }

  public event EventHandler AddTextView;

  public void ReceiveTextView(IAmTextView textView)
  {
   this.Controls.Add(textView.Control);
   Say.Carefully(SendText, this);
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
Das ist wirklich alles! Mehr manueller Quellcode steckt nicht in der Form1-Klasse.&lt;br /&gt;
Ich werde das Listing nun einzeln erklären.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Zeige mir deine implementierten Schnittstellen und ich sage dir, wer du bist!&lt;/b&gt;&lt;br /&gt;
Diese Aussage ist wörtlich zu verstehen. Sehen wir uns dazu den Klassenkopf an:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 11&quot;&gt;public partial class Form1 :
  Form,
  IAmTextTransmitter,
  IAmAddTextViewCaller,
  IAmTextViewReceiver&lt;/pre&gt;&lt;br /&gt;
Ich weiß an dieser Stelle exakt 4 Dinge von Form1. Zum Einen ist sie von der Basisklasse &quot;Form&quot; abgeleitet. Das ist aber nichts Besonderes.&lt;br /&gt;
Viel interessanter sind die Schnittstellen! Diese kann ich direkt so lesen, als wären sie eine &quot;Personenbeschreibung&quot; von Form1.&lt;br /&gt;
&quot;IAmTextTransmitter&quot; bedeutet: &quot;Ich bin ein Text-Transmitter.&quot; Somit weiß ich, dass Form1 aktiv einen Text versendet.&lt;br /&gt;
&quot;IAmAddTextViewCaller&quot; bedeutet: &quot;Ich bin ein AddTextView-Caller.&quot; Somit weiß ich, dass Form1 sagt, dass eine Textansicht hinzugefügt werden soll.&lt;br /&gt;
&quot;IAmTextViewReceiver&quot; bedeutet: &quot;Ich bin ein TextView-Receiver.&quot; Somit weiß ich, dass Form1 passiv eine Textansicht empfängt.&lt;br /&gt;
&lt;br /&gt;
Ohne den eigentlichen Quelltext gesehen zu haben, weiß ich in dem Moment sofort, welche Rolle die Form1 in dem Gesamtsystem spielt. Das geht aber eben nur, wenn hier keine Willkürlichkeit herrscht.&lt;br /&gt;
Sehen wir uns dazu die Schnittstellen selbst einmal an. (Alle Schnittstellen sind natürlich im Namespace &quot;PFDynamic&quot; enthalten. Ich habe das nur zur Übersichtlichkeit weggelassen.)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 7&quot;&gt;public interface IAmTextTransmitter
{
 event EventHandler SendText;
 string ReturnText();
}&lt;/pre&gt;&lt;br /&gt;
Zufällig passt diese Schnittstelle exakt zu dem theoretischen Beispiel meiner &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/transmitter-frequency-receiver-im.html&quot;&gt;TFR Triplet&lt;/a&gt; Erklärung. ;-)&lt;br /&gt;
Man sieht hier, dass die Schnittstelle ein Event &quot;SendText&quot; und eine Methode &quot;ReturnText()&quot; fordert. Mehr nicht.&lt;br /&gt;
Die anderen beiden Schnittstellen sind genauso übersichtlich und erklären sich quasi selber, weshalb ich da nichts dazu sage.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 7&quot;&gt;public interface IAmAddTextViewCaller
{
 event EventHandler AddTextView;
}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 7&quot;&gt;public interface IAmTextViewReceiver
{
 void ReceiveTextView(IAmTextView textView);
}&lt;/pre&gt;&lt;br /&gt;
Aber man sieht hier, dass die Schnittstellen nur das Nötigste enthalten. In der Regel sind es nicht mehr, als zwei Elemente. Das ermöglicht es, einer Klasse mal schnell eine Schnittstelle zuzuweisen und diese zu implementieren.&lt;br /&gt;
Kommen wir zum nächsten Punkt!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mit der Idee fängt alles an!&lt;/b&gt;&lt;br /&gt;
So banal das klingt, ist es aber auch! Es ist ein bisschen sowas, wie &quot;&lt;a href=&quot;http://dsoguy.blogspot.com/2007/01/programming-by-wishful-thinking.html&quot;&gt;Programming by Wishful Thinking&lt;/a&gt;&quot;. Allerdings mit der totalen Entkopplung der Objekte zueinander.&lt;br /&gt;
Bezogen auf diese kleine Anwendung, dachte ich mir Folgendes:&lt;br /&gt;
&quot;Wenn ich auf einen Button &lt;add view=&quot;&quot;&gt; klicke, soll eine Ansicht hinzugefügt werden. In einer TextBox möchte ich Text eingeben können, der automatisch bei allen anderen Ansichten aktualisiert wird. Zudem möchte ich jede Ansicht individuell entfernen können.&quot;&lt;/add&gt;&lt;br /&gt;
&lt;br /&gt;
So klickte ich mir zunächst die Oberfläche zusammen. Einen Button und eine TextBox. Die Ansichten ließ ich logischerweise weg, weil die ja dynamisch hinzugefügt werden sollten.&lt;br /&gt;
Ich klickte doppelt auf den Button, weil ich ja das Klick-Event haben wollte. Und was wollte ich mit dem Klick erreichen? Richtig, ich wollte eine Text-Ansicht hinzufügen. So programmierte ich es dann auch:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 34&quot;&gt;private void button1_Click(object sender, EventArgs e)
{
 Say.Carefully(AddTextView, this);
}&lt;/pre&gt;&lt;br /&gt;
Der Aufruf mit dem &quot;Say Carefully&quot; ist nur ein einfacher Wrapper, um mir Arbeit abzunehmen und die Lesbarkeit zu erhöhen. So sieht diese Wrapper-Klasse aus:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2&quot;&gt;using System;

static class Say
{ 
 public static void Carefully(EventHandler statement, object caller)
 {
  if (statement != null)
   statement(caller, EventArgs.Empty);
 }

 public static void Carefully(EventHandler statement, object caller, EventArgs arguments)
 {
  if (statement != null)
   statement(caller, arguments);
 }
}&lt;/pre&gt;&lt;br /&gt;
Diese Hilfsklasse verwende ich in allen MPT-Projekten. Das aber nur am Rande.&lt;br /&gt;
Wie man in dem Beispiel gesehen hat, formuliere ich bei dem Button-Klick im Grunde nur das, was ich damit erreichen will. Um das &quot;WIE&quot; habe ich mir in dem Moment noch keine Gedanken gemacht, weil dies nur die Gedanken blockieren würde. Durch den Button-Klick soll eine Ansicht hinzugefügt werden. Punkt! Mehr ist an dieser Stelle nicht wichtig. Dann hatte ich die jeweilige Caller-Schnittstelle dazu erstellt. (Siehe oben!)&lt;br /&gt;
&lt;br /&gt;
Die nächste Sache: So wie ich Text in die TextBox eingebe oder verändere, soll dieser an alle Empfänger gesendet werden.&lt;br /&gt;
Also nahm ich hierfür einfach das &quot;TextChanged&quot; Ereignis der TextBox her:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 29&quot;&gt;private void textBox1_TextChanged(object sender, EventArgs e)
{
 Say.Carefully(SendText, this);
}&lt;/pre&gt;&lt;br /&gt;
Das sollte sich auch wieder selbst erklären, denke ich. Das macht eben einen weiteren großen Vorteil aus, dass man den Quelltext nicht extra kommentieren braucht. Der Quellcode ist selbstredend. So sollte das IMHO auch sein. Wer Kommentare braucht, hat IMHO eine unsaubere Codebase und sollte an der Verständlichkeit seines Quellcodes arbeiten.&lt;br /&gt;
&lt;br /&gt;
So, und wer Text sendet, muss diesen auch bereitstellen! Dafür gibt es ja diese Funktion:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 24&quot;&gt;public string ReturnText()
{
 return textBox1.Text;
}&lt;/pre&gt;&lt;br /&gt;
Hier wird eben einfach der Text in der TextBox zurückgegeben. Einfacher geht es nicht.&lt;br /&gt;
&lt;br /&gt;
Eine letzte Sache fehlt noch: Wir wollten ja auch Text-Views empfangen. Kommt also nun zum Schluss diese Möglichkeit hinzu:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 41&quot;&gt;public void ReceiveTextView(IAmTextView textView)
{
 this.Controls.Add(textView.Control);
 Say.Carefully(SendText, this);
}&lt;/pre&gt;&lt;br /&gt;
Auch diese Methode kam quasi so zustande, wie ich sie gern verwenden wollte. Wir erinnern uns: Wir wollten alles nur über Schnittstellen abwickeln!&lt;br /&gt;
So wollte ich als Parameter eine Schnittstelle, die sich selber als &quot;IAmTextView&quot; bezeichnet. Und diese dient quasi als Wrapper für das &quot;Control&quot;, welches ich ja in der ersten Anweisung der &quot;Controls&quot;-Liste der Form-Klasse hinzufüge. Sonst wäre dies nicht Bestandteil der Form und somit nicht sichtbar.&lt;br /&gt;
Danach möchte ich, dass nochmal der Text gesendet wird. Denn die neu hinzugefügten Ansichten sind ja praktisch noch jungfräulich ... also leer.&lt;br /&gt;
&lt;br /&gt;
Das ist auch ein wichtiger Punkt! Ich hätte das Senden des Textes auch in das Button-Klick Event einfügen können, z.B. so:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; tab-size: 2; first-line: 34&quot;&gt;private void button1_Click(object sender, EventArgs e)
{
 Say.Carefully(AddTextView, this);
 Say.Carefully(SendText, this);
}&lt;/pre&gt;&lt;br /&gt;
Die Software hätte genauso funktioniert, da dies quasi serielle Funktionsaufrufe sind. Was wäre aber, wenn das Event &quot;AddTextView&quot; gar nicht bedient wird? Dann wird &quot;SendText&quot; umsonst aufgerufen, weil ja keine Ansicht hinzugefügt wurde und alle bestehenden Ansichten bereits aktualisiert sind. Ein unnötiger Funktionsaufruf, also. Bei diesem Beispiel fällt das ja nicht ins Gewicht. In der Praxis könnten hier aber komplexe Operationen dahinter stehen, was dann sehr wohl stören könnte.&lt;br /&gt;
&lt;br /&gt;
Oder ein anderes Beispiel:&lt;br /&gt;
Nach dem Aufruf von &quot;AddTextView&quot; wird die Verarbeitung an einen Thread übergeben, wodurch die Funktion sofort wieder zurück kommt und das Event &quot;SendText&quot; aufruft. Der andere Thread ist aber noch dabei, die &quot;TextView&quot; zu generieren. (Das kann ja in der Praxis auch sehr komplex sein.) Nun wurde &quot;SendText&quot; aber schon ausgeführt, obwohl noch keine neue &quot;TextView&quot; erzeugt wurde. Kurze Zeit später ist der Thread soweit und wir bekommen die &quot;TextView&quot;. Aber sie wird keine Daten enthalten, weil der Zug (SendText) schon abgefahren ist. Dumm gelaufen. (Aber keine Angst! Der Kunde wird sich schon über den Bug beschweren. *g*)&lt;br /&gt;
&lt;br /&gt;
Daher sollte man sich immer folgende Frage stellen:&lt;br /&gt;
&quot;Sind die Ereignisse abhängig oder unabhängig voneinander?&quot;&lt;br /&gt;
Am besten versucht man sich dabei immer das Thread-Beispiel vorzustellen. Also das Szenario, dass die Events quasi parallel ausgeführt werden.&lt;br /&gt;
Sind es parallele Prozesse, kann man diese auch parallel aufrufen bzw. implementieren.&lt;br /&gt;
Müssen die Events seriell, also nacheinander ausgeführt werden, sollten diese auch so aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Das soll es soweit erstmal gewesen sein. Im zweiten Teil geht es dann weiter. (Ich schätze mal, dass ich dann die &quot;Mittelmänner&quot; zeige.)</description><link>http://sachsencoder.blogspot.com/2010/04/1-mpt-beispiel-teil-1.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4408884687658143289</guid><pubDate>Sun, 18 Apr 2010 21:51:00 +0000</pubDate><atom:updated>2010-04-20T11:43:54.151+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Caller-Mediator-Listener</category><category domain="http://www.blogger.com/atom/ns#">Client-Provider-Server</category><category domain="http://www.blogger.com/atom/ns#">CML</category><category domain="http://www.blogger.com/atom/ns#">CPS</category><category domain="http://www.blogger.com/atom/ns#">Micro-Pattern-Trilogie</category><category domain="http://www.blogger.com/atom/ns#">MPT</category><category domain="http://www.blogger.com/atom/ns#">TFR</category><category domain="http://www.blogger.com/atom/ns#">Transmitter-Frequency-Receiver</category><title>Hypothese: &quot;Die Micro-Pattern-Trilogie reicht völlig!&quot;</title><description>Ehe wir uns die praktische Anwendung der Micro-Pattern-Trilogie (kurz MPT) ansehen, möchte ich hier zunächst eine kühne Behauptung aufstellen:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&quot;Ich behaupte, dass man nur unter Zuhilfenahme der MPT absolut jede denkbare Software realisieren kann, egal wie komplex diese ist!&quot;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Ziemlich gewagt, diese Aussage, oder? Gerade, wenn man bedenkt, dass es schon andere helle Köpfe gab, die sich viele &lt;a href=&quot;http://de.wikipedia.org/wiki/Entwurfsmuster&quot;&gt;Entwurfsmuster&lt;/a&gt; ausgedacht haben, um den heutigen Softwareproblemen Herr zu werden.&lt;br /&gt;
Ich sage auch nicht, dass alle Muster sinnlos sind. Im Gegenteil!&lt;br /&gt;
Es gibt aber eben auch Muster, welche IMHO redundant sind. Zum Beispiel gibt es da einmal den &quot;&lt;a href=&quot;http://de.wikipedia.org/wiki/Model_View_Controller&quot;&gt;Model View Controller&lt;/a&gt;&quot; und den &quot;&lt;a href=&quot;http://de.wikipedia.org/wiki/Model_View_Presenter&quot;&gt;Model View Presenter&lt;/a&gt;&quot;. Beide erfüllen unter&#39;m Strich die selbe Funktion: Das Eine soll vom Anderen getrennt sein und dennoch hängen alle drei Elemente zusammen. Beim MVC sieht man diesen Widerspruch sehr schön.&lt;br /&gt;
Warum machen sich die Entwickler also das Leben so schwer?&lt;br /&gt;
Vom MVC gibt es zig Modifikationen, sodass man nicht sagen kann: &quot;Ach ja, MVC! Deine Software funktioniert also so und so!&quot; Der andere guckt dich dann verdutzt an und sagt: &quot;Ähm ... nee, meine MVC-Variante funktioniert so und so!&quot; ... Ach so, verstehe ... oder auch nicht. Gut, dass wir drüber geredet haben. ;-P&lt;br /&gt;
&lt;br /&gt;
Bei der MPT sieht es aber anders aus! Hier ist die Spezifikation total simpel und eindeutig. Wenn ich von einem Caller-Mediator-Listener Triplet (kurz CML) rede, dann funktioniert es auch genau SO und nicht anders. Hier wird es keine Abwandlungen geben! (Ein Wassermolekül besteht schließlich auch immer aus zwei Wasserstoffatomen und einem Sauerstoffatom. Und wenn man von Wasser redet, weiß jeder, was das ist.)&lt;br /&gt;
&lt;br /&gt;
Wenn ich mir überlege, dass es zu diesen diversen Pattern ganze Bücher gibt, welche diese erklären ... OMG!&lt;br /&gt;
Und manche Pattern sind auch nicht gerade einfach zu verstehen. (Wie will man dann erst Quellcode verstehen, welcher mit so einem Pattern realisiert ist?)&lt;br /&gt;
&lt;br /&gt;
Sicher, MPT ist auch ein Muster. Aber ein sehr Einfaches, was letztlich jeder Mensch nachvollziehen kann.&lt;br /&gt;
Die MPT besteht nur aus drei einfachen Triplets:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/caller-mediator-listener-im-detail.html&quot;&gt;Caller-Mediator-Listener (CML)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/transmitter-frequency-receiver-im.html&quot;&gt;Transmitter-Frequency-Receiver (TFR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/client-provider-server-im-detail.html&quot;&gt;Client-Provider-Server (CPS)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Die Vorteile überwiegen die Nachteile um ein Vielfaches:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Totale Entkopplung der einzelnen Objekte!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Kein Objekt weiß von der Existenz eines anderen Objekts. Die einzelnen Objekte dürfen auch gar nichts voneinander wissen, geschweige denn direkt miteinander kommunizieren. Dies würde unweigerlich zu einer chaotischen Programmstruktur führen. Theoretisch sollte jedes Objekt völlig ohne Konstruktor-Argumente auskommen. Was ein Objekt benötigt, kommuniziert es einfach &quot;ins Blaue&quot; hinein. Irgendjemand wird &quot;ihm&quot; schon geben, was &quot;er&quot; verlangt (siehe CPS). Woher &quot;er&quot; es letztlich hat, interessiert &quot;ihn&quot; nicht. Die Mittelmänner (Mediator, Frequency, Provider) zählen hier ausdrücklich nicht als Objekte im oben genannten Sinne. Sie sind einfach notwendig, um die Objekte zu verbinden und dadurch Funktionalität zu gewährleisten. Man referenziert sie auch nicht, sondern sie sind einfach da.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Objekte kommunizieren vorsichtig bzw. passiv!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Das heißt, Objekte können zwar sagen, was sie wollen. Ihrem Wunsch muss aber nicht nachgegangen werden. Dadurch kann man auch mal temporär einen Kommunikationskanal unterbrechen, wenn man z.B. logische Fehler im Programm aufspüren will. Im besten Fall funktioniert dann eine Funktion nicht mehr, löst aber keine Exception aus. (Zwei Wassermoleküle kann man auch trennen, ohne dass die Welt untergeht. Bei der Software sollte es IMHO auch so sein.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Man kann agil und flexibel seine Software entwickeln!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Schon lange vorbei sind die Zeiten, wo man vorher erstmal großartig seine Software plant. (Und das möglichst noch mit UML.) Man entwirft höchstens im Kopf mal ein grobes Konzept, wie das Gesamtbild aussehen soll.&lt;/div&gt;&lt;div&gt;Software darf man IMHO nicht mit einem statischen Gebäude vergleichen. Software ändert sich ständig! Da kann ich wirklich ein Lied von singen. Besonders, wenn eine recht komplexe Änderung in recht kurzer Zeit umgesetzt sein soll. (Sehr lustig wird es, wenn dann plötzlich Probleme auftreten, mit denen man gar nicht gerechnet hat.)&lt;/div&gt;&lt;div&gt;Mit der MPT kann man quasi die Software so entwickeln, wie sie einem der Kunde von der Funktionalität her erklärt. Einen &quot;Button-Klick&quot; in der Story kann man z.B. sofort mit dem CML verknüpfen, da dieser Klick irgendwas auslösen soll. Wie es weiter geht? Das kann an dieser Stelle sogar offen bleiben. Es ist wie bei einem Puzzle, wo jenes CML Triplet einen kleinen Teil vom Ganzen ausmacht. Man platziert es erstmal irgendwo und nimmt sich das nächste Puzzle-Teil her. Dies kann z.B. ein völlig anderer Aspekt sein, der mit dem &quot;Button-Klick&quot; gar nix zu tun hat.&lt;/div&gt;&lt;div&gt;Diese Freiheit hat man nur deshalb, weil alle Triplets atomar und völlig unabhängig voneinander sind. Am Ende hat man aber ein &quot;fertiges&quot; Puzzle bzw. eine funktionale Software, welche das tut, was sie soll.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Durch Schnittstellen werden die Dinge miteinander verknüpft!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Das ist sogar ganz wichtig, bei diesem Konzept! Die Mittelmänner erwarten ausschließlich Schnittstellen als Konstruktor-Argument! Niemals eine konkrete Klasse! Dies wäre ein fataler Bruch bei der MPT und die Flexibilität wäre dahin.&lt;/div&gt;&lt;div&gt;Vielmehr sollte man den Vorteil darin sehen, dass eine Klasse beliebig viele Schnittstellen implementieren kann. (Zu diesem Thema wird es auch noch einen extra Beitrag geben, weil die Schnittstellen so wichtig sind.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;So kurze Datenwege, wie möglich!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Theoretisch dürften hier die transportierten Daten (siehe TFR und CPS) auf kürzestem Wege beim Ziel ankommen, weil das jeweilige Objekt direkt sagt, was es benötigt. (z.B. beim CPS)&lt;/div&gt;&lt;div&gt;Somit könnte das angeforderte &quot;Ding&quot; direkt übermittelt werden, ohne erst über zig Ecken wandern zu müssen. Wie gesagt, theoretisch! ;-)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;So, das wären spontan die Vorteile. Das ganze hat leider auch einen offensichtlichen Nachteil:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;SEHR AUFWÄNDIG!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Für jedes Triplet muss man zwei Schnittstellen anlegen und den Mittelmann vollständig implementieren.&lt;/div&gt;&lt;div&gt;Zudem werden da auch viele einzelne kleine Quellcodedateien anfallen.&lt;/div&gt;&lt;div&gt;Ja, das ödet wirklich sehr an und wäre zurecht ein Grund zu sagen: &quot;OMG, da bleibe ich lieber bei quick &amp;amp; dirty!&quot;&lt;/div&gt;&lt;div&gt;Da bleibt momentan nix anderes übrig, als in den sauren Apfel zu beißen oder es zu lassen.&lt;/div&gt;&lt;div&gt;(Ich habe da aber schon ein privates Projekt im Sinn, welches eine Art &lt;a href=&quot;http://de.wikipedia.org/wiki/Rapid_Application_Development&quot;&gt;RAD&lt;/a&gt;-Tool werden soll, um mir diese Arbeit abzunehmen. Natürlich möchte ich dieses Tool konsequent mit der MPT ins Leben rufen. Das wäre dann auch gleich die beste Erprobung für die Praxistauglichkeit der MPT.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Soviel dazu. Bis zum nächsten Artikel! :-)&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2010/04/hypothese-die-micro-pattern-trilogie.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-7790049508919716900</guid><pubDate>Sun, 18 Apr 2010 16:31:00 +0000</pubDate><atom:updated>2010-04-18T18:31:17.709+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Client-Provider-Server</category><category domain="http://www.blogger.com/atom/ns#">CPS</category><category domain="http://www.blogger.com/atom/ns#">Model-View-Presenter</category><category domain="http://www.blogger.com/atom/ns#">MVP</category><category domain="http://www.blogger.com/atom/ns#">Presenter First</category><title>&quot;Client - Provider - Server&quot; im Detail</title><description>Im &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/04/transmitter-frequency-receiver-im.html&quot;&gt;letzten Beitrag&lt;/a&gt; habe ich erklärt, wie das Transmitter-Frequency-Receiver Triplet (kurz TFR) funktioniert.&lt;br /&gt;
&lt;br /&gt;
Nun ist das letzte Triplet der &quot;Micro-Pattern-Trilogie&quot; dran: das Client-Provider-Server Triplet (kurz CPS).&lt;br /&gt;
&lt;br /&gt;
Wie kam ich auf das CPS Triplet? Das ergab sich aus der Tatsache, dass es neben einer passiven Datenübertragung auch eine Aktive geben muss. Einerseits würde das Konzept, ohne die Möglichkeit der Datenübertragung auf Abruf, unvollständig erscheinen. Zum Anderen ist dies sogar unabdingbar, wenn man konsequent ausschließlich mit dieser &quot;Micro-Pattern-Trilogie&quot; seine Software entwickelt. Was ich damit meine, wird in den zukünftigen Artikeln ersichtlicher werden. Es sei nur kurz erwähnt, dass es damit zu tun hat, wie man derartige Software zu entwickeln beginnt. (Das werde ich aber in anderen Beiträgen ausführlich erklären und würde hier zu weit führen.)&lt;br /&gt;
&lt;br /&gt;
Bei der Namensfindung orientierte ich mich auch wieder am realen Beispiel:&lt;br /&gt;
Ich (der &lt;b&gt;Client&lt;/b&gt;) suche etwas bei Google (der &lt;b&gt;Server&lt;/b&gt;). Dabei wandern meine Suchanfragen und meine persönlichen Suchergebnisse von Google über den &lt;b&gt;Provider&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Damit sollte die Sache eigentlich schon klar sein.&lt;br /&gt;
Hier nun die Präsentation:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;iframe frameborder=&quot;0&quot; height=&quot;342&quot; src=&quot;http://docs.google.com/present/embed?id=dg8c2dhz_70dx89szg7&amp;amp;interval=5&amp;amp;loop=true&quot; width=&quot;410&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
So, nun sind alle Triplets in ihrer Funktionsweise erklärt und wir tasten uns langsam aber sicher zu den praktischen Beispielen vor.</description><link>http://sachsencoder.blogspot.com/2010/04/client-provider-server-im-detail.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-1182160629526720748</guid><pubDate>Sat, 17 Apr 2010 19:45:00 +0000</pubDate><atom:updated>2010-05-07T09:57:03.479+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Model-View-Presenter</category><category domain="http://www.blogger.com/atom/ns#">MVP</category><category domain="http://www.blogger.com/atom/ns#">Presenter First</category><category domain="http://www.blogger.com/atom/ns#">TFR</category><category domain="http://www.blogger.com/atom/ns#">Transmitter-Frequency-Receiver</category><title>&quot;Transmitter - Frequency - Receiver&quot; im Detail</title><description>Im &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/caller-mediator-listener-im-detail.html&quot;&gt;letzten Beitrag&lt;/a&gt; habe ich erklärt, wie das Caller-Mediator-Listener Triplet (kurz CML) funktioniert.&lt;br /&gt;
&lt;br /&gt;
Nun möchte ich erklären, wie das Transmitter-Frequency-Receiver Triplet (kurz TFR) funktioniert.&lt;br /&gt;
Wie bin ich überhaupt darauf gekommen? Der Gedankengang war im Grunde recht einfach. Da das CML Triplet keine Daten übertragen darf, musste etwas her, was dies ausdrücklich spezifiziert.&lt;br /&gt;
Ich dachte zuerst an eine Möglichkeit, Daten passiv empfangen zu können. Als Beispiel sei hier die Statusleiste genannt, welche bei fast allen GUI-Anwendungen existiert. Diese Statusleiste fordert keine Daten an, sondern empfängt diese automatisch, wenn sich der Status geändert hat. (Meist ist dies ja ein einfacher String.)&lt;br /&gt;
&lt;br /&gt;
Oder ein anderes Beispiel:&lt;br /&gt;
Der Benutzer gibt z.B. in einer TextBox beliebigen Text ein, welcher gleichzeitig in mehreren Ansichten aktualisiert werden soll.&lt;br /&gt;
&lt;br /&gt;
Mit diesem Beispiel kam mir letztlich die Idee:&lt;br /&gt;
Es gibt einen Sender, welcher Daten aussendet. Gleichzeitig kann es mehrere Empfänger geben, welche diese Daten empfangen.&lt;br /&gt;
So etwas kennt jeder aus dem realen Leben: Fernsehsatelliten senden ein Fernsehsignal in Richtung Erde und diverse Sat-Empfänger können dieses Signal empfangen.&lt;br /&gt;
Es war sofort klar, dass die Schnittstelle für den Empfang schlicht &lt;b&gt;Receiver&lt;/b&gt; heißen musste.&lt;br /&gt;
Die Schnittstelle für den Sender wollte ich auch erst &quot;Sender&quot; nennen, jedoch gab es diese Bezeichnung schon im .NET Framework. Außerdem klang es nicht so &quot;cool&quot;.&lt;br /&gt;
Einmal kurz gegoogelt und ich fand den Begriff &lt;b&gt;Transmitter&lt;/b&gt;. Dieser passt auch besser zum Rundfunk-Beispiel.&lt;br /&gt;
Nun brauchte ich noch einen geeigneten Name für den Mittelmann.&lt;br /&gt;
Was verbindet beide Dinge miteinander? Wirklich spontan fiel mir sofort der &lt;a href=&quot;http://de.wikipedia.org/wiki/%C3%84ther_(Physik)&quot;&gt;Äther&lt;/a&gt; ein. Ich gebrauchte natürlich den englischen Begriff &lt;a href=&quot;http://en.wikipedia.org/wiki/Luminiferous_aether&quot;&gt;Aether&lt;/a&gt;. Tatsächlich blieb ich für einige kurze Experimente bei diesem Begriff, aber mich störte er immer mehr, weil man ihn heute im Grunde nur noch in der Esoterik antrifft.&lt;br /&gt;
Ich überlegte und überlegte, aber mir wollte keine Alternative einfallen. Dann nahm ich mir in Gedanken nochmal den Vergleich mit dem Rundfunk her. Was geschieht also, wenn man z.B. beim Sat-Receiver oder beim Radio den Sender wechselt? Klar, man ändert die Frequenz. Bingo! Das war der gesuchte Begriff! Und er passte auch genau zu dem Presenter-First Konzept. Auch hier entschied ich mich letztlich für die englische Bezeichnung: &lt;b&gt;Frequency&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Nach der langen Einleitung kommt nun die versprochene Präsentation:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;iframe frameborder=&quot;0&quot; height=&quot;342&quot; src=&quot;http://docs.google.com/present/embed?id=dg8c2dhz_688n44sbdb&amp;amp;interval=5&amp;amp;loop=true&quot; width=&quot;410&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;
So, dieses war der zweite Streich und der Dritte folgt sogleich!&lt;br /&gt;
&lt;br /&gt;
(Mal sehen, ob ich es bis morgen Abend schaffe. Dann hätten wir die graue Theorie hinter uns und es folgen dann endlich praktische Beispiele und Überlegungen für den praktischen Einsatz.)</description><link>http://sachsencoder.blogspot.com/2010/04/transmitter-frequency-receiver-im.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-5381428087161462856</guid><pubDate>Thu, 25 Mar 2010 20:24:00 +0000</pubDate><atom:updated>2010-04-17T21:46:09.192+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Caller-Mediator-Listener</category><category domain="http://www.blogger.com/atom/ns#">CML</category><category domain="http://www.blogger.com/atom/ns#">Model-View-Presenter</category><category domain="http://www.blogger.com/atom/ns#">MVP</category><category domain="http://www.blogger.com/atom/ns#">Presenter First</category><title>&quot;Caller - Mediator - Listener&quot; im Detail</title><description>In meinem &lt;a href=&quot;http://sachsencoder.blogspot.com/2010/03/presenter-first-geniale-idee.html&quot;&gt;ersten Beitrag&lt;/a&gt; hatte ich die Idee des &quot;Caller - Mediator - Listener&quot; Triplets kurz erklärt. Nun möchte ich dieses im Detail erläutern und erklären, was ich mir dabei gedacht habe.&lt;br /&gt;
&lt;br /&gt;
Der Grundgedanke, den ich hatte, war letztlich gar nix weltbewegend Neues.&lt;br /&gt;
Ich habe einfach den Sachverhalt der Objektkommunikation aus der objektorientierten Programmierung wörtlich genommen.&lt;br /&gt;
Somit gibt es eben:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;einen &lt;b&gt;Caller&lt;/b&gt;, der etwas zu sagen hat&lt;/li&gt;
&lt;li&gt;einen &lt;b&gt;Mediator&lt;/b&gt;, der die Botschaft vom Caller empfängt und weiterleitet&lt;/li&gt;
&lt;li&gt;einen &lt;b&gt;Listener&lt;/b&gt;, der letztlich die Nachricht empfängt und die eigentlichen Befehle durchführt&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Damit das ganze noch anschaulicher wird, habe ich eine Präsentation erstellt. Ich hoffe, es ist anschaulich genug.&lt;/div&gt;&lt;div&gt;(Da es sich aber hierbei um eines der einfachsten der insgesamt 3 Triplets handelt, sehe ich da keine Probleme.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;iframe frameborder=&quot;0&quot; height=&quot;342&quot; src=&quot;http://docs.google.com/present/embed?id=dg8c2dhz_67cdgh4ddc&amp;amp;interval=5&amp;loop=true&quot; width=&quot;410&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;
So, die nächsten beiden Triplets werden auf jeden Fall interessanter, denn da werden Daten übertragen! Da gibt es dann auch schönere Anwendungsbeispiele.&lt;br /&gt;
Als Vorlage werde ich gleich wieder diese Präsentation verwenden, dann bereitet es nicht ganz so viel Arbeit.&lt;br /&gt;
&lt;br /&gt;
PS.:&lt;br /&gt;
Alle Dateien, die hinsichtlich dieses Blogs anfallen, findet man auch in einem öffentlichen Ordner: &lt;a href=&quot;http://docs.google.com/leaf?id=0B0p6jU6QiR9-MmFiZjMyYjUtYmRlOC00YjIyLTg5ZmUtOTdlYWYzZDI3NWFj&amp;amp;hl=de&quot;&gt;KLICK&lt;/a&gt;&lt;/div&gt;</description><link>http://sachsencoder.blogspot.com/2010/03/caller-mediator-listener-im-detail.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-4952811440469043337</guid><pubDate>Mon, 22 Mar 2010 21:57:00 +0000</pubDate><atom:updated>2010-03-25T21:26:05.854+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Model-View-Presenter</category><category domain="http://www.blogger.com/atom/ns#">MVP</category><category domain="http://www.blogger.com/atom/ns#">Presenter First</category><title>Es dauert noch etwas ...</title><description>Eigentlich wollte ich die 3 Triplets heute in einem Beitrag in Textform erklären.&lt;br /&gt;
Mir kam aber eine bessere Idee in den Sinn!&lt;br /&gt;
Da Bilder bekanntlich mehr sagen, als 1000 Worte, beschloss ich diese Triplets mithilfe einer Präsentation zu beschreiben.&lt;br /&gt;
Dazu verwende ich Google Text &amp;amp; Tabellen.&lt;br /&gt;
Es funktioniert bis jetzt alles wunderbar und auch die grafischen Funktionen machen keine Probleme.&lt;br /&gt;
&lt;br /&gt;
Man darf sich also auf 3 anschauliche Präsentationen freuen. (Zumindest hoffe ich, dass sie anschaulich genug sein werden. *g*)&lt;br /&gt;
&lt;br /&gt;
Das ganze ist jedoch etwas aufwändig. Aber sobald die erste Präsentation fertig ist, werde ich sie hier im Blog veröffentlichen. Bis dahin bitte ich um etwas Geduld! :-)</description><link>http://sachsencoder.blogspot.com/2010/03/es-dauert-noch-etwas.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8264982132165404360.post-9134717756643527412</guid><pubDate>Sun, 21 Mar 2010 21:13:00 +0000</pubDate><atom:updated>2010-03-25T21:26:54.397+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Caller-Mediator-Listener</category><category domain="http://www.blogger.com/atom/ns#">CML</category><category domain="http://www.blogger.com/atom/ns#">Model-View-Presenter</category><category domain="http://www.blogger.com/atom/ns#">MVP</category><category domain="http://www.blogger.com/atom/ns#">Presenter First</category><title>Presenter First - Geniale Idee!</title><description>Meinen ersten Beitrag beginne ich sogleich mit einem Konzept, welches sich &quot;Presenter First&quot; nennt. Ich möchte hier nicht die Grundlagen dessen ausschweifend erklären.&lt;br /&gt;
Hierzu verweise ich lieber auf zwei Dokumente von den eigentlichen &quot;Erfindern&quot;.&lt;br /&gt;
&lt;br /&gt;
Da wäre zunächst das eigentliche Paper, welches die Sache konzeptionell erklärt:&lt;br /&gt;
&lt;a href=&quot;http://www.atomicobject.com/files/PresenterFirstAgile2006.pdf&quot;&gt;Presenter First: Organizing Complex GUI Applications for Test-Driven Development [pdf]&lt;/a&gt;&amp;nbsp;[doc01]&lt;br /&gt;
&lt;br /&gt;
Und dann noch ein eher praktisches Beispiel, welches in dem Magazin &quot;Better Software&quot; erschien:&lt;br /&gt;
&lt;a href=&quot;http://www.atomicobject.com/files/BigComplexTested_Feb07.pdf&quot;&gt;Big, Complex, and Tested? Just Say ‘When’ [pdf]&lt;/a&gt;&amp;nbsp;[doc02]&lt;br /&gt;
&lt;br /&gt;
Nun, als ich das erste mal von diesem Konzept hörte, war ich von dieser Idee total angetan.[1]&lt;br /&gt;
Man stellt sich dann aber dennoch die Frage: &quot;Wo fange ich da nun am besten an, meine Software zu entwerfen?&quot;&lt;br /&gt;
Klar, bei dem gewünschten Feature. Das ist ja der Sinn von dem Konzept.&lt;br /&gt;
Das mag auch noch einfach sein, wenn das Feature in etwa so aussieht: &quot;Wenn ich auf den Button [Beenden] klicke, soll die Anwendung beendet werden.&quot;&lt;br /&gt;
Das ist auch soweit einfach, wenn hierbei wirklich nur die Anwendung beendet werden soll und sonst nix weiter.&lt;br /&gt;
Was aber, wenn mit diesem einfachen Feature komplexe Aufräumarbeiten verbunden sind? Vielleicht soll der Benutzer noch gefragt werden, ob sein geändertes Dokument vorher gespeichert werden soll? Etc.&lt;br /&gt;
Da ist das zuerst genannte Feature die höchste Abstraktionsebene.&lt;br /&gt;
Aus der &quot;Presenter First&quot;-Sicht ist das im Grunde auch so richtig. Was mit dem Beenden-Vorgang sonst noch zusammen hängt, interessiert in dieser Abstraktionsebene überhaupt nicht. Das ist ja auch Sinn und Zweck dieser strikten Entkopplung.&lt;br /&gt;
Es stellt sich daher die Frage: &quot;Wie tief und fein sollte die Abstraktion sein? Das heißt, erstelle ich sehr viele kleine Sub-Presenter, oder sollte das an der Stelle doch etwas grober ausfallen?&quot;&lt;br /&gt;
&lt;br /&gt;
Desweiteren stand ich schon vor folgendem Problem:&lt;br /&gt;
Sollte zu jedem Presenter auch nur ein Fenster/Dialog gehören? Oder sollte jeder Button/jede Komponente einen eigenen Presenter bekommen?&lt;br /&gt;
Ersteres macht die ganze Sache sehr einfach und übersichtlich, ist aber sehr unflexibel und problematisch, wenn man z.B. noch einen Adapter oder generell noch weitere Abstraktionsebenen zwischen eine einzelne Komponente des User Interfaces schalten will.&lt;br /&gt;
Bei der anderen Variante gäbe es nicht dieses Problem. Aber hier hat man am Ende Unmengen einzelner Schnittstellen-, Presenter-, Model- und View-Klassen.&lt;br /&gt;
&lt;br /&gt;
Nun, die Erfinder meinen hier, man solle logisch zusammengehörige Komponenten gemeinsam mit einem Presenter verbinden.&lt;br /&gt;
Klar, das ist erstmal ein guter Kompromiss. Da könnte man die Komponente, welche noch weitere Adapter braucht, entsprechend separieren und die anderen Komponenten zusammen halten.&lt;br /&gt;
Allerdings ist mir das zu willkürlich.&lt;br /&gt;
&lt;br /&gt;
Und das ist gleich das Nächste. Die Willkürlichkeit, wie die Model-View-Presenter-Einheiten zusammengesetzt sind. Das heißt, bei dem originalen Konzept sieht man nicht direkt von Außen, wie der Daten- und Nachrichtenfluss verläuft. Das heißt, jemand, der den Quellcode zum ersten Mal sieht, wird nicht auf Anhieb wissen, was dieses Model oder jene View macht oder welche Rolle der Presenter dabei spielt.&lt;br /&gt;
Dazu müsste man sich nämlich erst tiefer in den Quellcode einlesen.&lt;br /&gt;
&lt;br /&gt;
Ich grübelte noch einige Zeit über die oben genannten Probleme. Immer wieder las ich mir die Dokumente durch.&lt;br /&gt;
Irgendwann ließ ich mir folgenden Text [doc02; letzte Seite unten] so richtig auf der Zunge zergehen:&lt;br /&gt;
&lt;blockquote&gt;The “micro-architecture” of Presenter First is like a carbohydrate chain in organic chemistry — interesting functionality arises from applying the same basic pattern of object composition. The mechanisms and domain may vary, but the core principles do not: When the customer says “when,” write it into a presenter.&lt;/blockquote&gt;Dann war es mir klar. Was dieses an sich tolle Konzept brauchte, war eine gewisse Ordnung in dem willkürlichen Chaos. So, wie auch die Moleküle oder die Zellen des Menschen nach einer gewissen Ordnung funktionieren.&lt;br /&gt;
Ich übertrug den Ordnungsbegriff auf die Softwareentwicklung und kam dann zu folgender Lösung:&lt;br /&gt;
&lt;br /&gt;
Jedes Objekt übernimmt einen sehr kleinen Aufgabenbereich in dem Gesamtsystem. Ein Button im UI wird höchstens nur als Auslöser für eine komplexe Aufgabe dienen. Vielleicht empfängt er auch mal Daten in Form einer neuen Beschriftung oder anderer Eigenschaftswerte. Aber in erster Linie wird er nur zum Triggern da sein.&lt;br /&gt;
&lt;br /&gt;
Somit übernimmt der Button eine entscheidende Aufgabe: Er ist ein &lt;b&gt;Caller&lt;/b&gt;!&lt;br /&gt;
Aber ein Caller alleine bringt leider nicht viel. Es muss auch jemand auf das bestimmte Signal hören, was der Caller ausgesandt hat. Also muss es noch einen &lt;b&gt;Listener&lt;/b&gt; geben.&lt;br /&gt;
Aber da fehlt noch einer! Caller und Listener sollen ja nix voneinander wissen. Ein Presenter muss immer existieren, der beide miteinander verbindet. Aber die Bezeichnung &quot;Presenter&quot; passt hier nicht gut. Zwischen einem &quot;Rufer&quot; und einem &quot;Zuhörer&quot; muss noch jemand vermitteln. Dies wäre im klassischen Sinne die &quot;Luft&quot;. &quot;Air&quot; klingt aber komisch, weshalb ich mich hier für &lt;b&gt;Mediator&lt;/b&gt; entschieden habe.&lt;br /&gt;
&lt;br /&gt;
Das ist nun also die erste Triplet-Gruppe von insgesamt 3 Gruppen, die ich mir ausgedacht habe, um ein bisschen Ordnung und Struktur in die Sache zu bekommen.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Caller - Mediator - Listener&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Die anderen Beiden nenne ich jetzt erstmal so, ohne Erläuterung.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Transmitter - Frequency - Receiver&lt;/b&gt;&lt;br /&gt;
und&lt;br /&gt;
&lt;b&gt;Client - Provider - Server&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
In den nächsten Beiträgen werde ich diese 3 Triplets genauer beleuchten.&lt;br /&gt;
(Theoretisch sollte sich schon die Funktion der letzten 2 Triplets anhand der Bezeichnungen erahnen lassen. *g*)&lt;br /&gt;
&lt;br /&gt;
Das soll es aber erstmal für heute gewesen sein.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;ol&gt;&lt;li&gt;Und ich bin noch immer davon begeistert. Doch ich habe noch so ein paar Schwierigkeiten damit, weshalb ich dieses Konzept noch nicht auf Arbeit verwende. Das werde ich aber in diesem und weiteren Blogbeiträgen nach und nach erläutern.&lt;/li&gt;
&lt;/ol&gt;</description><link>http://sachsencoder.blogspot.com/2010/03/presenter-first-geniale-idee.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item></channel></rss>