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.