Вопрос по архитектуре
От: Jeremy Россия  
Дата: 25.09.07 07:54
Оценка:
Есть такой простейший пример. Пусть предметная область состоит из двух сущностей — Организация и Департамент, связанных между собой отношением "один-ко-многим" (организация состоит из нескольких департаментов). Допустим нам надо реализовать сервисный метод, возвращающий количество департаментов для заданной организации.

Как это сделано сейчас:

Все обьекты предметной области описывается двумя классами (для примера возьмем Organization)

1. Обьект, описывающий данные (некий аналог фаулеровского DataTransferObject). Основные свойства подобных обектов:
— хранит связи на своих ближайших соседей по обьектному графу в виде идентификаторов (но не хранит сами связанные обьекты)
— не имеет никаких связей с внешним миром (другие слои приложения) и им можно оперировать вне сервисного контекста (в частности его можно передавать клиенту)

    class OrganizationData
    {
        public int Id;
        public int Name;
    }


2. Бизнес-обьект. Класс предметной области, описывающий структуру и поведение обьекта в доменной области. Этим классом можно оперировать только внутри сервисного контекста (секьюрити, коннект к БД, транзакции).


    class Organization
    {
        public Organization(int id)
        {
            this.id = id;
        }

        public Organization(OrganizationData data)
            : this(data.Id)
        {
            this.data = data;
        }

        public OrganizationData Data
        {
            get
            {
                if(data == null)
                {
                    // Load data from db here...
                    data = mapper.GetOrganization(id);
                }
                return data;
            }
        }

        public DepartmentCollection Departments
        {
            get
            {
                if(departments == null)
                {
                    // Load departments from db here
                    departments = mapper.GetDepartments(id);
                }
                return departments;
            }
        }

        public void Delete()
        {
            mapper.Delete(id);
        }

        public void Create()
        {
            mapper.Create(Data);
        }

        private int id;

        private OrganizationData data;

        private DepartmentCollection departments;

        private IDbMapper mapper;
    }


Обращаю внимание, что бизнес обьект общается с БД посредством отдельного интерфейса IDbMapper, реализация которого находится в слое доступа к данным. Также важно отметить, что в реализации применяется принцип LazyLoad, то есть например для того чтобы удалить Организацию нам не придется загружать данные о ней, достаточно только знать его идентификатор:


        new Organization(5).Delete();


Кроме всего прочего, при необходимости обьявляются специализированные классы коллекций типа:


    class DepartmentCollection : Collection<Department>{}


Таким образом, итоговый код получающий количестиво департаментов будет выглядеть примерно так:

    return new Organization(5).Departments.Count;


А теперь вопросы:

1. Критика?
2. Что смущает меня в этой архитектуре, так это наличие связи типа Organization -> IDbMapper, пусть и максимально ослабленной посредством интерфейса. В идеале хотелось бы чтобы обьект предметной области Organization не имел методов типа Delete и вообще не занимался (даже опосредованно) общением с БД. Один из вариантов (описанных у того же Фаулера например) это вынести все мапперы уровнем выше (в сервисный метод), то есть иметь нечто вроде:


    IDbMapper mapper = ...
    return mapper.GetDepartments(5).Count;


Но это, по-моему, еще хуже, поскольку стремительно приближает решение к структурному программированию и гораздо менее наглядно, особенно если логика сервисного метода потребует чего-то большего, нежели просто вычисления количества элементов в коллекции. Что делать?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.