Подтвердить что ты не робот

Использует ли один-к-одному интерфейс с объектами домена хорошую или плохую практику? Зачем?

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

Например:

Учетная запись объекта домена:

public class Account : IAccount
{
     public string Name {get;set;}
     //...some more fields that are also in IAccount
     public decimal Balance {get;set;}
}

И он соответствует интерфейсу

public interface IAccount
{
   string Name {get;set;}
   //... all the fields in Account
   decimal Balance {get;set;}
}

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

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

Сначала было заявлено, что эти интерфейсы обеспечивают "развязку", но я отменяю это, потому что интерфейсы имеют взаимно-однозначные отношения с объектами домена, что они действительно не обеспечивают никакой развязки, изменение интерфейса изменение объекта домена и наоборот.

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

Так что мне любопытно:

Почему у вас есть индивидуальные интерфейсы для ваших объектов домена?

Почему бы и нет?

Почему это хорошая или плохая практика?

Спасибо за чтение!

EDIT: я должен отметить, что я все время использую интерфейсы, и я считаю, что если он потребует, я буду использовать интерфейс при падении шляпы. Но я специально ссылаюсь на объекты домена с индивидуальными интерфейсами.

4b9b3361

Ответ 1

Это плохая практика, как описано, но...

Нет особых причин, по которым ваши интерфейсы должны отличаться от ваших доменных объектов; иногда это действительно правильное отображение. Но подозрительно, что это всегда так. Проблемой является вопрос о том, действительно ли были разработаны интерфейсы или были ли они просто выброшены на место из-за отсутствия времени/лень.

Чтобы использовать ваш пример, интерфейс IAccount, который вы описываете, раскрывает геттеры и сеттеры объекта Account; кажется немного странным и маловероятным, что все, что использует учетную запись, будет необходимо установить баланс в учетной записи, а это подразумеваемое разрешение указывается на этом уровне интерфейса. Нет ли места в вашей системе, где вы хотите просто проверить, но не установить баланс аккаунта?

Ответ 2

Самая большая причина всегда указывать объекты домена как интерфейсы, а не непосредственно как классы, - это дать вам определенную степень свободы при реализации. В вашем примере у вас есть только один вид IAccount, поэтому он немного лишний.

Но что, если бы у вас было, например:

public class Account : IAccount { ... }       // Usual account, persistent
public class MockAccount : IAccount { ... }   // Test mock object
public class TransAccount : IAccount { ... }  // Account, not persistent
public class SimAccount : IAccount { ... }    // Account in a performance sim

и т.д.?

Определяя объекты домена как интерфейсы, вы можете заменить реализации, не нарушая определения вашего домена.

Ответ 3

В общем, если мои классы не будут частью шаблона проектирования, такого как "Стратегия" или "Посетитель", я не добавляю интерфейсы.

Добавление интерфейсов действительно полезно для шаблонов проектирования, таких как "Стратегия" и "Посетитель", но в таких случаях я не копирую геттеры и сеттеры классов домена. Вместо этого я создаю интерфейсы, которые специфичны для создаваемых мной интерфейсов шаблона проектирования.

interface SomeStrategy {
   void doSomething(StrategyData data);
}

interface StrategyData {
   String getProperty1();

   String getProperty2();
} 

Это позволяет мне позволить классам домена реализовать эти интерфейсы или использовать шаблон адаптера. Я считаю, что это гораздо более чистый подход, который просто создает интерфейсы для этого.

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

Ответ 4

Интерфейсы "один к одному" на объектах являются анти-образными

Джеймс Грегори поставил его лучше меня здесь.

Ответ 5

Я согласен с тобой. Интерфейсы должны действовать как контракт, поэтому нет никакой ценности от наличия индивидуальных интерфейсов с объектами домена. Это может быть полезно, если вы хотите абстрагироваться от определенного поведения. Но это будет работать в определенных случаях.

Ответ 6

Почему этот человек вышел из строя?

Я нашел интерфейс для объекта домена, как сказал Чарли Мартин, позволяет мне выбирать мою реализацию.

Основным примером является идентификатор (object.Id) для объекта, это будет отличаться в зависимости от того, где вы храните этот объект, и ответственность за его создание может или не может быть сохранена при реализации данных позже. В SQL Server вы можете использовать autonumber, но в хранилище таблиц Azure вы можете использовать Guid, но вы не хотите менять бизнес-логику своего приложения, потому что вы меняете место хранения ваших данных.

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

Мы рассмотрим тот же аргумент о том, каким должен быть адрес, если бы у меня не было IAddress, новые программисты переписывали бы вещи для кредитных карт, если бы это не было для ICreditCard.

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

Есть место для большинства шаблонов даже для злоумышленника Синглтона, что означает его не "анти-шаблон", по крайней мере, насколько предполагает этот термин.