No estoy de acuerdo con su conclusión. Hay muchas buenas formas de encapsular en C# con todas las tecnologías mencionadas anteriormente, como para mantener buenas prácticas de codificación de software. También diría que depende de la demo de tecnología que estés viendo, pero al final todo se reduce a reducir el espacio de estado de tus objetos para que puedas asegurarte de que mantienen invariantes en todo momento.
Tome objetos marcos relacionales; la mayoría de ellos le permiten especificar cómo van a hidratar las entidades; NHibernate, por ejemplo, le permite decir access="property"
o access="field.camelcase"
y similares. Esto le permite encapsular sus propiedades.
Dependency injection trabaja en los otros tipos que tiene, principalmente aquellos que no son entidades, aunque puede combinar AOP + ORM + IOC de maneras muy agradables para mejorar el estado de estas cosas. IoC se usa a menudo desde capas encima de las entidades de tu dominio si estás creando una aplicación basada en datos, que supongo que eres, ya que estás hablando de ORM.
Ellos ("ellos" son servicios de aplicación y de dominio y otras clases intrínsecas del programa) exponen sus dependencias, pero de hecho pueden encapsularse y probarse en un aislamiento aún mejor que anteriormente desde los paradigmas de diseño por contrato/diseño -by-interface que a menudo usa cuando se burla de las dependencias en las pruebas basadas en simulacro (junto con IoC), lo moverá hacia la "semántica" clase-componente. Quiero decir: cada clase, cuando se construya usando lo anterior, estará mejor encapsulada.
Actualizado para la urig: Esto es válido tanto para la exposición de hormigón dependencias e interfaces que exponen. Primero sobre las interfaces: lo que estaba insinuando anteriormente era que los servicios y otras clases de aplicaciones que tienen dependencias, pueden con OOP depender de contratos/interfaces en lugar de implementaciones específicas. En C/C++ y en los idiomas más antiguos no existía la interfaz, y las clases abstractas solo pueden ir tan lejos. Las interfaces le permiten vincular diferentes instancias de tiempo de ejecución a la misma interfaz sin tener que preocuparse por la fuga del estado interno, que es lo que está tratando de evitar cuando abstrae y encapsula. Con las clases abstractas todavía puede proporcionar una implementación de clase, solo que no puede crear una instancia, pero los herederos todavía necesitan saber sobre las invariantes en su implementación y eso puede arruinar el estado.
En segundo lugar, acerca de las clases concretas como propiedades: debe tener cuidado con los tipos de tipos;) que expone como propiedades. Digamos que tienes una lista en tu instancia; entonces no expongas IList como la propiedad; esto probablemente se filtre y no se puede garantizar que los usuarios de la interfaz no agreguen cosas ni eliminen cosas de las que dependas; en su lugar, exponga algo como IEnumerable y devuelva una copia de la Lista, o mejor aún, hágalo como método: public IEnumerable MyCollection {get {return _List.Enum(); }} y puede estar 100% seguro de obtener tanto el rendimiento como la encapsulación. Nadie puede agregar o eliminar ese IEnumerable y todavía no tiene que realizar una costosa copia de matriz. El método de ayuda correspondiente:
static class Ext {
public static IEnumerable<T> Enum<T>(this IEnumerable<T> inner) {
foreach (var item in inner) yield return item;
}
}
Así que mientras usted no puede obtener el 100% de encapsulación en, por ejemplo la creación de una sobrecarga igual a operadores/método que puede acercarse con sus interfaces públicas.
También puede usar las nuevas características de .Net 4.0 basado en SpeC# para verificar los contratos de los que hablé anteriormente.
La serialización siempre estará allí y lo ha estado durante mucho tiempo. Anteriormente, antes del área de Internet se usaba para guardar su gráfico de objetos en el disco para su posterior recuperación, ahora se usa en servicios web, en semántica de copia y al pasar datos a, p. un navegador. Esto no necesariamente rompe la encapsulación si coloca algunos atributos [No serializados] o los equivalentes en los campos correctos.
Los inicializadores de objetos no son lo mismo que los constructores, son solo una manera de colapsar unas pocas líneas de código. Los valores/instancias en {} no se asignarán hasta que se hayan ejecutado todos sus constructores, por lo que en principio es lo mismo que no usar los inicializadores de objetos.
Supongo que lo que debe vigilar es desviarse de los buenos principios que aprendió de su trabajo anterior y asegurarse de mantener sus objetos de dominio llenos de lógica de negocios encapsulada detrás de buenas interfaces y lo mismo para su servicio -capa.
No dejes que nadie te engañe, esos inicializadores de objetos son solo azúcar sintáctico. – BobbyShaftoe
Sé que los inicializadores de objetos no son realmente constructores, pero ese no es mi punto. Le permiten construir un objeto usando el constructor predeterminado y establecer propiedades a mano. –
No estoy seguro de qué diferencia hay entre esas y simplemente escribiendo cada declaración para establecer cada propiedad. Pero está bien. – BobbyShaftoe