Frage

Ich bin ein großer Fan von NTiers für meine Entwicklung Entscheidungen, natürlich tut es jedes Szenario passen.

Zur Zeit arbeite ich an einem neuen Projekt und ich versuche, ein Spiel mit dem Weg habe ich normalerweise arbeiten, und zu versuchen, um zu sehen, ob ich es bis reinigen. Da ich ein sehr schlechter Junge gewesen und haben zu viel Code in der Präsentationsschicht wurde setzen.

Meine normale Business-Schicht-Struktur ist dies (Grundansicht davon):

  • Handel
    • Dienstleistungen
      • FooComponent
        • FooHelpers
        • FooWorkflows
      • BahComponent
        • BahHelpers
        • BahWorkflows
    • Utilities
      • Allgemein
      • ExceptionHandlers
      • Importeure
      • etc ...

Jetzt mit dem oben Ich habe großen Zugang zu direkt speichert ein Foo Objekt und ein Bah Objekt, über ihre jeweiligen Helfer.

Die XXXHelpers geben Sie mir den Zugang zu speichern, bearbeiten und die entsprechenden Objekte laden, aber wo kann ich die Logik setzen, um Objekte mit untergeordneten Objekten zu speichern.

Zum Beispiel:

Wir haben die folgenden Objekte (nicht sehr gut Objekte ich weiß)

  • Mitarbeiter
  • EmployeeDetails
  • EmployeeMembership
  • EmployeeProfile

Zur Zeit würde ich bauen diese alle in der Präsentationsschicht und leiten sie dann an ihre Helfer, ich finde, dass das falsch ist, denke ich, sollten die Daten über Präsentation in der Business-Schicht einige Ort und aussortiert auf einen einzigen Punkt übergeben werden es.

Aber ich bin auf einem wenig ratlos, wo ich diese Logik setzen würde und was den Sektor zu nennen, würde es gehen unter Hilfsmitteln wie EmployeeManager oder so etwas?

Was würden Sie tun? und ich weiß, das ist alles, bevorzugt.

Eine detailliertere Layout

Die Workflows enthalten alle Anrufe direkt an die DataRepository zum Beispiel:

public ObjectNameGetById(Guid id)
{
    return DataRepository.ObjectNameProvider.GetById(id);
}

Und dann der Helfer-Provider den Zugang zu den Workflows:

public ObjectName GetById(Guid id)
{
    return loadWorkflow.GetById(id);
}

Dies ist auf doppelten Code zu reduzieren, wie Sie einen Anruf im Workflow getBySomeProperty haben und dann mehr Anrufe in den Helfern, die anderen Operationen durchführen könnte und die Daten auf unterschiedliche Weise zurückgeben, ein schlechtes Beispiel wäre öffentlich GetByIdAsc und GetByIdDesc

Durch die Anrufe an das Datenmodell seperating durch die DataRepository verwenden, bedeutet dies, dass es für eine andere Instanz zu Swap-Modell möglich wäre (die das Denken war), aber ProviderHelper wurde nicht abgebaut, so dass es nicht austauschbar ist, wie es leider zu EF hart codieren. Ich habe nicht die Absicht, die Zugangstechnologie zu ändern, aber in Zukunft könnte es etwas besser oder einfach nur etwas sein, dass alle kühlen Kinder sind jetzt mit, dass ich stattdessen implementieren möchte.

projectName.Core

projectName.Business
    - Interfaces
        - IDeleteWorkflows.cs
        - ILoadWorkflows.cs
        - ISaveWorkflows.cs
        - IServiceHelper.cs
        - IServiceViewHelper.cs
    - Services
        - ObjectNameComponent
            - Helpers
                - ObjectNameHelper.cs
            - Workflows
                - DeleteObjectNameWorkflow.cs
                - LoadObjectNameWorkflow.cs
                - SaveObjectNameWorkflow.cs
    - Utilities
        - Common
            - SettingsManager.cs
            - JavascriptManager.cs
            - XmlHelper.cs
            - others...

        - ExceptionHandlers
            - ExceptionManager.cs
            - ExceptionManagerFactory.cs
            - ExceptionNotifier.cs


projectName.Data
    - Bases
        - ObjectNameProviderBase.cs
    - Helpers
        - ProviderHelper.cs
    - Interfaces
        - IProviderBase.cs
    - DataRepository.cs

projectName.Data.Model
    - Database.edmx

projectName.Entities (Entities that represent the DB tables are created by EF in .Data.Model, this is for others that I may need that are not related to the database)
    - Helpers
        - EnumHelper.cs

projectName.Presenation

(abhängig, was der Aufruf der Anwendung ist)

projectName.web
projectName.mvc
projectName.admin

Die Testprojekte

projectName.Business.Tests
projectName.Data.Test
War es hilfreich?

Lösung

1 für eine interessante Frage.

Also, das Problem, das Sie beschreiben, ist ziemlich häufig - ich einen anderen Ansatz nehmen würde - zuerst mit den logischen Schichten und zum anderen mit den Versorgungs- und Helfer Namensräume, die ich versuchen würde und Faktor vollständig aus - ich werde Ihnen sagen, warum in einer Sekunde.

Aber zuerst, mein bevorzugter Ansatz ist hier ziemlich gemeinsame Enterprise-Architektur, die ich versuchen werde in Kürze zu markieren, aber es gibt viel mehr Tiefe gibt. Es hat einige radikale Veränderungen im Denken erfordern - mit NHibernate oder Entity Framework können Sie Ihre Objektmodell direkt und lassen Sie das ORM befassen sich mit Dingen wie Mapping und aus der Datenbank und verzögertes Laden Beziehungen usw. Dadurch werden Sie erlauben die Abfrage zu implementieren alle Ihre Business-Logik in einem Domänenmodell.

Zuerst werden die Stufen (oder Projekte in Ihrer Lösung);

YourApplication.Domain

Das Domain-Modell - die Objekte Ihr Problem Raum darstellen. Dies sind nur alte CLR-Objekte mit allen Ihren wichtigen Geschäftslogik. Dies ist, wo Ihr Beispiel Objekte leben würden, und ihre Beziehungen würden als Sammlungen vertreten. Es gibt nichts in dieser Schicht die sich mit Ausdauer usw., es ist nur Objekte.

YourApplication.Data

Repository-Klassen - das sind Klassen, die sie mit der Gesamt Wurzel bekommen (en) Ihrem Domain-Modells.

Zum Beispiel ist es in Ihrer Beispielklasse unwahrscheinlich ist, dass Sie bei EmployeeDetails aussehen würden wollen, ohne auch an Mitarbeitern sucht (eine Annahme, die ich weiß, aber Sie erhalten die Kern - Rechnungszeilen werden ein besseres Beispiel, Sie werden in der Regel auf Rechnung erhalten Linien über eine Rechnung, anstatt sie unabhängig) geladen werden. Als solche können die Repository-Klassen, von denen Sie eine Klasse pro Aggregat Wurzel wird für immer anfänglichen Einheiten aus der Datenbank mit dem ORM in Frage, Implementierung alle Abfragestrategien (wie Paging oder Sortierung) und die Rückkehr des Aggregats Wurzel zu der Verantwortung Verbraucher. Das Repository würde den aktuellen aktiven Datenkontext (ISession in NHibernate) verbrauchen -., Wie diese Sitzung erstellt wird, hängt davon ab, welche Art von Anwendung, die Sie bauen

YourApplication.Workflow

  • Könnte auch YourApplication.Services genannt werden, aber dies kann mit Web-Services zu verwechseln
  • Das Tier dreht sich alles um miteinander in Beziehung, komplexe atomare Operationen -. Anstatt hat ein paar Dinge in Ihrer Präsentationsebene aufgerufen werden, und deshalb erhöhen Kopplung, Sie solche Operationen in Workflows oder Dienstleistungen wickeln können
  • Es ist möglich, dass Sie, ohne dass dies in vielen Anwendungen tun könnten.

Weitere Ebenen hängen dann von der Architektur und der Anwendung, die Sie umsetzen.

YourApplication.YourChosenPresentationTier

Wenn Sie Web-Services verwenden Ihre Ebenen zu verteilen, dann würden Sie DTO Verträge erstellen, die nur die Daten repräsentieren Sie zwischen der Domäne und den Verbraucher ausgesetzt wird. Sie würden Montierer definieren, würde wissen, wie aus der Domain-Daten in und aus diesen Verträgen bewegen (Sie würden nie Domain-Objekte über den Draht! Senden)

In dieser Situation und Sie auch den Client erstellen, würden Sie die Bedienung und Datenverträge verbrauchen in Ihrer Präsentationsebene vorstehend definiert ist, wahrscheinlich zu dem DTOs Bindung direkt als jeder DTO Ansicht spezifisch sein sollte.

Wenn Sie keine Notwendigkeit, Ihre Ebenen zu verteilen, die erste Regel verteilter Architekturen zu erinnern ist nicht verteilen, dann würden Sie die Workflow / Dienstleistungen und Repositories verbrauchen direkt aus asp.net, mvc, wpf, WinForms usw.

Dass nur Blätter, wo die Daten Kontexten etabliert sind. In einer Web-Anwendung, ist jede Anforderung in der Regel ziemlich enthielt selbst, so dass ein Antrag scoped Kontext am besten ist. Das bedeutet, dass der Kontext und die Verbindung wird zu Beginn der Anforderung festgelegt und am Ende angeordnet ist. Es ist trivial Ihre c zu erhaltenhosen IoC / Dependency Injection-Framework zu konfigurieren pro Anforderung Komponenten für Sie.

In einer Desktop-Anwendung, WPF oder WinForms, würden Sie einen Kontext pro Form haben. Dies stellt sicher, dass Änderungen an Domain-Entitäten in einem Bearbeitungs Dialog, dass das Modell Update aber nicht machen es auf die Datenbank (zB: Abbrechen ausgewählt wurde). Nicht stören anderen Kontexten oder schlechter Ende nach oben versehentlich anhielt werden

Dependency Injection

Alle oben genannten würde zunächst als Schnittstellen definiert werden, mit konkreten Implementierungen durch eine IoC und Dependency Injection-Framework realisiert (meine Präferenz ist Burg windsor). Dies ermöglicht es Ihnen, zu isolieren, Mock und Unit-Test einzelne Ebene unabhängig und in einer großen Anwendung, Dependency Injection ist ein Lebensretter!

Die Namensräume

Schließlich ist der Grund, würde ich verlieren die Helfer Namespace ist, oben in dem Modell, brauchen Sie nicht sie, sondern auch, wie Dienstprogramm Namespaces geben sie faul Entwickler eine Entschuldigung nicht über, wo ein Stück Code, logisch zu denken sitzt. MyApp.Helpers. * Und MyApp.Utility. * Nur bedeutet, dass, wenn ich einen Code haben, eine Ausnahme-Handler sagen, dass vielleicht logisch innerhalb MyApp.Data.Repositories.Customers gehört (vielleicht ist es ein Kunde ref nicht eindeutig zuzuordnen Ausnahme ist), ein fauler Entwickler kann es nur in MyApp.Utility.CustomerRefNotUniqueException platzieren, ohne wirklich zu denken.

Wenn Sie gemeinsamen Rahmen Typ-Code haben, dass Sie einpacken müssen, fügen Sie ein MyApp.Framework Projekt und relevante Namensräume. Ob Du ein neues Modell Bindemittel hinzugefügt, steckte es in MyApp.Framework.Mvc, wenn es gemeinsame Logging-Funktionalität ist, es ausdrückte in MyApp.Framework.Logging und so weiter. In den meisten Fällen sollte es keine Notwendigkeit, ein Dienstprogramm oder Helfer-Namensraum einzuführen.

einpacken

, so dass die Oberfläche kratzt - Hoffnung es ist eine Hilfe. Dies ist, wie ich die Entwicklung von Software heute, und ich habe absichtlich kurz zu fassen versucht - wenn ich auf irgendwelchen Besonderheiten erarbeiten können, lassen Sie es mich wissen. Das letzte, was auf diesem eigenwilligen Stück zu sagen, ist das oben ist für recht groß angelegte Entwicklung - wenn Sie schreiben Notizblock Version 2 oder ein Firmentelefonbuch, über die wahrscheinlich total übertrieben !!!

ist

Prost Tony

Andere Tipps

Es gibt ein schönes Diagramm und eine Beschreibung auf dieser Seite über die Anwendung Layout alhtough sieht weiter unten in dem Artikel die Anwendung ist nicht gespalten in physikalische Schichten (separates Projekt) - Entity Framework POCO Repository

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top