{"id":191,"date":"2015-03-21T15:39:39","date_gmt":"2015-03-21T13:39:39","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=191"},"modified":"2015-07-04T14:37:55","modified_gmt":"2015-07-04T12:37:55","slug":"wenn-daten-fliessen","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/wenn-daten-fliessen\/","title":{"rendered":"Wenn Daten flie\u00dfen"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder.<\/p>\n<p>Wer kennt noch das EVA-Prinzip? Eingabe-Verarbeitung-Ausgabe. Das war eines der ersten Themen im Informatikunterricht. Demnach also kein neuen Prinzip, was deshalb aber nicht weniger interessant ist. Insbesondere, wenn ich an das Single Resposibility Principle (SRP) denke, l\u00e4sst sich dies gut vereinbaren.<\/p>\n<p>Dazu hat sich insbesondere in der .Net Welt das Flow-Pattern etabliert, welches Events als Kommunikationsmedium zwischen gekapselten Funktionseinheiten (Klassen) nutzt. Hierzu findet ihr auch einige Artikel in der dotnetpro von Ralf Westphal und Stefan Lieser.<\/p>\n<h2>Flow-Pattern<\/h2>\n<p>Bei der Idee hinter diesem Pattern geht es genau darum: dass Daten flie\u00dfen. Jede Klasse hat dabei nur genau eine Verantwortlichkeit &#8211; bei diesem Pattern geht es kaum noch anders. Die Grundstruktur dazu sieht wie folgt aus:<\/p>\n<pre class=\"lang:c# decode:true \">    public class ExtractCharacter\r\n    {\r\n        public void Process()\r\n        {\r\n\r\n        }\r\n\r\n        public event Action&lt;string&gt; Progress;\r\n    }<\/pre>\n<p>Der Klassenname &#8222;<em>ExtractCharacter<\/em>&#8220; ist bereits so gew\u00e4hlt, dass die Verantwortlichkeit der Klasse klar ist. Eine Kombination aus Substantiv und Verb schafft hierbei oft Klarheit. Es gibt nur eine einzige Methode mit dem Namen &#8222;<em>Process<\/em>&#8222;, welche alle zur Verarbeitung erforderlichen Parameter erh\u00e4lt, jedoch keinen Wert zur\u00fcckgibt. Stattdessen wird f\u00fcr die R\u00fcckgabe des Ergebnisses ein Event mit dem Namen &#8222;<em>Progress<\/em>&#8220; verwendet, da hier im Beispiel typisiert ist und einen &#8222;<em>string<\/em>&#8220; zur\u00fcckgibt. Die Action stellt hier einen Delegaten dar &#8211; einen Funktionszeiger. D.h. hier kann eine Funktion, die einen Parameter vom Typ &#8222;<em>string<\/em>&#8220; erh\u00e4lt, &#8222;verbunden&#8220; werden.<\/p>\n<p>Weitere \u00f6ffentliche Methoden gibt es bei Anwendung des Flow-Patterns nicht, womit es bereits schwieriger wird, der Klasse verschiedene Verantwortlichkeiten zu \u00fcbertragen.<\/p>\n<p>Die Idee f\u00fcr das Beispiel ist, dass ein bestimmtes Zeichen aus einem angegebenen Text extrahiert wird (mag wenig sinvoll erscheinen, ist aber als Beispiel sch\u00f6n einfach ;-)).\u00a0 Meine Erwartungen dr\u00fccke ich als Unit Test aus.<\/p>\n<pre class=\"lang:c# decode:true\">        [TestMethod]\r\n        public void ExtractsCorretCharacters()\r\n        {\r\n            string actual = string.Empty;\r\n            ExtractCharacter sut = new ExtractCharacter();\r\n\r\n            sut.Progress += result =&gt; actual = result;\r\n            sut.Process('e', \"Dies ist der gesamte Text.\");\r\n            actual.Should().Be(\"eeeee\");\r\n        }<\/pre>\n<p>Das zu testende Objekt (subject unter test &#8211; &#8222;sut&#8220;) der Klasse &#8222;ExtractCharacter&#8220; wird erstellt. Dann wird das R\u00fcckgabe-Event &#8222;Progress&#8220; aboniert und per Lambda-Ausdruck wird das Ergebnis &#8222;result&#8220; der lokalen Variable &#8222;actual&#8220; zugewiesen, um sp\u00e4ter das Ergebnis vergleichen zu k\u00f6nnen. Dann wird die Verarbeitung angesto\u00dfen per &#8222;sut.Process(&#8218;e&#8216;, &#8222;Dies ist der gesamte Text.&#8220;)&#8220; und die Behauptung aufgestelllt, dass das Ergebnis = &#8222;eeeee&#8220; ist.<\/p>\n<p>Dieser Test l\u00e4sst sich nat\u00fcrlich im derzeitigen Zustand der Klasse &#8222;ExtractCharacter&#8220; nicht kompilieren, daher erg\u00e4nze ich die entsprechende Methodensignatur.<\/p>\n<pre class=\"lang:c# decode:true\">    public class ExtractCharacter\r\n    {\r\n        public void Process(char characterToExtract, string textToExtractFrom)\r\n        {            \r\n        }\r\n\r\n        public event Action&lt;string&gt; Progress;\r\n    }<\/pre>\n<p>Damit l\u00e4sst sich der Test zumindest kompilieren. Wie erwartet schl\u00e4gt der Test fehl und l\u00e4uft auf rot. Warum? Unsere Klasse macht ja gerade noch recht wenig. Das wollen wir \u00e4ndern und ich erg\u00e4nze diese Implementierung:<\/p>\n<pre class=\"lang:c# decode:true \">    public class ExtractCharacter\r\n    {\r\n        public void Process(char characterToExtract, string textToExtractFrom)\r\n        {\r\n            StringBuilder resultBuilder = new StringBuilder();\r\n            IEnumerable&lt;char&gt; stringQuery = from c in textToExtractFrom \r\n                         where c == characterToExtract select c;\r\n\r\n            stringQuery.ToList&lt;char&gt;().ForEach(c =&gt; resultBuilder.Append(c));\r\n            this.Progress(resultBuilder.ToString());\r\n        }\r\n\r\n        public event Action&lt;string&gt; Progress;\r\n    }<\/pre>\n<p>Da alle gefundenen Zeichen wieder als String zusammengesetz werden sollen, definiere ich einen &#8222;StringBuilder&#8220;, da dieser deutlich schneller ist, als die Operation &#8222;string += string&#8220;. Die direkte Stringverkn\u00fcpfung erzeugt bei jedem Aufruf ein neues Objekt der Klasse <em>String<\/em> f\u00fcr das Ergebnis und braucht damit mehr Speicher als auch Zeit.<\/p>\n<p>Per LINQ werden jetzt alle Zeichen extrahiert, die im gesetzten Text mit dem gesuchten Zeichen \u00fcbereinstimmen und davon eine Liste erstellt (&#8222;<em>stringQuery<\/em>&#8222;). In Zeile 7 wird per Lambda-Ausdruck jedes Zeichen der Ergebnisliste aus dem verhierigen Schritt an den StringBuilder angehangen. F\u00fcr die Ergebnissr\u00fcckgabe wird abschlie\u00dfend das \u00f6ffentliche Event &#8222;<em>Progress<\/em>&#8220; ausgel\u00f6st und dabei die Verkn\u00fcpfung aller gefundenen Zeichen als &#8222;<em>string<\/em>&#8220; mitgegeben.<\/p>\n<p>Eine erneute Ausf\u00fchrung des Test signalisiert: alles gr\u00fcn und damit ist meine formulierte Erwartung erf\u00fcllt.<\/p>\n<p>Implementieren wir eine weitere Klasse nach dem Flow-Pattern, welche die Anzahl Zeichen in einem Text z\u00e4hlt und die Anzahl als Ergebnis zur\u00fcck gibt. Mein Anforderung definiere ich wie folgt:<\/p>\n<pre class=\"lang:c# decode:true \">        [TestMethod]\r\n        public void CorrectCharacterCount()\r\n        {\r\n            int characterCount = 0;\r\n            CountCharacters sut = new CountCharacters();\r\n            sut.Progress += result =&gt; characterCount = result;\r\n            sut.Process(\"eeeee\");\r\n\r\n            characterCount.Should().Be(5);\r\n        }<\/pre>\n<p>Wie oben erstelle ich die neue Klasse CountCharacters, aboniere das Ergebnis, f\u00fchre die Funktion aus und behaupte, das Ergebnis ist 5 (diesmal nicht 42). Meine schnellste Implementierung, bis der Test gr\u00fcn wird, sieht so aus:<\/p>\n<pre class=\"lang:c# decode:true \">    public class CountCharacters\r\n    {        \r\n        public void Process(string textToCountCharactersIn)\r\n        {\r\n            this.Progress(textToCountCharactersIn.Count&lt;char&gt;());\r\n        }\r\n\r\n        public event Action&lt;int&gt; Progress;\r\n    }<\/pre>\n<p>Jetzt haben wir zwei sehr kleine Klassen erstellt, die jeweils genau ein Verantwortlichkeit haben. Was machen wir jetzt damit? Hier kommt jetzt die Modularit\u00e4t des Flow-Pattern zur Geltung. Wir k\u00f6nnen unsere kleinen Komponenten miteinander verkn\u00fcpfen, sofern wir dabei auf die ein- und ausgehenden Parameter achten. Zur Demonstration erstelle ich einen Intrationstest (klassen\u00fcbergreifend).<\/p>\n<pre class=\"lang:c# decode:true \">        [TestMethod]\r\n        public void ExtractAndCountCharacterInText()\r\n        {\r\n            int actual = 0;\r\n            ExtractCharacter extractCharacter = new ExtractCharacter();\r\n            CountCharacters countCharacters = new CountCharacters();\r\n\r\n            extractCharacter.Progress += countCharacters.Process;\r\n            countCharacters.Progress += result =&gt; actual = result;\r\n\r\n            extractCharacter.Process('e', \"Dies ist der gesamte Text.\");\r\n            actual.Should().Be(5);\r\n        }<\/pre>\n<p>Zun\u00e4chst werden alle erforderlichen Objekte erstellt. Jetzt kommt die Verkn\u00fcpfung unserer kleinen Bausteine: die Methode &#8222;<em>Process<\/em>&#8220; des Objekts &#8222;<em>countCharacters<\/em>&#8220; mit dem Eingangsparameter wird gebunden an das Event &#8222;<em>Progress<\/em>&#8220; des Objekts &#8222;<em>ExtractCharacter<\/em>&#8222;. Das funktioniert deshalb, weil &#8222;ExtractCharacter&#8220; einen Wert vom Typ &#8222;<em>string<\/em>&#8220; zur\u00fcckgibt.\u00a0 In Zeile 9 wird wieder das Ergebnis der lokalen Variable &#8222;actual&#8220; zugewiesen, damit dieses sp\u00e4ter verglichen werden kann.<\/p>\n<p><strong>Wenn wir nun in Zeile 11 die Methode &#8222;<em>Process<\/em>&#8220; des Objekts &#8222;<em>extractCharacter<\/em>&#8220; aufrufen, wird dort das Ergebnis (die extrahierten &#8218;e&#8217;s) direkt an &#8222;<em>Process<\/em>&#8220; von &#8222;<em>countCharacters<\/em>&#8220; \u00fcbergeben.<\/strong><\/p>\n<p>Wenn ich nun per Flow-Pattern einen ganzen Baukasten von kleinen Funktionseinheiten mit definierten Ein- und Ausgangsparameter erstelle, kann ich diese &#8211; je nach Anforderung &#8211; flexibel miteinander verbinden. Das ist angewandtes Single Responsibilit\u00e4t Principle und damit echte Wiederverwendbarkeit.<\/p>\n<p>Eine konfigurative Unterst\u00fctzung beim Verketten von Einheiten bietet eine Flow-Engine wie z.B. von Ralf Westphal. Weitere Informationen und die Engine findet ihr unter <a title=\"http:\/\/blog.ralfw.de\/2013\/01\/beispielhafte-nichtbeachtung.html\" href=\"http:\/\/blog.ralfw.de\/2013\/01\/beispielhafte-nichtbeachtung.html\">http:\/\/blog.ralfw.de\/2013\/01\/beispielhafte-nichtbeachtung.html<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h2>Zusammenfassung<\/h2>\n<p>In diesem Artikel haben wir uns angeschaut, das das Flow-Pattern ist und wie es dabei unters\u00fctzten kann, Software modular zu gestalten und das SRP ganz leicht anzuwenden. Wie das zum Thema &#8222;Objektorientierung wie sie gemeint war&#8220; passt, k\u00f6nnt ihr unter <a title=\"http:\/\/geekswithblogs.net\/theArchitectsNapkin\/archive\/2013\/09\/08\/oop-as-if-you-meant-it.aspx\" href=\"http:\/\/geekswithblogs.net\/theArchitectsNapkin\/archive\/2013\/09\/08\/oop-as-if-you-meant-it.aspx\">http:\/\/geekswithblogs.net\/theArchitectsNapkin\/archive\/2013\/09\/08\/oop-as-if-you-meant-it.aspx<\/a> nachlesen.<\/p>\n<p>&nbsp;<\/p>\n<p>Viel Spa\u00df beim Ausprobieren und Happy Coding w\u00fcnschen<\/p>\n<p>eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p><em>Verwendete Werkzeuge:<\/em><\/p>\n<ul>\n<li>Visual Studio 2013 Community (<a title=\"https:\/\/www.visualstudio.com\/en-us\/products\/visual-studio-community-vs.aspx\" href=\"https:\/\/www.visualstudio.com\/en-us\/products\/visual-studio-community-vs.aspx\" target=\"_blank\">https:\/\/www.visualstudio.com\/en-us\/products\/visual-studio-community-vs.aspx<\/a>)<\/li>\n<li>Microsoft UnitTesting (<a title=\"https:\/\/msdn.microsoft.com\/de-de\/library\/hh694602.aspx\" href=\"https:\/\/msdn.microsoft.com\/de-de\/library\/hh694602.aspx\" target=\"_blank\">https:\/\/msdn.microsoft.com\/de-de\/library\/hh694602.aspx<\/a>)<\/li>\n<li>Fluent Assertions (<a title=\"https:\/\/github.com\/dennisdoomen\/fluentassertions\" href=\"https:\/\/github.com\/dennisdoomen\/fluentassertions\" target=\"_blank\">https:\/\/github.com\/dennisdoomen\/fluentassertions<\/a>)<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder. Wer kennt noch das EVA-Prinzip? Eingabe-Verarbeitung-Ausgabe. Das war eines der ersten Themen im Informatikunterricht. Demnach also kein neuen Prinzip, was deshalb aber nicht weniger interessant ist. Insbesondere, wenn ich an das Single Resposibility Principle (SRP) denke, l\u00e4sst sich dies gut vereinbaren. Dazu hat sich insbesondere in der .Net Welt das Flow-Pattern etabliert, welches [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":214,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[15,14,17,16,13],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/191"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=191"}],"version-history":[{"count":25,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/191\/revisions"}],"predecessor-version":[{"id":219,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/191\/revisions\/219"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/214"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}