¿Los campos / miembros protegidos son realmente tan malos?

Ahora, si lee las convenciones de nombres en MSDN para C #, notará que establece que las propiedades siempre son preferibles a los campos públicos y protegidos. Algunas personas me han dicho que nunca debes usar campos públicos o protegidos. Ahora estoy de acuerdo en que todavía tengo que encontrar una razón por la cual necesito tener un campo público, pero ¿los campos protegidos realmente son tan malos?

Puedo ver si necesita asegurarse de que se realicen ciertas comprobaciones de validación al obtener / establecer el valor, sin embargo, en mi opinión, muchas veces parece una sobrecarga adicional. Quiero decir digamos que tengo una clase GameItem con campos para baseName, prefixName y sufijoName. ¿Por qué debería tomar la sobrecarga tanto de la creación de las propiedades ( C# ) o de los métodos de acceso y del rendimiento que tendría lugar (si hago esto para cada campo de una aplicación, estoy seguro de que se sumría un poco menos, especialmente en ciertos lenguajes como PHP o ciertas aplicaciones con rendimiento es crítico como los juegos)?

¿Los campos / miembros protegidos son realmente tan malos?

No. Son mucho, mucho peor.

Tan pronto como un miembro sea más accesible que private , usted está garantizando a otras clases cómo se comportará ese miembro. Como un campo está totalmente fuera de control, ponerlo “en la naturaleza” abre su clase y clases que heredan o interactúan con su clase para un mayor riesgo de errores. No hay forma de saber cuándo cambia un campo, no hay manera de controlar quién o qué lo cambia.

Si ahora, o en algún momento en el futuro, cualquiera de sus códigos alguna vez depende de un campo de cierto valor, ahora tiene que agregar comprobaciones de validez y lógica alternativa en caso de que no sea el valor esperado, en cada lugar donde lo use. Esa es una gran cantidad de esfuerzo perdido cuando podrías haberlo convertido en una maldita propiedad;)

La mejor forma de compartir información con clases derivadas es la propiedad de solo lectura :

 protected object MyProperty { get; } 

Si absolutamente tiene que hacerlo leer / escribir, no lo haga. Si realmente, realmente tiene que hacer que sea de lectura y escritura, vuelva a pensar en su diseño. Si aún necesita que sea de lectura y escritura, discúlpese con sus colegas y no lo haga de nuevo 🙂

Muchos desarrolladores creen, y te dirán, que esto es demasiado estricto. Y es cierto que puedes vivir bien sin ser tan estricto. Pero tomar este enfoque lo ayudará a pasar de simplemente obtener un software notablemente sólido. Pasará mucho menos tiempo corrigiendo errores.

Y con respecto a cualquier preocupación sobre el rendimiento, no lo haga. Le garantizo que nunca, en toda su carrera, escribirá el código tan rápido que el cuello de botella es la stack de llamadas en sí.

OK, tiempo downvote.

  • En primer lugar, las propiedades nunca afectarán el rendimiento (siempre que no hagan mucho). Eso es lo que todos los demás dicen, y estoy de acuerdo.

  • Otro punto es que las propiedades son buenas, ya que puede colocar puntos de interrupción en ellas para capturar los eventos de obtención / configuración y averiguar de dónde vienen.

El rest de los argumentos me molestan de esta manera:

  • Suenan como “argumento por prestigio”. Si MSDN lo dice, o algún famoso desarrollador o autor que todo el mundo quiera lo dice, debe ser así.

  • Se basan en la idea de que las estructuras de datos tienen muchos estados inconsistentes, y deben estar protegidos contra el desplazamiento o la ubicación en esos estados. Dado que (a mi parecer) las estructuras de datos son demasiado enfatizadas en la enseñanza actual, entonces típicamente necesitan esas protecciones. Mucho más preferible es minimizar la estructura de datos de manera que tienda a normalizarse y no tener estados inconsistentes. Entonces, si se cambia un miembro de una clase, simplemente se cambia, en lugar de dañarse. Después de todo, de alguna manera se escribió / escribió mucho software bueno en C, y eso no sufrió masivamente por la falta de protecciones.

  • Se basan en una encoding defensiva llevada a extremos. Se basa en la idea de que tus clases se utilizarán en un mundo en el que nadie puede confiar en el código para que no pierda tus pertenencias. Estoy seguro de que hay situaciones en las que esto es cierto, pero nunca las he visto. Lo que he visto es situaciones en las que las cosas se complicaron terriblemente para eludir las protecciones para las que no había necesidad, y para tratar de proteger la consistencia de las estructuras de datos que eran terriblemente complicadas y no normalizadas.

En cuanto a los campos y las propiedades, puedo pensar en dos razones para preferir propiedades en la interfaz pública (la protección también es pública en el sentido de que otra persona además de tu clase puede verla).

  • La exposición de propiedades le brinda una manera de ocultar la implementación. También le permite cambiar la implementación sin cambiar el código que la usa (por ejemplo, si decide cambiar la manera en que se almacenan los datos en la clase)

  • Muchas herramientas que funcionan con clases que usan la reflexión solo se centran en las propiedades (por ejemplo, creo que algunas bibliotecas para la serialización funcionan de esta manera). Usar propiedades consistentemente hace que sea más fácil usar estas herramientas .NET estándar.

En cuanto a los gastos generales:

  • Si el getter / setter es el fragmento usual de una línea de código que simplemente lee / establece el valor de un campo, entonces el JIT debería ser capaz de alinear la llamada, por lo que no hay ningún rendimiento overhad.

  • La sobrecarga sintáctica se reduce en gran medida cuando usa propiedades implementadas automáticamente (C # 3.0 y más reciente), así que no creo que esto sea un problema:

     protected int SomeProperty { get; set; } 

    De hecho, esto le permite, por ejemplo, set protegido y get público muy fácilmente, por lo que esto puede ser aún más elegante que usar campos.

Los campos públicos y / o protegidos son malos porque pueden manipularse desde fuera de la clase declarante sin validación; por lo tanto, puede decirse que rompen el principio de encapsulación de la progtwigción orientada a objetos.

Cuando pierde la encapsulación, pierde el contrato de la clase declarante; no puede garantizar que la clase se comporte como se esperaba o se espera.

El uso de una propiedad o un método para acceder al campo le permite mantener la encapsulación y cumplir el contrato de la clase declarante.

En realidad, depende de si su clase es una clase de datos o una clase de comportamiento.

Si mantiene separados su comportamiento y sus datos , está bien exponer los datos de sus clases de datos, siempre que no tengan ningún comportamiento.

Si la clase es una clase de comportamiento, entonces no debe exponer ningún dato.

Estoy de acuerdo con la respuesta de propiedad de solo lectura. Pero para jugar al abogado del diablo aquí, realmente depende de lo que estés haciendo. Estaré encantado de admitir que escribo código con miembros públicos todo el tiempo (tampoco hago ningún comentario, sigo las pautas o ninguna de las formalidades).

Pero cuando estoy en el trabajo, esa es una historia diferente.