Estoy escribiendo desde una perspectiva de Java (para evitar tener que poner 'desde una perspectiva de Java' en todas partes).
El diseño cuidadoso de una API es algo más que una simple "organización". Muchas de las clases públicas que escribo son utilizadas por muchos clientes y al usar el modificador de acceso más bajo posible, soy libre de cambiar el funcionamiento interno de mis clases sin romper su código (¡y por lo tanto recibir llamadas y correos electrónicos desagradables!).
tl; dr : la encapsulación / ocultación de información, puede cambiar su representación y funcionamiento interno sin romper el código del cliente, los campos mutables públicos no son seguros para subprocesos, promueven la inmutabilidad.
Un módulo que está bien diseñado ocultará sus datos internos y los detalles de implementación de otros módulos y separará limpiamente su API de su implementación. Esto significa que la comunicación entre los módulos se realiza solo a través de sus API y son ajenos al funcionamiento interno de cada uno.
La importancia de esto es que desacopla los módulos entre sí, lo que permite desarrollarlos, probarlos, utilizarlos, optimizarlos y modificarlos de forma aislada, y se pueden desarrollar en paralelo. También aumenta la reutilización porque los módulos que no están estrechamente acoplados pueden potencialmente usarse en otros contextos.
En el libro de Joshua Bloch "Java efectiva", afirma que la regla de oro es:
haga que cada clase o miembro sea lo más inaccesible posible. En otras palabras, use el nivel de acceso más bajo posible en consonancia con el correcto funcionamiento del software que está escribiendo.
Después de diseñar su API pública, su instinto debe ser hacer que todo lo demás sea privado, y solo si otra clase en el mismo paquete realmente necesita acceder a un miembro, debe hacerlo privado del paquete (eliminar el modificador). La necesidad de miembros protegidos en una clase pública debe ser relativamente rara, ya que un miembro protegido se convierte en parte de la API exportada de la clase.
Cuando tiene todo como público, significa que se accede directamente a los campos de datos de la clase y que no puede cambiar su representación sin cambiar la API. En general, tampoco puede cambiar el funcionamiento interno de su clase, ya que tiene el potencial de romper el código de quienquiera que esté usando su clase. Este problema / riesgo se multiplica por el número de sus clientes, ya que su clase puede usarse en todas partes.
Si un campo no es definitivo o es una referencia final a un objeto mutable (por ejemplo, Fecha) y es public
, renuncia a la capacidad de limitar lo que está almacenado en el campo o imponer invariantes en el campo. Entonces, si desea limitar un int
a un cierto rango de valores, tener el campo public
significa que ya no tiene control sobre lo que está almacenado en el campo. También pierde la capacidad de realizar cualquier acción cuando se modifica un campo, lo que significa que las clases con campos mutables públicos no son seguras para subprocesos .
Los campos
Public final
con un objeto mutable en ellos también tienen todas las desventajas de un campo no final. Si bien no puede cambiar la referencia del objeto, el objeto aún puede modificarse, lo que puede romper el funcionamiento interno de su clase y generar resultados no deseados y desastrosos.
Al hacer que los campos sean privados, también minimiza la mutabilidad de su clase. Las clases inmutables son generalmente más fáciles de diseñar, implementar y usar que las clases mutables. Los campos privados impiden que los clientes de su clase obtengan acceso a objetos mutables y modifiquen los objetos directamente. Por lo general, tampoco le da a un cliente referencias a los objetos mutables (les da copias).
A medida que su clase minimiza la mutabilidad o se vuelve completamente inmutable, también se convierte en inherentemente seguro para subprocesos y no requiere sincronización. No se pueden corromper por múltiples hilos que acceden a ellos simultáneamente. Una enorme ganancia funcional de inmutabilidad es que es una de las formas más fáciles de lograr la seguridad de subprocesos.