Mal uso de encapsulamiento (getters y setters)

Algo que siempre veo (en los últimos 3 proyectos en donde he participado) es la mala práctica del encapsulamiento, el mal uso de los métodos getters y setters.

He podido observar un código de este tipo:



public class MantenimientoUsuario extends Mantenimiento{

private List roles;
private Usuario filter;

public String iniciar(){
setRoles(new ArrayList());
setFilter(new Usuario());
}


public String registrar(){
String codigo = getFilter().getCodigo().

// codigo para el metodo registrar

}


// Metodos Getters y Setters

public List getRoles(){
return this.roles;
}

public void setRoles(List roles){
this.roles = roles;
}

public Usuario getFilter(){
return this.filter;
}

public void setFilter(Usuario filter){
this.filter= filter;
}
}




En este caso tenemos las variables roles y filter de la clase MantenimientoUsuario. Supongamos de que manejamos algún tipo de framework para la capa View (Struts, JSF, etc.) y en el jsp utilizaremos solamente la variable filter. También tengamos en cuenta que ninguna clase llama a MantenimientoUsuario para utilizar su variable global roles.

En este caso, encontramos 2 problemas con el código:

1) El uso innecesario de los métodos getRoles() y setRoles(). Muchos programadores están acostumbrados a siempre generar metodos getters y setters en donde muchas veces no se necesita.

2) El uso de los métodos de acceso dentro de la misma clase. En el ejemplo se generaron métodos de acceso para que el JSP pueda utilizar la varibale filter.

La función de los métodos de acceso es para que otra clase o algún recuros accedan a las variables de clase a través de estos métodos. Pero.. ¿la misma clase está utilizando sus métodos de acceso? WTF.

Si el objeto MantenimientoUsuario pudiera hablar, dijera algo como esto: " ¿Por qué rayos estoy utilizando los métodos de acceso en "iniciar" y "registrar", no se suponen que esos métodos lo utilizaría alguien externo?. Son mis variables y las puedo utilizar directamente!!! "

Cuando vi la invocación del método setFilter dentro del método "iniciar", sinceramente pensé que provenía de su padre :S

Si modificamos el código....




public class MantenimientoUsuario extends Mantenimiento{
private List roles;
private Usuario filter;

public String iniciar(){
roles = new ArrayList();
filter = new Usuario();
}


public String registrar(){
String codigo = filter.getCodigo().

// codigo para el metodo registrar

}


// Metodos Getters y Setters

public Usuario getFilter(){
return this.filter;
}

public void setFilter(Usuario filter){
this.filter= filter;
}
}



:D

Comentarios

Anónimo ha dicho que…
Lo que para unos es mala práctica para otros es buena. Un profesor que tuve recomendaba hacer lo que tu criticas, su argumento era que se podía agregar comportamiento (por ejemplo validaciones) en el settet y/o getter que entonces quedaba automáticamente disponible (incluso para la propia clase).

La verdad es que no creo que exista una formula única, y dependerá de cada caso. En términos generales estoy de acuerdo contigo, pero no creo que convenga ser demasiado dogmático al respecto.
ckomiya ha dicho que…
De acuerdo contigo existen muchas formas de hacer las cosas. Sin embargo, hay autores de libros que recomiendan estas cosas por ejemplo, al hacer esto chocan con otros autores, al final uno es libre de seguir las prácticas de cualquier persona.

Ahora, a mi me impactó un poco. Ya que cuando encontré ese método "setFilter" pensé que venía de su clase padre. Pues crea cierta confusión. Volviendo a esto de los autores hay un libro que es "ThoughtWorks Anthology" de Jeff Bay, que menciona como última regla de calistenia: No utilizar setters y getters (aún tendría que comprobar esto).

El post también menciona de que no está bien tener métodos que nunca van a ser utilizados. Como también el poder minimizar cadenas de getters que se ven feo: getFilter().getA().getB()

En el momento de desarrollo tal vez pase. Pero para las personas que tengan que hacer modificaciones al código, les afecta :(

Ahora estoy corrigiendo cosas de otra persona y encuentro unas cosas que confunden (fuera de getters y setters) como el mal uso del "this". Encuentro "this" por las puras. Y esto da que pensar que la clase padre tiene una variable con nombre similar (similar al "setFilter")

Bueno y en fin... muchas cosas.

Saludos
ckomiya ha dicho que…
Gracias por los comentarios :)
PaK0s ha dicho que…
ps como dice el primer cometario para unos es buena para otros mala, tal vez analizar si el geter y el setter deverian de ser privados o publicos, pero creo que es una buena practica ponerlos, por que tal vez en una clase al inicio un geter es simplemente una variable dentro de la clse, pero quien no dice que podria cambiar por ser un calculo en un futuro :S, entoces habria que manipular mas la clase para darle matenimiento si lo dejas con sus getter y su setter = si dices es que solo lo utilzo internamente ponlo como privados, pero creo que si deverias ponerlo por qe en el caso qe te comento solo tendrias que modificar tu getter o setter y todo el resto de tu codigo quedaria = sin necesidad de tocarlo, auque son puntos de vista distitos, tambien te ahorarias trabajo si evitas el crear el metodo pero la posiblidad cambia, alli se tendria que analizar las posiblidades de que un geteer o setter pudiese cambiar y si combiene el acceso directo al dato, tras un analicis ps el te dira crea el getter o no.

pakos
www.devtics.com.mx
Juan Pablo Stange ha dicho que…
Como bien dijo el comentario anterior, los setters y getters pueden tener validaciones necesarias, esta perfecto utilizar setters y getters dentro de una misma clase, y si te confunde lo del padre, simplemente usa la palabra this y super cuando sea conveniente, saludos!