2009-03-19 6 views
2

Meine Frage ist eher architektonischer Natur, weniger mit der tatsächlichen Implementierung verbunden.Einen WCF-Dienst richtig schichten

Ich habe eine API basierend auf WCF erstellt, kann aber nicht wirklich entscheiden, wie die PL von der BL zu trennen. Ich habe meinen Dienst dünn gemacht, so dass es nur ein Minimum an Implementierung hält, so etwas wie:

public TagItemResponse TagItem(TagItemRequest request) 
{ 
    return (new ItemTagRequestProcessor()).GetResponse(request); 
} 

als natürlich die erste Frage stellt sich, in welcher Schicht gehören die RequestProcessors? Ich denke, es wäre falsch, sie als Fassade zu bezeichnen, aber gleichzeitig haben sie nichts mit der Präsentation zu tun. Im Moment entschied ich, dass sie trotzdem in den PL gehören. Die Prozessor Methoden nehmen meine DTO (Datacontracts) als Eingabe, die Anforderungsnachricht (Basisklasse) validieren, authentifizieren (Basisklasse) und schließlich eine einzige DTO Antwort zurück, etwa so:

protected override void Process(TagItemRequest request, TagItemResponse response, Host host) 
{ 
    var profile = ProfileFacade.GetProfile(host, request.Profile); 
    var item = ItemFacade.GetItemId(host, request.Item); 
    var tags = new List<Tag>(); 

    foreach (var name in request.Tags) 
    { 
     var tag = TagFacade.GetTag(profile, name); 
     ItemFacade.TagItem(item, tag); 
     tags.Add(tag); 
    } 

    ItemFacade.UntagItem(item, tags); 
} 

Jetzt frage ich mich, warum Brauche ich die Fassadenklassen 1: 1 bezogen auf meine Geschäftsobjekte? Zum Beispiel habe ich eine HostFacade, die als eine Schicht zwischen dem HostDAO und den Prozessoren fungiert. Es enthält jedoch sehr wenig Logik, es behandelt nur die DAO-Aufrufe.

public static Host GetHost(HostDTO dto) 
{ 
    return HostDAO.GetHostByCredentials(dto.Username, dto.Password); 
} 

Frage: Ich könnte auch die Prozessoren und die Fassaden zusammenführen, oder?

Ich habe viele Artikel/Bücher zu diesem Thema gelesen, aber ich kann immer noch nicht auf dem "richtigen" Weg zu gehen und tendieren, jedes Mal einen anderen Ansatz wählen, wenn ich das Problem stelle. Ich frage mich, ob es überhaupt einen richtigen Ansatz gibt.

Ich habe f.ex gefunden. Das doFactory-Beispiel, in dem sie direkt von der Service-Implementierung aus mit den DAO-Klassen gesprochen haben. Das mag ich nicht wirklich, da die meisten ServiceContract-Methoden eine gewisse Logik teilen und sich daher gut für die Verwendung mit gemeinsamen Basisklassen eignen.

Ich habe auch andere Beispiele gefunden, wo nur die Fassaden von innerhalb der Dienste aufgerufen werden, aber das scheint nur für sehr feinkörnige Nachrichten gut zu funktionieren. Meine Nachrichten sind "fett" und zusammengesetzt, um die Anzahl der Anrufe an den Dienst so weit wie möglich zu reduzieren. Meine zusätzliche Verarbeitungsschicht scheint das eigentliche Problem zu sein.

Wahrscheinlich gibt es keine einzige Antwort darauf, wie man einen WCF-Dienst richtig schichtet, aber hoffentlich gibt es einige von Ihnen da draußen mit einer Meinung, die entweder meinem Instinkt entsprechen oder für mich etwas neues Licht auf das Thema werfen.

Danke!

Geoffrey

+0

PL und BL? Bitte seien Sie klarer, damit Leute, die mit diesen Akronymen nicht vertraut sind, nicht verwirrt sind. –

+0

@ unforgiven3 Sie haben Recht, vielleicht hätte ich explizit Presentation Layer (PL), Business Layer (BL) und Data Layer (DL) geschrieben. Ich habe einfach angenommen, dass angesichts des Kontexts (Architekturfrage) Leute, die antworten könnten, verstehen würden. Wie auch immer, Punkt genommen. –

Antwort

3

Zuerst Ich gehe davon aus, dass durch PL Sie Präsentationsschicht bedeuten, nicht Schicht Persistenz?

Bei der Implementierung eines mehrschichtigen Anwendungsdesigns sollte die Hauptfrage immer lauten: Kann ich die Implementierung einer niedrigeren Schicht ersetzen, ohne die Implementierung der obigen Schicht (en) zu beeinträchtigen?

Dies wird normalerweise am besten durch die Persistenzschicht veranschaulicht. Wenn Sie beispielsweise von SQL Server 2008 zu MySQL wechseln, ändert sich die Persistenzschicht (natürlich). Sind aber auch Veränderungen in der Business-Schicht notwendig? Fängt die Business-Schicht beispielsweise SqlException-Instanzen ab, die nur von SqlClient ausgelöst werden? In einem guten Design benötigt die Business-Schicht keine Änderungen.

Das gleiche Prinzip sollte für die Trennung zwischen Business-Schicht und Präsentationsebene gelten.In Ihrem Beispiel würde ich sagen, dass ItemTagRequestProcessor nicht in der Präsentationsschicht sein sollte. Erstens hat es nichts mit der Präsentation zu tun, zweitens ist die Implementierung der Verarbeitung einer Anfrage kein Problem für die Präsentationsschicht. Vergleichen Sie es mit einer Web-Anwendung, ein TagItemResponse zu einem Client zu präsentieren ist das Anliegen der Web- (Präsentations-) Ebene. Beim Abrufen einer Instanz von TagItemResponse handelt es sich um eine Schicht unter der Präsentationsschicht.

Die Entscheidung, ob eine Fassade zwischen Ihrer Business-Schicht und der Persistenzschicht erstellt werden soll, ist schwierig. Normalerweise implementiere ich keine Fassade, weil sie eine zusätzliche (normalerweise unnötige) Indirektionsebene hinzufügt. Außerdem sehe ich kein Problem beim Aufruf von Persistenz-Layer-Methoden direkt aus Business-Layer-Methoden. Wenn Sie nur dasselbe Prinzip berücksichtigen: können Sie die Implementierung der Persistenzebene ändern, ohne die Implementierung der Business-Schicht zu beeinträchtigen.

Mit freundlichen Grüßen

Ronald Wildenberg

+1

@rwwilden Danke für die ausführliche Antwort! Ich kann mich auf Ihren Rat beziehen und Ihre Argumente sehen. Das DoFactory-Beispiel hat mich aus dem Gleichgewicht gebracht, indem ich die Nachrichtenverarbeitung direkt im Service abgewickelt habe. –

+0

@Ronald Konnten Sie bitte http://stackoverflow.com/questions/9498962/contract-first-soa-designing-business-domain-wcf beantworten? – Lijo