Wzór repozytorium: jak leniwie ładować? czy powinienem podzielić ten agregat?

Mam model domeny, który ma koncepcję Edytora i projektu.

Redaktor jest właścicielem wielu projektów, a projekt ma nie tylko właściciela edytora, ale także kilku członków redakcji. W związku z tym redaktor ma również szereg "połączonych" projektów.

Biorę podejście DDD do modelowania tego i używam wzorca repozytorium dla trwałości. Jednak nie grok wzór jeszcze wystarczająco dobrze, aby określić, jak mam to zrobić.

Pracuję nad założenie, że Edytor i projekt są potencjalnie w tym samym agregacie, z głównym edytorem. Mogę zatem uzyskać redaktora, a następnie wyliczyć jego projekty, a stamtąd mogę wyliczyć redaktorów członków projektów.

Jednakże, jeśli Mogę pobierać tylko Edytory z mojego repozytorium, czy to nie znaczy, że muszę załadować wszystkie projekty z repozytorium, gdy otrzymam edytor, który je posiada? A jeśli chcę leniwie załadować redaktorów członkowskich, projekt potrzebuje odniesienia do repozytorium też?

Alternatywnie, jeśli podzielę agregat i mam repozytorium Edytora i repozytorium projektu, jak powinienem obsługiwać transakcję między tymi dwoma, na przykład gdy nowy projekt jest dodawany do edytora? Na przykład:

Editor e = new Editor("Editor Name");
editorRepository.Add(e);

Project p = e.CreateProject("Project Name");
projectRepository.Add(p);    // These two lines
editorRepository.Save(e);    // should be atomic

Czy źle interpretuję intencje wzorca repozytorium?

Author: Jim G., 2009-01-19

4 answers

Czy źle interpretuję intencje wzorca repozytorium?

Powiem "tak", ale wiedz, że ja i każda osoba, z którą pracowałem, pytaliśmy o to samo z tego samego powodu... "nie myślisz o czwartym wymiarze, Marty".

Uprośćmy to trochę i zostańmy przy konstruktorach zamiast najpierw tworzyć metody:

Editor e = new Editor("Editor Name");
e = editorRepository.Add(e);

Project p = new Project("Project Name", e);
p = projectRepository.Add(p);

Poniżej, twoje repozytorium projektu zawsze przechowuje poprawnego właściciela (p.EditorId) w danych projektu, ponieważ stworzony, i jakkolwiek ponownie wypełnisz projekty edytora, będzie tam. Dlatego dobrą praktyką jest umieszczanie wszystkich wymaganych właściwości w konstruktorach. Jeśli nie chcesz przekazać całego obiektu, wystarczy e.Id.

A jeśli chcę leniwie załadować redaktorów członkowskich, projekt potrzebuje odniesienia do repozytorium, jak również?

Teraz, Jak ponownie wypełnić projekty redaktora na żądanie, masz kilka opcji w zależności od tego, co zamierzasz. Proste repozytorium mówi, że chcesz:

IEnumerable<Project> list = projectRepository.GetAllProjects()
                                .Where(x => x.editorId == e.Id);

Ale gdzie to umieścić? Nie wewnątrz projektu, czy edytora, masz rację, albo będą musieli uzyskać dostęp do repozytoriów i to nie jest dobre. Powyższy fragment jest luźno sprzężony, ale sam nie nadaje się do wielokrotnego użytku. Właśnie osiągnąłeś granice wzorca repozytorium.

Następna jest warstwa adaptera dla Twojej aplikacji, ze współdzielonym źródłem repozytoriów (StaticServiceWrapper) i albo jakimś obiektem EditorAdapter (lub agregatem lub cokolwiek byś nazwał ich) lub Teraz możesz mieszać w metodach rozszerzeń, które mogą płynnie rozmawiać z dowolnymi niezbędnymi repozytoriami. Nie zrobiłem tego dokładnie w ten sposób w systemie produkcyjnym, ale aby pokazać zwięzły przykład:

public static class Aggregators
{
    // one to one, easy
    public static Editor GetOwner(this Project p)
    {
        return StaticServiceWrapper.editorRep.GetEditorById(p.editorId);
    }

    // one to many, medium
    public static IEnumerable<Project> GetProjects(this Editor e) 
    { 
        return StaticServiceWrapper.projectRep.GetAllProjects()
                .Where(x => x.editorId == e.Id);
    }

    // many to many, harder
    public static IEnumerable<Editor> GetMembers(this Project p)
    {
        var list = StaticServiceWrapper.projectMemberMap.GetAllMemberMaps()
                        .Where(x => x.projectId == p.projectId);

        foreach ( var item in list )
            yield return StaticServiceWrapper.editorRep.GetEditorById(item.editorId);
    }
}

Zasadniczo, po zakończeniu getall, GetById, Add, Update,Remove Object repozytorium jest gotowe, musisz zostawić skojarzenia w spokoju i przejść w górę hierarchii obiektów / warstw do zabawnych części, takich jak adaptery i pamięci podręczne i logika biznesowa ("Oh, my!").

 30
Author: ifatree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-14 04:40:20

A może podział obowiązków na redaktora i redaktora?

Bez znajomości Twojej domeny, wyobrażam sobie, że mają inne obowiązki - na przykład właściciel EditorOwner może być dość bogaty( i może być zbiorczym korzeniem), ale projekt może potrzebować tylko ograniczonej ilości informacji o swoich członkach, więc obiekt EditorMember może być dość lekki.

Te obiekty domeny mogą również odnosić się do użytkowników, ale byłoby to w innym kontekście.

Robi to pomaga, czy tylko komplikuje sprawę?

 4
Author: Michael Hart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 04:55:44

To zależy od potrzeb Twojej aplikacji. Jeśli załadowanie wszystkich projektów dla danego edytora jest dużym problemem, spróbuj użyć leniwego wzorca ładowania, takiego jak Virtual Proxy .

Jeśli chodzi o leniwe Ładowanie redaktorów projektu, jeśli używasz Wirtualnego Proxy, nie widzę problemu z wstrzyknięciem proxy do EditorRepository, ponieważ nie uważam, że proxy jest częścią domeny.

Jeśli podzielisz Agregat, możesz zbadać jednostkę pracy wzór jako jedno z rozwiązań atomiczności. Ten problem nie jest jednak unikalny dla DDD i jestem pewien, że istnieją inne rozwiązania dla zachowań transakcyjnych.

 3
Author: moffdub,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 02:45:29

Tutaj masz 2 różne relacje, jeden dla własności i jeden dla członkostwa.

Relacja własności jest prosta jeden do wielu (Jeden właściciel dla każdego projektu). Relacja członkowska jest wiele do wielu (wielu redaktorów według projektów, wiele projektów według redaktorów).

Możesz podać właściwość właściciela na klasie projektu i podać metodę na ProjectRepository, aby uzyskać wszystkie projekty należące do określonego edytora.

Dla wielu relacji, zapewnić własność członków na klasie projektu i metody na ProjectRepository, aby uzyskać wszystkie projekty zawierające określony edytor jako członek.

Wydaje się również, że redaktorzy i projekty są bytami, prawdopodobnie podzieliłbym agregat, ale być może te terminy mają określone znaczenie w Twoim kontekście, które czynią je subentities agregatu.

 0
Author: thinkbeforecoding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-11 13:01:07