Pregunta

A mi antiguo trabajo C ++, siempre nos tomamos gran cuidado en encapsular las variables miembro, y sólo exponerlos como propiedades cuando sea absolutamente necesario. Tendríamos constructores muy específicos que se aseguró de que construyó totalmente el objeto antes de utilizarlo.

En estos días, con marcos ORM, la dependencia de la inyección, la serialización, etc., parece que es mejor sólo confiar en el constructor por defecto y exponiendo todo acerca de su clase en las propiedades, por lo que se puede inyectar cosas, o construir y poblar los objetos de forma más dinámica.

En C #, se ha dado un paso más con inicializadores de objeto, que le dan la capacidad de definir básicamente su propio constructor. (Sé inicializadores de objeto no son realmente constructores personalizados, pero espero que mi punto.)

¿Hay alguna preocupación general con esta dirección? Parece que la encapsulación está empezando a ser menos importante a favor de la conveniencia.

EDIT: Sé que todavía se puede encapsular cuidadosamente miembros, pero me siento como cuando se está tratando de poner hacia fuera algunas clases, ya sea que usted tiene que sentarse y pensar cuidadosamente acerca de cómo encapsular cada miembro, o simplemente exponerlo como una propiedad, y la preocupación acerca de la forma en que se inicia más tarde. Sólo parece que el enfoque más fácil en estos días es para exponer las cosas como propiedades, y no ser tan cuidadoso. Tal vez me equivoque solo plano, pero eso es sólo mi experiencia, espeically con las nuevas características del lenguaje C #.

¿Fue útil?

Solución

No estoy de acuerdo con su conclusión. Hay muchas buenas maneras de encapsular en C # con todas las tecnologías mencionadas anteriormente, como para mantener las buenas prácticas de software de codificación. También me gustaría decir que depende de la tecnología cuya demostración que usted está mirando, pero al final todo se reduce a la reducción del espacio de estado de los objetos para que pueda asegurarse de que tienen sus invariantes en todo momento.

Tome marcos relacionales objetos ; la mayoría de ellos le permiten especificar cómo se va a hidratar las entidades; NHibernate, por ejemplo, le dice tan access="property" o access="field.camelcase" y similares. Esto le permite encapsular sus propiedades.

Inyección de dependencia trabajos sobre los otros tipos que tiene, sobre todo aquellas que no son entidades, a pesar de que se pueden combinar AOP + ORM + COI en algunos aspectos muy buenos para mejorar el estado de estas cosas. COI se utiliza a menudo a partir de capas por encima de las entidades del dominio si usted está construyendo una aplicación basada en datos, lo que supongo que eres, ya que estamos hablando de ORM.

( "ellos" siendo los servicios de aplicaciones y de dominio y otras clases intrínsecas al programa) exponer sus dependencias, pero en realidad puede ser encapsulado y probado en el aislamiento aún mejor que antes ya que los paradigmas de diseño por contrato / diseño- por-interfaz que se utiliza a menudo cuando burlarse dependencias en las pruebas basadas en simulacro (en conjunción con la COI), se moverá hacia "semántica" clase-as-componente. Es decir: cada clase, cuando se construyó usando lo anterior, será mejor encapsulado

.

Actualización de urig: Esto es válido tanto para la exposición de hormigón dependencias e interfaces que exponen. En primer lugar acerca de las interfaces: Lo que estaba insinuando anterior era que los servicios y otras aplicaciones de clases que tienen dependencias, pueden con programación orientada a objetos dependerá de contratos / interfaces más que las implementaciones específicas. En C / C ++ y lenguajes anteriores, no había la interfaz y las clases abstractas sólo puede ir tan lejos. Interfaces le permiten atar diferentes instancias de tiempo de ejecución a la misma interfaz sin tener que preocuparse por fugas de estado interno que es lo que está tratando de escapar de abstraer y encapsular cuando. Con clases abstractas todavía puede proporcionar una implementación de la clase, al igual que no se puede crear una instancia de ella, pero herederos todavía necesita saber acerca de las invariantes en su aplicación y que pueden estropear el estado.

En segundo lugar, sobre las clases concretas como propiedades: hay que tener cuidado acerca de qué tipos de tipos;) se expone como propiedades. Digamos que tiene una lista en la instancia; a continuación, no exponga IList como la propiedad; esto probablemente se fuga y no se puede garantizar que los consumidores de la interfaz no añaden cosas o eliminar cosas, que los que depende; en cambio exponer algo así como IEnumerable y devolver una copia de la lista, o mejor aún, hacerlo como un método: MiColeccion pública IEnumerable {get {return _List.Enum (); }} Y puede estar 100% seguro de conseguir tanto el rendimiento como la encapsulación. Nadie puede agregar o quitar a ese IEnumerable bien y aún así no tener que realizar una copia vestidos costosos. El correspondiente método de ayuda:

static class Ext {
    public static IEnumerable<T> Enum<T>(this IEnumerable<T> inner) {
        foreach (var item in inner) yield return item;
    }
}

Así, mientras que no se 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 utilizar las nuevas características de .Net 4.0 construidas sobre Spec # para verificar los contratos que hablé anteriormente.

serialización siempre estará ahí y ha sido durante mucho tiempo. Previamente, antes de que el área de Internet que se utiliza para guardar el gráfico de objetos en el disco para su posterior recuperación, ahora se ha utilizado en los servicios web, copia de la semántica y al pasar los datos a, por ejemplo, un navegador. Esto no significa necesariamente romper la encapsulación si se pone un par de atributos [NonSerialized] o las equivalentes en los campos correctos.

inicializadores de objeto no son los mismos que los contrastructors, no son más que una forma de colapsar unas pocas líneas de código. Valores / instancias en el {} no será asignado hasta que todos los constructores han funcionado, por lo que, en principio, que es lo mismo que no usar inicializadores de objeto.

supongo, lo que tiene que tener en cuenta es desviarse de los principios de buena que ha aprendido de su trabajo anterior y asegúrese de mantener los objetos de dominio lleno de lógica de negocio detrás de encapsulado buenas interfaces y lo mismo para su servicio- capa.

Otros consejos

Los miembros privados siguen siendo increíblemente importante. El control del acceso a los datos objeto interno siempre es buena, y no debe ser ignorada.

Muchas veces los métodos privados que he encontrado para ser excesiva. La mayoría de las veces, si el trabajo que está haciendo es lo suficientemente importante como para salir, puede refactorizar de tal manera que a) el método privado es trivial, o bien b) es una parte integral de otras funciones.

Además, la prueba de la unidad, que tiene muchos métodos privada hace que sea muy difícil de probar la unidad. Hay maneras de evitar que (hacer prueba de objetos amigos, etc.), además de añadir dificultades.

No me descontar los métodos privados por completo sin embargo. Cada vez que hay algoritmos internos importantes, que realmente no tienen sentido fuera de la clase que no hay razón para exponer esos métodos.

Creo que la encapsulación es todavía importante, que ayuda más en las bibliotecas que cualquier otra cosa en mi humilde opinión. Puede crear una biblioteca que hace X, pero no es necesario que todos sepan cómo se creó X. Y si desea crear más específicamente para ofuscar la forma de crear X. La forma en que aprendí sobre la encapsulación, recuerdo también que se debe definir siempre las variables como privadas para protegerlos de un ataque de datos. Para protegerse contra un hacker romper su código y el acceso a las variables que no se supone que deben utilizar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top