Setters/getters para todo??
06-04-2006 | Desarrollo |Estoy revisando código Delphi/ObjectPascal hecho por otros y una cosa que no entiendo es porque en una clase para establecer y leer el valor de una propiedad se utiliza un setter y un getter para todo, aunque el setter no haga nada más que poner el valor a la propiedad. A eso yo lo llamo “ortodoxia”.
Si tengo una propiedad que al cambiar no se ha de hacer nada, ¿para que utilizar un setter? ¿para complicar más el código? ¿porque asi es como ha de hacerse? Cuando lo necesite ya lo escribire, ¿que problema hay en acceder a la propiedad directamente?
Ejemplo con getter/setter:
TUno = class;
private
FNombre: string;
FNumero: integer;
procedure SetNombre(Value: string);
function GetNombre: string;
procedure SetNumero(Value: integer);
function GetNumero: integer;
public
property Nombre: string read GetNombre write SetNombre;
property Numero: integer read GetNumero write SetNumero;
end;
procedure TUno.SetNombre(Value: string);
begin
FNombre := Value;
end;
function TUno.GetNombre: string;
begin
result := FNombre;
end;
procedure TUno.SetNumero(Value: integer);
begin
FNumero := Value;
end;
function TUno.GetNumero: integer;
begin
result := FNumero;
end;
Ejemplo limpio:
TUno = class;
public
Numero: integer;
Nombre: string;
end;
¿Cual de los dos os parece mejor?
Deben ser manías mías, pero creo que el segundo es mejor, no? más claro, más corto, con menos posibilidad de errores, seguramente más eficaz a la hora de compilar, etc.


06-04-2006 14:15
Se ha abierto la caja de Pandora!!!!
:D
Aquí me huelo que viene una sesión de lucha libre.
06-04-2006 15:54
Lo bueno de la programación es que cada uno lo puede hacer como le venga en gana.
Personalmente prefiero la primera opción por una cuestión de organización, estandarización.
Si siempre usas getters y setters para las propiedades es mucho más fácil desarrollar porque no tienes que pensar si este tenía o no un setter o un getter.
También me parece muy importante a la hora de mantener el código. Es mucho más mantenible tener funciones para acceder a los datos porque si mañana tienes que validar el campo no tienes que modificar todos los ficheros en los que accedías a ese campo.
Para trabajar en equipo estas cuestiones son muy importantesy ayudan a evitar muchos problemas.
En resumen, como he dicho al pricipio cada quien es libre de hacerlo como le parezca.
Un saludo,
06-04-2006 16:16
Por supuesto que cada uno programa según sus manías
Para nada se han de modificar las otras partes del programa si yo tengo un setter/getter, de hecho es transparente para el resto del mundo fuera de la clase.
Si en una parte del programa tengo (por ejemplo), suponiendo que U es una instancia de TUno:
U.Numero := 10;
Eso no cambia porque Numero tenga setter/getter.
Reconozco que por organización, por hacerlo siempre igual, puede ser interesante, pero sacrificando cantidad de código y aumentando un poco (muy poco) la complejidad del mismo.
Repito, puede que sea demasiado maniatico al escribir código.
06-04-2006 17:05
Para gustos hay colores, pero creo que getters/setters te da más flexibilidad. El problema de no usarlos desde el principio es el que han expuesto antes, si a mitad de desarrollo descubres que son necesarios (para validar los datos, generar una entrada en un log, refactorizar parte de la clase que contiene las propiedades o cualquier otra cosa), te arriesgas a tener que cambiar el código de un montón de clases en lugar de hacerlo en un punto centralizado.
06-04-2006 18:28
Yo creo que el ejemplo que nos has puesto es una deformación de lenguajes como Java o C++, y en Delphi no tiene mucho sentido hacerlo así.
Me explico: si en Java permitimos el acceso público a un atributo (obj.numero = 10), nos estamos arriesgando a que si algún día tenemos que poner un setter (para hacer una comprobación, por ejemplo), tengamos que buscar todos los sitios donde se asigna al atributo.
Si desde un primer momento usas un setter en vez de la asignación directa, te ahorras ese cambio futuro.
Sin embargo, en Delphi/Object Pascal no tiene sentido, ya que se puede sustituir una variable por una propiedad y el código cliente ni se entera. Ambos dos serán: obj.numero := 10
Así que ese código que nos has puesto “huele” a influencia de Java o C++, (que por cierto, es entendible ya que la mayoría de los programdores de Delphi hemos “chupado” mucho de otros lenguajes :).
Sin embargo, yo no soy muy amigo de las propiedades de Delphi (y C#, que ha copiado), ya que de cara al usuario de la clase, no se sabe muy bien si está usando una propiedad o un atributo.
¿Y pienso que estoy accediendo directamente al atributo y sin embargo es una propiedad con métodos read/write lentos?
De cara a la legibilidad, también prefiero evitar las propiedades. Si estoy buscando un bug y paso por una línea que dice obj.numero = 10, tengo que andar mirando si es una propiedad, y si tiene método de write, ver su código. Sin embargo, si no uso propiedades, estaré seguro de que sólo es una asignación directa a una variable.
Un saludo
JM
06-04-2006 19:20
Pues a mi no me gusta ninguna de las dos opciones.
Por un lado una propiedad pública es algo que debería estar prohibido, rompe el principio más basico de la OO, la encapsulación. Y no es una cuestión de “purismo” es que el código encapsulado es mucho más mantenible, puedo cambiar la representación interna de una clase cuanto quiera si no modifico el contrato de la clase. Las propiedades pí¹blicas aumentan el acoplamiento y esto a la larga puede traer enormes problemas. Como habeis dicho antes, aunque esto es un principio de diseño basico en OO, en delphi se minimiza ya que en el futuro puedo hacer el apañejo de cambiar lo que antes era un mienbro pí¹blico de la clase por un property, aunque esto me obliga a retocar la implementación completa de la clase para cambiar el nombre y la visibilidad del antiguo mienbro pí¹blico, no es muy grave pero es un rollo y puede dar lugar a combinaciones de nombres de lo más variopintas
La otra opción tampoco me convence, primero porque se convierte en una (mala)costumbre poner un get/set a cada propiedad sencillamente porque si, y segundo porque como comentaba JM cuando leo el código me gusta saber que esta pasando, y este tipo de construcciones me impiden saber si estoy accediento directamente a una propiedad o estoy llamando a un método si no miro el código de la clase que estoy usando.
El problema esta en como se piensa, el error viene de pensar “necesito acceder a esta propiedad de tal objeto”, en realidad lo que queremos si usamos OO es “comunicarme con tal objeto para obtener tal información”, pues expresemos eso en el código haciendo que ese objeto sea capaz de entender ese mensaje y devolvernos lo que necesitamos, es decir, crear un método getNombre o getNumero, pero un METODO, no esas guarreridas automagicas de los getter/setters.
07-04-2006 09:16
Bueno, bueno, que conversación más interesante …
JM, has dado en el clavo, porque esos “vicios” vienen de Java, seguro.
Rastafari, me parece demasiado radical lo que propones
A mi me parece más “elegante” tratar las propiedades directamente y no a través de llamadas (setNombre(‘Juan’), getNombre,...)
pkito, no puedo estar de acuerdo con lo que comentas, el cambio a realizar es prácticamente el mismo, si necesitas añadir una validación a una propiedad solo tocaras o añadiras el setter.
07-04-2006 09:19
Hombre… en alguna cosa estoy de acuerdo contigo, pero en otras no.
Tienes razón cuando dices que se abusa de getters/propiedades/atributos, etc. cuando lo que habría que hacer es “pedir al objeto que haga algo”, en vez de preguntarle por sus datos y hacelo desde fuera.
Muchas veces se tiene la costumbre de poner un get/set automático por cada miembro privado, automaticamente, y eso no tiene sentido, ya que se está rompiendo igual la encapsulación, pero con una máscara de OOP.
(sobre este tema merece la pena leer este artículo de Martin Fowler)
Sin embargo, creo que con el tema de las propiedades de equivocas. En Delphi/C# (y supongo que algún otro) dan un paso más y sustituyen los get/set por una propiedad. Esa propiedad se accede de la misma forma que una variable normal (primer error) y lo que se hace en tiempo de compilación es sustituír la asignación por una llamada a un set y la lectura por una llamada a su get.
Se trata de disfrazar un get/set de variable para que desde fuera no se note la diferencia (grave error).
Así que si dices que “las propiedades públicas deberían estar prohibidas”, deberías decir también que “los métodos públicos deberían estar prohibidos”, ya que al fin y al cabo una propiedad se tranforma en un get/set.
07-04-2006 09:30
Pues yo veo que una propiedad (tal como se implementa en Delphi/C#) encapsula bastante, ya que desde fuera de la clase no hay forma de alterar las validaciones o funcionalidad del setter correspondiente.
Yo lo veo como una facilidad a la hora de escribir código, me resulta comodo tratar una propiedad como una variable más. Y, si es necesario, implementar un setter/getter, pero si no es necesario no, y de eso es de lo que me quejo, de la manía que tenemos a veces de complicar las cosas más de lo necesario, también por eso existe la refactorización, no?
07-04-2006 15:16
El tema es que si quieres definir una propiedad desde el Analizador de objetos, no figuran las definidas en el codigom limpio, en cambio si las que defines como propery.
Yo solo defino properties si necesito definir algo en tiempo de diseño.
Saludos
08-04-2006 14:26
Bueno….
Si estan familiarizados con la teoria del Paradigma de objetos sabran que dice q para leer y modificar atributos se debe usar settery getter, eso no implica q su pueda programar si ellos.
Cualquier paradigma q sea puramente de objetos como puede ser smalltalk siempre tendarn getter y setter
salu2
11-04-2006 09:37
Considero que la primera forma es mejor, debido a la estandarización y a las ventajas que pueden aportar las propiedades.
El problema de los ejemplos es que al ser una clase con tan solo dos atributos (o propiedades) y no hacer un uso interno ni mostrar un ejemplo más complejo, hace que el segundo sea mejor ya que es más corto y más claro.
12-04-2006 12:53
Bueno, tampoco ha sido para tanto el abrir la caja de Pandora. Suele ser curioso, pero las principales discusiones suelen tener como base este tipo de cuestiones. También la gente en este foro está muy civilizada, los otros foros que visito tienen un alto componente artístico en “insultillos” como “amasijador de bytes” o similar.
Bueno, en mi opinión prefiero los getters/setters por el tema de la herencia y puesto que no es lo mismo heredar desde zona private que desde public en la mayoria de lenguajes orientados a objeto. En JAVA o Delphi la cosa queda bastante clarita…pero en C++ se complica que no veas. Por tanto, de este modo Standard es más facil no tener que recordar cada visibilidad de cada lenguaje: “¿Era a nivel de UNIT o a nivel de clase?”. Usualmente no se complica mucho la gente y se mete todo en “public” y “private”, pero desde las “Friendly” hasta “Protected” existen muchas opciones a tener en cuenta en las clases.
Aún así PREFIERO que todo el codigo tenga uniformidad sobre la standarización. Si se ha hecho de la forma sencilla del ejemplo, perfecto… pero luego no liar con property’s, getters o procedimientos vagabundos.
De todos modos el objetivo principal son 2: QUE SE PERMITA EVOLUCIONAR FACILMENTE a partir del código actual y que SEA CLARO. Todo lo demás es más superfluo.
Me ha gustado este post.
Saludos.
13-03-2007 16:06
La estandarización de código garantiza la portabilidad y encapsulacion de las clases y de las librerias del una aplicación lo que provee de estabilidad a la aplicación, es decir, el mantenimiento se hace más fácil, menos costoso y con menos errores
05-10-2008 03:01
Segun como yo veo al mundo cuando pienso en objetos pienso mas en responsabilidades y mensajes y menos en atributos y propiedades.
Tener getters y setters para todo me lleva a pensar que me esta importando demasiado los datos de un objeto. Y si me empiezan a importar demasiado los datos de un objeto entonces algo huele mal porque me estoy yendo un poquito afuera del paradigma (y claramente irme del paradigma no esta bueno!).
En su lugar estaria bueno pensar en que tengo objetos y ellos tienen responsabilidades. Envío un mensaje a un objeto para que este realice algo y de esta forma colaborar. No quiero pedirle un dato para realizar algo por afuera y despues seguir por otro lado. Los objetos no son contenedores de datos. En todo caso son contenedores de comportamiento, de responsabilidades. Me gusta pensar en “tell dont ask” en cuanto a que quiero decir, queiro enviar mensajes, quiero pensar colaboraciones entre objetos y no en pedir datos y hacer validaciones y calculos por afuera. Esto me lleva a tener modelos anemicos. Objetos sin comportamiento. Los getters y setters no son malos en realidad. El punto es que ponerlos indiscriminadamente y asi por que si me va a llevar a pensar en objetos anemicos sin comportamiento ya que en realidad estan exponiendo todo su estado a todo el mundo.
Uh.. se me hizo largo el comentario.
Saludos, Pablo.
06-10-2008 10:56
Pablo, me gusta como lo has enfocado.
La verdad es que muchas veces se implementa la manipulación de los valores de los objetos fuera de éstos, convirtiéndolos en meros contenedores de datos.
Un saludo.