Я не согласен с твоим выводом. Есть много хороших способов инкапсуляции в 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] или их эквиваленты в правильные поля.
Инициализаторы объектов - это не то же самое, что конструкторы, они просто способ свернуть несколько строк кода. Значения / экземпляры в {} не будут назначаться до тех пор, пока все ваши конструкторы не будут запущены, поэтому в принципе это то же самое, что и не использовать инициализаторы объектов.
Я предполагаю, что вам нужно остерегаться отхода от хороших принципов, которые вы усвоили из своей предыдущей работы, и следить за тем, чтобы ваши объекты домена были заполнены бизнес-логикой, инкапсулированной за хорошими интерфейсами, и то же самое для вашего уровня обслуживания.
person
Henrik
schedule
18.02.2009