¿Por qué no debería usar POJOs inmutables en lugar de JavaBeans?
immutability (6)
Prefiere JavaBeans cuando
- tienes que interactuar con ambientes que los esperan
- usted tiene muchas propiedades para las cuales sería inconveniente hacer todas las inicializaciones en instanciación
- tiene un estado que es costoso o imposible de copiar por alguna razón, pero requiere una mutación
- cree que en algún momento tendrá que cambiar la forma de acceder a las propiedades (por ejemplo, pasar de valores almacenados a valores calculados, autorización de acceso, etc.)
- quieres conformarte a los estándares de codificación que insisten sin pensar que de alguna manera está más "orientado a objetos" para usar JavaBeans
Prefiere POJOs Inmutables Cuando
- tienes un pequeño número de propiedades simples
- no tiene que interactuar con entornos asumiendo convenciones JavaBean
- es fácil (o al menos posible) copiar el estado al clonar su objeto
- nunca planeas clonar el objeto en absoluto
- estás bastante seguro de que no tienes que modificar cómo se accede a las propiedades como se indica anteriormente
- no le importa escuchar gimoteos (o burla) acerca de cómo su código no está lo suficientemente "orientado a objetos"
He implementado algunas aplicaciones Java ahora, solo aplicaciones de escritorio hasta ahora. Prefiero usar objetos inmutables para pasar los datos en la aplicación en lugar de usar objetos con mutadores (setters y getters ), también llamados JavaBeans.
Pero en el mundo de Java, parece ser mucho más común usar JavaBeans, y no puedo entender por qué debería usarlos en su lugar. Personalmente, el código se ve mejor si solo se trata de objetos inmutables en lugar de mutar el estado todo el tiempo.
Los objetos inmutables también se recomiendan en el Ítem 15: Minimizar la mutabilidad , Effective Java 2ed .
Si tengo un objeto Person
implementado como JavaBean , se vería así:
public class Person {
private String name;
private Place birthPlace;
public Person() {}
public setName(String name) {
this.name = name;
}
public setBirthPlace(Place birthPlace) {
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
Y la misma Person
implementada como un objeto inmutable :
public class Person {
private final String name;
private final Place birthPlace;
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
O más cerca de una struct
en C:
public class Person {
public final String name;
public final Place birthPlace;
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
}
También podría tener getters en el objeto inmutable para ocultar los detalles de implementación. Pero como solo lo uso como struct
, prefiero omitir los "captadores" y mantenerlo simple.
Simplemente, no entiendo por qué es mejor usar JavaBeans, o si puedo y debo continuar con mis POJOs inmutables.
Muchas de las bibliotecas de Java parecen tener un mejor soporte para JavaBeans, pero tal vez más apoyo para POJOs inmutables se vuelve más popular con el tiempo.
Bueno, depende de lo que estás tratando de hacer. Si trabajas con una capa persistente, y buscas una fila de la base de datos en un POJO, y quieres cambiar una propiedad y guardarla de nuevo, usar el estilo JavaBean sería mejor, especialmente si tienes muchas propiedades.
Considere que su persona tiene muchos campos como, primero, segundo nombre, apellido, fecha de nacimiento, miembros de la familia, educación, trabajo, salario, etc.
Y esa Persona resulta ser una mujer que acaba de casarse y aceptó que se cambie su apellido, y necesita actualizar la base de datos.
Si usa POJO inmutables, busca un objeto Person que la represente, luego crea un nuevo objeto Person al cual le pasa todas las propiedades que no modificó como están, y el nuevo apellido, y lo guarda.
Si fuera un Java Bean, puede hacer setLastName () y guardarlo.
Es ''Minimizar la mutabilidad'' no ''nunca usar objetos mutables''. Algunas situaciones funcionan mejor con objetos mutables, en realidad es su trabajo decidir si hacer que un objeto mutable se ajuste mejor a su programa o no. No siempre debes decir "debes usar objetos inmutables", sino cuántas clases puedes convertir en inmutables antes de que comiences a hacerte daño.
Desde Java 7 puedes tener frijoles inmutables, lo mejor de ambos mundos. Usa la anotación @ConstructorProperties en tu constructor.
public class Person {
private final String name;
private final Place birthPlace;
@ConstructorProperties({"name", "birthPlace"})
public Person(String name, Place birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public Place getBirthPlace() {
return birthPlace;
}
}
Me sorprendió que la palabra Hilo no apareciera en ninguna parte de esta discusión.
Uno de los principales beneficios de las clases inmutables es que son intrínsecamente más seguras para subprocesos debido a que no tienen un estado mutable y compartido.
Esto no solo hace que su codificación sea más fácil, también le dará dos beneficios de rendimiento como efecto secundario:
Menos necesidad de sincronización.
Más posibilidades de usar variables finales, lo que puede facilitar optimizaciones subsiguientes del compilador.
Realmente estoy tratando de avanzar hacia objetos inmutables en lugar de clases de estilo JavaBean. Exponer las entrañas de los objetos a través de getters y setters probablemente no sea la opción predeterminada.
No creo que los objetos inmutables se vuelvan tan populares, para ser honestos.
Veo las ventajas, pero marcos como Hibernate y Spring están muy de moda actualmente (y también por una buena razón), y realmente funcionan mejor con beans.
Así que no creo que la inmutabilidad sea mala, pero ciertamente limitaría tus opciones de integración con los marcos actuales.
EDITAR Los comentarios me piden aclarar mi respuesta un poco.
Ciertamente hay áreas problemáticas donde la inmutabilidad es muy útil, y de hecho se usa. Pero creo que el valor predeterminado actual parece ser mutable, ya que es lo que más se espera, y solo inmutable si tiene una clara ventaja.
Y aunque es posible usar constructores con argumentos en Spring, parece ser una forma de usar código heredado y / o de terceros con su nuevo código Spring. Al menos eso es lo que recogí de la documentación.
Resumiendo otras respuestas, creo que:
- La inmutabilidad facilita la corrección (las estructuras se pueden pasar por referencia y usted sabe que nada será destruido por un cliente defectuoso / malicioso) y la simplicidad del código
- La mutabilidad facilita la homogeneidad : Spring y otros marcos crean un objeto sin argumentos, establecen las propiedades del objeto y voi là . También facilite las interfaces utilizando la misma clase para proporcionar datos y guardar modificaciones (no necesita
get(id): Client
ysave(MutableClient)
, siendo MutableClient algún descendiente del cliente.
Si hubiera un punto intermedio (crear, establecer propiedades, hacer inmutables), los marcos podrían fomentar un enfoque inmutable.
De todos modos, sugiero pensar en objetos inmutables como "leer solo Java Beans" enfatizando el punto de que si eres un buen chico y no tocas ese peligroso método setProperty, todo estará bien.