Я не согласен с вашим выводом. Есть много хороших способов инкапсуляции в c # со всеми вышеупомянутыми технологиями, чтобы поддерживать хорошие методы кодирования программного обеспечения. Я бы также сказал, что это зависит от того, на какую технологическую демонстрацию вы смотрите, но в конечном итоге все сводится к сокращению пространства состояний ваших объектов, чтобы вы могли всегда следить за тем, чтобы они сохраняли свои инварианты.
Взять объектные реляционные рамки ; большинство из них позволяют вам указать, как они собираются увлажнять сущности; NHibernate, например, позволяет вам, так сказать, access="property"
или access="field.camelcase"
и тому подобное. Это позволяет вам инкапсулировать ваши свойства.
Внедрение зависимостей работает с другими имеющимися у вас типами, в основном с теми, которые не являются сущностями, даже если вы можете комбинировать AOP + ORM + IOC несколькими очень хорошими способами, чтобы улучшить состояние этих вещей. IoC часто используется на уровнях выше ваших доменных сущностей, если вы создаете приложение, управляемое данными, что, я полагаю, и есть, поскольку вы говорите об ORM.
Они («они» являются прикладными и доменными службами и другими внутренними классами для программы) раскрывают свои зависимости, но на самом деле могут быть инкапсулированы и протестированы в еще лучшей изоляции, чем ранее, поскольку парадигмы «дизайн по контракту / дизайн» Интерфейс, который вы часто используете при имитации зависимостей в тестировании на основе имитаций (в сочетании с IoC), приведет вас к «семантике» класса как компонента. Я имею в виду: каждый класс, построенный с использованием вышеизложенного, будет лучше инкапсулирован.
Обновлено для urig: Это верно как для демонстрации конкретных зависимостей , так и для предоставления интерфейсов. Сначала об интерфейсах: на что я намекал выше, было то, что сервисы и другие классы приложений, которые имеют зависимости, могут с ООП зависеть от контрактов / интерфейсов, а не от конкретных реализаций. В C / C ++ и более старых языках не было интерфейса, и абстрактные классы могут зайти так далеко. Интерфейсы позволяют привязывать разные экземпляры среды выполнения к одному и тому же интерфейсу, не беспокоясь о утечке внутреннего состояния, от которой вы пытаетесь избавиться при абстрагировании и инкапсуляции. С абстрактными классами вы все еще можете обеспечить реализацию класса, просто вы не можете создать его экземпляр, но наследникам все еще нужно знать об инвариантах в вашей реализации, и это может испортить состояние.
Во-вторых, о конкретных классах как свойствах: вы должны быть осторожны с типами типов;) вы выставляете их как свойства. Скажем, у вас есть список в вашем случае; тогда не выставляйте IList как собственность; это, вероятно, утечка, и вы не можете гарантировать, что потребители интерфейса не будут добавлять или удалять вещи, от которых вы зависите; вместо этого выставьте что-то вроде IEnumerable и верните копию списка, или, что еще лучше, сделайте это как метод:
public IEnumerable MyCollection {get {return _List.Enum (); }} и вы можете быть на 100% уверены, что получите как производительность, так и инкапсуляцию. Никто не может добавить или удалить этот IEnumerable, и вам все равно не нужно выполнять дорогостоящее копирование массива. Соответствующий вспомогательный метод:
static class Ext {
public static IEnumerable<T> Enum<T>(this IEnumerable<T> inner) {
foreach (var item in inner) yield return item;
}
}
Так что, хотя вы не можете получить 100% инкапсуляцию, скажем, при создании перегруженных операторов равенства / метода, вы можете приблизиться к общедоступным интерфейсам.
Вы также можете использовать новые функции .Net 4.0, построенные на Spec #, чтобы проверить контракты, о которых я говорил выше.
Сериализация всегда будет там и была в течение долгого времени. Ранее, до интернет-области, он использовался для сохранения графа объектов на диске для последующего поиска, теперь он используется в веб-сервисах, в семантике копирования и при передаче данных, например браузер Это не обязательно нарушит инкапсуляцию, если вы добавите несколько [NonSerialized] атрибутов или эквивалентов в правильные поля.
Инициализаторы объектов - это не то же самое, что конструкторы, они просто способ свернуть несколько строк кода. Значения / экземпляры в {} не будут назначены до тех пор, пока не будут запущены все ваши конструкторы, поэтому в принципе это все равно, что не использовать инициализаторы объектов.
Я полагаю, что вам следует остерегаться отклонения от хороших принципов, которые вы узнали из предыдущей работы, и убедитесь, что ваши доменные объекты заполнены бизнес-логикой, инкапсулированной за хорошими интерфейсами и тем же для вашей службы. слой.