Я беспокоюсь, что добавляю слишком много интерфейсов
Я создаю свою модель домена и продолжаю реорганизовывать ее. Как и я, я считаю, что мне нравятся интерфейсы, поскольку он позволяет мне создавать многоразовые методы/контроллеры/представления для конкретных типов на основе их интерфейсов. Тем не менее, я нахожу, что я создаю интерфейс каждый раз, когда добавляю новое свойство к одному из объектов моего домена.
Например, у меня есть объект MemberStatus, который наследуется от абстрактного объекта Entity, который, в свою очередь, реализует интерфейс IIdentifiableEntity, что означает, что он имеет свойство Id. MemberStatus также реализует интерфейс INamedEntity, означающий, что у него есть свойство Name, интерфейс IOrderedEntity, означающий, что у него есть свойство DisplayOrder и интерфейс IHasMembers, что означает что у него есть объекты коллекции Collection. Здесь код:
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()
Ответы
Ответ 1
Тот факт, что вы используете интерфейсы, - это хорошо. Тем не менее, вы должны спросить себя, создаю ли интерфейс IEnabled
, когда-либо ссылаюсь на свой класс только на этот интерфейс? то есть будут ли контексты, в которых я взаимодействую с моим классом исключительно через единственное свойство, которое предоставляет интерфейс?
Также вы можете рассмотреть контексты, в которых вы будете взаимодействовать с несколькими реализациями этого интерфейса IEnabled
?
Если ответ на оба этих вопроса "нет", интерфейс очень мало предназначен.
Сказав это, пожалуйста, не беспокойтесь об этом! это очень мало вреда.
Ответ 2
Не создавайте интерфейсы, которые вы не предвидите неизбежной необходимости. Обратите внимание на YAGNI (вам это не понадобится). В противном случае вы получите ненужный сложный код.
Ответ 3
Я думаю, ваша проблема в том, что вы пытаетесь обучить свою модель домена во все gui, в котором вы показываете данные.
Вместо этого рассмотрите объекты объекта домена, которые имеют поведение, близкое к данным и в его c'tor, дайте ему Action<DomainEvent>
. Теперь убедитесь, что вы только ТОЛЬКО передаете данные OUT из объекта домена через это действие.
Теперь ты слушаешь. Всякий раз, когда вы действительно хотите внести изменения в свой домен, вызовите на нем метод. Обновите свой графический интерфейс с помощью Action<DomainEvent>
, выполнив эти события и сохраните их в любой интересующей вас модели.
Посмотрите http://www.infoq.com/presentations/ddd-eric-evans и рассмотрите его пункты о событиях домена.
Теперь вам больше не нужно добавлять странные интерфейсы, связанные с техническим доменом в ваш бизнес-домен. И запомни; если вы делаете CRUD, как показано на примерах, то вы НЕ выполняете дизайн, управляемый доменом. У вас анемичный домен.
Конечная точка: используйте интерфейсы для вещей, которые на самом деле должны быть взаимозаменяемыми. Вы несете много вещей в своем приложении, которые могут быть взаимозаменяемы друг с другом?
Позвольте мне также связать это, чтобы вы подумали: