Я волнуюсь, я добавляю слишком много интерфейсов - PullRequest
20 голосов
/ 20 января 2012

Я создаю модель своего домена и продолжаю ее рефакторинг. Как и я, я обнаружил, что мне нравятся интерфейсы, так как это позволяет мне создавать повторно используемые методы / контроллеры / представления для конкретных типов на основе их интерфейсов. Тем не менее, я обнаружил, что создаю интерфейс каждый раз, когда добавляю новое свойство к одной из моих сущностей домена.

Например, у меня есть MemberStatus объект, который наследуется от абстрактного Entity объекта, который, в свою очередь, реализует интерфейс IIdentifiableEntity , что означает, что он имеет свойство Id , MemberStatus также реализует интерфейс INamedEntity , означающий, что он имеет свойство Name, интерфейс IOrderedEntity , означающий, что он имеет свойство DisplayOrder, и интерфейс IHasMembers , означающий, что он имеет Член коллекции объектов. Вот код:

public class MemberStatus : Entity, INamedEntity, IOrderedEntity, IHasMembers
{
  public string Name { get; set; }
  public float DisplayOrder { get; set; }
  public ICollection<Member> Members { get; set; }
}

public abstract class Entity : IIdentifiableEntity
{
  public int Id { get; set; }
}

public interface IIdentifiableEntity
{
  int Id { get; set; }
}

public interface INamedEntity
{
  string Name { get; set; } 
}

public interface IOrderedEntity
{
  float DisplayOrder { get; set; }
}

public interface IHasMembers
{
  ICollection<Member> Members { get; set; }
}

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

Однако меня беспокоит, будет ли уместным продолжать добавлять простые интерфейсы с одним свойством каждый раз, когда я добавляю новое свойство к моим конкретным объектам. Например, скажем, я хочу добавить свойство bool Enabled ... я должен продолжать создавать интерфейс IEnabled ? Причина, по которой я спрашиваю, состоит в том, что некоторые из инициализаторов контроллера, которые используют дженерики, становятся очень длинными, как показано в следующей строке кода. Это нормально и лучше всего?

public abstract class OrderedCrudController<TEntity> : CrudController<TEntity> where TEntity : Entity, INamedEntity, IOrderedEntity, IHasMembers, new()

Ответы [ 3 ]

19 голосов
/ 20 января 2012

Хорошо, что вы используете интерфейсы.Тем не менее, вы должны спросить себя: если я создам IEnabled интерфейс, буду ли я когда-либо ссылаться на свой класс только этим интерфейсом?т.е. будут ли контексты, в которых я взаимодействую со своим классом исключительно через одно свойство, предоставляемое интерфейсом?

Кроме того, можете ли вы рассмотреть контексты, в которых вы будете взаимодействовать с множественной реализацией этого IEnabled интерфейса?

Если ответом на оба вопроса является «нет», то интерфейс служит очень малой цели.

Сказав это, пожалуйста, не беспокойтесь об этом!это приносит очень мало вреда.

15 голосов
/ 20 января 2012

Не создавайте интерфейсы, в которых вы не предвидите неизбежную потребность. Соблюдайте принцип YAGNI (он вам не понадобится). В противном случае вы получите ненужно сложный код.

3 голосов
/ 20 января 2012

Я думаю, что ваша проблема в том, что вы пытаетесь приспособить модель своего домена к тому графическому интерфейсу, в котором вы отображаете данные.

Вместо этого, рассмотрите объекты вашего домена, которые имеют поведение, близкое к данным, и в их поле присвойте ему Action<DomainEvent>. Теперь убедитесь, что вы ТОЛЬКО когда-либо передаете данные из объекта домена через это действие.

Теперь слушай. Всякий раз, когда вы на самом деле хотите внести изменения в свой домен, вызовите для него метод. Позвольте вашему GUI обновляться через Action<DomainEvent>, принимая эти события и сохраняя их в любой интересующей вас модели чтения.

Взгляните на http://www.infoq.com/presentations/ddd-eric-evans и рассмотрите его мнения о событиях в домене.

Теперь вам больше не нужно добавлять странные интерфейсы, связанные с техническим доменом, в ваш бизнес-домен. И запомни; если вы делаете CRUD, как показывают ваши примеры, то вы НЕ делаете дизайн, управляемый доменом. У вас анемичный домен.

Конечная точка: используйте интерфейсы для вещей, которые действительно должны быть взаимозаменяемыми. Вы несете в своем приложении много INamed вещей, которые можно взаимозаменять друг с другом?

Позвольте мне также связать это, чтобы вы рассмотрели:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...