2010-07-07 14 views
26

Estoy leyendo el libro "Código limpio" y estoy luchando con un concepto. Cuando se habla sobre objetos y estructuras de datos, se establece lo siguiente:Código de limpieza: ¿Deberían los objetos tener propiedades públicas?

  • Los objetos ocultan sus datos detrás de las abstracciones y exponen las funciones que operan con esos datos.
  • Las estructuras de datos exponen sus datos y no tienen funciones significativas.

Entonces, lo que obtendré de esto es que no debería tener propiedades públicas en mi objeto, solo debería tener métodos que realicen operaciones en las propiedades. Si necesito acceder a las propiedades, deberían estar en una estructura de datos, que podría ser devuelta por un método en mi objeto. Con este enfoque, parece que necesitaría un método GetHeight() y SetHeight() para mi propiedad Height en mi objeto, en lugar de simplemente usar obtener y establecer de la propiedad.

Tal vez no entiendo exactamente lo que se sugiere, pero esta es mi comprensión de "Los objetos ocultan sus datos." Si pudieras ayudarme a entender esto, ¡lo agradecería mucho!

¡Gracias de antemano!

+2

Para añadir a la respuestas a continuación, la confusión probablemente se debe al hecho de que muchos idiomas no admiten propiedades. En este caso, puede elegir entre los métodos de acceso y los campos públicos, y la opción correcta es siempre los métodos de acceso. C# no tiene este problema, ya que admite propiedades. –

Respuesta

17

Las propiedades públicas están bien. No tener que escribir explícitamente GetHeight() y SetHeight() métodos es de qué se tratan las propiedades. Una propiedad en C# es datos no; se ve mejor como un par de métodos getter/setter. (Las propiedades se compilan en realidad en los métodos en la IL generada)

La ocultación de datos es posible porque puede cambiar la implementación sin cambiar la interfaz.Por ejemplo, podría cambiar

public int Height { get; set; } 

en

public int Height { get { return m_width; } set { m_width = value; } } 

si decide que su objetivo siempre debe ser cuadrada. El código que usa tu clase no necesitaría ninguna modificación.

De modo que si su objeto expone propiedades públicas, aún "oculta los datos detrás de las abstracciones y expone las funciones que operan con esos datos", como recomienda el libro.

4

Las propiedades son, de hecho, métodos.
El compilador compila propiedades para obtener/establecer métodos MIL.

30

De hecho, una propiedad de C# no es datos, es un descriptor de acceso, por lo que se trata de una función que funciona con datos.

Debe evitar los campos públicos, no las propiedades públicas.

+3

sí, pero los campos públicos son correctos en objetos de transferencia de datos –

+2

Evito los DTO, pero en contextos particulares. Cuando tengo que usarlos, prefiero auto-propiedades. – onof

+0

Para casi todos los proyectos, no hay ninguna razón para preferir propiedades sobre campos, y varias razones para preferir campos. Los campos son: [1] guarranteed behaviourless (cambiar a una propiedad para agregar el comportamiento requiere una recompilación esto es * bueno *); [2] a veces más rápido y nunca más lento; [3] tienen un código más corto; [4] puede ser 'readonly', que es una garantía mucho más sólida que' get' solamente. Solo use propiedades si está escribiendo una API pública que tiene propiedades que necesitan permitir el comportamiento en versiones futuras que sean compatibles con binarios o que necesiten un setter privado (pero considere 'readonly' en su lugar). –

2

Generar accesos públicos con campos privados establece un contrato entre el código de usuario y su clase. Idealmente, este contrato no debería cambiar con las revisiones del código.

En C#, la forma de hacer cumplir el contrato es con un interface. Las interfaces le permitirán especificar el método requerido y las implementaciones de propiedad, pero no permiten campos.

Además, en varios puntos de .NET, a menudo se prefieren las propiedades a los campos. p.ej. PropertyGrid control solo enumera las propiedades, las clases de modelo ASP.NET MVC requieren propiedades, etc.

3

Las propiedades son esencialmente cortas para los métodos Getter y Setter. El objetivo de los métodos Getter y Setter es hacer que el objeto maneje cualquier operación en variables para que pueda realizar cualquier operación adicional (como la validación de datos) sin causar consecuencias indeseables.

Creo que es posible que se cuelguen las propiedades automáticas, que no tienen variables de respaldo y, como resultado, se ven como variables.

0

En realidad mediante el uso de una propiedad, p.

public class Temp 
{ 
    public int SomeValue{get;set;} 
    public void SomeMethod() 
    { 
    ... some work 
    } 
} 

usted está ocultando sus datos, ya que es una variable implícita para almacenar el valor establecido y devuelto por la propiedad SomeValue.

Si tiene

public class Temp 
{ 
    private int someValue; 
    public int SomeValue 
    { 
    get{ return this.someValue;} 
    set{ this.someValue = value;} 
    } 
    public void SomeMethod() 
    { 
    this.someValue++; 
    } 
} 

A continuación, podrás ver lo que quiero decir. Está ocultando los datos del objeto someValue y restringiendo el acceso a él utilizando la propiedad SomeValue.

3

El libro trata de describir la teoría de que un objeto no debe exponer cómo se implementa realmente la clase. En objetos más complicados, muchas de las variables internas no necesariamente transmiten la información correcta desde una perspectiva externa y solo deben tener métodos que actúen sobre ellas.

Sin embargo, hacer de esto una regla difícil y rápida se desmorona cuando tienes objetos simples. En el caso de un rectángulo, alto y ancho son propiedades básicas que el usuario querrá saber. Y dado que la implementación de esto es sencilla, el hecho de no usar get y set hará que su código sea más complicado de lo que debe ser.

10

Es sobre todo otra definición del término "propiedad". Una propiedad en C# no es lo que la mayoría de los otros idiomas consideran propiedades.

Ejemplo:
A C++ propiedad pública es:

class foo 
{ 
    public: 
    int x; 
}; 

El término correspondiente en C# sería un campo público:

class foo 
{ 
    public int x; 
} 

lo que llamamos en C# como propiedades serían los emisores y getters en otros idiomas:

C#:

class foo 
{ 
    public int X { get; set; } 
} 

correspondiente C++:

class foo 
{ 
    private: 
    int x; 

    public: 
    void setX(int newX) { this->x = newX; } 
    int getX() { return this->x; } 
} 

En resumen:
C# propiedades son totalmente bien, simplemente no ciegamente por defecto para obtener y conjunto y no hacer que cada campo de datos en su clase de una propiedad pública, piense en lo que los usuarios de su clase realmente necesitan saber/cambiar.

1

Al igual que en otras publicaciones en este hilo, señalaré que las propiedades en C# son solo casos especiales de funciones de acceso que usted menciona.De hecho, puede refinar los métodos get_Property y set_Property en el IL de su objeto que tienen un indicador que indica que son propiedades, lo mismo es cierto para los eventos que implementan los métodos add_ y remove_ prefixed.

Una distinción importante cuando se trata de abstracciones es si el establecimiento de la propiedad va a actuar sobre el objeto que no sea simplemente actualizar el estado interno o lanzar una excepción PropertyChanged.

Si observa muchos de los objetos BCL internos, las propiedades se implementan de tal forma que puede establecer todas las propiedades en cualquier orden para configurar el objeto. Si se realiza un procesamiento complejo, generalmente es una mejor opción un método que describe lo que va a suceder.

9

Cuando haya terminado de código limpio, recomiendo que lea otro libro de Bob Martin:

Agile Principles Patterns and Practices In C#

En este libro el cuenta el volumen del libro discute un estudio de casos y en ella, Bob aplica los principios discutidos en Clean Code. Leí Clean Code primero, pero en retrospectiva, creo que "Agile Patterns ..." debe leerse primero, ya que Clean Code es más un manual diario o manual de buenos principios SW.

Por ejemplo, en "patrones ágiles ..." se utiliza el siguiente código:

public class OrderData 
{ 
public string customerId; 
public int orderId; 
public OrderData() {} 

... 

} 

La siguiente validación del uso de ofertas públicas de datos con su pregunta:

Don' se ofenderá por el uso de los miembros de datos públicos . Esto no es un objeto en el verdadero sentido. Es simplemente un contenedor de datos . No tiene comportamiento interesante que debe ser encapsulado. Convertir las variables de datos en privadas, y proporcionar getters y setters sería un desperdicio de tiempo. Podría haber usado una estructura en lugar de una clase, pero quiero que el OrderData se pase por referencia en lugar de por valor.


Aparte:

En lo personal, tengo que decir que Robert Martin ha hecho una gran contribución a la comunidad de desarrolladores de SW (junto con Martin Fowler, plumas Michael ..) con estos libros. Creo que deben leer.

+0

También hay [The Clean Coder] (http://www.amazon.com/The-Clean-Coder-Professional-Programmers/dp/0137081073) - tema diferente, pero vale la pena leer en mi humilde opinión. – TrueWill

2

Aquí está el acuerdo.

Aunque las variables públicas pueden ser útiles en ocasiones, a menudo es mejor mantenerlas en privado.

Es fácil mantener su código organizado si el objeto es el único con control sobre su variable.

Imagine que desea mantener una altura entre 0 y 200. Si tiene un método para establecer su altura, puede controlar esto fácilmente.

Por ejemplo (me va a utilizar Java para el motivo de velocidad):

public void setHeight(int newHeight) 
{ 
    if (newHeight < 0) 
     height = 0; 
    else if (newHeight > 200) 
     height = 200; 
    else 
     height = newHeight 
} 

Como se puede ver, este enfoque es muy estructurado y controlado.

Ahora imagina que tenemos una línea de código que edita esta altura externamente porque eliges hacerla pública. A menos que lo controle fuera del código, puede obtener una altura que no se comporta bien con su programa. Incluso si quiere querer controlarlo, estaría repitiendo el código.

Ejemplo muy básico, pero creo que se entiende bien.

5

Mientras que las propiedades públicas no son un olor código inmediata, considere este artículo:

Coding with Reason by Yechiel Kimchi (del libro 97 cosas que todo programador debe saber)

" ... no pida un objeto para que la información funcione, en cambio, pida al objeto que haga el trabajo con la información que ya tiene ".

Esto no entra en juego todo el tiempo (por ejemplo, objetos de transferencia de datos). Lo que tengo cuidado es Inappropriate Intimacy.

+2

+1 para que la cita se cuelgue en mi escritorio! Gracias por la referencia. – JSprang

+0

Este es el enfoque estrictamente OOP. Difícil de lograr en algunos contextos. Considera el patrón MVVM. – onof

3

En OO puro "un objeto real" tiene que ocultar por completo los datos que utiliza para cumplir con su responsabilidad. Por lo tanto, debe evitarse la exposición de datos internos, sin importar si esto se realiza mediante un campo público, una propiedad pública o funciones públicas de captador/definidor.

¡Los datos internos NO SE ESCONDEN ni se resisten simplemente al acceso de enrutamiento a través de una propiedad!

Para responder a su pregunta: - Evitar las propiedades públicas si está escribiendo un objeto - Use propertiers públicas si está escribiendo estructuras de datos (un campo público haría el trabajo, también)

Cuestiones relacionadas