DDD - Управление связью между доменом и хранилищем

У меня очень простой вопрос: как сохранить личные данные моего класса в хранилище для сохранения?

Независимо от принятого нами архитектурного стиля, все согласны с тем, что бизнес-объекты не должны знать, "как" спасти себя, то есть они не должны реализовывать базу данных или другие детали персистентности. Однако мне кажется, что бизнес-объекты - это единственные, кто знает, "что" им нужно сохранить. Репозиторий знает, как извлечь из базы данных, но если он хочет знать, как перевести бизнес-объект в термины базы данных, то он должен знать, что переводить.

Учтите, что я могу использовать базу данных, но я не размечаю свои классы аннотациями гибернации, потому что я мог бы так же часто сохранять их в простой текстовый файл.

Предполагая, что мои классы здесь на самом деле названы в честь конкретных бизнес-объектов, что было бы неправильно делать что-то вроде

interface Exporter
{
    public void Export(String id, String value1, String value2);
}

interface Repository
{
    public Entity FindById(String id);
}

class Entity
{
    private String id;
    private String value1;
    private String value2;
    private String derivedvalue;

    public Entity() {}

    public Entity(String id, String value1, String value2)
    {
        this.id = id;
        this.value1 = value1;
        this.value2 = value2;
        this.derivedvalue = /* derived from id, value1, and value2 */;
    }

    public void DoBusiness()
    {
        // ...
    }

    public void Export(Exporter exporter)
    {
        Exporter.Export(this.id, this.value1, this.value2);
    }
}

и используя его как

FlatFileRepositoryAndExporter flatfile = new FlatFileRepositoryAndExporter(...);
Entity entity = flatfile.FindById(...);

// Do business logic
entity.DoBusiness();

entity.Export(flatfile);

Я понимаю, что существуют рамки, которые могут мне помочь, но в конечном итоге все они полагаются на своего рода отражение. Я хочу знать, не задумываясь, как я могу статически составлять свои объекты, чтобы представить их данные, сохраняя при этом инкапсуляцию. Единственный ответ, который я могу придумать - это шаблон посетителей.

2 ответа

Решение

Я склонен согласиться с @MikeSW в том, что сделать внешние инструменты персистентности способными собирать состояние объекта домена с помощью незначительных корректировок области (или отражения, как это делают ORM), часто проще, чем позволить самому объекту домена полностью контролировать то, что сохраняется.

Есть третий способ, который заключается в том, чтобы заставить объект испускать события, описывающие то, что произошло, а не раскрывать его состояние - это Event Sourcing. Тогда тот, кто захочет, может слушать их и сохранять изменения в любой форме, которую они хотят получить.

Не усложняй свою жизнь слишком сильно. То, что вы пытаетесь сделать, - это, по сути, сувенир, который работает, но имеет высокие (как при очень скучных) затраты на обслуживание. Я обычно json сериализую вещи независимо от того, где я их храню, и я настроил json.net для сериализации защищенных свойств. В общем, у меня есть защищенные свойства или просто защищенные сеттеры, и это работает довольно хорошо.

Хотя это не пуристическое решение, компромисс очень низок, внутренности объекта не открыты для его пользователя. И вы можете иметь такие вещи, как

 private List<string>_data=new List<string>();
public IEnumerable<string> Data 
{
   get { return _data;}
   protected set {  _data=value.ToList(); }

}

Этот подход достаточно прост, очень удобен в обслуживании и настойчив в использовании.

Кстати, экспортер, учитывая его цель, должен иметь дело только с публичными членами, и объект не должен знать об этом.

Другие вопросы по тегам