Code-Inside Casts: Jetzt auch noch Videos…

Code-Inside wird noch (Bloggen, Twittern, in Social Bookmarking…) webzwonulliger – neustes Experiment: Screencasts.
Videos können sehr eindrucksvoll zeigen, wie einfach und schnell etwas zu bewerkstelligen ist – wesentlich besser als Seitenweise Text. Daher habe ich jetzt mal ein Screencast zum Thema “3 Schichten Architektur” erstellt.

Ich habe mich dabei (trotz der bescheidenen Qualität und der (scheinbar nur für neue Mitglieder?) 10 Minuten Videolängenbegrenzung) bewusst für YouTube entschieden:

  • Gigantische Nutzerzahlen
  • Keine Hostingkosten
  • Einfache Verlinkung
  • Es kennt einfach jeder und die Usability ist im Vergleich zur Konkurrenz einfach unschlagbar

So ganz 100% bin ich auch nicht mit dem Ergebnis zufrieden, allerdings ist so ein Screencast doch etwas ganz anderes als ein Blogpost. Dazu kommt dass der Mensch im Normalfall seine Stimme eigentlich nicht wirklich selber hören mag… aber beurteilt selbst und ich würde mich über Feedback freuen:

HowToCode "ReadYou": Evolution der Architektur

Mein kleines Projekt “ReadYou” kommt in winzigen Schritten vorwärts – allerdings mehr auch nicht. Grund hierfür ist meist, dass wenn man sich in ein Thema mal versucht einzulesen, man sofort auf zwei neue interessante Sachen stößt. So z.B. die Mockinggeschichte um meine UnitTests besser zu gestalten.

Architekturumgestaltung

Meine Grundsätzliche Architektur war so aufgebaut wie in diesem Blogpost beschrieben.

Durch das gute Feedback zu dem 3-Schichten Architektur Blogpost habe ich es nun grob so eingeteilt:

image

Mein Model liegt nun nicht mehr im Data rum, sondern ist theoretisch auf allen Schichten erreichbar und daher in einer eigenen DLL zu finden. Das Model besteht aus einfachen POCOs – die nichts anderes machen außer Daten halten.

Da ich möglichst flexibel bin und auch alles fein säuberlich testen kann, ist jede Schicht aufgeteilt in:

image

Bei Data ist natürlich genau dasselbe vorzufinden: Die Trennung zwischen den Interfaces und der eigentlichen Implementierung die ich vorgenommen habe.

Response & Request bei den Services

Als ich mein Interface für den BookService vorbereitet habe, habe ich überlegt, was ich alles für “Aufrufe” brauche:

    public interface IBookService
    {
        IList<Book> GetBooks();
        IList<Book> GetBooksByAuthor(Author author);
        IList<Book> GetBooksByUser(User user);
        IList<Book> GetBooksByTag(Tag tag);
        IList<Book> GetBooksByCategory(Category cat);
       ....

    }

Allerdings ist das nicht wirklich schön – mein Service hätte äußerst viele Methoden um Bücher ranzuholen. Einmal anhand des Autors, einmal nach Kategorie etc.
Komplexer wären noch Sachen wie: “GetBooksByCategoryAndUser” – heiei… für jeden Fall eine Methode zu schreiben, erscheint mir nicht sinnvoll.

Meine Lösung: Request & Response

Wie ein “WebService” geben meine Services auch Responses zurück und verlangen ein Request Objekt:

image

Diese Objekte habe ich in ReadYou.Service.Model hinterlegt – da sie nur im Service vorkommen, ich allerdings diese Definitionen und die Logik in seperaten DLLs trennen wollte:

image

Dabei leitet der “GetBooksRequest” von “BaseRequest” ab und beim Response genauso.

Durch dieses Objekt kann ich später genau mein “GetBooksRequest” definieren:

    public class GetBooksRequest : BaseRequest
    {
        public Tag Tag { get; set; }
        public Category Category { get; set; }
        public User User { get; set; }
        public Author Author { get; set; }
    }

Jetzt könnte ich mir sowas wie “Gib mir alle Bücher vom Autor XYZ, des Users ABC mit der Kategory “Krimi”" – das erlaubt mir einige Freiheiten und sollte erweiterbar sein, falls mir wieder was neues einfällt.

Wie sieht das im Projekt aus?

image

Alles ist aufgeteilt – dabei fehlen allerdings noch UnitTests für den “Data” Teil und für die WebApp (die hier noch nicht zu sehen ist). Unter “Common” befinden sich nur ein paar Extensions die mir das leben erleichtern :)

Mit dieser Ordnung bin ich gerade recht zufrieden – alles ist soweit getrennt und alles was Logik hat, hat auch ein Interface. Späße wie Dependency Injection und co. steht auch nichts im Wege.
Durch die Response / Request Sache bin ich später recht flexibel – auch wenn es etwas mehr Schreibaufwand ist.

Das wichtigste ist allerdings:

Wie seht ihr das? Ist die Idee mit den Response/Request Objekten vielleicht doch nicht so toll? Gebt einfach euer Feedback ab – den Code (sobald ich noch etwas weiter bin), werde ich auf Codeplex zur Verfügung stellen. Momentan ist diese Version noch nicht hochgeladen.

HowTo: 3-Tier / 3-Schichten Architektur

Eine 3-schichtige Architektur ist eigentlich ein “Klassiker” in der Softwareentwicklung. Da allerdings das Thema sehr weitläufig ist und Anfänger (und unbelehrbare Entwickler) aus Mangel an Zeit, Lust oder Erfahrung zurückschrecken gibt es genügend Beispiele wo einfach darauf verzichtet wurde.

Um den Grundgedanken zu vermitteln und um zu zeigen, dass es eigentlich sehr einfach ist, sowas am Projektanfang zu implementieren, schreibe ich diesen Artikel

Was für “Schichten” und warum 3?
Fast jede Software greift auf Daten zurück – sei es XML, ein Webservice, eine Datenbank, eine Textdatei oder ein X-beliebiges anderes System.
Diese Daten werden irgendwie verarbeitet – sei es eine mathematische Funktion, eine Validierung oder eine bestimmte Filter und Suchfunktion.
Damit das Ergebnis auch irgendwo angezeigt wird (bzw. die Eingaben entgegen genommen werden) gibt es in den meisten Fällen auch ein Frontend, sei es eine Consolen-Applikation, eine Website oder irgend etwas anderes.

Jetzt wären wir bei den 3-Schichten angekommen:
 image

“Nur 3? Ich hab mehr!”
Natürlich kann man unzählige Schichten noch dazwischen schieben. Ein Beispiel ist z.B. die Software Factory von Microsoft. Da gibt es noch etliche Mappings zwischen den Data-Access-Schichten bis hin zu den Service-Schichten. Siehe auch den Wiki-Artikel zu den Schichtenmodellen.

“Ich frage nur Daten ab – ich brauch nur 2 Schichten.”
Über SQL etc. kann man natürlich auch Filtern, Sortieren etc. – da könnte man auch die “Business” Schicht in Frage stellen. Aus meiner Erfahrung sollte man das allerdings lieber nicht machen – später können noch irgendwelche Anforderung dazukommen, die nix im Data Access Layer zu suchen haben. Bis es soweit ist, könnte die Business-Schicht die Daten einfach nur “durchreichen”.

Beispielapplikation:
image

Data-Access Layer: “ThreeTier.Data”
Business Layer: “ThreeTier.Service”
Presentation Layer: “ThreeTier.ConsoleApp”
+ Unit-Tests: “ThreeTier.Tests”

Hier haben wir eine recht einfache Beispielapplikation – das ganze noch mit ein paar kleinen Unit-Tests bestückt (Einführung in Unit-Tests hier).

Die Architektur sieht man z.B. auch recht gut in Rob Conerys Storefront Projekt.

Schichten im Detail: ThreeTier.Data
image 
Hier definiere ich erst mal meine Objekte, welche ich im System nutze – simple POCOs.
Zugegeben, man kann sich darüber streiten ob man sein “Model” tatsächlich mit in dem Data-Projekt haben möchte. Da allerdings alles meistens mit irgendwelchen Daten zusammenhängt, passt das schon.
Wir haben hier nur die User Klasse:

image 
Im Ordern “DataAccess” liegt unsere Schnittstellen (Einführung zu Schnittstellen) zu den Datenquellen.
In diesem Fall haben wir nur die Schnittstelle “IUserRepository” (Repository zu dt. sowas wie Lager, Speicherort etc.) – dort definieren wir, welche Operationen ich generell auf eine X-beliebige Datenquelle ich ausführen möchte:
image
Das “DemoUserRepository” ist die konkrete Implementierung dieser Schnittstelle. Da ich keine DB oder ähnliches wollte, werden hier statische Daten zurückgegeben.

Welchen Vorteil bringt mir jetzt das Interface?
Das Interface könnte man hier in Frage stellen, allerdings erlaubt es später recht einfach die Datenquelle zu wechseln – weil alles auf der Schnittstelle beruht.
Da man im Regelfall mit einer DB etc. arbeitet möchte man z.B. in Unit-Tests nicht unbedingt die Datenbank fluten, sondern kann sich hier statische Testdaten zurückgegeben lassen. Einfach durch die Schnittstelle.
So könnte man auch leichter von einem “Showcase” zu einer echten Implementierung umschwenken.

Da ich in meinem Beispiel aber nur statische Daten zurückgebe, habe ich im Unit-Tests genau diese getestet.

Schichten im Detail: ThreeTier.Service

image
Im Service haben wir nach dem gleichen Prinzip auch eine Schnittstelle für unseren “UserService” erstellt.

image

In unserem UserService gibt es einmal eine Login-Methode und eine Methode, welche (ganz im Sinne von Social Networking) die Freunde von einem User zurück gibt. Hierbei habe ich zudem auch nur statische Daten genommen. Das ganze basiert allerdings auf dem “UserRepository”.

Schichten im Detail: ThreeTier.ConsoleApp
image

Mal wieder ein Konsolenprogramm – zwar ist das keine schöne Oberfläche, aber für das Beispiel soll es genügen:

        static void Main(string[] args)
        {
            Console.WriteLine("Great Social Community System - Please Login...");
            Console.Write("Name: ");
            string loginname = Console.ReadLine();
            Console.Write("PW: ");
            string password = Console.ReadLine();

            IUserService srv = new DemoUserService();

            if (srv.Login(loginname, password))
            {
                Console.WriteLine("Hello: " + loginname);
                Console.WriteLine("Your demo friend collection in the system: ");
                List<User> friends = srv.GetFriendsFromUser(loginname).ToList();

                foreach (User friend in friends)
                {
                    Console.WriteLine(" + " + friend.Login + " - Id: " + friend.Id);
                }
            }
            else
            {
                Console.WriteLine("Login failed");
            }

            Console.ReadLine();
        }

Ausgabe:

image 

Extras: Unit-Tests

Um ein gutes Beispiel zu geben, habe ich sogar 6 Unit-Tests geschrieben. Das Frontend hab ich allerdings nicht getestet ;)
image

Code-Coverage: 97% (Data + Service)
image

Resultat:

Durch die 3-Schichtige Architektur ist es später leichter Möglich neue Features einzubauen und die Applikation zu Warten. Im Team macht sich das auch recht gut, da man dadurch eine bessere Teamaufteilung machen kann.

[ Download Source Code ]

Video:

MVC Storefront – Real World Application Building Excercise: ASP.NET MVC, TDD & more

Schonmal etwas von Test-Driven-Developement gehört oder ASP.NET MVC?

Rob Conery (Entwickler von SubSonic und nun bei ASP.NET Team beschäftigt) versucht sich nun genau an diesen Dingen und dokumentiert dies – mittlerweile sind so bereits 10 Teile zusammengekommen:

Ich finde diese Videos sehr interessant gemacht – vor allem sieht man, warum welche Architekturentscheidung so oder so getroffen wurde – Rob erklärt ziemlich präzise jeden einzelnen Schritt und alles im TDD Umfeld.

Ich empfehle auch die Kommentare zu lesen, da dort bereits einige Architekturentscheidungen durch diskutiert wurden. Diese Diskussionen sind doch sehr lehrreich – insgesamt finde ich die momentane Architektur, welche Rob gewählt hat, sehr interessant.

Das Ganze gibts auch auf Codeplex zum Download.

Buchempfehlung: Entwufsmuster von Kopf bis Fuß

Entwufsmuster sind immer ein Thema in der Softwarearchitektur, allerdings gibt es zwar das wunderbare Standardwerk von der Gang of Four, leider ist das dort etwas arg trocken beschrieben und besonders als Nachmittagsliteratur schwer verdaulich.
Wer trotzdem gerne ein Buch über Entwufsmuster haben möchte, welche diese zudem sehr detailiert und mit (Java)-Beispielcode erlernen will, dem empfehle ich das “Entwurfmuster von Kopf bis Fuß” Buch.

Besonders hervorzuheben sind dabei folgende Punkte:

  • Der Schreibstil ist angenehm locker und auch viele Zeichnungen / Konzeptionen etc. kommen zum Einsatz, dadurch erhöht sich wirklich der Spaß am lesen.
  • Die wesentlichen Entwurftmuster werden gut und sehr verständlich Schritt für Schritt erklärt. Dabei werden auch Risiken oder “Nebenwirkungen” genannt.
  • Um mal viele Entwurfsmuster in einem Demoprojekt zu sehen, gibts zum Ende des Buches ein kleines Beispiel mit Enten ;)
  • Der Beispielcode ist in Java geschrieben, allerdings kann man das auch gut auf .NET / C# mappen, sodass es da zu keinen Schwierigkeiten kommt
  • Das Buch ist eigentlich für jeden Software Entwickler gut geeignet, da es sehr verständlich und praxisorientiert ist – zudem gefällt mir sehr gut der Schreibstil und die gesamte Machart des Buches ;) .

[ Amazon Link ]