Softwarearchitektur: Komponenten Teil 1 - Was wir von anderen Industrien lernen können.

16. Februar 2012 22:41

imageWenn man erfahrene Entwickler fragt, wie man große und Komplexe Softwareprojekte umsetzt, bekommt man meistens zwei Dinge zu hören: Schichten und Komponenten. Beiden ist gemeinsam, dass sie dazu dienen, innerhalb meines Softwaresystems klare Grenzen zwischen Funktionalitäten zu ziehen und sie in Module aufzuteilen mit all den einhergehenden Vorteilen wie besserer Wiederverwendbarkeit, Wartbarkeit, Testbarkeit und – vor allem – der besseren Verteilbarkeit auf einzelne Entwickler.

Herr Ober da liegt ein Haar neben meiner Suppe…

Schaut man über den Tellerrand hinaus in andere Ingenieursbereiche erkennt man, dass dort identische Probleme existieren – und gelöst wurden: durch Modularität. Modular ist etwas, was in sich eine geschlossene Einheit bildet und über verschiedene definierte Schnittstelle angesprochen wird und seinerseits die Fähigkeiten anderer Module ebenfalls über definierte Schnittstellen nutzt. Für Benutzer eines Moduls ist deren innerer Aufbau meist vollkommen unwichtig. Betrachtet man das Modul einer Backstraße zum backen von Brot, so ist klar: Es benötigt Mehl, Hefe und Wasser und produziert Brot, mehr muss ich von Außen nicht wissen um damit Brot herzustellen. Angeschlossen an ein Mehlsilo, ein Hefesilo und eine Wasserleitung kann es also los gehen. Klar wachsen Backstraßen nicht auf Bäumen, sie müssen von irgendjemandem gebaut werden. Bei dem Bau solch eines Systems, schauen wir uns die Lösung zu zwei Problemen an, die wir auch in der Softwareentwicklung haben:

  1. Wie und wo fangen wir bei großen Systemen an zu entwickeln?
  2. Wie können wir die Arbeit auf mehrere Personen aufteilen?

Aus dem Bereich der Mathematik und der Informatik kennt man die Taktik des “Divide And Conquer” (Teile und herrsche), welches besagt das man ein großes Problem in viele kleinere Probleme unterteilt. Das macht man so lange bis alle kleinen Probleme lösen werden können und somit das Gesamtproblem gelöst ist.

Fangen wir also an unser “Problem” aufzuteilen: Eine Backstraße besteht (vermutlich, Leser der Backindustrie mögen mich bitte korrigieren) aus den Untermodulen Teigverarbeitung, Teigherstellung und Backofen wobei in das Modul Teigverarbeitung die Eingabe von Mehl, Hefe und Wasser erhält.

image

Wie dabei dieser Teig erzeugt wird, wie die Rohlinge geformt werden oder wie gebacken wird – das interessiert den Benutzer von Außen nicht. Hauptsache an den Schnittstellen steht das definierte Ergebnis mit den definierten Eigenschaften bereit.

Nun ist so eine Teigherstellungsmaschine (die in der Backstraße enthalten ist) auch kein einfaches Modul und so ist es ebenfalls aus Untermodulen zusammengesetzt, die – ihr werdet es nicht glauben – über fest definierte Schnittstellen miteinander kommunizieren (gähn…)

image

Mangels Maschinenbaustudium vermute ich das solch ein Modul aus einem Mixer (zum vermengen der Zutaten) und einem Kneter (der alles zu einem Teig knetet) bestehen wird. Dieses Spiel könnte man nun so lange treiben, bis man bei Schrauben und Kabeln der einzelnen Module angekommen ist.

image

Haben wir den überschaubaren Level der Schrauben und Kabel erreicht, kann losgebaut werden. Die Module auf unterster Ebene können auf die Ingenieure verteilt werden, da sie ja keine anderen Komponenten brauchen um fertiggestellt zu werden. Aber auch an den Modulen der oberen Schichten kann gebaut werden (Halterungen, Rohre, Kabel, usw.) weil deren Arbeit ebenfalls unabhängig ist – auch von Untermodulen. Denn deren Ausmaße und Schnittstellen sind je genau definiert – die Ingenieure müssen dies nur beim Bau berücksichtigen. Wurde unsere Beispiel sauber durchspezifiziert, kann an 6 Stellen losgebaut werden.

Und wie man sich die Brötchen, die aus der Backstraße kommen, mit der Softwareentwicklung verdienen kann, indem man sich genau das Prinzip zu nutze macht, schauen wir uns im nächsten Teil an… Weil jetzt habe ich Hunger!

Mobile Developer Conference 2012 in Hamburg

15. Februar 2012 06:38

Am 13.2 und 14.2 fand, wie jedes Jahr, die Mobile Developer Conference 2012 statt. An zwei Tagen wurden in jeweils drei Tracks aktuelle T20120213_MDevCon_Tielke_0010hemen rund um iOS, Android, Windows Phone 7 und natürlich auch Trends präsentiert und mit den Teilnehmern diskutiert. Die sehr gut besuchte Konferenz fand im Radisson Blue auf dem Hamburger Messegelände statt und bot, mit großen und gut ausgestatteten Konferenzräumen die idealen Rahmenbedingungen für eine großartige Konferenz. Zum ersten Mal war auch ich mit einem Vortrag dabei. Da die Entwicklung von mobilen Anwendungen auf immer mehr Plattformen publiziert werden muss und es dabei wichtig ist, die Kosten in einem erträglichen Rahmen zu halten und eine gut erweiterbare und wartbare Software zu schaffen, wählte ich als Thema “Unite the Worlds – .NET als Backend”. In dem 60-minütigen Vortrag ging es neben der Frage “Warum überhaupt ein einheitliches Backend bei mobilen Anwendungen?” vor allem um die konkrete Umsetzung und warum Microsoft .NET dafür eine ideale Plattform ist. Der komplett gefüllte Raum bot eine super Atmosphäre und spannende Fragen und Diskussionen mit den Teilnehmern und hat wirklich enorm viel Spaß gemacht. Nach dem Vortrag entstand eine rege Diskussion mit den Teilnehmern in der Lounge, bei der sich viele als überrascht zeigten, wie einfach ein Backend mit .NET zu realisieren ist und wie viele Probleme damit vermieden werden können.

Zusätzlich führte der Chefredakteur Markus Stäuble mit mir ein Interview zu meiner Markteinschätzung von Windows Phone 7:

Ich möchte mich auf diesem Wege noch einmal bei allen Teilnehmern für die rege Teilnahme und das Feedback bedanken und hoffe mit meinem Vortrag den ein oder anderen entscheidenden Impuls für Ihre mobilen Projekte gegeben zu haben. Natürlich möchte ich mich auch bei der Neuen Mediengesellschaft Ulm für die Einladung zu dieser Konferenz bedanken und hoffe beim nächsten Mal wieder dabei sein zu können.

Links:
Mobile Developer Conference 2012
Fotos auf Facebook

Test Driven Development mit .NET und C#–Tipp #2: Abhängigkeiten auflösen mit Stubs

19. Oktober 2011 20:45

Das Testen von Code ist eine wichtige und – für Entwickler – richtig coole Angelegenheit. Doch Testen ist weitaus mehr, als ein Testrunner und ein paar Attribute für Klassen und Methoden. In der Reihe “TDD Tipps” versuche ich regelmäßig Probleme zu erläutern, die beim Testen auftauchen und mit einem praktischen Hinweis einen Lösungsweg aufzuzeigen.

Unit-Tests sollen das Verhalten von nur einem einzigen Modul, für uns in diesem Fall einer Klasse, testen. Aber warum? Nehmen wir an wir testen die Methode Foo() in einer Klasse A die eine Referenz auf eine Klasse B hat. Im Laufe der Methode Foo() aus Klasse A wird die Methode Bar() aus Klasse B aufgerufen. Wenn wir jetzt A.Foo() testen, wird Code aus B.Bar() ausgeführt. Also ist das Ergebnis unseres Tests nicht mehr alleine von A, sondern auch von B abhängig und damit hängt auch der Testerfolg von A.Foo() von B.Bar() ab. Was hier noch nach einem einfachen Problem aussieht, wird spätestens zu einem Problem, wenn B eine externe Ressource nutzen würde, wie einen Webdienst, einen Mailserver, Datenbankserver o.ä. Aus dem und vielen anderen Gründen, sollte man in seinem Design immer so wenig Abhängigkeiten wie möglich haben. Was in der Theorie und in den zahlreichen Demos in Büchern und Konferenzen immer ganz einfach und simpel aussieht, gestaltet sich in der Praxis als teilweise sehr kompliziert. Wenn man ein Klassendesign entwirft, hat man an einigen Stellen zwangsläufig Abhängigkeiten.

Abbildung 1 verdeutlich das Problem noch einmal:

image

Abbildung 1: Klassendesign das getestet werden soll.

Würden wir nun einen Test für die Methode Foo() ) der Klasse A schreiben und dort ein Objekt der Klasse A instanziieren, würde dieses automatisch ein Objekt der Klasse B erzeugen, da A.Foo() ja deren Funktionalität nutzt.

Um solche Abhängigkeiten aufzulösen, bietet sich der Einsatz von Interfaces an. Mit nur einem Interface haben wir die Klassen voneinander entkoppelt und die Abhängigkeit zwischen A und B aufgelöst.image

Abbildung 2: Die Klassen A und B sind durch das Interface entkoppelt.

Zusätzlich übernimmt jetzt nicht mehr A selbst die Instanziierung von B, sondern wir injizieren dem Objekt von A mittels Konstruktorparameter b ein Objekt, das die Schnittstelle IB implementiert. Dadurch können wir von außen bestimmen, welches Objekt die Funktionalität IB.Bar() übernimmt, die wir von A.Foo() aus aufrufen.

Man stelle sich vor ,dass B.Bar() eine Datenbank aufruft. Gibt es dort einen Fehler, löst diese Methode eine InvalidOperationException aus. Unsere Methode A.Foo(), die ja B.Bar() aufruft, soll auf diese Exception mit einer CustomException reagieren. Wenn wir das mit dem Design aus Abbildung 1 testen möchten, müssten wir eine Datenbank aufsetzen, diese Tabellen in der Datenbank so manipulieren, dass in der Methode B.Bar() die gewünschte Exception auftritt und dann den Test für A.Foo() durchführen. Wir müssen quasi ein Szenario für B.Bar() simulieren, obwohl wir nur A.Foo() testen wollen. Das ist hier bereits verwirrend und in größeren Systemen führt das zu unglaublich kompliziertem Testcode den nach ein paar Tagen der Tester selbst nicht mehr versteht.

Mit dem Design aus Abbildung 2 ist das überhaupt kein Problem: In unserem Testprojekt legen wir einen sogenannten Stub an. Stub heißt, das er ein “dummer” Stellvertreter einer Interfaceimplementierung ist, der fest definierte Werte zurückgibt.

public class IBExceptionStub : IB
{
    public void Bar()
    {
        throw new InvalidOperationException("...");
    }
}

Listing 1: Ein Stub für einen Test der von B.Bar() eine Exception erwartet.

Schreiben wir nun also einen Test, der prüfen möchte, ob A.Foo() die erwartete CustomException auch tatsächlich auslöst, brauchen wir nur noch folgenden Code zu schreiben:

[TestMethod]
[ExpectedException(typeof(CustomException))]
public void Foo_DatabaseNotAvailable_CustomException()
{
    IB ib = new IBExceptionStub();
    A a = new A(ib);

    a.Foo();
}

Listing 2: Der Test für A.Foo() nutzt den ExceptionStub um einen Fehlerfall von B.Bar() zu simulieren.

Damit haben wir zwei Punkte erreicht:

Erstens können wir unterschiedlichste Verhalten von A in Abhängigkeit von Verhalten in B testen. Möchten wir z.B. ein Verhalten von A.Foo testen, wenn von B.Bar() aus der Datenbank ein ungültiger User geladen wird, schreiben wir einfach einen kleinen Stub.

Zweitens das Design ist wesentlich flexibler geworden durch die Entkopplung durch das Interface. Das Design aus Abbildung 1 wäre nicht durch eine Klasse C ersetzbar, welche die Methode Bar() ebenfalls anbietet. Das zweite Design könnte dies ohne Probleme, wenn C das Interface IB implementieren würde.

Das Ganze funktioniert so natürlich nur wenn Constructorinjection möglich ist. Sollte das nicht möglich sein, nutzt man dazu das ServiceLocator-Pattern. Aber das schauen wir uns in einem anderen Tipp genauer an.

Alle Beiträge der Reihe “TDD Tipps” sind hier zu finden.

Web Developer Conference 2011

18. Oktober 2011 22:19

Vom 17-18.11 fand zum ersten Mal die Web Developer Conference im Hamburger InterContinental Hotel statt. Mehr als 150 Teilnehmer konnten sich dabei in zwei Tracks auf den neusten Stand in der Webentwicklung bringen. Neben Vorträgen zu HTML5, JavaScript, NodeJs und vielen weiteren Themen, war auch ich kurzfristig mit einem Vortrag zum Thema “Schnittstellen im Web – Aktueller Technologiestand bei Webdiensten” vertreten. In der 60-minütigen Session versuchte ich den Teilnehmern die verschiedensten Technologien wie REST, SOAP und Data-Services zu erläutern, zu erklären wie und wo man diese Dienste in Architekturen am besten unterbringt und was man beim Thema Security zu beachten hat.

An dieser Stelle möchte ich mich noch einmal bei allen Teilnehmern meiner Session und natürlich auch allen Teilnehmern des Events bedanken. Es war für einen Desktopentwickler ein wirklich super cooler Informationsaustausch, der mir viele Anregungen und Perspektiven der Softwareentwicklung in den nächsten Jahren aufgezeigt hat. Ich freue mich schon auf die nächste Veranstaltung.

Wie mit den Teilnehmern besprochen, gibt es hier auch meine Folien zu dem Vortrag.

Links
Folien

Ein internal Interface in C# implementieren ohne public Methoden

12. Oktober 2011 14:15

Ab und zu kommt man in die Situation, dass man ein Interface in C# sowohl für public-Zwecke (Verwendung außerhalb eines Projekts) und auch für internal-Zwecke (Verwendung in dem jeweiligen Projekt) verwendet. Dabei gibt es das Problem, dass in C# keine Zugriffsmodifizierer für Interfacemethoden zulässig sind. Wie man das Ziel trotzdem erreicht, zeigt das Listing 1.

    public interface IPublic
    {
        void Foo();
    }

    internal interface IInternal : IPublic
    {
        void Bar();
    }

    class Something : IInternal
    {
        public void Foo()
        {
            throw new NotImplementedException();
        }

        void IInternal.Bar()
        {
            throw new NotImplementedException();
        }
    }

Listing 1: Das implementieren eines internal und eines public Interfaces

Der Trick daran ist es, die Funktionalität in ein Public Interface (hier IPublic) und ein Internal Interface (hier IInternal) aufzuteilen. Da IInternal von IPublic abgeleitet ist, bietet die interne Schnittstelle alle angebotenen Methoden an und die öffentliche Schnittstelle nur die öffentlich zugänglichen. Aber warum dann nicht in ein Interface? Ganz einfach, in einem Interface kann nur der Zugriffsmodifizierer für das gesamte Interface angegeben werden, nicht für einzelne Methoden oder Eigenschaften.

Weiter ist zu beachten das wenn ein Interface implizit implementiert wird, müssen dadurch alle implementierten Methoden public sein, egal welchen Zugriffsmodifizierer das Interface hat. Daher wird die Methode Bar() aus dem Interface IInternal explizit implementiert, womit wir das gewünschte Verhalten erzielt wird.

Test Driven Development mit .NET und C#–Tipp #1: Events testen

11. Oktober 2011 23:08

Das Testen von Code ist eine wichtige und – für  Entwickler – richtig coole Angelegenheit. Doch Testen ist weitaus mehr, als ein Testrunner und ein paar Attribute für Klassen uns Methoden. In der Reihe “TDD Tipps” versuche ich regelmäßig Probleme zu erläutern, die beim Testen auftauchen und mit einem praktischen Hinweis einen Lösungsweg aufzuzeigen.

Um Klassen untereinander zu benachrichtigen und voneinander zu entkoppeln, können Events genutzt werden. Wenn man Klassen mit Events testen möchte, muss natürlich auch das korrekte auslösen des Events getestet werden. Hat man kein entsprechendes Mock-Framework zur Hand, geht das auch relativ einfach mit Lambda-Expressions. Gegeben sei folgende Klasse Foo mit dem Event Bar (die so natürlich NICHT im Produktivcode auftauchen sollte):

public class Foo
{
    public event EventHandler Now;
    public void Bar()
    {
        Now(null, null);
    }
}

Listing 1: Die Klasse Foo mit dem Event Now, das getestet werden soll

Das Testen ist relativ einfach und simple:

[TestMethod]
public void Bar_EventSubscribed_EventIsRaised()
{
    bool isRaised = false;
    Foo foo = new Foo();
    foo.Now += (sender, args) => isRaised = true;
            
    foo.Bar();

    Assert.IsTrue(isRaised);
}

Listing 2: Die Methode, die testet, ob das Event ausgelöst wurde

Zunächst wird eine Variable isRaised deklariert und mit false initialisiert. Diese Variable erfasst, ob das Event ausgelöst wurde. Danach wird mit einem Lambda-Ausdruck dafür gesorgt, dass diese Variable auf true gesetzt wird, wenn das Event ausgelöst wird. Im Assert-Teil ist dann nur noch zu prüfen, ob diese Variable auf true gesetzt wurde.

Alle Beiträge der Reihe “TDD Tipps” sind hier zu finden.

Ist der .NET-Entwickler der neue VB6-Entwickler?

14. September 2011 07:55

Etwas mehr als 12 Stunden sind seit der BUILD vergangen… Die Konferenz die endlich Klarheit bringen sollte, die uns Entwicklern die Marschrichtung für die Zukunft aufzeigen sollte. Das Gefühl war schon irgendwie beängstigend am Vormittag, die Nervosität bei vielen Leuten spürbar. Durch die Verschwiegenheit von Microsoft im Vorfeld wurden die wildesten Gerüchte gestreut: Wird HTML5&JS die neue primäre Sprache für Windowsentwicklung? Wird es .NET weiterhin in seiner jetzigen Form geben? Haben wir viele Jahre eine Technologie gelernt, die nun veraltet ist?

Die Keynote begann, Windows 8 wurde gezeigt und dann war es raus: Es wird eine neue Laufzeitumgebung geben, genannt Windows RT, welche für die Entwicklung von Windows 8 Apps genutzt wird. Diese Runtime kann mit diversen Sprachen genutzt werden, neben HTML/JS und C++ glücklicherweise auch C#… Das HTML gesetzt war, vermuteten viele bereits, aber eine wirkliche Bekenntnis zu C# und zu .NET gab Microsoft bis dato nicht. Aber ist jetzt alles gut für das .NET Framework? Nein – ich denke nicht!

Wirklich viele Informationen über die nächste .NET Version gab es ja nicht. Bei der Sessionlist der BUILD ist mir folgende Session aufgefallen, auf die ich meine Argumentation stütze:

image

Das .NET-Framework wird also neue Erweiterungen bekommen, um Anwendungen für Windows 8 zu schreiben, bzw. die Windows RT aus .NET heraus nutzen zu können. Das man neue Erweiterungen für ein Betriebssystem bereitstellt, kennen wir bereits von Windows 7. Allerdings wurde das damals als “Windows 7 API Code Pack” bereitgestellt und nicht als Bestandteil einer neuen Version von .NET zu Verfügung gestellt.

Das Konzept von Microsoft war es (einmal!?), ein Framework für alle Windowsplattformen zur Verfügung zu stellen. Damit war sichergestellt, das Anwendungen, die auf einer Frameworkversion auf Betriebssystem X laufen, auch auf einem Betriebssystem Y läuft, vorausgesetzt es existiert eine Runtime dazu. Sollte Microsoft also wirklich die API für Windows 8 in .NET integrieren, wäre diese Plattformunabhängigkeit Geschichte. Macht man sich da das eigene Konzept kaputt?

Schaut man sich die Sessions zur BUILD an, wird eines deutlich: Der Kernpunkt dieser Konferenz ist neben Windows 8 vor allem HTML5 und JavaScript.

  • 9 Sessions zu .NET
  • 7 Sessions zu ASP.NET
  • 7 Sessions zu C#
  • 40 (!!!) Sessions zu HTML5

Merkwürdig das HTML5 als Technologie die langjährig gefeierte Technologie .NET mit einer gigantischen Entwicklergemeinde zu überholen scheint. Schaut man sich die Sessions im Bereich .NET, ASP.NET und C# an, mangelt es an wirklichen Innovationen und es erweckt den Eindruck, das diese Frameworkversion einzig und allein für die Kompatibilität mit Windows 8 entwickelt wurde und um die Brücke für ASP.NET Entwickler hin zu HTML5 Metro UI zu schlagen.

Wir sind bald im zehnten Jahr des .NET-Zeitalters angekommen. In dieser Zeit hat sich viel Verändert, das Framework wurde massiv erweitert und um coole und innovative Features ergänzt, wie z.B. LINQ. Wir haben mit WPF eine UI-Technologie die in der Lage ist, hardwarebeschleunigte Oberflächen zu entwickeln die schick und modern aussehen. Nun hat Microsoft mit Windows 8 ihr Flaggschiff zurück auf 0 gestellt (mehr oder weniger), und so viele Bereiche neu entwickelt wie bei keinem Betriebssystem vorher. Aber womit wurden die Oberfläche von Windows entwickelt? Mit HTML5 und JavaScript! Wurde das Betriebssystem auf Basis von managed Code geschrieben? Nein, aber warum? Das Forschungsbetriebssytem Singularity von Microsoft Research hat doch gezeigt, das ein performantes managed OS möglich ist und zahlreiche Vorteile hat. Welche großen Microsoftprodukte gibt es den, die mit .NET umgesetzt wurden, wenn wir Sharepoint einmal außen vor lassen? Keins!

Diese Tatsache zeigt mir, das Microsoft selbst nicht mehr an eine Zukunft von .NET glaubt und diese Version 4.5 des Frameworks untermauert das Ganze noch einmal. Egal mit wem man im Vorfeld gesprochen hat und über ein mögliches AUS von .NET diskutierte, jeder entgegnete mit der selben Antwort “Microsoft wird doch keine Technologie sterben lassen, in die sie so viele Jahre so viel Geld investiert haben”. Aber haben die VB6 Entwickler das nicht früher vielleicht auch behauptet bevor .NET veröffentlicht wurde? Ich befürchte die .NET Entwickler werden die neuen VB6 Entwickler…


video2brain - Videotraining

© Copyright 2011 by David Tielke - Impressum