6

Używam asp.net mvc ze strukturą encji i zaczynam uczyć się DDD. Pracuję nad projektem, który zawiera ankiety. Oto mój model domeny:Jaki jest najlepszy sposób na zbudowanie modelu widoku?

public class Survey 
{ 
    public int? SurveyID { get; set; } 
    public string Name { get; set; } 
    public decimal MinAcceptanceScore { get; set; } 
    public int UserFailsCount { get; set; } 

    public IEnumerable<SurveyQuestion> Questions { get; set; } 
    public IEnumerable<Prize> Prizes { get; set; } 
    public IEnumerable<SurveyAttempt> UserAttempts { get; set; } 
} 

muszę różne części badań dla różnych widoków, więc stworzyliśmy różne ViewModels:

public class ShortSurveyViewModel 
    { 
     public int? SurveyID { get; set; } 
     public string Name { get; set; } 
     public int UserFailsCount { get; set; } 
     public IEnumerable<SurveyAttempt> UserAttempts { get; set; } 
    } 

    public class ShortSurveyWithPrizesViewModel 
    { 
     public int? SurveyID { get; set; } 
     public string Name { get; set; } 
     public int UserFailsCount { get; set; } 
     public IEnumerable<SurveyAttempt> UserAttempts { get; set; } 
     public IEnumerable<Prize> Prizes { get; set; } 
    } 

    public class SurveyEditViewModel 
    { 
     public int? SurveyID { get; set; } 
     public string Name { get; set; } 
     public decimal MinAcceptanceScore { get; set; } 
     public int UserFailsCount { get; set; } 

     public IEnumerable<SurveyQuestion> Questions { get; set; } 
     public IEnumerable<Prize> Prizes { get; set; } 
    } 

Jaki byłby najlepszy sposób na budowanie mojego architekturę, jeśli chcę mój repozytorium ankiet w celu uzyskania informacji potrzebnych do modelu podglądu aproperty?

Różne solusions które widzę:

  1. Repository może powrócić IQueryable do SurveyService i serwisu może powrócić widoku modelu appropriete, ale waham się, że robi to w porządku, ponieważ myślę, zobacz modele powinny być tworzone w interfejsie , a nie warstwa Service.

  2. Utwórz trzy odpowiednie klasy w mojej warstwie domeny. Ale teraz domena będzie zależna od reprezentacji i przy każdym nowym widoku powinna zostać utworzona nowa klasa domeny.

  3. Pobierz pełny obiekt domeny i odwzoruj tylko właściwości potrzebne dla określonego widoku. To nie jest dobre, ponieważ na moim przykładzie pytania były potrzebne tylko w jednej reprezentacji i może to być duża kolekcja.

+1

Użyj widoki częściowe –

+1

ViewModels powinien żyć w interfejsie użytkownika i zostać zapełniony w kontrolerze. DAL i warstwy domeny nie powinny o nich wiedzieć –

+0

@DaveA Będę używał częściowych widoków, ale pytanie nie dotyczy tego. Pytam o optymalny sposób budowania moich modeli widoków. –

Odpowiedz

8

Domain Driven Design:

  • Trzeba repozytorium powracającego łączną root - w przypadku Survey i wszystkie relacje, które nie mogą istnieć bez rodzica Survey
  • To repozytorium będzie ładować zawsze cały Survey klasę iw zależności od Twoje wymagania to tylko niektóre relacje (naprawdę dogmatyczny DDD zawsze ładowałby cały agregat, ale to nie jest dobre podejście do bezpaństwowej sieci).
  • Twoja warstwa aplikacji (kontroler) zapyta repozytorium o numer Survey oraz wybrane relacje i wypełni modele widoku.

Cebula architektura:

  • Będziesz tworzyć jakieś repozytorium narażając IQueryable<Survey> - co gorsza będzie używany rodzajowe repozytorium z interfejsu CRUD
  • Będziesz tworzyć jakąś służbę wzywającą repozytorium oraz budowania LINQ-podmioty rzutowanie na swoje DTO i zwracanie ich do warstwy aplikacji (kontrolera)
  • Co teraz? Możesz użyć tych DTOs bezpośrednio lub użyć innego zestawu obiektów wykorzystywanych jako Pana zdaniem niektórych modelach z UI podobne atrybuty itd. Istnieje oczywiście coś nie tak ...

Prosta architektura:

  • Będziesz zastosowanie wstrzykuje IDbSet<Survey> bezpośrednio w kontrolerze jako repozytorium
  • zrobisz LINQ-podmioty bezpośrednio projekcje w kontrolerze do wypełnienia zobacz modele

Ther e nie jest najlepszym sposobem. Zawsze chodzi o twój cel i twoje oczekiwania. W przypadku małych aplikacji można żyć z prostą architekturą bez żadnego problemu.

Projektowanie oparte na domenach jest bardziej złożone. Główną koncepcją DDD są encje domeny, obiekty wartości i ich skład. Domena enkapsuluje dane i logikę wykonywaną na tych danych. DDD nie działa z częściowymi danymi lub DTO - kiedy twoje domeny nie mają żadnej logiki, robisz to źle (nazywa się to anemicznym modelem). Usługa w DDD nie jest mediatorem między warstwą aplikacji a repozytorium. Służy do obsługi logiki biznesowej, która nie jest powiązana z jednostką jednej domeny (dlatego nie może być enkapsulowana w jednostce domeny). Repozytorium to kod infrastruktury niezbędny do zmaterializowania agregatów z pamięci masowej i utrzymywania ich w pamięci masowej. Logika aplikacji (kontroler) może wchodzić w interakcje z domenami, usługami i kodem infrastruktury.

Nie lubię architektury cebuli.

+0

To jest dobrze przemyślane wyjaśnienie. Zastanawiam się, czy mógłbyś wyjaśnić, dlaczego nie lubisz architektury cebuli i być może wyjaśnisz, dlaczego coś jest nie tak ... Nie mam wystarczająco dużo doświadczenia, aby było dla mnie oczywiste. Również nie w pełni rozumiem różnicę między trzecim pociskiem pod DDD a trzecim pociskiem pod cebulą. Czy nie jesteś zasadniczo w tym samym miejscu, to znaczy, kontroler obecnie posiadający obiekty domeny (jednostki w jednym przypadku i DTO w drugim), które mapuje do modeli widoku? Nie gram w diabły adwokata, tylko próbuję się uczyć. –

+0

Dziękuję, Ladislav. Bardzo pouczająca odpowiedź. Ale nie rozumiem, dlaczego nie lubisz architektury cebuli. Z Twojej odpowiedzi wynika, że ​​może to być najlepszy wybór, ponieważ prosta architektura nie odpowiada moim potrzebom, a DDD może nie być dobre dla bezpaństwowej sieci. A gdyby tak nie było, naprawdę dogmatyczny DDD mógłby mieć pewne właściwości Survey, które nie byłyby wypełnione danymi? –

+1

@ Forty-Two: To tylko moja osobista opinia z wcześniejszych doświadczeń. Architektura cebulowa moim zdaniem prowadzi do zbędnych warstw. Pracowałem nawet nad projektami, w których warstwy zostały podzielone na warstwy podrzędne. Pod koniec projektu mieliśmy po prostu mnóstwo kodu, w którym metody górnej warstwy mają tylko jedną linię kodu wywołującego niższą warstwę. Każda dodatkowa funkcjonalność wymagała aktualizacji wielu plików tylko po to, żeby coś przekazać. To naprawdę nie było dobre. –

0

Biorąc pod uwagę fakt, że głównym problemem jest ilość danych pobierane z modelu danych w porównaniu z ilością danych, niezbędnych z punktu widzenia modelu, powiedziałbym odpowiednie podejście dla Ciebie byłoby zbudować widoków w baza danych i ich odpowiednie modele danych.

Dzięki temu można przycinać ilość danych pobranych z bazy danych podczas jednej podróży.

Chociaż modele danych prawie naśladują modele widoków, to nie stanowi to problemu, służą one dwóm różnym celom. Model widoku jest dla Widoku do wiązania - Model danych wie, jak pobierać i zapisywać dane. Zbudowanie tych widoków pozwoliłoby uzyskać optymalne dane - a mimo to umieścić niestandardową logikę zapisu w tych samych modelach, aby można je było zapisywać w razie potrzeby - w związku z tym powstaje potrzeba przenoszenia danych z jednego modelu danych do następnego.

+0

Czy dobrze zrozumiałem, że powinienem mieć dwa dokładne modele (jeden w warstwie danych, inny w prezentacji), a jeśli zmienię jedno, inny również się zmieni? –

+0

@AlexeyAza: będziesz miał dwa modele, model danych (w warstwie danych) i model widoku (w warstwie prezentacji z kontrolerami), ale kluczem jest to, że myślę, że będziesz chciał zbudować Widoki w bazy danych, a nie tylko pobieranie danych z tabeli przez cały czas. Oznacza to, że będziesz mieć modele danych pasujące do Widoku, a modele widoków będą prawdopodobnie wyglądać podobnie do tych modeli danych. Kiedy możesz pobierać dane bezpośrednio z tabeli, użyj standardowego modelu danych dla swojej tabeli i mapuj do modelu widoku. –

+0

Może to ma sens. Ale wyobraźmy sobie sytuację, w której moje pytania mają stronicowanie. Gdzie byś to zastosował? –