<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
  <title>Codelution Blog</title>
  <subtitle>Wissenstransfer. Der digitale Raum ist unser Zuhause.</subtitle>
  <link href="https://codelution.de/de/blog/feed.xml" rel="self" />
  <link href="https://codelution.de/" />
  <updated>2026-09-01T00:00:00Z</updated>
  <id>https://codelution.de/</id>
  <author>
    <name>Codelution GmbH</name>
    <email>info@codelution.de</email>
  </author>
  <entry>
    <title>Die 6 Säulen erfolgreicher Softwareprojekte</title>
    <link href="https://codelution.de/de/blog/post/erfolgreiche-softwareentwicklung/" />
    <updated>2021-05-13T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/erfolgreiche-softwareentwicklung/</id>
    <content type="html">&lt;p&gt;Bei Softwareprojekten gibt es eine Reihe wiederkehrender Faktoren, die den Unterschied zwischen einem erfolgreichen Abschluss und einem Fass ohne Boden machen. Besonders bei den inzwischen oft eingesetzten agilen Vorgehensmodellen gibt es eine Reihe von Aspekten und Zusammenhängen, die es unbedingt zu beachten gilt.&lt;/p&gt;
&lt;p&gt;Bei Softwareprojekten gibt es eine Reihe wiederkehrender Faktoren, die den Unterschied zwischen einem erfolgreichen Abschluss und einem Fass ohne Boden machen. Besonders bei den inzwischen oft eingesetzten agilen Vorgehensmodellen gibt es eine Reihe von Aspekten und Zusammenhängen, die es unbedingt zu beachten gilt.&lt;/p&gt;
&lt;p&gt;In der Softwareentwicklung kommen die verschiedensten Vorgehensmodelle zum Einsatz. Dabei kann ganz grob zwischen klassischen Modellen (wie z.B. dem Wasserfallmodell) oder iterativen Modellen (z.B. Scrum) unterschieden werden. Egal welches Modell eingesetzt wird, es kommen immer wieder die gleichen Projektphasen zum Einsatz. Die Vorgehensmodelle unterscheiden sich primär in der Reihenfolge und der Art und Weise wie sie durchlaufen werden.&lt;/p&gt;
&lt;h2 id=&quot;die-projektphasen&quot;&gt;Die Projektphasen&lt;/h2&gt;
&lt;p&gt;In klassischen Modellen, werden die Projektphasen der Reihe nach abgearbeitet. Bei iterativen Modellen wiederholen sich bestimmte Projektphasen, um besser auf sich ändernde oder unklare Anforderungen eingehen zu können.&lt;/p&gt;
&lt;p&gt;Die Projektphasen sind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Planungsphase (u.a. Anforderungsanalyse)&lt;/li&gt;
&lt;li&gt;Definitionsphase (Entwurf)&lt;/li&gt;
&lt;li&gt;Implementierungsphase (Umsetzung)&lt;/li&gt;
&lt;li&gt;Test&lt;/li&gt;
&lt;li&gt;Inbetriebnahme (auch Veröffentlichung)&lt;/li&gt;
&lt;li&gt;Instandhaltung&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/erfolgreiche-softwareentwicklung/ea7c5e52-124d-4213-a1c9-7a26a25a1e29_Projektphasen.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;auf-fehlersuche&quot;&gt;Auf Fehlersuche&lt;/h2&gt;
&lt;p&gt;Wenn Probleme im Softwareprojekt auftauchen, sollte die erste Frage immer sein: woher, aus welcher Phase, kommen die Probleme? In der Praxis offenbart sich bei der Suche nach der Ursache dann oft, dass mehrere Phasen nicht richtig durchgeführt wurden bzw. der gesamte Entwicklungsprozess an sich große Mängel aufweist.&lt;/p&gt;
&lt;p&gt;Ein typischer, und sehr schnell fataler, Fehler liegt in der ungenügenden Durchführung der Entwurfsphase. Gerade wenn ein erfahrener Softwarearchitekt fehlt, neigen Teams zu sogenannten Brain-To-Code. Dabei wird die Konzeptphase mehr oder weniger übersprungen und es wird direkt &amp;quot;gehackt&amp;quot;. Es wird schnell Programmcode geschrieben und zunächst auch &amp;quot;Working Software&amp;quot; erzeugt. Aufgrund des fehlenden Softwaredesigns ergeben sich jedoch mittelfristig unerwünschte Abhängigkeiten im Programm und es treten Fehler auf. Durch diese Abhängigkeiten führen Bugfixes an der einen Stelle dann unbewusst zu Beschädigungen an anderer Stelle. Die Produktivität sinkt. Die typischen Symptome zeigen sich dann in der Regel nach einem Invest von 9-18 &amp;quot;Entwickler Mannmonaten&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Agil bedeutet nicht ungeplant.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Bei iterativen Vorgehensmodellen wird zumeist versucht &amp;quot;agil&amp;quot; zu sein.&lt;/p&gt;
&lt;p&gt;Agil bedeutet in diesem Zusammenhang, dass man &amp;quot;flink&amp;quot; auf geänderte Anforderungen reagieren kann. Anstatt zu Projektbeginn eine umfassend detaillierte Planung durchzuführen, werden die oben genannten Phasen für jedes Feature immer wieder erneut durchlaufen.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In agilen Prozessen muss daher beispielsweise die Planungsphase als fester Termin im Sprint eingeplant sein - das ist bei Ihnen sicherlich der Fall, oder?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Wir wollen ja nicht nach Brain-To-Code arbeiten sondern unsere Software ingenieursmäßig konzipieren.&lt;/p&gt;
&lt;h2 id=&quot;beispiel-scrum&quot;&gt;Beispiel Scrum&lt;/h2&gt;
&lt;p&gt;Das verbreiteste agile Vorgehensmodell im Bereich der Softwareentwicklung ist sicherlich Scrum. Wo finden wir die o.g. Phasen in Scrum? Und was sollte man dabei beachten?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Anforderungsanalyse - für mehrere Sprints im Voraus&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Die Anforderungsanalyse sollte vor jedem Sprint stattgefunden haben. In größeren Projekten kann damit sogar ein eigenes Team beauftragt werden. Es sollte sichergestellt werden, dass die Anforderungen für mehrere Sprints im Voraus definiert werden. So stabil sollten die Anforderungen schon sein. Sonst laufen Sie Gefahr, immer wieder Funktionalitäten aufgrund neuer Erkenntnisse ändern zu müssen. Die Anforderungen fließen dann in Form von User Stories ins Backlog ein.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Planungsphase - Verbindliche Termine&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Die Planungsphase muss vor Umsetzungsbeginn und damit direkt am Anfang des Sprints stattfinden. Verbindliche Termine schaffen Struktur und sorgen für eine nachhaltige Produktqualität. Das Softwaredesign sollte vom Team gemeinsam entwickelt werden - auch wenn die Umsetzung danach durch einzelne Entwickler stattfindet. Dadurch verteilen Sie das Wissen im Team und holen auch schwächere Teammitglieder ab.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Umsetzung - neueste Technik verwenden&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Der Großteil des Sprints konzentriert sich auf die Umsetzung. Die Umsetzung sollte nach neuestem Stand der Wissenschaft und Technik erfolgen. Zu diesem Punkt gehört nicht nur die Entwicklung von Funktionalitäten, sondern auch von UI-Entwürfen oder Erweiterungen für Dev-Ops.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Tests - Keep it going&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tests können und sollten fortlaufend durchgeführt werden. Verwenden Sie verschiedene Testverfahren. Unit-Tests, UI-Tests, Integrationstests, ... Vor der Sprint-Demo mit den Stakeholdern sollte das Team alle umgesetzten Funktionalitäten noch einmal gemeinsam durchtesten.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Inbetriebnahme - Demo mit den Stakeholdern&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Natürlich gibt es auch dedizierte Inbetriebnahmen. Dennoch sollten Sie auch während der Sprints immer eine Inbetriebnahme durchführen: und zwar vor der Demo. Deployen Sie Ihre Anwendung beispielsweise auf einen speziell dafür eingerichteten Demo-Server - dieser sollte den Stakeholdern auch nach der Demo zur Verfügung gestellt werden. Wir sagen deswegen: auch die Inbetriebnahme findet sich bei Scrum - in Form der Demo mit den Stakeholdern.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Instandhaltung - Retrospektive für fortlaufende Verbesserung&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nach Abschluss eines (agilen) Projekts können sich Instandhaltungs- oder Betreuungsaufgaben ergeben. Diese lassen sich auch gut mittels KANBAN managen. Ansonsten nutzen Sie bei Scrum die Retrospektive, um Ihren Entwicklungsprozess &amp;quot;in Stand zu halten&amp;quot; und fortlaufend zu verbessern.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sie haben weiterführende Fragen oder stehen vor Herausforderungen in Ihrem eigenen Entwicklungsprozess? Sprechen Sie uns gerne an. Wir freuen uns über Ihre Nachricht.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Vorsicht wenn Entwickler den Begriff Refactoring verwenden</title>
    <link href="https://codelution.de/de/blog/post/vorsicht-wenn-entwickler-den-begriff-refactoring-verwenden/" />
    <updated>2021-05-22T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/vorsicht-wenn-entwickler-den-begriff-refactoring-verwenden/</id>
    <content type="html">&lt;p&gt;Kennen Sie das, Sie besprechen neue Anforderungen und dann sagt ein Entwickler: „das müssen wir refactorn‘“? Was genau ist Refactoring und warum sollten alle stutzig werden wenn dieser Begriff fällt?&lt;/p&gt;
&lt;p&gt;Refactoring ist ein bekannter Begriff in der Softwareentwicklung und wurde vor Martin Fowler in dessen Buch „Refactoring – Improving the Design of existing Code“ geprägt. Wie der Titel impliziert, zielt Refactoring darauf ab, die Struktur und das Design von Programmcode zu verbessern, ohne dabei die Funktionalität des Codes (also sein externes Verhalten) zu verändern. Refactoring ist quasi eine Art interne Modifizierung.&lt;/p&gt;
&lt;p&gt;Als das Buch erschien, entstand zu Recht ein großer Hype, da die Ansätze neu und auch gut waren. Fowler beschreibt in seinem Buch verschiedene „Code-Smells“, das sind Merkmale an denen man schlechten Code erkennen kann. Gleichzeitig werden Refactorings vorgeschlagen, also Änderungsschritte, um von schlechtem Code zu besserem, wartbarem Code zu kommen. Das Buch enthält viele „Musterrefactorings“, quasi Rezepte, wie Programmcode ‚einfach‘ von A nach B gewandelt werden kann.&lt;/p&gt;
&lt;h2 id=&quot;erst-kommt-der-fehler-dann-das-refactoring&quot;&gt;Erst kommt der Fehler, dann das Refactoring&lt;/h2&gt;
&lt;p&gt;Wenn bei Ihnen Refactoring ein Thema ist, wurden im Voraus schon Fehler gemacht. Es liegen Qualitätsprobleme vor und die Erweiterungsfähigkeit der Software muss erst wiederhergestellt werden.&lt;/p&gt;
&lt;p&gt;Kleine Teilaspekte einer Software können leicht &amp;quot;gerefactored&amp;quot; werden. Oft ist es aber so, dass im Rahmen eines &amp;quot;sog. Refactorings&amp;quot; an verschiedensten Stellen Änderungen vorgenommen werden müssen oder sogar die Domänenlogik schlecht oder falsch abgebildet ist. Aus einem mikroskopischen Refactoring ergeben sich mehrere Änderungen an verschiedensten Stellen im Programm. Dabei handelt es sich bereits um ein (partielles) &amp;quot;Redesign&amp;quot;. Wenn dieses dann auch noch das System an anderer Stelle beschädigt können Sie einpacken.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In vielen Unternehmen wird Refactoring stillschweigend akzeptiert.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unser Ansatz ist aber: wir sollten es gleich richtig machen!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Software sollte so umgesetzt werden, dass Refactoring erst gar nicht notwendig ist. Kommt es zu Problemen, hat zu Beginn ein stimmiges Softwaredesign in der Konzeptionsphase gefehlt. Software muss von Beginn an nachhaltig und erweiterbar sein. Ein wohlüberlegtes Softwaredesign ist notwendig und reduziert Folgekosten, die bei Änderungsschritten anfallen, um die Wartbarkeit wieder herzustellen.&lt;/p&gt;
&lt;h2 id=&quot;kein-widerspruch-zu-yagni&quot;&gt;Kein Widerspruch zu YAGNI&lt;/h2&gt;
&lt;p&gt;Ein erweiterbares Softwaredesign gibt es nicht für umsonst. Dennoch verstößt es nicht gegen das Clean Code Prinzip YAGNI (You ain’t gonna need it). YAGNI bezieht sich auf die Umsetzung von unnötigen Funktionalitäten. Die konzeptionellen Arbeiten die für ein sauberes Softwaredesign notwendig sind, sind nie unnötig sondern Voraussetzung für eine nachhaltige Produktentwicklung.&lt;/p&gt;
&lt;h2 id=&quot;ganzheitlicher-clean-code-ansatz-als-loesung&quot;&gt;Ganzheitlicher Clean-Code Ansatz als Lösung&lt;/h2&gt;
&lt;p&gt;Wie erreichen wir nachhaltige, erweiterbare Software? Leider gibt es hier keinen magischen Schalter, nach dessen Betätigung alles reibungslos funktioniert. Angefangen beim Entwicklungsprozess, über die richtigen Technologien, bis hin zu den individuellen Codingskills der Teammitglieder, müssen eine Vielzahl von Aspekten berücksichtigt werden. Die Praktiken aus der Clean-Code Initiative (wie z.B. die &lt;a href=&quot;https://www.informatik-aktuell.de/entwicklung/methoden/solid-die-5-prinzipien-fuer-objektorientiertes-softwaredesign.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SOLID Prinzipien&lt;/a&gt;) dienen als wichtiger Start. Moderne Clean-Code Ansätze betrachten die Softwareentwicklung deswegen immer ganzheitlich und beziehen auch immer angrenzende Aspekte der Entwicklung mit ein.&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Refactoring ist ein häufig verwendeter Begriff ist, den nicht nur Entwickler, sondern auch viele Abteilungsleiter und Personen in Managementfunktionen immer wieder hören werden. Die wichtigste Erkenntnis ist: Wenn Software immer wieder gerefactored werden muss, dann liegen Qualitätsprobleme vor. Massive Folgekosten sind die Konsequenz. Refactoring kann durch ganzheitliche Maßnahmen im Voraus verhindert werden.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>IOSP: das vielleicht unbekannteste Clean Code Prinzip</title>
    <link href="https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/" />
    <updated>2021-06-17T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/</id>
    <content type="html">&lt;p&gt;Viele Clean Code Prinzipien (wie z.B. DRY, KISS, YAGNI) sind weit verbreitet und den meisten Entwicklern bekannt. Diese Prinzipien sind intuitiv und schnell zu verstehen. Überraschenderweise ist eines der mächtigsten und wirkungsvollsten Clean Code Prinzipien aber relativ unbekannt. Es handelt sich um das IOSP. Das sogenannte Integration Operation Segregation Principle. Dieses Prinzip wird die Art und Weise wie Sie Software entwerfen entscheidend verändern.&lt;/p&gt;
&lt;h2 id=&quot;herausforderung&quot;&gt;Herausforderung&lt;/h2&gt;
&lt;p&gt;Verständlicher und leicht zu wartender Quellcode ist der Traum eines jeden Softwareentwicklers. Zu Beginn der Umsetzung ist das auch meist der Fall. Unser Programmcode ist noch übersichtlich und leicht zu verstehen:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/cc3c954b-4be2-4a72-9760-68ef9ad3b218_code-with-primary-aspects.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mit zunehmender Zeit, mutiert Programmcode jedoch immer weiter zu Spaghetti-Code. Schon nach kurzer Zeit sieht der oben gezeigte Code dann so aus:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/a115be38-11f0-4ae2-9405-cf3c33ce0ed7_code-with-secondary-aspects.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Warum ist das so? Der Grund dafür ist, dass die primäre Intention des Codes, durch (notwendige) Sekundäraspekte verschmutzt wird. Sekundäraspekte sind Aspekte wie Validierung, Logging, Asynchronität, Fehlerbehandlung usw. Kurz gesagt alle Aspekte, die nicht primär der Erfüllung unserer Business-Anforderungen, dienen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/6d4589ba-330a-4fd3-ac69-01d9026289c7_sekundaraspekte-erkl-rt.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Das sogenannte Integration Operation Segregation Principle ist eines der Schlüsselprinzipien mit dessen Hilfe wir zu verständlichem Programmcode zurückkehren können. Dieses Prinzip wird die Art und Weise wie Sie Software entwerfen entscheidend verändern!&lt;/p&gt;
&lt;h2 id=&quot;erklaerung-des-iosp&quot;&gt;Erklärung des IOSP&lt;/h2&gt;
&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;/h3&gt;
&lt;p&gt;Das &lt;strong&gt;I&lt;/strong&gt;ntegration &lt;strong&gt;O&lt;/strong&gt;peration &lt;strong&gt;S&lt;/strong&gt;egregation &lt;strong&gt;P&lt;/strong&gt;rinciple, zielt darauf ab den Programmcode in &lt;strong&gt;I&lt;/strong&gt;ntegrationsslogik (Integration) und &lt;strong&gt;O&lt;/strong&gt;perationslogik (Operation) aufzutrennen (engl. segregate).&lt;/p&gt;
&lt;p&gt;Unter &lt;strong&gt;Operationslogik&lt;/strong&gt; verstehen wir den Teil unserer Geschäftslogik, der das „wie“ im Detail beschreibt. Dabei kommen alle bekannten Kontrollstrukturen (if, else, …), Operatoren oder Datentypen usw. zum Einsatz.&lt;/p&gt;
&lt;p&gt;Die &lt;strong&gt;Integrationslogik&lt;/strong&gt; ist der Teil unserer Anwendung, der keine eigene „Berechnungslogik“ enthält, sondern nur noch Operationslogik (oder andere Integrationslogik) aufruft, also nur aus Funktionsaufrufen besteht.&lt;/p&gt;
&lt;h3 id=&quot;beispiel&quot;&gt;Beispiel&lt;/h3&gt;
&lt;p&gt;Schauen wir uns das IOSP anhand eines einfachen Hello World Beispiels an. Die Besonderheit in unserem Beispiel ist, wir wollen in Abhängigkeit eines Konfigurationsschalters den Text Hello World in Großbuchstaben oder in Kleinbuchstaben ausgeben.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Program&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt;[] &lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; textErzeugen = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; TextErzeugen(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; TextGrossSchreiben(), &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; ConfigService());

        Console.WriteLine(textErzeugen.Erzeugen());

        Console.ReadLine();
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextErzeugen&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ITextErzeugen&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ITextGrossSchreiben _textGrossSchreiben;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; IConfigService _configService;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; Text = &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextErzeugen&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;ITextGrossSchreiben textGrossSchreiben, IConfigService configService&lt;/span&gt;)&lt;/span&gt; 
    {
        _textGrossSchreiben = textGrossSchreiben;
        _configService = configService;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Erzeugen&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (_configService.SollTextGrossGeschriebenWerden)
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; _textGrossSchreiben.GrossSchreiben(Text);

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; Text;
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextGrossSchreiben&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ITextGrossSchreiben&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;GrossSchreiben&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; text&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; text.ToUpper();
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Natürlich könnte dieses einfache Beispiel auch komplette in einer Methode implementiert sein. Für Lernzwecke ist aber bereits eine gewisse Modularisierung vorgesehen. Aktuell gibt es noch keine Unterscheidung zwischen Integrationslogik und Operationslogik. So wird beispielsweise in der Klasse TextErzeugen der Config Service aufgerufen (Integrationslogik). Gleichzeitig liegt durch das if Statement aber auch Operationslogik vor. Ähnlich verhält es sich mit der Main Methode. Der Aufruf von textErzeugen.Erzeugen() ist Integrationslogik. Das Ausgeben auf der Konsole ist hingegen Operationslogik.&lt;/p&gt;
&lt;p&gt;Wir gehen einen Schritt weiter und werfen einen Blick auf die Unit-Tests der Klasse TextErzeugen:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;[&lt;span class=&quot;hljs-meta&quot;&gt;TestClass&lt;/span&gt;]
&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextErzeugenTests&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; ITextErzeugen _target;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; IConfigService _configService;

    [&lt;span class=&quot;hljs-meta&quot;&gt;TestInitialize&lt;/span&gt;]
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;SetUp&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; textGrossSchreiben = MockRepository.GenerateStub&amp;lt;ITextGrossSchreiben&amp;gt;();
        _configService = MockRepository.GenerateStub&amp;lt;IConfigService&amp;gt;();

        textGrossSchreiben.Stub(x =&amp;gt; x.GrossSchreiben(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;)).IgnoreArguments().Return(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;HELLO WORLD&amp;quot;&lt;/span&gt;);

        _target = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; TextErzeugen(textGrossSchreiben, _configService);
    }

    [&lt;span class=&quot;hljs-meta&quot;&gt;TestMethod&lt;/span&gt;]
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; Erzeugen_GrossSchreibenAktiviert_ErzeugtHelloWorldTextGroß()
    {
        _configService.Stub(c =&amp;gt; c.SollTextGrossGeschriebenWerden).Return(&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;);

        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; result = _target.Erzeugen();

        Assert.AreEqual(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;HELLO WORLD&amp;quot;&lt;/span&gt;, result);
    }

    [&lt;span class=&quot;hljs-meta&quot;&gt;TestMethod&lt;/span&gt;]
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Erzeugen_GrossSchreibenDeaktiviert_ErzeugtHelloWorldTextKlein&lt;/span&gt;()&lt;/span&gt;
    {
        _configService.Stub(c =&amp;gt; c.SollTextGrossGeschriebenWerden).Return(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);

        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; result = _target.Erzeugen();

        Assert.AreEqual(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;, result);
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In den Unit-Tests, wird (in Abhängigkeit des Konfigurationsschalters) geprüft, ob der Text groß oder klein geschrieben werden soll. Bedenken Sie aber, dass wir eigentlich das &lt;strong&gt;Erzeugen&lt;/strong&gt; von Text testen möchten. Stattdessen testen wir, dass die Funktion das Ergebnis liefert, welches wir im Stub selbst vorgegeben haben – was wird hier also überhaupt getestet? Es handelt sich schon gar nicht mehr um einen einfachen Unit-Test, sondern vielmehr um einen Integrationstest. Die Abhängigkeiten unserer zu testenden Klasse sind ein Problem. Mit weiteren Abhängigkeiten wird der Test noch komplexer. Endlose Mocking und Stubbing Orgien sind die Konsequenz. Wenn wir die Topologie unseres Programms bzw. dessen Programmteile betrachten, fällt schnell auf, dass Integrationslogik und Operationslogik vermischt sind:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/33a3c38b-b408-49eb-9ed4-5ca33e8588ee_IOSP---wrong.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;loesung&quot;&gt;Lösung&lt;/h2&gt;
&lt;p&gt;Die Lösung unserer o.g. Probleme liegt in der konsequenten Anwendung des IOSP. Wir trennen strikt zwischen Integrationslogik und Operationslogik und erhalten folgende Programmtopologie:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/iosp-das-vielleicht-unbekannteste-clean-code-prinzip/5e89035a-aadb-4e25-820e-446224859de8_IOSP---correct.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Es ist deutlich zu sehen, dass sich die Operationslogik (das „WIE“) immer in den Blättern des „Programmtopologiebaumes“ befindet. Diese Operationslogik ist durch Anwendung des IOSP nun sehr klar und erfüllt ausschließlich den im Namen der Klasse / Funktion definierten Zweck:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextErzeugen&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ITextErzeugen&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Erzeugen&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Hallo Welt!&amp;quot;&lt;/span&gt;;
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ConfigService&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;IConfigService&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;SollTextGrossGeschriebenWerden&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;TextGrossSchreiben&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ITextGrossSchreiben&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;GrossSchreiben&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; text, &lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; grossSchreiben&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; grossSchreiben ? text.ToUpper() : text;
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Da die Abhängigkeiten verschwunden sind, lassen sich die „Operationsfunktionen“ auch ganz einfach Unit-Testen.&lt;/p&gt;
&lt;p&gt;Die Klarheit der Funktionen mit Operationen hat im Vergleich zum letzten Beispiel deutlich zugenommen. Das trifft auch auf die Klassen mit reiner Integrationslogik zu, wie z.B. der HelloWorld Klasse:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;HelloWorld&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;IHelloWorld&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ITextErzeugen _textErzeugen;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; IConfigService _configService;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ITextGrossSchreiben _textGrossSchreiben;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ITextAusgeben _textAusgeben;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;HelloWorld&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;
        ITextErzeugen textErzeugen,
        IConfigService configService,
        ITextGrossSchreiben textGrossSchreiben,
        ITextAusgeben textAusgeben&lt;/span&gt;)&lt;/span&gt;
    {
        _textErzeugen = textErzeugen;
        _configService = configService;
        _textGrossSchreiben = textGrossSchreiben;
        _textAusgeben = textAusgeben;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;SayHello&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; text = _textErzeugen.Erzeugen();
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; grossSchreiben = _configService.SollTextGrossGeschriebenWerden();
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; grosserText = _textGrossSchreiben.GrossSchreiben(text, grossSchreiben);

        _textAusgeben.Ausgeben(großerText);
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vergleichen Sie jetzt noch einmal die erste Version des vermeintlich einfachen HelloWorld Beispiels mit dieser optimierten Version! Wunderschön. Das Programm – besonders die SayHello Methode – ist deutlich einfacher und verständlicher. Sie besteht aus reinen Funktionsaufrufen. Wir können diese Funktion von oben nach unten „lesen“ und verstehen, ohne Code zu „interpretieren“.&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Das IOSP trennt die &lt;strong&gt;Intention&lt;/strong&gt; (WAS wollen wir tun) von der tatsächlichen &lt;strong&gt;Ausführung&lt;/strong&gt; (WIE wollen wir es tun). Das führt zu lesbarem und verständlichem Programmcode. Das IOSP ist eines der Schlüsselprinzipien um Spaghetti-Code zu vermeiden. Und ja, auch Sie können das! Das IOSP bietet noch viel mehr Vorteile, die den Rahmen des Blogartikels sprengen würden.&lt;/p&gt;
&lt;p&gt;Unser Beispiel war einfach, dennoch können Sie das IOSP in jedem Programm und auf eine Vielzahl von Problemen anwenden! Die Umsetzung erfordert allerdings Übung. Beim Design von Software gibt Vorgehensmuster, um IOSP-kompatiblen Code zu erhalten. Sie sollten sich dabei von einem erfahrenen Coach begleiten lassen.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Wie funktioniert die Zusammenarbeit mit einem Softwaredienstleister?</title>
    <link href="https://codelution.de/de/blog/post/wie-funktioniert-die-zusammenarbeit-mit-einem-softwaredienstleister/" />
    <updated>2021-07-15T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/wie-funktioniert-die-zusammenarbeit-mit-einem-softwaredienstleister/</id>
    <content type="html">&lt;p&gt;Sie ziehen die Zusammenarbeit mit einem Softwaredienstleister in Betracht oder haben sich bereits dafür entschieden? Im folgenden Artikel erklären wir, wie die Zusammenarbeit mit einem SW-Dienstleister prinzipiell abläuft, worauf Sie achten sollten und wie Sie auch bei vielen parallel laufenden Projekten den Überblick behalten.&lt;/p&gt;
&lt;p&gt;Sie ziehen die Zusammenarbeit mit einer Softwareagentur in Betracht oder haben sich bereits dafür entschieden? Im diesem Artikel erklären wir, wie die Zusammenarbeit mit einem SW-Dienstleister prinzipiell abläuft, worauf Sie achten sollten und wie Sie auch bei vielen parallel laufenden Projekten den Überblick behalten.&lt;/p&gt;
&lt;h2 id=&quot;kennenlernen&quot;&gt;Kennenlernen&lt;/h2&gt;
&lt;p&gt;Aller guter Anfang startet mit einem unverbindlichen Erstkontakt. Möglicherweise hatten Sie in der Vergangenheit bereits Kontakt mit einem Dienstleister?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unser Tipp ist: ziehen Sie auf jeden Fall auch kleinere Partner (&amp;lt; 10 Mitarbeiter) in Betracht. Von diesen erhalten Sie oftmals bessere Services als von großen Agenturen, bei denen Sie nach Schema F behandelt werden.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Im optimalen Fall arbeiten Sie sogar mit mehr als nur einem Dienstleister zusammen. Wie auch beim Aktien Portfolio oder bei der Verteilung von Know-How auf ihre internen Mitarbeiter ist Diversifizierung langfristig unerlässlich.&lt;/p&gt;
&lt;h2 id=&quot;beratungsgespraech&quot;&gt;Beratungsgespräch&lt;/h2&gt;
&lt;p&gt;Nach dem ersten positiven Eindruck findet im zweiten Schritt ein Vorgespräch statt. Hier tauschen Sie sich über den genauen Bedarf an Unterstützung aus. Zudem wird beraten, welches das passende Projektmodell für eine mögliche Zusammenarbeit ist. Unterschieden wird zwischen dem klassischen Werkvertrag mit Fixpreis, und Dienstleistungsverträgen auf Stundensatzbasis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Werkverträge kommen in Frage, wenn das zu liefernde Werkstück (die Software) klar definiert werden kann und Sie aus Planungsgründen einen fixen Preis bevorzugen.&lt;/li&gt;
&lt;li&gt;Dienstleistungsverträge kommen in Frage, wenn die Anforderungen nicht ganz klar sind, oder Sie auch nach Beauftragung das Projekt beeinflussen bzw. steuern möchten.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dienstleistungs- oder Werkverträge treffen keine Auskunft darüber, wo die Leistung erbracht wird. Allerdings ist es bei Dienstleistungsverträgen etwas üblicher, dass die Leistungserbringung direkt in Ihrem Unternehmen stattfindet (z.B: Beraterverträge, flexible Projekt-Unterstützung für Ihr Team usw.). Es sind aber auch Mischformen denkbar.&lt;/p&gt;
&lt;p&gt;Der Dienstleister muss zu diesem Zeitpunkt schon eine kleine Bedarfsanalyse durchführen. Möglicherweise werden bereits zu diesem Zeitpunkt Betriebsgeheimnisse ausgetauscht.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unser Tipp: Ein seriöser Dienstleister sollte Sie bereits zu diesem Zeitpunkt auf den Abschluss einer Geheimhaltungserklärung hinweisen.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;anforderungsermittlung&quot;&gt;Anforderungsermittlung&lt;/h2&gt;
&lt;p&gt;Im nächsten Schritt werden die Projektanforderungen konkret bestimmt. Bei Werkverträgen werden alle umzusetzenden Funktionalitäten definiert. Auch bei agilen Projekten, die meist mittels Dienstleistungsverträgen durchgeführt werden, muss Konsens über die Produktvision und die Grundmenge an Anforderungen geschaffen werden. &amp;quot;Agil&amp;quot; bedeutet nicht ungeplant, sondern dass Sie während des Projekts flexibel die Anforderungen ändern können.&lt;/p&gt;
&lt;p&gt;Der Dienstleister sollte von sich aus eine Übersicht über die benötigten Skills und Tätigkeiten erstellen. Je nach Aufwand, muss die Anforderungsermittlung extra vergütet werden. Dafür sollten Sie dann auch ein Ergebnis erhalten, das Sie auch an andere Dienstleister (zur Erstellung von  Alternativangeboten) verwenden können, zum Beispiel in Form eines Lasten- bzw. Pflichtenhefts, Visionsdokuments, o.ä..&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unser Tipp: Wenn die Anforderungsermittlung bepreist wird, können Sie das Ergebnis zur Angebotserstellung durch alternative Dienstleister verwenden.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;angebot&quot;&gt;Angebot&lt;/h2&gt;
&lt;p&gt;Die Ergebnisse der Anforderungsermittlung münden dann in einem qualifizierten Angebot. Je nach Umfang der Anforderungen und Projektmodell sollte das Angebot auch Spezifikationen umfassen, z.B. in Form eines Pflichtenhefts. Achten Sie beim Angebot auf:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WAS:&lt;/strong&gt; Welches &amp;quot;Werkstück&amp;quot; liefert Ihr Partner genau, welche Dienstleistungen erbringt er im Detail?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WANN&lt;/strong&gt; werden welche Ergebnisse bzw. Dienstleistungen geliefert?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WIE:&lt;/strong&gt; In welcher Form erfolgt die Übergabe von Programmcode, UI-Entwürfen und Dokumentation? Gibt es Adobe XD Klickprototypen für UI-Entwürfe? Folgt die Dokumentation einem branchenüblichen Standard, wie z.B. Arc42?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WO&lt;/strong&gt; erfolgt die Erbringung der Leistung?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WIE LANGE&lt;/strong&gt; ist das Angebot gültig? Wie lange &amp;quot;reserviert&amp;quot; der Anbieter seine Ressourcen?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ABNAHME:&lt;/strong&gt; welches Mitspracherecht haben Sie bei der Abnahme der beauftragten Leistungen und aufgrund welcher Kriterien erfolgt die Abnahme? Natürlich wünschen Sie sich viel Kontrolle bei der Abnahme. Bedenken Sie aber: Abnahmeprozesse sind auch für Ihr Unternehmen aufwändig. Für formale Abnahmen sollte eine Frist definiert werden (z.B. zwei Wochen), nach deren Ablauf die gelieferten Leistungen automatisch als abgenommen gelten.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ZAHLUNG:&lt;/strong&gt; Bei Werkverträgen sind Anzahlungen, Abschlagszahlungen und eine Schlusszahlung üblich. Es muss ersichtlich sein, was Sie in welcher Form für welche Zahlung erhalten.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Für externe Ressourcen (Dienstleister) gilt das selbe wie für interne Ressourcen (Ihre Mitarbeiter). Sie müssen sicherstellen, dass Ihr Business auch nach Ausfall einer Ressource funktionsfähig bleibt. Gerade für größere Projekte gilt deswegen:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unser Tipp: ein professioneller Dienstleister wird nicht versuchen sich unentbehrlich zu machen, sondern seinen Wert durch das Anbieten einer Übergabephase und Integrationsphase zu beweisen.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;beauftragung&quot;&gt;Beauftragung&lt;/h2&gt;
&lt;p&gt;Nach eingehender Prüfung des Angebots erfolgt dann die Beauftragung des Dienstleisters und die Zusammenarbeit kann beginnen.&lt;/p&gt;
&lt;h2 id=&quot;reporting&quot;&gt;Reporting&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Unser Tipp: Um den Überblick über extern beauftragte Projekte zu behalten ist ein leistungsfähiges Reporting&lt;/em&gt; &lt;strong&gt;&lt;em&gt;unerlässlich&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. Das Reporting sollte alle relevanten Informationen enthalten und einfach zu verstehen sein.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Bei Codelution verwenden wir ein Online-Kundenportal und kommunizieren regelmäßig die folgenden Informationen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Was genau wurde beauftragt?&lt;/strong&gt; In unserem Kundenportal legen wir alle Beauftragungen und Verträge ab. In der Projektübersicht können unsere Kunden alle Verträge und Unterpositionen samt Status einsehen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/wie-funktioniert-die-zusammenarbeit-mit-einem-softwaredienstleister/20fed5bd-9d3c-43af-a3ad-c9a957c2ba0e_Projekt-bersicht.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wie laufen die Beauftragungen?&lt;/strong&gt; Neben regelmäßigen Gesprächen setzen wir auf monatliche Projektberichte in Form von verbindlichen schriftlichen Dokumenten. In diesen kommunizieren wir den Projektstatus. Kurz. Aussagekräftig. Ohne technische Details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wann enden die Projekte?&lt;/strong&gt; Ein Gantt-Chart eignet sich optimal, um bei einer Vielzahl von Projekten den Überblick zu behalten (oft gibt es auch noch Abhängigkeiten zwischen den Projekten). Auch bei agilen Projekten, hilft ein Releaseplan in Form eines Ganttdiagramms ungemein.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/wie-funktioniert-die-zusammenarbeit-mit-einem-softwaredienstleister/64baa67a-2504-461f-aa8a-2c87563eff2a_Projektplan.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Ein erfolgreiches Projekt startet mit einer professionellen Projektanbahnung, bei der bestimmt wird, ob eine Zusammenarbeit für beide Seiten Sinn ergibt, eine klare Bestimmung des Status-Quo und einer möglichst exakten Festlegung des Zieles und der zu erbringenden Leistungen. Auch bei agilen Projekten sollte eine Grundmenge der anfänglichen Anforderungen klar sein. Während der Zusammenarbeit stellt ein professionelles Reporting sicher, dass Sie immer den Überblick behalten und maximale Transparenz geschaffen wird. Wenn dies alles gewährleistet wird, dann haben Sie die besten Voraussetzungen dafür, dass Ihr Projekt zu einem vollen Erfolg wird.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Test Driven Development: Wahrscheinlich machen Sie&#39;s falsch</title>
    <link href="https://codelution.de/de/blog/post/test-driven-development-wahrscheinlich-machen-sies/" />
    <updated>2021-10-17T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/test-driven-development-wahrscheinlich-machen-sies/</id>
    <content type="html">&lt;p&gt;Test Driven Development (TDD) ist eine Methodik bei der Entwicklung von (Unit-) Tests. Dieser Artikel diskutiert die Vor- und Nachteile der testgetriebenen Entwicklung und wann TDD zum Irrweg wird.&lt;/p&gt;
&lt;p&gt;TDD ist eine aus XP (eXtreme Programming) bekannte Methodik, bei der die Unittests vor der eigentlichen Implementierung kodiert werden. Basierend auf den Anforderungen an das Programm werden in kurzen Iterationen Tests und erst nach einem Test die entsprechende Lösung entwickelt. Da es bei bzw. direkt nach der Entwicklung des Tests noch keine Implementierung gibt, gegen die der Test ausgeführt werden kann, schlägt jeder Test zunächst fehl. Man sagt auch, der Test ist rot. Im nächsten Schritt wird die Implementierung für den Test geschrieben. Der Test wird dadurch grün. Danach kann die Implementierung refaktoriert werden (blau). Der TDD Zyklus ist also:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/test-driven-development-wahrscheinlich-machen-sies/e2f1dd7b-0f63-4321-bec2-306ad5c9f94b_TDD-Zyklus---Red-Green-Refactor.JPG&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Oder auch:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/test-driven-development-wahrscheinlich-machen-sies/77cb4a69-a847-4850-b455-457af61c4006_TDD-Zyklus---fail-work-better.JPG&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;vorteile&quot;&gt;Vorteile&lt;/h2&gt;
&lt;p&gt;Die testgetriebene Entwicklung kann Vorteile bringen. Dazu werfen wir einen Blick auf die einzelnen Schritte im TDD Zyklus:&lt;/p&gt;
&lt;h3 id=&quot;write-test-code&quot;&gt;Write Test Code&lt;/h3&gt;
&lt;p&gt;Das Schreiben von Testcode vor der eigentlichen Implementierung mag zunächst komisch anmuten. Es bringt jedoch den Vorteil, dass die Testabdeckung des Produktivcodes erhöht ist. Produktivcode wird nur aus dem Zweck heraus geschrieben den Testcode zu &amp;quot;erfüllen&amp;quot;.&lt;/p&gt;
&lt;h3 id=&quot;write-functional-code&quot;&gt;Write Functional Code&lt;/h3&gt;
&lt;p&gt;Die vorab geschriebenen Tests definieren die Anforderungen an unser Programm. Tests werden also direkt aus den Anforderungen abgeleitet. Dadurch, dass es bereits einen Test gibt, und unsere Implementierung gegen den Test geschrieben wird, stellt TDD sicher, dass die Anforderungen erfüllt sind. Der Test ist zudem eine Dokumentation für den danach geschriebenen Code. Allerdings gilt dieser Punkt auch für Unittests die nicht mittels &amp;quot;Test first&amp;quot; geschrieben wurden.&lt;/p&gt;
&lt;h3 id=&quot;refactor&quot;&gt;Refactor&lt;/h3&gt;
&lt;p&gt;Der letzte Schritt im TDD Zyklus ist der Refactoring Schritt. Das Design des vorab geschriebene Programmcodes wird verbessert. Sie stellen sicher, dass der Code den Zweck zum Ausdruck bringt und verständlich ist. Dass der Programmcode weiterhin korrekt ist, kann durch erneutes Ausführen der Tests einfach validiert werden. An dieser mikroskopischen Stelle ist Refactoring übrigens auch ein zulässiger Schritt. Kritischer ist Refactoring zu betrachten, wenn es zu einem späteren Zeitpunkt durchgeführt wird, oder mehrere Codestellen betrifft (siehe &lt;a href=&quot;https://codelution.de/de/blog/post/vorsicht-wenn-entwickler-den-begriff-refactoring-verwenden&quot;&gt;&amp;quot;Vorsicht wenn Entwickler den Begriff Refactoring verwenden&amp;quot;&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;nachteile-und-loesung&quot;&gt;Nachteile und Lösung&lt;/h2&gt;
&lt;p&gt;TDD ist nicht prinzipiell schlecht. Allerdings proklamieren viele Befürworter von TDD, dass die Entwicklung in Baby-Steps und das Schreiben des Testscodes vor dem Produktivcode, zu einem &amp;quot;speziellen Softwaredesign&amp;quot; führt (was auch immer das genau bedeuten mag). Klar ist: dadurch, dass der Test vor der Implementierung geschrieben wird, ist ein Entwickler dazu gezwungen seinen zukünftigen &amp;quot;Produktivcode&amp;quot; selbst zu verwenden, noch bevor es ein dritter (Kollege o.ä.) muss. Dadurch werden zumindest Usability-Probleme im Interfacedesign früh erkannt.&lt;/p&gt;
&lt;p&gt;Durch den starken Fokus auf den zu entwickelnden Test bzw. dessen Lösung, geht jedoch auch der Blick aufs Große und Ganze verloren.  Mit zunehmender Entwicklungszeit entstehen immer mehr Abhängigkeiten zwischen den einzelnen (getesteten) Units. Die Units &amp;quot;verweben&amp;quot; sich miteinander. Es entsteht Spaghetticode. Deswegen sollten Sie auch bei TDD auf die &lt;a href=&quot;https://codelution.de/de/blog/post/erfolgreiche-softwareentwicklung&quot;&gt;wichtige Konzeptphase&lt;/a&gt; (auch Definitionsphase genannt) keinesfalls verzichten. Entwerfen Sie das Softwaredesign auf höherer Flugebene gemeinsam im Team - und setzen Sie die Lösung dann auf niedrigerer Flugebene um, gerne mit TDD.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Der Unterschied: Dependency Inversion Principle vs. Dependency Injection</title>
    <link href="https://codelution.de/de/blog/post/dependency_inversion_principle_vs_dependency_injection/" />
    <updated>2022-02-04T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/dependency_inversion_principle_vs_dependency_injection/</id>
    <content type="html">&lt;p&gt;Die Begriffe Dependency Injection und Dependency Inversion Principle werden häufig verwechselt, oder die Unterschiede sind nicht klar. Ganz verwirrend wird es, wenn noch der Begriff &amp;quot;Inversion of Control&amp;quot; dazukommt. Wir bringen Licht ins Dunkle.&lt;/p&gt;
&lt;p&gt;Neulich wurde ich gefragt, was der Unterschied zwischen Dependency Injection und dem Dependency Inversion Principle ist. Im Prinzip handelt es sich um zwei komplett unterschiedliche Dinge, die man nicht direkt vergleichen kann. Aber: beim Dependency Inversion Principle kommt in der Praxis zumeist Dependency Injection zum Einsatz. Zeit, den Unterschied genau zu beleuchten.&lt;/p&gt;
&lt;h2 id=&quot;dependency-inversion-principle&quot;&gt;Dependency Inversion Principle&lt;/h2&gt;
&lt;p&gt;Das Dependency Inversion Principle (DIP) ist, wie der Name schon sagt, ein Prinzip. Um genau zu sein handelt es sich um das letzte der fünf &lt;a href=&quot;https://www.informatik-aktuell.de/entwicklung/methoden/solid-die-5-prinzipien-fuer-objektorientiertes-softwaredesign.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SOLID Prinzipien&lt;/a&gt;. Das sind fünf Prinzipien für das Design von objektorientierter Software. Das Ziel der SOLID Prinzipien ist es, das innere Design von Softwareprodukten unkompliziert und erweiterbar zu gestalten.&lt;/p&gt;
&lt;p&gt;Für die Masse der Entwickler, die objektorientiert arbeiten, erkläre ich DIP ganz anschaulich an folgendem Beispiel: Ein Autofahrer soll verschiedene Fahrzeuge fahren können: einen Schaltwagen, einen Automatikwagen und ein selbstfahrendes Auto.&lt;/p&gt;
&lt;p&gt;Eine mögliche Implementierung (&lt;strong&gt;die aber gegen das DIP verstößt!&lt;/strong&gt;) könnte wie folgt aussehen. Zunächst werfen wir einen Blick auf die Klassen der jeweiligen Autos. Wir fangen mit dem Schaltwagen an, dessen Implementierung für sich gesehen zunächst logisch aussieht. Der Schaltwagen bietet verschiedene Methoden an. Neben der Möglichkeit einen Gang hochzuschalten, gibt es auch Methoden zum &amp;quot;drücken&amp;quot; oder &amp;quot;loslassen&amp;quot; der Kupplung:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ManualCar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...&lt;/span&gt;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...&lt;/span&gt;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;PressClutch&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...&lt;/span&gt;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ReleaseClutch&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...&lt;/span&gt;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Upshift&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...   &lt;/span&gt;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Downshift&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Code...&lt;/span&gt;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das folgende Listing zeigt die Klasse für den Automatikwagen. Auch dieser scheint für sich genommen richtig implementiert. Da unser Fahrer keine Kupplung betätigen kann, gibt es lediglich die Möglichkeit zum Umschalten des sog. &amp;quot;Sportmodus&amp;quot;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;AutomaticCar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ChangeMode&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; isSportMode&lt;/span&gt;)&lt;/span&gt;
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unser autonom fahrendes E-Auto ist der Knaller! Wir müssen es nicht einmal an- oder ausschalten. Das Fahrzeug ist so intelligent, dass es zwischen An und Aus wechselt sobald jemand im Fahrzeug sitzt. Den Elektromotor müssen wir sowieso nicht &amp;quot;starten&amp;quot;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;SmartCar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ChangeMode&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; isSportMode&lt;/span&gt;)&lt;/span&gt;
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Spannend wird jetzt die Implementierung des Fahrers. In Abhängigkeit des jeweiligen Fahrzeuges muss der Fahrer unterschiedliche Methoden seines Autos aufrufen. Bedenken Sie bitte, dass ich aktuell noch die Problemstellung verdeutlichen möchte und wir gleich zu einer bessern Lösung kommen.&lt;/p&gt;
&lt;p&gt;Die Fahrer-Klasse entscheidet Mittels des Enums, um welche Art von Auto es sich handelt:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;enum&lt;/span&gt; Cars
{
    ManualCar,
    AutomaticCar,
    SmartCar
}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Driver&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Driver&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;ManualCar manualCar, AutomaticCar automaticCar, SmartCar smartCar&lt;/span&gt;)&lt;/span&gt;
    {
        ManualCar = manualCar;
        AutomaticCar = automaticCar;
        SmartCar = smartCar;
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; ManualCar ManualCar { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; }
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; AutomaticCar AutomaticCar { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; }
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; SmartCar SmartCar { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Cars SelectedCar { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;switch&lt;/span&gt; (SelectedCar)
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.ManualCar:
            {
                ManualCar.PressClutch();
                ManualCar.Start();
                ManualCar.ReleaseClutch();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.AutomaticCar:
            {
                AutomaticCar.Start();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.SmartCar:
            {
                &lt;span class=&quot;hljs-comment&quot;&gt;// do nothing (starts if driver enteres car)&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
        }
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;switch&lt;/span&gt; (SelectedCar)
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.ManualCar:
            {
                ManualCar.Stop();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.AutomaticCar:
            {
                AutomaticCar.Stop();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.SmartCar:
            {
                &lt;span class=&quot;hljs-comment&quot;&gt;// do nothing (stops if driver leaves car)&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
        }
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Upshift&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;switch&lt;/span&gt; (SelectedCar)
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.ManualCar:
            {
                ManualCar.PressClutch();
                ManualCar.Upshift();
                ManualCar.ReleaseClutch();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.AutomaticCar:
            {
                AutomaticCar.ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.SmartCar:
            {
                SmartCar.ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
        }
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Downshift&lt;/span&gt;()&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;switch&lt;/span&gt; (SelectedCar)
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.ManualCar:
            {
                ManualCar.PressClutch();
                ManualCar.Upshift();
                ManualCar.ReleaseClutch();
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.AutomaticCar:
            {
                AutomaticCar.ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;);
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
            &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; Cars.SmartCar:
            {
                SmartCar.ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;);
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Leider haben die unterschiedlichen Autos zu einer Art Code Duplikation geführt. Der Code ist nie exakt gleich, aber immer sehr ähnlich. Mittels eines einfachen Extract Method Refactorings lässt sich dieser Code Smell nicht entfernen. Switch-Case Statements sind ein typisches Indiz dafür, dass das Dependency Inversion Principle verletzt ist. Die Anwendung wird schnell unwartbar. Wir müssen perspektivisch überall mit switch-case die Fahrzeuge unterschiedlich ansprechen. Ist Ihnen aufgefallen, dass in der Downshift-Methode des Fahrers beim Schaltwagen die Upshift Methode aufgerufen wird (Copy-Paste Fehler!)? Unsere Realisierung ist also nicht nur schlecht zu warten und zu erweitern, sondern auch noch fehleranfällig.&lt;/p&gt;
&lt;p&gt;Das Problem ist übrigens nicht, dass die Autos unterschiedlich sind, sondern dass sich der Fahrer um die jeweilige Unterscheidung kümmern muss. Die Abhängigkeit des Fahrers zu den Autos ist zu stark.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/dependency_inversion_principle_vs_dependency_injection/1e0b9ef9-4f8e-45cf-9bca-1cb655332443_Starke-Abh-ngigkeiten.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jetzt ist es Zeit für die Definition des DIP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Das DIP ist definiert mit:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;High-level modules should not depend on low-level modules. Both should depend on abstractions.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Abstractions should not depend on details. Details should depend on abstractions.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Vereinfacht ausgedrückt, sagt es aus, dass alle &amp;quot;Teile&amp;quot; unserer Anwendung immer nur von Abstraktionen, aber nicht von der konkreten Realisierung abhängig sein sollten.  Für Klassen bedeutet das, dass sie keine Referenzen auf andere konkrete Klassen, sondern zu deren Interfaces besitzen sollen. Sind diese Interfaces nicht vorhanden, müssen sie eingeführt werden.  Da es sich um ein Prinzip handelt, sollte es so weit irgendwie möglich immer eingesetzt werden.&lt;/p&gt;
&lt;p&gt;Für unser Beispiel bedeutet das, dass wir eine Abstraktion eines Autos einführen:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ICar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;;
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;;
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IncreaseDynamic&lt;/span&gt;()&lt;/span&gt;;
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DecreaseDynamic&lt;/span&gt;()&lt;/span&gt;;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;GetDestination&lt;/span&gt;()&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;TIPP: Definieren Sie Abstraktionen immer aus Sicht des Verwenders! Abstraktionen dienen dazu, ein (möglichst sinnhaftes) Verhalten für den Konsumenten bereitzustellen und die Implementierungsdetails hinter einer Sinnvollen Schnittstelle quasi zu &amp;quot;verstecken&amp;quot;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Der Fahrer interessiert sich in unserem Beispiel nicht für die Details des Autos. Er will seinen Zweck erfüllt haben. Unser Fahrer will nicht unbedingt hoch- oder herunterschalten. Was unser Fahrer wirklich will, ist dynamischer oder komfortabler fahren.&lt;/p&gt;
&lt;p&gt;Am Beispiel des Schaltwagens zeigt sich, dass trotzdem die fahrzeugspezifische Logik abgebildet werden kann (und ja auch muss). Die Methoden PressClutch() und ReleaseClutch() werden jetzt einfach innerhalb von Increase- bzw. DecreaseDynamic() aufgerufen.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ManualCar&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ICar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IncreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        PressClutch();
        DownShift();
        ReleaseClutch();
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DecreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        PressClutch();
        UpShift();
        ReleaseClutch();
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;PressClutch&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ReleaseClutch&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;UpShift&lt;/span&gt;()&lt;/span&gt;
    {   
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DownShift&lt;/span&gt;()&lt;/span&gt;
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;SmartCar&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;ICar&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IncreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;);
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DecreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        ChangeMode(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ChangeMode&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; isSportMode&lt;/span&gt;)&lt;/span&gt;
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Code der Driver-Klasse erfährt jetzt eine massive Vereinfachung. Er kann einfach nur die Abstraktion verwenden. Das ist pure Eleganz und zeigt die Mächtigkeit des Dependency Inversion Principles:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Driver&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ICar _car;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Driver&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;ICar car&lt;/span&gt;)&lt;/span&gt;
    {
        _car = car;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Start&lt;/span&gt;()&lt;/span&gt;
    {
        _car.Start();
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Stop&lt;/span&gt;()&lt;/span&gt;
    {
        _car.Stop();
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IncreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        _car.IncreaseDynamic();
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DecreaseDynamic&lt;/span&gt;()&lt;/span&gt;
    {
        _car.DecreaseDynamic();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unser Programm würde sich bei einer neuen Fahrzeugklasse auch problemlos erweitern lassen. Das neue Fahrzeug muss nur ebenso unsere Schnittstelle ICar implementieren und wir müssen nicht hunderte von Stellen, Switch-Case Statements, If-Else, usw. im Programmcode anpassen. Unser High-Level Modul Fahrer ist jetzt nicht mehr von den Low-Level Modulen (den Autos) abhängig. Stattdessen sind beide von der Abstraktion des Autos - dem Interface - abhängig. Der Fahrer ist vom Interface abhängig, da er es anstelle des konkreten Typs verwendet. Die Autos sind vom Interface abhängig, da sie dessen Schnittstelle realisieren.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/dependency_inversion_principle_vs_dependency_injection/45f6722a-1fa9-409f-bc81-5f4beac0b336_Abh-ngigkeiten-invertiert.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Die Abhängigkeiten verlaufen jetzt nicht mehr von &amp;quot;oben nach unten&amp;quot; sondern (zumindest teilweise) &amp;quot;bottom to top&amp;quot;. Teilweise, weil der Fahrer immer noch von dem Interface abhängig ist. Dieses Interface ist aus komponentenorientierter Sicht auf Ebene der Autos zu sehen. Meine persönliche Meinung ist daher, dass die Abhängigkeiten beim Dependency Inversion Principle nicht umgedreht (to invert) werden, sondern eigentlich eher eine &amp;quot;Umlenkung&amp;quot; über das Interface existiert.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/dependency_inversion_principle_vs_dependency_injection/b3dbfcdb-8f4b-414e-91fb-51a52c0f5de5_Abh-ngigkeiten-umgelenkt.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fakt ist aber, dass die Abhängigkeit zu den konkreten Typen nicht mehr explizit existiert. Man könnte auch von einer schwachen Abhängigkeit sprechen.&lt;/p&gt;
&lt;p&gt;Wenn Sie sich für eine ausführliche Erklärung über die SOLID Prinzipien interessieren, dann empfehle ich Ihnen gerne unsere &lt;a href=&quot;https://www.informatik-aktuell.de/entwicklung/methoden/solid-die-5-prinzipien-fuer-objektorientiertes-softwaredesign.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;5 teilige Artikelserie auf informatik-aktuell.de&lt;/a&gt;. Mein Kollege Andre Krämer und ich, erklären die SOLID Prinzipien anhand eines durchgängigen Beispiels. Aus didaktischen Gründen fangen wir in der Artikelserie sogar beim Dependency Inversion Principle an.&lt;/p&gt;
&lt;h2 id=&quot;dependency-injection&quot;&gt;Dependency Injection&lt;/h2&gt;
&lt;p&gt;Bei Dependency Injection (DI) handelt es sich nicht um ein Prinzip, sondern vielmehr um eine Technologie. Viele moderne Frameworks wie z.B. Angular bieten Out Of The Box Unterstützung für DI. Das Framework - oder ein dedizierter &amp;quot;DI-Container&amp;quot; - unterstützt uns dabei die Abhängigkeiten in unserer Anwendung flexibel und dynamisch (zur Laufzeit) aufzulösen.&lt;/p&gt;
&lt;p&gt;Die Begrifflichkeit &amp;quot;inject&amp;quot; (injizieren) ist entscheidend. Dependency Injection folgt dem &amp;quot;Inversion Of Control&amp;quot; Pattern. Unsere Klassen sollen sich nicht um die Auflösung der Abhängigkeiten kümmern. Stattdessen werden diese, z.B. durch Konstruktorparameter, Getter, Setter usw. vom Dependency Injection Framework an unsere Klasse übergeben. Beim Bootstrappen unserer Anwendung werden dabei Abstraktionen und deren Realisierung am Dependency Injection Framework registriert. Dann kann der DI-Container verwendet werden, um eine Einstiegsklasse o.ä. aufzulösen. Diese besitzt logischerweise Abhängigkeiten zu ersten Abstraktionen. Deren Realisierungen wieder zu anderen Abstraktionen usw. Alle diese Abhängigkeiten werden dann vom DI Container instanziiert und aufgelöst. Der DI Container spannt sozusagen ein ganzes Abhängigkeitsnetz auf. DI besitzt noch mehr Vorteile. Diese behandeln wir z.B. ausführlich in unserer &lt;a href=&quot;https://codelution.de/de/training/clean-code-training&quot;&gt;Clean Code Schulung&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Durch das Dependency Inversion Principle erhalten wir wartbaren und erweiterbaren Code. Anstelle von starken Abhängigkeiten zu konkreten Typen, besitzen unsere Klassen Abhängigkeiten zu Abstraktionen. Die Abhängigkeiten verschwinden nicht ganz. Sie werden nur schwächer und unser Programm wird wartbar und erweiterbar. Durch Dependency Injection, können die Abhängigkeiten zu Abstraktionen dynamisch, d.h. zur Laufzeit aufgelöst werden.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Codelution auf den IT-Tagen 2023!</title>
    <link href="https://codelution.de/de/blog/post/codelution-auf-den-it-tagen-2023/" />
    <updated>2024-03-22T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/codelution-auf-den-it-tagen-2023/</id>
    <content type="html">&lt;p&gt;Zum ersten Mal waren wir im Dezember 2023 nicht nur mit einem Vortrag, sondern auch mit unserem eigenen Stand auf den IT-Tagen in Frankfurt vertreten, eine der größten IT-Konferenzen für Software-Entwicklung, -Architektur, DevOps, KI, Datenbanken, IT-Security, Agile und IT-Management. Ein bunter Mix aus 220 spannenden Vorträgen, interessanten Ausstellern, eine Menge wissensdurstiger Besuchern und einem abwechslungsreichen Abendprogramm 😊&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/codelution-auf-den-it-tagen-2023/Medien-7--1-.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Wir konnten uns dort nicht nur mit unserem nagelneuen Stand präsentieren, sondern auch fachlich einen echten Mehrwert bieten. Stefan hat den Zuschauern in seinem Vortrag „SOLID-Hardcore“ im Turbospeed die 5 Solid-Prinzipien anhand eines leicht verständlichen Beispiels erklärt und auf unterhaltsame Art und Weise sein Expertenwissen komprimiert in 45 Minuten vermittelt.&lt;/p&gt;
&lt;p&gt;Die Interessen der Besucher waren vielfältig und wir konnten in den Gesprächen am Stand über die aktuellen Bedarfe in den Entwicklerteams, Trends und Neuerungen sprechen.&lt;/p&gt;
&lt;p&gt;Nach wie vor ist das Thema Clean Code für viele Softwareentwickler ein spannendes Thema in Bezug auf erfolgreiche, effektive und nachhaltige Projekte genauso wie die Wartbarkeit und Erweiterbarkeit von Code und Effizienz innerhalb des Teams.&lt;/p&gt;
&lt;p&gt;Aber auch das Thema Git ist auf großes Interesse gestoßen. Viele Unternehmen setzen das Versionsverwaltungssystem noch nicht oder nicht richtig ein.&lt;/p&gt;
&lt;p&gt;Wir konnten den interessierten Besuchern am Stand einen kleinen Überblick über unser Schulungsportfolio geben und über Herausforderungen in den Teams und in den Projekten sowie Lösungsmöglichkeiten sprechen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/codelution-auf-den-it-tagen-2023/CMA_2654-Ausstellung-Codelution-IT-Tage-2023.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Das Abendprogramm war ebenfalls sehr unterhaltsam gestaltet, neben Bier und Snacks gab es ein Tischkicker-Turnier mit der aktuellen Weltmeisterin und Zeit für Austausch auch außerhalb des Entwickler-Alltags.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/codelution-auf-den-it-tagen-2023/csm_DSC_1921-IT-Tage_2023_e5bad8cb0d.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Vorne hui, innen pfui? UI/UX-Projekte nachhaltig aufbauen!</title>
    <link href="https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/" />
    <updated>2024-04-29T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/</id>
    <content type="html">&lt;p&gt;Ein tolles UI-Design ist ein Anfang. Aber ist es auch nachhaltig strukturiert bzw. umgesetzt?&lt;/p&gt;
&lt;p&gt;Nur durch nachhaltige Lösungen können wir langfristigen Erfolg sicherstellen.&lt;/p&gt;
&lt;p&gt;Erweiterbarkeit, Wartbarkeit und Wiederverwendbarkeit sind auch im Frontend unabdingbar. In diesem Blogartikel werfen wir einen Blick auf den Aufbau von Frontend-Projekten. Je weiter wir im Blogartikel kommen, umso exklusiver werden die Prinzipien, die wir kennenlernen. Wir enthüllen Techniken, die Sie so auch bei großen Designagenturen nicht bekommen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Die Basis: der Styleguide&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Am Anfang unseres Blogartikels steht ein schönes UI-Design. Zum Beispiel in Form eines Styleguides. Der Styleguide dient als Spezifikation für die Umsetzung. Er enthält Farbdefinitionen oder beschreibt die Typographie. Also Schriftarten, Schriftgrößen oder Schriftschnitte. Ein Styleguide beschreibt auch das Design von Oberflächenelementen. Bei modernen Softwareprojekten ist ein Styleguide unerlässlich. Bei Codelution setzen wir diese Art der UI-Spezifikation deswegen als Minimum ein. Besser wäre es noch, den Styleguide zum Designsystem weiterzuentwickeln, aber das sprengt den Rahmen dieses Artikels.&lt;/p&gt;
&lt;p&gt;Ein einfacher Styleguide muss nicht aufwändig sein. Hier sehen wir ein Beispiel mit 21 Seiten:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/Screenshot2024-05-24103842.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daran können wir schon das erste Best-Practice für ein erfolgreiches Frontend Projekt erkennen:&lt;/p&gt;
&lt;h3 id=&quot;best-practice-1&quot;&gt;&lt;strong&gt;Best-Practice #1:&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id=&quot;der-styleguide-muss-konsistent-umgesetzt-werden&quot;&gt;&lt;strong&gt;Der Styleguide muss konsistent umgesetzt werden.&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Hierzu sollte ein UI-Designer in die Entwicklung eingebunden werden. Der UI-Designer sollte die Arbeit der Entwickler reviewen. Wie ein Code Review sollte das Design Review regelmäßig durchgeführt werden - z.B. regelmäßig während der Sprints und auch wenn die Entwickler keine Rückfragen haben. Das geschulte Auge eines Profis lässt sich nicht einfach ersetzen.&lt;/p&gt;
&lt;p&gt;Als nächstes stehen die Ziele Wiederverwendbarkeit, Erweiterbarkeit und Wartbarkeit an.&lt;/p&gt;
&lt;p&gt;Der Schlüssel zur Wiederverwendbarkeit liegt in einer sinnvollen Modularisierung.&lt;/p&gt;
&lt;p&gt;Softwareentwickler sind Modularisierung eigentlich gewöhnt. Interessant wird es im Bereich UI. Hier findet die Modularisierung nicht nur anhand der Domäne (Fachlichkeit) statt - wichtig ist auch noch die &amp;quot;Integrationstiefe&amp;quot;. Konkret heißt das, dass wir zwischen Smart Components und Dumb Components unterscheiden.&lt;/p&gt;
&lt;p&gt;Smart Components sind unsichtbare UI-Bausteine mit Domäne - also Geschäftslogik. Dumb Components sind primitive Oberflächenelemente, z.B. Steuerelemente (UI-&amp;quot;Controls&amp;quot;) wie Textfelder und Buttons. Diese haben keine Logik.&lt;/p&gt;
&lt;h3 id=&quot;best-practice-2&quot;&gt;&lt;strong&gt;Best-Practice #2:&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id=&quot;bei-der-modularisierung-zwischen-smart-und-dumb-components-trennen&quot;&gt;&lt;strong&gt;Bei der Modularisierung zwischen Smart- und Dumb-Components trennen.&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Smart Components verwenden Dumb Components (oder andere Smart Components). Dumb Components verwenden niemals Smart Components. Dumb Components empfangen Eingabedaten des Benutzers und übergeben diese an ihre Smart Components. Umgekehrt können Smart Components Daten an ihre Dumb Components übergeben, damit diese dem Benutzer angezeigt werden (Beispiel eine Label-Komponente).&lt;/p&gt;
&lt;p&gt;Die Schachtelung von Smart und Dumb Components könnte dann ungefähr so aussehen (die Smart Components sind hier in türkis hervorgehoben, die Dumb Components in rot.:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/SmartDumpComponents.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;An dieser Stelle werfen wir einen Blick auf die typische Modularisierung einer Anwendung. Die sog. Shell definiert den Rahmen, das Grundgerüst unserer Anwendung.&lt;/p&gt;
&lt;p&gt;Die Anwendung ist weiter in Feature Module unterteilt. Bei modernen Webanwendungen werden diese &amp;quot;lazy&amp;quot; - also erst bei Bedarf vom Webserver geladen.&lt;/p&gt;
&lt;p&gt;Die Featuremodule greifen auf geteilte Komponenten und Services zurück - z.B. in einem oder mehreren Domäne Modul/en.&lt;/p&gt;
&lt;p&gt;Die Featuremodule und das/die Domänemodul/e sind die Stellen, in denen die Smart Components kodiert sind. Die Dumb Components sind auf einer tieferen Schicht kodiert, z.B. in einer Widget Bibliothek.&lt;/p&gt;
&lt;p&gt;Die Referenzen verlaufen von oben nach unten:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/Screenshot2024-04-29164433.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vor wenigen Jahren haben wir die Dumb Components noch technologiespezifisch umgesetzt. Bei Angular beispielsweise mit Widget Libraries. Der aktuelle Stand der Technik sind aber HTML5 Webcomponents. Diese sind &amp;quot;webtechnologieagnostisch&amp;quot; und können Framework übergreifend eingesetzt werden (Angular, React, Vue, ...). HTML5 Webcomponents können z.B. mit Lit.dev entwickelt werden.&lt;/p&gt;
&lt;h3 id=&quot;best-practice-3&quot;&gt;&lt;strong&gt;Best-Practice #3:&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id=&quot;frameworkunabhaengige-dumb-component-libraries-auf-basis-von-html5-webcomponents-entwickeln&quot;&gt;&lt;strong&gt;Frameworkunabhängige Dumb Component Libraries auf Basis von HTML5 Webcomponents entwickeln.&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Grundvoraussetzung für eine einfache Erweiterbarkeit ist die Modularisierung unserer Anwendung.&lt;/p&gt;
&lt;p&gt;Eine Dumb Component Library, nennen wir sie &amp;quot;Widget-Library&amp;quot; lässt sich zentral erweitern und alle Konsumenten der Library können von den neuen Erweiterungen profitieren. Es versteht sich von selbst, dass bei größeren Softwaresystemen die Widget-Library wie ein eigenes Produkt versioniert, packetiert usw. werden sollte.&lt;/p&gt;
&lt;p&gt;Jetzt gehen wir auf einen noch unbekannteren Aspekt der Widgets ein: ihrem übergeordneten Verwendungszweck - ihrem &amp;quot;superordinate type&amp;quot; sozusagen. Das bedeutet, dass wir unsere UI-Widgets kategorisieren und zwar nach: Struktur (also Layouting Components) und Verhalten (Behavior Components).&lt;/p&gt;
&lt;h3 id=&quot;best-practice-4&quot;&gt;&lt;strong&gt;Best-Practice #4:&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id=&quot;ui-widgets-nach-strukturellen-komponenten-und-verhaltenskomponenten-trennen&quot;&gt;&lt;strong&gt;UI Widgets nach strukturellen Komponenten und Verhaltenskomponenten trennen.&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Das heißt nicht, dass getrennte Widget Libraries für Structural oder Behavioral Components benötigt werden, sondern, dass bei der Kodierung der Komponenten die Aspekte Layout und Interaktion getrennt werden sollten.&lt;/p&gt;
&lt;p&gt;Bleibt noch die Wartbarkeit als hegeres Ziel unseres &amp;quot;Softwaredesigns&amp;quot;. Ein häufiges Problem bei der Entwicklung von UI Libraries ist, dass das Styling nicht von der strukturellen Definition der eigentlichen UI-Controls getrennt wird.&lt;/p&gt;
&lt;p&gt;Für unser neues Projekt wollen wir aber nicht von vorneherein die Fehler für das nächste historisch gewachsene Softwareprodukt machen. Der nicht-funktionale Aspekt der Wartbarkeit soll wirklich im Vordergrund stehen.&lt;/p&gt;
&lt;p&gt;Wir müssen das Styling, also das Aussehen von der &amp;quot;Struktur und dem Verhalten&amp;quot; der Widgets trennen - nur so können wir später ein guten Theming usw. realisieren. Außerdem erleichtert diese Vorgehensweise ungemein spätere Änderungen im Design.&lt;/p&gt;
&lt;h3 id=&quot;best-practice-5&quot;&gt;&lt;strong&gt;Best-Practice #5:&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id=&quot;styling-aus-ui-controls-extrahieren-und-von-top-to-bottom-definieren&quot;&gt;&lt;strong&gt;Styling aus UI-Controls extrahieren und von top to bottom definieren.&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Bei Webtechnologien setzen Sie als eine der Möglichkeiten CSS Variablen ein. Diese lassen sich im Gegensatz zu SASS / SCSS zur Laufzeit des Programms ändern und sind damit wirklich variabel.&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;&lt;strong&gt;FAZIT&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In diesem Beitrag haben Sie die Basis zum Aufbau von nachhaltigen Designsystemen gelernt. Damit Sie nicht heute das Legacy System von morgen bauen sollten die folgenden Punkte berücksichtigt werden:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ui-ux-projekte-nachhaltig-aufbauen/Screenshot2024-05-24104538.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Im Detail gibt es natürlich noch mehr Best-Practices, aber das ist eine solide Basis. Go for it!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Rückblick auf die DWX 2024: Codelution mittendrin!</title>
    <link href="https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/" />
    <updated>2024-07-08T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/</id>
    <content type="html">&lt;p&gt;Ein voller Erfolg und viele Partien Blitzschach!&lt;/p&gt;
&lt;p&gt;Die Developer Week (DWX) 2024, eine der bedeutendsten Konferenzen im Bereich Softwareentwicklung, fand dieses Jahr vom 01.-05. Juli im Messezentrum Nürnberg statt. Mit über 200 Vorträgen, Workshops und Keynotes von Experten aus der ganzen Welt bot die Konferenz eine Plattform für Wissensaustausch und Networking auf höchstem Niveau. In diesem Jahr war die Codelution GmbH stolz darauf, als Aussteller mit einem Messestand vertreten zu sein.&lt;/p&gt;
&lt;h2 id=&quot;ein-treffpunkt-fuer-innovation-und-austausch&quot;&gt;Ein Treffpunkt für Innovation und Austausch&lt;/h2&gt;
&lt;p&gt;Die DWX ist bekannt dafür, die neuesten Trends und Technologien der Softwareentwicklung zu präsentieren. Auch 2024 enttäuschte die Veranstaltung nicht: Themen wie künstliche Intelligenz, Cloud-Computing, DevOps und moderne Programmiersprachen standen im Fokus. Die Teilnehmer hatten die Möglichkeit, von den Besten der Branche zu lernen und sich über zukunftsweisende Technologien auszutauschen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/1720068975482.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;codelution-gmbh-am-puls-der-zeit&quot;&gt;Codelution GmbH am Puls der Zeit&lt;/h2&gt;
&lt;p&gt;Unser Stand war während der gesamten Konferenz ein beliebter Treffpunkt für Entwickler, IT-Profis und Entscheidungsträger. Wir freuten uns, unsere neuesten Innovationen und Lösungen zu präsentieren, die darauf abzielen, Softwareprojekte effizienter und effektiver zu gestalten. Besonders stolz sind wir auf die zahlreichen Gespräche, die wir mit Fachleuten aus verschiedenen Branchen führen konnten. Diese Interaktionen sind für uns von unschätzbarem Wert, um die Bedürfnisse und Herausforderungen unserer Kunden noch besser zu verstehen.&lt;/p&gt;
&lt;h2 id=&quot;eine-partie-blitzschach-als-highlight&quot;&gt;Eine Partie Blitzschach als Highlight&lt;/h2&gt;
&lt;p&gt;Eine besondere Überraschung erwartete die Besucher an unserem Stand: Sie konnten eine Partie Blitzschach gegen den Geschäftsführer persönlich spielen. Diese Idee erwies sich als echter Publikumsmagnet und sorgte für viel Spaß und spannende Momente. Es war faszinierend zu sehen, wie das schnelle Schachspiel nicht nur die Köpfe rauchen ließ, sondern auch als Eisbrecher für tiefgehende technische Gespräche diente.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/1719837470033.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;inspirierende-vortraege-und-workshops&quot;&gt;Inspirierende Vorträge und Workshops&lt;/h2&gt;
&lt;p&gt;Neben den Aktivitäten an unserem Stand bot die DWX 2024 eine Fülle an inspirierenden Vorträgen und Workshops. Die Themenvielfalt reichte von praktischen Tipps zur Verbesserung der Codequalität über die Implementierung sicherer Cloud-Lösungen bis hin zu innovativen Methoden im Bereich maschinelles Lernen. Jeder Vortrag bot neue Erkenntnisse und regte zum Nachdenken an. Mit den beiden Vorträgen von Stefan Dirschnabel zum Thema IOSP und SOLID konnten wir weitere Impulse für sauberen, nachhaltigen und erweiterbaren Code setzen, um so für erfolgreiche Softwareprojekte zu sorgen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/1720420490715.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;ein-herzliches-dankeschoen&quot;&gt;Ein herzliches Dankeschön&lt;/h2&gt;
&lt;p&gt;Wir möchten uns herzlich bei allen Besuchern unseres Messestands bedanken. Ihre Neugier, Ihr Feedback und Ihre Begeisterung haben die DWX 2024 zu einem unvergesslichen Erlebnis für uns gemacht. Wir freuen uns bereits jetzt auf die nächsten Veranstaltungen und darauf, unsere Gespräche und gemeinsamen Projekte fortzusetzen und die ein oder andere Partie Schach zu spielen!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/ruckblick-auf-die-dwx-2024-codelution-mittendrin/1720421827956.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Die DWX 2024 war ein voller Erfolg und hat einmal mehr gezeigt, wie wichtig der Austausch und die Zusammenarbeit innerhalb der Entwicklergemeinschaft sind. Die Codelution GmbH ist stolz darauf, Teil dieser dynamischen und zukunftsorientierten Gemeinschaft zu sein. Wir sind gespannt auf die kommenden Herausforderungen und darauf, gemeinsam mit Ihnen die Zukunft der Softwareentwicklung zu gestalten.&lt;/p&gt;
&lt;p&gt;Bleiben Sie dran und folgen Sie uns auf unseren Social-Media-Kanälen, um keine Neuigkeiten und Updates zu verpassen!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Das CODELUTION Zertifizierungssystem</title>
    <link href="https://codelution.de/de/blog/post/das-codelution-zertifizierungssystem/" />
    <updated>2024-10-31T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/das-codelution-zertifizierungssystem/</id>
    <content type="html">&lt;p&gt;In den letzten Jahren ist bei CODELUTION viel passiert – doch was jetzt kommt, hebt unsere Entwicklertrainings auf ein völlig neues Level. Ab Herbst 2024 starten wir mit etwas, das uns schon lange unter den Nägeln brennt: Ein Zertifizierungssystem, das wirklich zu moderner Softwareentwicklung passt.&lt;/p&gt;
&lt;h2 id=&quot;warum-wir-das-machen&quot;&gt;Warum wir das machen&lt;/h2&gt;
&lt;p&gt;Wir waren in den vergangenen Monaten auf vielen Konferenzen unterwegs – IT-Tage, Magdeburger Dev Days, DWX – und haben dort nicht nur unser Programm vorgestellt, sondern auch zugehört. Was wir immer wieder gehört haben: Es fehlt ein praxisnahes, herstellerunabhängiges System, das Skills wirklich messbar und sichtbar macht. Und genau das setzen wir jetzt um.&lt;/p&gt;
&lt;h2 id=&quot;rollen-statt-tools-so-funktioniert-unser-ansatz&quot;&gt;Rollen statt Tools – so funktioniert unser Ansatz&lt;/h2&gt;
&lt;p&gt;Während viele bekannte Zertifizierungen sich auf konkrete Technologien beschränken (Microsoft, AWS, Google usw.), gehen wir einen anderen Weg:
&lt;strong&gt;Unsere Zertifikate richten sich nach Rollen, nicht nach Tools.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Egal ob du Frontend-Entwickler:in, Clean-Code-Profi oder DevOps-Engineer bist – bei uns steht deine &lt;strong&gt;Kompetenz&lt;/strong&gt; im Vordergrund, nicht das Framework, mit dem du arbeitest. Wer heute mit Angular arbeitet und morgen React nutzt, muss sich nicht komplett neu zertifizieren lassen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/das-codelution-zertifizierungssystem/Screenshot2024-10-31110537.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;strukturierte-lernpfade-mit-echten-nachweisen&quot;&gt;Strukturierte Lernpfade mit echten Nachweisen&lt;/h2&gt;
&lt;p&gt;Ein gutes Training ist mehr als ein einzelner Workshop. Deshalb haben wir unsere Kurse in Lernpfade gegliedert – Schritt für Schritt kannst du dich weiterentwickeln, dein Wissen vertiefen und am Ende deine Skills nachweisen.
Und ja, &lt;strong&gt;es gibt Prüfungen&lt;/strong&gt; – zumindest ab einem bestimmten Level. Denn wir wollen keine &amp;quot;Zertifikate fürs Dabeisein&amp;quot;, sondern echten Wert schaffen.&lt;/p&gt;
&lt;h2 id=&quot;open-badges-deine-qualifikation-zum-mitnehmen&quot;&gt;Open Badges: Deine Qualifikation zum Mitnehmen&lt;/h2&gt;
&lt;p&gt;Nach jedem abgeschlossenen Kurs bekommst du ein &lt;strong&gt;Open Badge&lt;/strong&gt; – ein digitales Zertifikat, das mehr enthält als nur ein hübsches Logo. Arbeitgeber:innen (und natürlich du selbst) sehen auf einen Blick, was du gelernt hast und wo du stehst. Die Badges sind standardisiert, fälschungssicher und lassen sich direkt in LinkedIn &amp;amp; Co. einbinden.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/das-codelution-zertifizierungssystem/SoftwareDeveloperAssociateBadge-CODELUTION.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;was-ist-mit-den-bisherigen-schulungen&quot;&gt;Was ist mit den bisherigen Schulungen?&lt;/h2&gt;
&lt;p&gt;Falls du schon in den letzten Jahren an unseren Trainings teilgenommen hast: Gute Nachrichten!
Wir rollen das System &lt;strong&gt;rückwirkend&lt;/strong&gt; aus – das heißt, auch Teilnehmende früherer Kurse (ab etwa 2021) erhalten ihre Badges automatisch. Ihr bekommt dazu bald eine E-Mail von uns.&lt;/p&gt;
&lt;h2 id=&quot;ein-blick-in-die-zukunft&quot;&gt;Ein Blick in die Zukunft&lt;/h2&gt;
&lt;p&gt;Unser Kursangebot wächst stetig weiter. Ganz neu im Programm ist zum Beispiel ein Modul zu &lt;strong&gt;Domain-Driven Design&lt;/strong&gt;, außerdem bauen wir aktuell den Bereich &lt;strong&gt;KI &amp;amp; Entwicklung&lt;/strong&gt; aus.
Warum? Ganz einfach: In einer Branche, in der sich Wissen in kürzester Zeit überholt, ist &lt;strong&gt;kontinuierliche Weiterbildung&lt;/strong&gt; der Schlüssel – und wir wollen euch dabei bestmöglich unterstützen.&lt;/p&gt;
&lt;h2 id=&quot;fazit-mehr-als-ein-zertifikat&quot;&gt;Fazit: Mehr als ein Zertifikat&lt;/h2&gt;
&lt;p&gt;Unser Ziel ist es nicht, einfach ein weiteres Zertifikatssystem auf den Markt zu bringen. Wir wollen Entwickler:innen dabei helfen, sich &lt;strong&gt;nachhaltig und nachvollziehbar weiterzuentwickeln&lt;/strong&gt; – mit einem System, das zu echten Projekten, echten Rollen und echter Praxis passt.&lt;/p&gt;
&lt;p&gt;Folge uns auf &lt;a href=&quot;https://youtube.com/@CODELUTION&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;YouTube&lt;/a&gt;, bleib über neue Kurse auf dem Laufenden – oder sprich uns direkt an, wenn du Fragen hast.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Docker einfach erklärt</title>
    <link href="https://codelution.de/de/blog/post/docker-einfach-erklaert/" />
    <updated>2025-05-15T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/docker-einfach-erklaert/</id>
    <content type="html">&lt;p&gt;Haben Sie schon mal von Docker gehört, wissen aber nicht genau, was es eigentlich ist. In diesem Beitrag unserer Einfach erklärt Serie erkläre ich Ihnen, wie Docker funktioniert und warum es für Sie und Ihr Unternehmen ein Game Changer sein kann, selbst wenn Sie kein IT-Experte sind. Am Ende zeige ich Ihnen außerdem einen praktischen Tipp, wie Sie Docker schnell und einfach ausprobieren können.&lt;/p&gt;
&lt;p&gt;Mein Name ist Stefan Dirschnabel und ich bin Trainer für Softwareentwickler. In diesem Beitrag erkläre ich Ihnen die fünf wichtigsten Punkte über Docker.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Erstens, was es ist.&lt;/li&gt;
&lt;li&gt;Zweitens, wie es funktioniert.&lt;/li&gt;
&lt;li&gt;Drittens, warum Docker so beliebt ist.&lt;/li&gt;
&lt;li&gt;Viertens, welche Vorteile Docker bringt&lt;/li&gt;
&lt;li&gt;und fünftens, wie Sie direkt damit starten können.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Am Ende des Beitrags zeige ich Ihnen wie Sie Docker in wenigen Minuten selber ausprobieren können.&lt;/p&gt;
&lt;h2 id=&quot;was-ist-docker&quot;&gt;Was ist Docker?&lt;/h2&gt;
&lt;p&gt;Docker ist eine Software, die es Ihnen ermöglicht, Ihre Anwendungen und alle Abhängigkeiten der Anwendung in sogenannte Container zu verpacken. Stellen Sie sich einen Container wie eine kleine Box vor, die alles enthält, was Ihre Anwendung zum Laufen braucht. Das kann also sein: Programmcode, Bibliotheken, die Einstellung der Anwendung und so weiter und so fort. So können Sie sicherstellen, dass Ihre Software überall gleich funktioniert – egal ob auf Ihrem Laptop, in der Cloud oder auf einem Server.&lt;/p&gt;
&lt;h2 id=&quot;wie-funktioniert-docker&quot;&gt;Wie funktioniert Docker?&lt;/h2&gt;
&lt;p&gt;Schauen wir uns erstmal an, wie eine virtuelle Maschine funktioniert. Auf der Hardware unseres Servers oder Computers läuft bei virtuellen Maschinen eine Software, die sich Hypervisor nennt. Der Hypervisor teilt und verteilt die Hardware-Ressourcen an unsere virtuellen Maschinen.&lt;/p&gt;
&lt;p&gt;Die virtuellen Maschinen sind also digitale Nachbildungen von physischen Maschinen – also Computern oder Servern. Virtualisierung ermöglicht es also, Hardware-Ressourcen effizient zu nutzen, Kosten zu senken und die Flexibilität zu erhöhen. Wir können Server zum Beispiel konsolidieren, Umgebungen isolieren, Software schneller bereitstellen oder auch skalieren.&lt;/p&gt;
&lt;p&gt;Virtuelle Maschinen haben aber natürlich auch ein paar Nachteile. Wir haben zum einen den Ressourcen-Overhead, denn wir benötigen für jede virtuelle Maschine ein komplett neues Betriebssystem. Dieser Betriebssystem-Block ist immer wieder dupliziert.
Außerdem haben wir eine schlechte Start-Performance, weil eben das ganze Betriebssystem immer hochfahren muss, und einen hohen Wartungsaufwand.&lt;/p&gt;
&lt;p&gt;Docker basiert auf einer Technologie namens Containerisierung. Anders als bei virtuellen Maschinen werden nicht die ganzen Betriebssysteme immer wieder kopiert, sondern das Betriebssystem wird mit dem Host quasi geteilt, kann man sagen.&lt;/p&gt;
&lt;p&gt;Wir sparen uns also den Betriebssystem-Block, den wir bei jeder virtuellen Maschine hatten.
Dadurch sind Container viel schlanker, starten schneller und benötigen weniger Ressourcen.
Die Container teilen sich den Kern des Host-Betriebssystems und sparen dadurch Platz und Rechenleistung.&lt;/p&gt;
&lt;h2 id=&quot;warum-ist-docker-so-revolutionaer&quot;&gt;Warum ist Docker so revolutionär?&lt;/h2&gt;
&lt;p&gt;Docker hat die Art und Weise, wie Software entwickelt, getestet und bereitgestellt wird, revolutioniert. Hier sind die drei Hauptgründe dafür:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Erstens: Einheitlichkeit&lt;/strong&gt;
Egal ob Entwickler, Tester oder Betreiber – jeder arbeitet mit derselben Umgebung.
Das reduziert Fehler.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zweitens: Flexibilität&lt;/strong&gt;
Docker-Container laufen überall: lokal, in der Cloud oder in hybriden Systemen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Drittens: Effizienz&lt;/strong&gt;
Dank der schlanken Architektur können Sie mehr Anwendungen auf derselben Hardware ausführen.&lt;/p&gt;
&lt;h2 id=&quot;welche-vorteile-bringt-docker&quot;&gt;Welche Vorteile bringt Docker?&lt;/h2&gt;
&lt;p&gt;Warum ist Docker so beliebt? Docker ist besonders für Unternehmen interessant, die schnell und zuverlässig neue Software ausliefern möchten.&lt;/p&gt;
&lt;p&gt;Die wichtigsten Vorteile sind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Schneller Start:&lt;/strong&gt; Container starten in wenigen Sekunden.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kostenersparnis:&lt;/strong&gt; Weniger Ressourcenverbrauch bedeutet geringere Hardware- und Cloud-Kosten.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Einfache Skalierbarkeit:&lt;/strong&gt; Wenn mehr Leistung benötigt wird, starten wir einfach zusätzliche Container.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;bonus-docker-selbst-ausprobieren&quot;&gt;Bonus: Docker selbst ausprobieren&lt;/h2&gt;
&lt;p&gt;Jetzt kommt der versprochene Bonus: Sie können Docker selbst ausprobieren. Besuchen Sie einfach &lt;a href=&quot;https://www.docker.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;docker.com&lt;/a&gt; und laden Sie Docker Desktop herunter. Nach der Installation von diesem Programm können Sie mit einem einfachen Befehl (docker run hello-world) einen eigenen Container starten – ganz ohne Vorkenntnisse. Das ist der erste Schritt, um in die Welt der Container einzutauchen.&lt;/p&gt;
&lt;p&gt;Wenn Ihr Interesse geweckt ist, dann werfen Sie einen Blick auf unsere Schulung zu Docker. Ihre Wettbewerber werden ständig besser, schneller und effizienter. Für weitere spannende Erklärvideos abonnieren Sie gerne unseren Youtube Kanal.&lt;/p&gt;
&lt;p&gt;Viel Erfolg bei der Umsetzung!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Unit Testing - HARDCORE</title>
    <link href="https://codelution.de/de/blog/post/unit-testing---hardcore/" />
    <updated>2025-06-03T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/unit-testing---hardcore/</id>
    <content type="html">&lt;p&gt;Passend zum Vortrag auf dem Karlsruher Entwicklertag gibt&#39;s hier das zum Vortrag passende Youtube Video!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Gutes Funktionsdesign</title>
    <link href="https://codelution.de/de/blog/post/funktionsdesign/" />
    <updated>2025-11-19T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/funktionsdesign/</id>
    <content type="html">&lt;p&gt;Wir Entwickler schreiben jeden Tag Funktionen und Methoden. In diesem Beitrag sprechen wir deswegen über Clean-Code-Grundlagen, gutes Funktionsdesign. Was unterscheidet gute von schlechten Funktionen?&lt;/p&gt;
&lt;p&gt;Wenn wir in der Softwareentwicklung Funktionen entwerfen, gibt es drei zentrale Gestaltungspunkte, die den Unterschied zwischen guten und schlechten Funktionen ausmachen. In diesem Beitrag zeige ich euch, worauf es beim Funktionsdesign ankommt und wie ihr typische Fallstricke vermeidet. Ganz am Ende gibt es auch noch einen kleinen und einfachen Trick um die Lesbarkeit und Verständlichkeit deutlich zu verbessern.&lt;/p&gt;
&lt;p&gt;Beim Funktionsdesign unterscheiden wir zwischen drei primären Gestaltungspunkten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;den Parameter die an eine Funktion übergeben werden&lt;/li&gt;
&lt;li&gt;der Verarbeitung der Funktion&lt;/li&gt;
&lt;li&gt;dem Rückgabewert&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;parameteranzahl&quot;&gt;Parameteranzahl&lt;/h2&gt;
&lt;p&gt;Der erste Gestaltungspunkt sind die Parameter. Wichtige Fragen sind: welche Parameter werden übergeben, und wie viele?&lt;/p&gt;
&lt;p&gt;Robert Martin unterscheidet in seinem Buch Clean Code zwischen drei Arten von Funktionen: monadischen, dyadischen und triadischen Funktionen. Martin bezieht sich hier auf die Anzahl der Parameter die an eine Funktion übergeben werden.&lt;/p&gt;
&lt;h3 id=&quot;monadische-funktionen&quot;&gt;Monadische Funktionen&lt;/h3&gt;
&lt;p&gt;Monadische Funktionen sind Funktionen, die nur einen Parameter entgegennehmen. Diese Art von Funktion ist intuitiv sehr einfach zu verstehen. Tendenziell streben wir also eher monadische Funktionen - oder besser gesagt Funktionen mit eher weniger als vielen Parametern an.&lt;/p&gt;
&lt;p&gt;Wenn Sie Code schreiben, werden Sie monadische Funktionen quasi automatisch in einem der folgenden Fälle verwenden:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sie stellen eine Frage über ein Argument.&lt;/li&gt;
&lt;li&gt;Sie wandeln ein Argument in ein anderes um.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;gute-monadische-funktionen&quot;&gt;Gute monadische Funktionen&lt;/h4&gt;
&lt;p&gt;Beispiele hierfür sind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Frage&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-typescript&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; isLoggedIn = &lt;span class=&quot;hljs-title function_&quot;&gt;isLoggedIn&lt;/span&gt;(user);
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Umwandlung&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-typescript&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; upperText = &lt;span class=&quot;hljs-title function_&quot;&gt;toUpper&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;lowerText&amp;quot;&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die hier gezeigten Beispiele sind gleichzeitig Beispiele für gute monadische Funktionen. Es gibt aber auch Grenzfälle.&lt;/p&gt;
&lt;h4 id=&quot;grenzfaelle&quot;&gt;Grenzfälle&lt;/h4&gt;
&lt;p&gt;Die folgende Funktion ist schon nicht mehr so schön:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;enableFeature&lt;span class=&quot;hljs-punctuation&quot;&gt;(&lt;/span&gt;FEATURE.REPORTING&lt;span class=&quot;hljs-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zwar handelt es sich um eine monadische Funktion, allerdings besitzt diese keinen Rückgabewert. Es muss also irgendetwas spezielles in der Funktion &amp;quot;passieren&amp;quot;. Von außen, also als Verwender, ist dieses &amp;quot;passieren&amp;quot; nicht so einfach zu erkennen. Es hilft nur eins: Sie müssen in die Funktion &amp;quot;reinspringen&amp;quot; und nachsehen, was genau gemacht wird. Dieses Springen, von Funktion zu Funktion, ist ein typisches Zeichen dafür, dass der Abstraktionsgedanke des &amp;quot;Moduls Funktion&amp;quot; nicht verständlich genug ist.&lt;/p&gt;
&lt;p&gt;Merke: besser sind Funktionen mit einem klaren Rückgabewert. Allerdings handelt es sich bei uns um einen Grenzfall, denn in unserem Szenario werden andere Systemteile per Event-Mechanismus über das aktivierte Feature benachrichtigt. In so einem Event Fall, können Sie keinen sinnvollen Rückgabewert definieren.&lt;/p&gt;
&lt;h4 id=&quot;schlechte-monadische-funktionen&quot;&gt;Schlechte monadische Funktionen&lt;/h4&gt;
&lt;p&gt;Eher nicht empfehlenswert sind monadische Funktionen wie zum Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;mergeDefaultConfig&lt;span class=&quot;hljs-punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;hljs-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Was passiert hier wirklich? Wenn die Funktion keinen Rückgabewert liefert (wonach es aussieht), dann verändert sie die &amp;quot;config&amp;quot;. Dieses Verhalten kann schnell übersehen werden und dann zu unerwarteten Effekten im Programmablauf führen. Besser und klarer ist es immer nach dem EVA-Prinzip zu arbeiten, also mit Eingabe (Parameter), Verarbeitung, Ausgabe (Rückgabewert).&lt;/p&gt;
&lt;h3 id=&quot;dyadische-funktionen&quot;&gt;Dyadische Funktionen&lt;/h3&gt;
&lt;p&gt;Funktionen mit zwei Parametern sind gang und Gäbe in der Entwicklung. Die Parameter sollten dabei in einem inhaltlichen Bezug zueinander stehen.&lt;/p&gt;
&lt;h4 id=&quot;gute-dyadische-funktionen&quot;&gt;Gute dyadische Funktionen&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; sum = &lt;span class=&quot;hljs-title function_&quot;&gt;add&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; origin = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Point&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;grenzfaelle-1&quot;&gt;Grenzfälle&lt;/h4&gt;
&lt;p&gt;Es mag sich banal anhören, aber bedingt durch die zwei Parameter, wird die Verständlichkeit sofort deutlisch schwerer - besonders wenn der Namen der Funktion nicht wirklich optimal ist. Wer gewinnt die Konfliktauflösung beispielsweise im folgenden Fall? Die localVersion oder die remoteVersion?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;version&lt;/span&gt; = resolveConflictBetween(localVersion, remoteVersion);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;schlechte-dyadische-funktionen&quot;&gt;Schlechte dyadische Funktionen&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;moveTo&lt;span class=&quot;hljs-punctuation&quot;&gt;(&lt;/span&gt;origin.xCoordinate, origin.yCoordinate&lt;span class=&quot;hljs-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;bessere-dyadische-funktionen&quot;&gt;Bessere dyadische Funktionen&lt;/h4&gt;
&lt;p&gt;Es gibt einfache Mechanismen die Sie anwenden können um schlechte oder schwer zu verstehende (Grenzfälle) dyadische Funktionen direkt zu verbessern:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; version = &lt;span class=&quot;hljs-title function_&quot;&gt;resolveConflictAndPreferLocalVersion&lt;/span&gt;(localVersion, remoteVersion); &lt;span class=&quot;hljs-comment&quot;&gt;// klares Naming&lt;/span&gt;

&lt;span class=&quot;hljs-title function_&quot;&gt;moveTo&lt;/span&gt;(origin); &lt;span class=&quot;hljs-comment&quot;&gt;// zwei Parameter mittels eines Datenobjekts vereinfachen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das Beispiel mit moveTo ist besonders ärgerlich, denn augenscheinlich gab es bereits eine Point Datenstruktur, aber diese wurde einfach nicht verwendet.&lt;/p&gt;
&lt;p&gt;Merke: reduziere die kognitive Last für den Verwender durch gutes Naming oder durch das Zusammenführen von vielen zu wenigeren Parametern.&lt;/p&gt;
&lt;h3 id=&quot;triadische-funktionen-und-mehr&quot;&gt;Triadische Funktionen und mehr&lt;/h3&gt;
&lt;p&gt;Eine berechtigte Frage ist nun, wieviele Parameter wir noch tolerieren wollen? Prinzipiell ist es immer schwierig eine pauschale Aussage zu treffen, aber der Beratersatz &amp;quot;es kommt darauf an&amp;quot; hilft natürlich auch niemandem weiter. Ich würde für mich die Grenze daher bei 3-4 Parametern ziehen.&lt;/p&gt;
&lt;p&gt;Funktionen mit mehr Parametern werden schnell sehr unintuitiv, müssten wahrscheinlich aufgeteilt werden, und sind wenn, dann nur in begrenztem lokalen Scope zulässig. Zum Beispiel als private Methoden innerhalb einer Klasse.&lt;/p&gt;
&lt;p&gt;Bei wichtigen öffentlichen Methoden, oder Komponenten Kontrakten, sollten Sie klare Datenobjekte (im Zweifelsfalle auch Command oder Query Objekte) einführen, um die Lesbarkeit zu gewährleisten und das Verständnis durch den Namen des Datentyps zu verbessern.&lt;/p&gt;
&lt;p&gt;Dies ist auch das allgemeine Pattern, das Sie immer anwenden können um zwischen den verschiedenen Funktionstypen zu &amp;quot;wechseln&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;anzahl-rueckgabewerte&quot;&gt;Anzahl Rückgabewerte&lt;/h2&gt;
&lt;p&gt;Mit dem Rückgabewert verhält es sich so ähnlich wie mit den Parametern. Ein klarer Rückgabewert ist besser als die Rückgabe von mehreren Werten mittels z.B. eines generischen Datencontainers (Tuple / Pair, Tripple, Quadrupel, ...). Anstelle eines generischen Datencontainers könnte hier auch Array, anonymes Objekt o.ä. stehen.&lt;/p&gt;
&lt;p&gt;Wenn bei einem Rückgabewert stattdessen ein klarer Datentyp verwendet wird sorgt dies für besseres Verständnis bei den Verwendern unserer Methode. Und denken Sie daran: Code wird viel öfter gelesen und verwendet, als geschrieben (nur 1-mal).&lt;/p&gt;
&lt;p&gt;Allerdings haben generische Datencontainer teilweise trotzdem ihre Berechtigung. Tendenziell würde ich aber versuchen Ihre Verbreitung im System zu reduzieren. Denn wenn der Context größer wird, wird es immer schwerer zu verstehen, für was der Tuple denn genau steht - immerhin trägt er keinen klaren Namen und durchläuft eine Art &amp;quot;Flüsterpost&amp;quot; wenn er von Variable zu Variable zugewiesen wird und dabei das Naming Stück für Stück degradiert...&lt;/p&gt;
&lt;h2 id=&quot;parameter-und-rueckgabetyp&quot;&gt;Parameter- und Rückgabetyp&lt;/h2&gt;
&lt;p&gt;Neben der Parameteranzahl ist der Typ des Parameters bzw. des Rückgabewerts selbst ein interessantes Modellierungskriterium.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parameter: den Parametertyp unserer Funktion/Methode möchten wir dabei so allgemein, also so unspezifisch wie möglich halten. Wenn wir beispielsweise die Preise einer Auflistung von Tellern berechnen wollen, bietet es sich an für den Parametertyp die kleinste gemeinsame Basisklasse des Auflistungstyps zu verwenden:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;public &lt;span class=&quot;hljs-built_in&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;AddPrices&lt;/span&gt;(&lt;span class=&quot;hljs-title class_&quot;&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title class_&quot;&gt;Dish&lt;/span&gt;&amp;gt; dishes&amp;gt;) {
&lt;span class=&quot;hljs-comment&quot;&gt;// ...&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Vorteil für den Verwender ist jetzt, dass er im Aufruf der AddPrices Funktion sehr flexibel ist. Er kann übergeben: Array, List, Set, ... - solange die Auflistung die er verwendet eben vom Typ IEnumerable ist.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rückgabewert: den Rückgabewert sollten wir so spezifisch wie nötig halten. Beispiel:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;OpenCsvFile&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;myFile.csv&amp;quot;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;: CsvFile &lt;span class=&quot;hljs-comment&quot;&gt;// CsvFile extends File, Rückgabewert aber CsvFile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Erstens möchte der Verwender klar eine Csv Datei öffnen und zweitens würde er wenn wir File zurückgeben nicht an CsvFile spezifische Informationen (wie z.B. das Trennzeichen) kommen können.&lt;/p&gt;
&lt;h2 id=&quot;seiteneffekte&quot;&gt;Seiteneffekte&lt;/h2&gt;
&lt;p&gt;Von einem Seiteneffekt spricht man dann, wenn die Funktion unerwartete, quasi versteckte Effekte ausführt. Die Funktion lügt uns sozusagen an. Die folgende Funktion suggeriert durch ihren Namen lediglich das Aktualisieren der EMail Adresse, tatsächlich wird aber auch noch eine E-Mail Benachrichtigung verschickt.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;function &lt;span class=&quot;hljs-title function_&quot;&gt;updateUser&lt;/span&gt;(userId: string, newEmail: string): &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; {
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; user = userRepository.&lt;span class=&quot;hljs-title function_&quot;&gt;getUser&lt;/span&gt;(userId);
  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!user) &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;;

  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; oldEmail = user.email;
  user.email = newEmail;
  userRepository.&lt;span class=&quot;hljs-title function_&quot;&gt;save&lt;/span&gt;(user);

  &lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment&quot;&gt;// Seiteneffekt: externer Call&lt;/span&gt;
    notificationService.&lt;span class=&quot;hljs-title function_&quot;&gt;sendEmailChangeNotification&lt;/span&gt;(oldEmail, newEmail);
  } &lt;span class=&quot;hljs-keyword&quot;&gt;catch&lt;/span&gt; (err) {
    &lt;span class=&quot;hljs-comment&quot;&gt;// ...&lt;/span&gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Besser wäre es gewesen das Verschicken der Notification raus zu ziehen und updateUser gefolgt von sendEMailChangeNotification in einem &amp;quot;UpdateUserEMailUseCase&amp;quot; aufzurufen.&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Wir Entwickler schreiben jeden Tag Funktionen. Das Wissen um gutes Funktionsdesign sollte daher zum Standardrepertoire eines jeden Entwicklers gehören. Gute Funktionen führen dazu, dass Sie Ihren Quellcode nicht &amp;quot;lesen und interpretieren&amp;quot; müssen, sondern dass Sie Ihr Programm &amp;quot;lesen und verstehen&amp;quot; können.&lt;/p&gt;
&lt;p&gt;Wir haben in der Vergangenheit bereits tausende Entwicklerteams in genau diesen Bereichen geschult. Lassen Sie uns gerne sprechen, wir freuen uns jederzeit über Ihren Anruf.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CODE &amp; BEER in Karlsruhe</title>
    <link href="https://codelution.de/de/blog/post/code--beer-in-karlsruhe/" />
    <updated>2026-09-01T00:00:00Z</updated>
    <id>https://codelution.de/de/blog/post/code--beer-in-karlsruhe/</id>
    <content type="html">&lt;h2 id=&quot;drei-talks-gute-gespraeche-und-ein-bier-danach&quot;&gt;Drei Talks, gute Gespräche und ein Bier danach&lt;/h2&gt;
&lt;p&gt;Softwareentwicklung besteht nicht nur aus Code. Es geht um gute Entscheidungen, funktionierende Zusammenarbeit und die Frage, wie wir Software langfristig verständlich, wartbar und zuverlässig halten.&lt;/p&gt;
&lt;p&gt;Genau darum geht es bei &lt;strong&gt;CODE &amp;amp; BEER&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Am &lt;strong&gt;29. Oktober 2026&lt;/strong&gt; veranstalten wir von Codelution zum ersten Mal einen kleinen Entwicklerabend in Karlsruhe. Drei technische Talks, anschließend Bier und Fingerfood, dazu Zeit für Gespräche mit anderen Entwicklern und IT-Interessierten aus Karlsruhe und Umgebung.&lt;/p&gt;
&lt;p&gt;Die Teilnahme ist &lt;strong&gt;kostenlos&lt;/strong&gt;, die Plätze sind allerdings begrenzt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;👉&lt;/strong&gt; &lt;a href=&quot;https://www.eventbrite.de/e/1998753060208?aff=oddtdtcreator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;Hier kostenlos für CODE &amp;amp; BEER anmelden!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/code--beer-in-karlsruhe/2X7A8693-1--2-.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;drei-talks-drei-perspektiven-auf-moderne-softwareentwicklung&quot;&gt;Drei Talks - drei Perspektiven auf moderne Softwareentwicklung&lt;/h2&gt;
&lt;p&gt;Für unseren ersten CODE &amp;amp; BEER Abend haben wir drei Themen ausgewählt, die Softwareentwickler in ihrem Alltag regelmäßig beschäftigen: Versionsverwaltung, Softwarearchitektur und der Betrieb moderner Anwendungen.&lt;/p&gt;
&lt;h2 id=&quot;was-ihr-ueber-git-nicht-wisst&quot;&gt;&lt;strong&gt;🪼 Was ihr über Git nicht wisst&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Git gehört inzwischen zum Standardwerkzeug praktisch jedes Entwicklerteams. Trotzdem gibt es einige Funktionen, bei denen selbst erfahrene Entwickler gelegentlich überlegen müssen:&lt;/p&gt;
&lt;p&gt;Was passiert eigentlich bei einem Rebase? Warum entstehen dabei Konflikte? Was genau macht ein Cherry-Pick? Und was bedeutet History-Rewriting eigentlich?&lt;/p&gt;
&lt;p&gt;Unter dem Titel „Was ihr über Git nicht wisst“ geht es nicht darum, möglichst viele Git-Befehle auswendig zu lernen. Stattdessen stellt Florian das Grundprinzip hinter Git in den Mittelpunkt.&lt;/p&gt;
&lt;p&gt;Wer versteht, wie Git seine Historie tatsächlich organisiert, kann viele der vermeintlich komplizierten Funktionen plötzlich nachvollziehen.&lt;/p&gt;
&lt;p&gt;Rebase und Cherry-Pick werden dann nicht mehr zu mysteriösen Befehlen, die man irgendwo aus einer Dokumentation kopiert, sondern zu Werkzeugen, deren Verhalten man verstehen und bewusst einsetzen kann.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eventbrite.de/e/1998753060208?aff=oddtdtcreator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;ZUR ANMELDUNG&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/code--beer-in-karlsruhe/8LdaK1f5a_dea0wM_2X7A7405.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;architekturmuster-endlich-verstehen&quot;&gt;&lt;strong&gt;🏗️ Architekturmuster endlich verstehen&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Monolith, Modulith, Layered Architecture, Clean Architecture und dann gibt es auch noch Begriffe wie Dependency Inversion und IODA.&lt;/p&gt;
&lt;p&gt;Bei Softwarearchitektur kann man schnell den Eindruck bekommen, dass es für jedes Problem noch ein weiteres Pattern gibt.&lt;/p&gt;
&lt;p&gt;Stefan möchte deshalb einen Schritt zurückgehen und die grundlegenden Konzepte miteinander vergleichen.&lt;/p&gt;
&lt;p&gt;In seinem Talk „Architekturmuster endlich verstehen“ geht es nicht darum, das nächste Architektur-Pattern zu verkaufen. Stattdessen werden die wichtigsten Ansätze Schritt für Schritt gegenübergestellt.&lt;/p&gt;
&lt;p&gt;Eine gute Softwarearchitektur sollte nicht möglichst viele Schichten, Abstraktionen und Patterns enthalten. Entscheidend ist, ob sie dabei hilft, ein System wartbar, erweiterbar und verständlich zu halten.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eventbrite.de/e/1998753060208?aff=oddtdtcreator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;ZUR ANMELDUNG&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/code--beer-in-karlsruhe/StefanBlog.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📦Von Code zu Container: Docker in der Praxis:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Container auf Linux-Basis sind heute ein etablierter Standard, wenn es um den Betrieb moderner Backend-Anwendungen geht. Sie schaffen eine flexible und konsistente Umgebung, in der eine Anwendung inklusive ihrer benötigten Abhängigkeiten bereitgestellt werden kann.&lt;/p&gt;
&lt;p&gt;Der große Vorteil: Ein Container bringt alles mit, was zum Ausführen der Anwendung benötigt wird – auf dem Zielsystem wird im Wesentlichen nur eine passende Container-Runtime benötigt. Dadurch lassen sich Anwendungen flexibel betreiben, egal ob auf der eigenen Entwickler-Maschine, im Rechenzentrum oder in der Cloud.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eventbrite.de/e/1998753060208?aff=oddtdtcreator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;ZUR ANMELDUNG&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/code--beer-in-karlsruhe/RolandBlog.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Softwareentwicklung muss nicht trocken sein&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CODE &amp;amp; BEER soll bewusst ein entspannter Nachmittag sein.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3 Talks.
Gute Gespräche.
Bier.
Fingerfood.
Schach.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://codelution.de/de/blog/post/code--beer-in-karlsruhe/SchachBlog.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;code-and-beer-alle-infos-auf-einen-blick&quot;&gt;CODE &amp;amp; BEER - alle Infos auf einen Blick&lt;/h2&gt;
&lt;p&gt;📅 &lt;strong&gt;29. Oktober 2026&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🕓 &lt;strong&gt;ab 16 Uhr&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;📍 &lt;strong&gt;CyberForum Church, Karlsruhe&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🎤 &lt;strong&gt;3 technische Talks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🍺 &lt;strong&gt;Bier&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🥨 &lt;strong&gt;Fingerfood&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;♟️&lt;strong&gt;Schach&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;Networking mit Entwicklern und IT-Interessierten aus Karlsruhe und Umgebung&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;🎟️ &lt;strong&gt;Kostenlose Teilnahme&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Die Teilnehmerzahl ist begrenzt. Die Anmeldung ist bis zum 16.10. möglich&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;👉&lt;/strong&gt; &lt;a href=&quot;https://www.eventbrite.de/e/1998753060208?aff=oddtdtcreator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;Jetzt kostenlos anmelden!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wir freuen uns auf euch bei CODE &amp;amp; BEER in Karlsruhe! 🍺&lt;/p&gt;
</content>
  </entry>
</feed>