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:
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:
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:
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:
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?
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.




Mariusz
14. August 2008
Hey Robert,
es ist unglaublich lehrreich dich beim Entwicklen des ReadYou Projektes hier im Blog zu begleiten. Deine Ideen und Gedankengänge kann man sehr gut nachvollziehen und dass du auch gleich noch Lösungen zu den auftretenden Problemen lieferst, ist umso besser
Ich wollte mal kurz nachfragen, mit welchem Programm du deine Diagramme, wie das obige Architekturdiagramm, erstellst?!
Merci und mach weiter so!
Robert Mühsig
14. August 2008
PowerPoint 2007 – ist auch super zum UI Prototyping:
http://code-inside.de/blog/2008/04/22/ui-prototyping-mit-powerpoint-2007/
Mariusz
14. August 2008
Sehr schön, danke dir
Oliver Guhr
14. August 2008
Dein Modell sieht keinen O/R Mapper vor, willst du die Datenbankzugriffe selber schreiben oder eine DB zugriffsschicht mit "Fluent Interfaces" bauen?
Robert Mühsig
14. August 2008
Das Model sieht dies sehr wohl vor: Im "Data" passiert der Datenzugriff.
Ob ich dort nun auf eine XML Datei zugreife, SQL Statements zusammenbaue oder einen O/R Mapper nehme, ist am Ende egal.
Bei dem Einsatz von Linq2Sql "mappe" ich die generierten Objekte zu meinem Model.
DB <-> O/R Mapper <-> mein Model
Im MVC Storefront macht Rob Conery z.B. sowas:
http://blog.wekeroad.com/mvc-storefront/
Matthias
16. August 2008
Wie händelst du komplexere Abfragen wie z.B.:
"Gib mir alle Bücher vom Autor X und Autor Y, des Users A oder User BÂ Â mit der Kategory “Krimi”"
Um etwas flexibler zu sein wäre es möglich beim GetBooksRequest eine Liste an Tags, Categories, Usern und Autoren zu übergeben. Aber dann ist die Verknüpfung zwischen den verschiedenen Suchparametern immer noch fest. Sprich entweder wertest du 2 Autoren in der Liste als UND-Verknüpfung oder als ODER-Verknüpfung, aber der Benutzer hat nicht die Wahl zwischen beidem.
Robert Mühsig
18. August 2008
Die Frage ist, ob ich solche "spezial" Fälle abdenken möchte: YAGNI ist auch so ein Zauberwort. In meinem Fall sind die Bedingungen alles "Und" Verknüpfungen – Bücher von zwei verschiedenne Nutzern geht dann nicht.
Allerdings werde ich mir den Flal mal durch den Kopf gehen lassen
Mariusz
1. September 2008
Ich find die Idee seine BusinessLogic auf eine Datenbank zu mappen, wie es Rob macht sehr elegant.
Ich bin bis jetzt den anderen Weg gegangen und hab die Datenbankstruktur auf meine BusinessObjekte abgebildet bzw. auf meiner Datenbankstruktur BusinessObjekte abgeleitet.
Die Idee vom Rob eignet sich wunderbar zum TDD und ich werd das mal bei mir auch ausprobieren
Mariusz
14. September 2008
Hi Robert,
du willst als DAL ja LINQ2SQL benutzen. Hast du evt. schon das ADO.NET Entity Framework angesehen und vielleicht in Betracht gezogen das zu benutzen? Wenn nein, welche Gründe sprechen hier für LINQ2SQL und gegen ADO.NET EF?
Ich stehe selbst vor der Wahl, welche Technik ich einsetzen soll und hab bis jetzt leider noch kein KO Kriterium für eins der Beiden finden können.
Vielleicht hast du dich damit schon auseinandergsetzt und könntest mir meine Entscheidung ein wenig erleichtern
Robert Mühsig
14. September 2008
Hallo Mariusz,
ich nutze LINQ2SQL in meiner DAL – allerdings erstelle ich mir meine eigenen POCOs und mappe die LINQ2SQL Klassen/Objekte auf meine eigenen POCOs. Die generierten Klassen sind auf "internal" gesetzt.
Rob Conery hat dies in seinem MVC Storefront ganz anschaulich in den ersten Webcasts erklärt.
Dieses mapping auf eine eigene Objektstruktur kostet zwar Zeit, allerdings muss ich mich mit solchen schweren Gedanken dann nicht ewig plagen. Wenn mir Linq2SQL nicht mehr gefällt, nehm ich ADO.NET EF oder SubSonic – wenn allerdings die generierten Klassen (sei es von LINQ2SQL, ADO.NET EF oder SubSonic) quer durch die gesamte Applikation verteilt ist, hat man sich festgesetzt.
Vor- und Nachteile habe ich noch nicht abgewogen – das EF ist natürlich der "große" Bruder und hat sicherlich einige Features die LINQ2SQL nicht bietet.
Mariusz
15. September 2008
Danke dir Robert, nun weiß ich, dass ich mit der Entscheidung LINQ2SQL nicht falsch liege
Den Webcast hab ich gesehen und war ein wenig überrascht, dass er es auf diesem Wege macht. Jedoch erkannte ich den Vorteil…eigene POCO’s ergeben keine Abhängigkeit zu anderen Frameworks in der Applikation.
Interessant wird das Entity Framework erst dann, wenn man vom eigenen Modell die Datenbank generieren lassen kann. Darauf freue ich mich jetzt schon
Robert Mühsig
15. September 2008
Irgendwo habe ich mal den Stichpunkt "ADO.NET EF unterstützt POCOs" gefunden.
IMHO ist es wichtig, dass man sicher stellt, dass nicht überall wild in der DB rumgeschrieben werden kann – sondern das über eine saubere Schnittstelle geht. Mit Linq2Sql und ADO.NET EF (und bei den meisten O/R Mappern) kann man einfach mitten im Front-End code ein "User.Save()" o.Ä. aufrufen – sowas sollte vermieden werden.
Mariusz
15. September 2008
In der Version 2 soll das EF die POCO’s unterstützen laut Aussage im EF Design Blog. Für die Version 1 gibt es einen kleinen POCO Adapter von Jaroslaw Kowalski…hatte bis jetzt keine Zeit das mal zu testen :-/
Marcel
29. September 2008
Ich finde den Ansatz mit den seperaten POCOs (Model) prima und freue mich schon auf die Fortsetzung des Artikels (und auf den Beispielcode
Marcel
29. September 2008
Zunächst einmal: super Artikel!:-) Ich bin auch gerade an den ersten Überlegungen meiner Anwendungsarchitektur und möchte dafür einen Prototypen basteln. Das jede Schicht sein eigenes Interface hat, find ich gut. Ich bin mir jetzt aber nicht sicher an welcher Stelle ich das eigentliche Objekt initialisieren sollte. Wo initialisierst du bspw. deinen  DataLayer? In der BL?Vielen Dank!
Robert Mühsig
6. October 2008
Mein ServiceLayer greift direkt auf die entsprechendne DataLayer zu – allerdings durch einen DI-Container (wie StructureMap, Unity etc.) gekapselt, sodass ich im Code nur mit den jeweiligen Interfaces rede.
Ich werde demnächst mal etwas weiter an dem Projekt rumbauen – es ist leider in letzter Zeit etwas eingeschlafen
Peter Bucher
22. December 2008
Hoi Robert
Evt. reicht dir anstelle des Request- / Response-Ansatzes schon ein Predicate mit dem du das Ergebnis filtern kannst. Oder halt optional dazu.
Timo
25. February 2009
Moin!
Wird das ReadYou Projekt eigentlich noch weitergeführt, oder ist es nun tot?
Gruß
Robert Mühsig
25. February 2009
Es wird weitergeführt – nur momentan in einer anderen Form. Das ursprüngliche Projekt lebt aber auch noch, allerdings wie es mit Privaten-Projekten meist so ist: Keine Zeit
Timo
25. February 2009
"Es wird weitergeführt – nur momentan in einer anderen Form. "
Kannst du das näher erläutern?
Finde Dein Projekt echt stark, da es ein schönes Beispiel für die Einführung in 3-Tier Architektur ist. In Kombination mit dem .Net Applikatioin Server von "rainbird" (http://yellow-rainbird.de/blogs/rainbird/archive/2008/04/12/die-neue-erweiterte-version-meines-n-tier-architekturbeispiels-ist-da.aspx) ist das wirklich genial…
Robert Mühsig
25. February 2009
Momentan hab ich zwei Projekte:
- ein Community-Projekt mit ein paar Arbeitskollegen zusammen (ich werde später darüber auch Berichten) :
Im Prinzip hatten wir mit der ReadYou Architektur begonnen, haben das ausgebaut und dann kamen neue Sachen hinzu. Grundsätzlich ist es eine MVC Anwendung, welche als Datenspeicher eine SQL Datenbank nutzt
- ReadYou: Aufgrund des Community Projekts ist das etwas zurückgetreten, aber auch das soll eine MVC Applikation werden, allerdings werde ich das einfach mal Probeweise in Hinblick auf Windows Azure entwickeln.
Die Architektur bleibt aber bei beiden Projekten so ziemlich gleich, sodass auch ReadYou irgendwann das Licht der Welt erblickt (und das vielleicht aus der großen Internetwolke
)