what language help example documentacion development c# data-structures object properties abstraction

c# - language - Código de limpieza: ¿Deberían los objetos tener propiedades públicas?



inheritance c# (13)

Al igual que otras publicaciones en este hilo, señalaré que las propiedades en C # son solo casos especiales de funciones de acceso que mencionas. 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 la configuración de la propiedad va a actuar sobre el objeto, además de 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.

Estoy leyendo el libro "Código limpio" y estoy luchando con un concepto. Cuando se habla de objetos y estructuras de datos, dice lo siguiente:

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

Entonces, lo que obtengo 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 get y establecer 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 por adelantado!


Aquí está el trato.

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 (voy a usar Java por velocidad):

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

Como 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 quisiera controlarlo, estaría repitiendo el código.

Un ejemplo muy básico, pero creo que hace entender el punto.


Cuando haya terminado el Código Limpio, le recomendaría que lea el otro libro de Bob Martin:

Patrones y prácticas de principios ágiles en C #

En este libro, la gran cantidad del libro trata sobre un estudio de caso y, en él, 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 usa el siguiente código:

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

La siguiente validación del uso de datos públicos trata su pregunta:

No se ofenda con el uso de miembros de datos públicos. Esto no es un objeto en el verdadero sentido. Es simplemente un contenedor de datos. No tiene un comportamiento interesante que deba ser encapsulado. Hacer que las variables de datos sean privadas y proporcionar getters y setters sería una pérdida de tiempo. Podría haber usado una estructura en lugar de una clase, pero quiero que OrderData se pase por referencia y no por valor.

Aparte:

Personalmente, tengo que decir que Robert Martin hizo una contribución masiva a la comunidad de desarrolladores de SW (junto con Martin Fowler, Michael Feathers ...) con estos libros. Creo que deben leer.


De hecho, una propiedad C # no es datos, es un descriptor de acceso, por lo que es una función que opera sobre datos.

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


El libro intenta 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 que esto sea una regla dura 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.


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 ESTÁN OCULTADOS NI RESUMEN simplemente enrutando el acceso a través de una propiedad!

Para responder a su pregunta: - Evite las propiedades públicas si está escribiendo un objeto - Utilice las propiedades públicas si está escribiendo estructuras de datos (un campo público también lo haría)


En realidad mediante el uso de una propiedad, por ejemplo

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

Está ocultando sus datos ya que hay una variable implícita para almacenar el valor establecido y devuelto por la propiedad SomeValue.

Si usted tiene

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

Entonces verás a qué me refiero. Está ocultando los datos del objeto en someValue y restringiendo el acceso a él utilizando la propiedad SomeValue.


Es principalmente 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:
Una propiedad pública de C ++ 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 nombramos en C # como propiedades sería setters y getters en otros idiomas:

DO#:

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

C ++ correspondiente:

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

En breve:
Las propiedades de C # son totalmente correctas, solo que no las predeterminan ciegamente para obtenerlas y establecerlas y no hacen que cada campo de datos de su clase sea una propiedad pública, piensen en lo que los usuarios de su clase realmente necesitan saber / cambiar.


Generar accesadores 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 cumplimiento del contrato es con una 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. por ejemplo, el control PropertyGrid solo enumera las propiedades, las clases del modelo ASP.NET MVC requieren propiedades, etc.


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 puede estar colgado de las propiedades automáticas, que no tienen variables de respaldo y, como resultado, se ven como variables en sí mismas.


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


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

Codificación con Reason por Yechiel Kimchi (del libro 97 Cosas que todo programador debería saber )

"... no le pida información a un objeto para que trabaje. En cambio, pídale 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 busco es Intimidad Inapropiada .


Las propiedades públicas están bien. No tener que escribir los GetHeight() explícitos GetHeight() y SetHeight() es de qué se tratan las propiedades. Una propiedad en C # no es datos; se ve mejor como un par de métodos getter / setter. (Las propiedades en realidad se compilan en 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ías cambiar

public int Height { get; set; }

dentro

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

si decidiste que tu objeto siempre debe ser cuadrado. El código que usa tu clase no necesitaría ninguna modificación.

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