Шаблон для общедоступных и внутренних интерфейсов на бизнес-объектах

Я хотел бы разработать модель домена с использованием внутренних интерфейсов, а затем создать ограниченные общедоступные интерфейсы (для пользователей сборки)

Хотя это возможно в CSharp, я продолжаю сталкиваться с грязным кодом, связанным с параллельными интерфейсами:

public interface IAccount { IList<ITran> Transactions { get; } }
internal interface IAccountInternal : IAccount { IList<ITranInternal> Transactions { get; } }
internal class Account : IAccountInternal { }

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

Кроме того, я хотел бы гарантировать, что общедоступные интерфейсы реализованы с использованием внутренних интерфейсов (в отличие от прямого доступа к конкретным классам).

Это должен быть общий сценарий, может ли кто-нибудь порекомендовать чистый подход?


person Jack    schedule 12.06.2011    source источник
comment
Если учетная запись является внутренней, пользователи не смогут ее использовать, если вы не добавите какую-либо фабрику.   -  person Andrei    schedule 12.06.2011
comment
почему вы полны решимости сделать почти все внутренним?   -  person Adam Ralph    schedule 12.06.2011
comment
Чего вы надеетесь достичь с помощью этого шаблона? Какую проблему вы надеетесь решить? Как это принесет цену вашим пользователям/клиентам?   -  person Cos Callis    schedule 12.06.2011
comment
на мой взгляд, интерфейсы - это коммуникационные токены в программировании, и если есть внутренний интерфейс, то это не интерфейс по сути, это что-то другое.   -  person jackie    schedule 13.06.2011
comment
пользователям сборки нужен только простой API на основе интерфейса - я не хочу раскрывать им внутреннюю работу - мне нужны интерфейсы для внутренних классов, чтобы обеспечить тестирование и модульность   -  person Jack    schedule 13.06.2011


Ответы (2)


используя общую ковариантность интерфейса в dot net 4.0, мне удалось навести порядок (обратите внимание на модификатор «out» в параметре T)

public interface IListReadOnly<out T> : IEnumerable<T> {
    int Count { get; }
    T this[int index] { get; }
}//class

это позволяет мне возвращать коллекции внутренних объектов, типизированных как общедоступные объекты, потому что:

public interface IPublic { }
internal interface IPrivate : IPublic { }

теперь это работает:

private IListReadOnly<IPrivate> list = ...
public IListReadOnly<IPublic> List { get { return list; } }
person Jack    schedule 12.06.2011

Это кажется плохой идеей, эта модель кажется очень сложной.

Моя первая мысль — уменьшить потребность во внутренних интерфейсах. Если вы используете их для модульного тестирования, я бы рекомендовал тестировать только внешний (общедоступный) интерфейс и вообще отказаться от использования внутренних интерфейсов.

Кроме того, если вы сможете уточнить необходимость модели внутренней предметной области, это может помочь другим лучше ответить на ваш вопрос.

person Jonathan Rauch    schedule 12.06.2011
comment
модульные тесты были бы слишком крупнозернистыми, и я потерял бы все преимущества интерфейсов для самых сложных частей работы — там, где они мне больше всего нужны. - person Jack; 13.06.2011