CONSULTA Ruby Initialize complejo

32 views
Skip to first unread message

Matias Mascazzini

unread,
Jun 17, 2020, 10:57:27 AM6/17/20
to rubysur
Hola,
jugando con POROs me surgió una caso de uso particular, me gustaría saber sus opiniones al respecto.

Necesito que al momento de inicializar un objeto se realice un "parseo" de los parámetros que recibe. Puntualmente uno de los parámetros es un array, necesito transformarlo aplicando una función y asignar el valor a la variable de instancia.

¿Qué estrategia sería una buena práctica utilizar?
1- crear un método privado para realizar la transformación: @c = metodo_privado(c)
2- hacer un setter tipo: def c=(c) ...
3- hacer un setter del tipo: def c { @c ||= <procesar aqui el parametro> }
4- los parámetros recibidos deberían ya venir parseados y simplemente asignarlos.
5- otra...

class Foo
   def initialize (a, b, c=[])
       @a = a
       @b = b
       @c = ???
   end
end

La verdad que generalmente simplemente se los asignó como el caso 4, y los libros que consulte solo tienen ejemplos simples donde hacen eso.

Saludos
Matías Mascazzini

Geronimo Diaz

unread,
Jun 17, 2020, 11:05:26 AM6/17/20
to rubysur
Hola Matias,

Yo en esos casos dejo c sin tocarlo para referencia, y me manejo con un parsed_c dentro de la instancia, privado o público dependerá del caso. 

Saludos

Geronimo Diaz
Ruby/RoR Dev
--
Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/rubysur/CAOAUXOM%3DYfn0wtLwA9Lo2TbcnMkS0K502%3DOq0wamDp6wNt7tng%40mail.gmail.com.

Mauricio Pautasso

unread,
Jun 17, 2020, 11:07:54 AM6/17/20
to rub...@googlegroups.com
Mmm veamos que dice el resto, pero la opción 1 la veo bien. 

Abrazo. 

--
Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/rubysur/CAOAUXOM%3DYfn0wtLwA9Lo2TbcnMkS0K502%3DOq0wamDp6wNt7tng%40mail.gmail.com.
--

Jhon Quintero

unread,
Jun 17, 2020, 11:10:07 AM6/17/20
to rub...@googlegroups.com

Pablo Russo

unread,
Jun 17, 2020, 11:10:22 AM6/17/20
to rub...@googlegroups.com
No se cuan compleja es la lógica en cuestión, pero otra alternativa es usar un factory y dejar el initialize y la clase original más simple.

--
Pablo.-



Michel Martens

unread,
Jun 17, 2020, 11:15:33 AM6/17/20
to rubysur
Creo que lo ideal es que la clase no tenga que modificar nada, que
reciba los parámetros tal como los necesita. Si fuera imprescindible
lidiar con esto dentro de la clase, entonces podrías agregar otro
constructor:

Foo.new(params)
Foo.from_json(params)

Esta solución es bastante estándar. Lo tener varios constructores se
ve mucho porque es práctico, pero de todas formas no es ideal.
> Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/rubysur/CAEngUXdiksobr_gi6%3DcP%3D7UZNVN9kYrCJ3RvQ5GczgDVTaMBQA%40mail.gmail.com.

Joaquín Vicente

unread,
Jun 17, 2020, 11:22:45 AM6/17/20
to rub...@googlegroups.com
Lo primero que me preguntaría es de quien es la responsabilidad de procesar eso?
Está vinculado a las responsabilidades de la clase Foo? o es algo total externo?
Ejemplos:
1) Foo recibe un array con valores y solo le interesa almacenar el más grande? es responsabilidad de Foo
2) le estás pasando los query params y querés quedarte solo con uno de esos? Eso no es responsabilidad de Foo, debería procesarse afuera
3) Recibís nombre+apellido por separado y querés guardarlo todo junto? Eso lo podés hacer en tu constructor.
4) Es posible que quieras modificar el atributo más adelante? Entonces un setter puede ser mejor opción 


Emanuel Gauler

unread,
Jun 18, 2020, 7:52:35 AM6/18/20
to rub...@googlegroups.com
Hola Matías. 

Creo que deberías responder éstas preguntas 
¿qué hace Foo con ése arreglo? Y, 
¿porqué el parámetro c es un arreglo?



Matias Mascazzini

unread,
Jun 18, 2020, 8:52:13 AM6/18/20
to rubysur
Hola,
la verdad que quería dejar planteado el problema de forma general y no específico. Justamente el tema de la responsabilidad que planteó Joaquín es un asunto clave.

Otra cuestión que surge... ¿ un parámetro de un constructor debería venir previamente parseado ? Miguel planteó que idealmente si; entonces la responsabilidad es del que envía el mensaje no del receptor. En ese caso porque el receptor del mensaje no es responsable de validar y decirle al emisor que le está mandando mal los datos en los parámetros del mensaje.


El jue., 18 de jun. de 2020 a la(s) 08:52, Emanuel Gauler (emanue...@gmail.com) escribió:
Hola Matías. 

Creo que deberías responder éstas preguntas 
¿qué hace Foo con ése arreglo? Y, 
Foo necesita que ese arreglo tenga cierto tipo de datos y formato... supongamos que sean todos numéricos.  En mi caso por ahora no hace nada particular, sino que se usan para compararse con los datos de otras instancias de la misma clase.

¿porqué el parámetro c es un arreglo?
Es un atributo que representa un conjunto de datos del mismo tipo que de alguna manera definen lo que es Foo.  Podría ser un hash. ¿Lo ves como muy raro que un atributo sea un arreglo de datos? ¿Que pasaría si son un array de objetos de otra clase?


Hernan Fernandez

unread,
Jun 18, 2020, 9:27:03 AM6/18/20
to rub...@googlegroups.com
Hola
Yo usaría un método privado si es una tarea "simple", fácil de testear, ¿reusable?,
sino iria con un Service Object, tenes esa lógica separada y más fácil de reutilizar de ser necesario.

Saludos

On Wed, Jun 17, 2020 at 11:57 AM Matias Mascazzini <matia...@gmail.com> wrote:

Emanuel Friedrich

unread,
Jun 18, 2020, 9:56:52 AM6/18/20
to rub...@googlegroups.com
Para mi el punto siempre esta en torno a la pregunta:

Voy a necesitar este parseo en otro lado?

Si no, da la sensacion que debe estar dentro, como prefieras, si con method o setter.

Pero si tenes un modulo de "parseo" ya y mentalmente sentis que es un desafio leer esto en esta clase (nuestra mente arma ya una suerte de scopes, al menos la mia, prefiere leer un tipo de codigo en un cierto lugar, no en otro), lo pones en ese modulo/clase aparte. Por ej.

class FooCArrParser;

o meterlo dentro de un modulo/clase ya existente.

Y Hernan dijo algo interesante, si lo vas a testear (aunq no soy ducho en tests) el metodo quiza sea lo mejor.

Tambien esta el tema de que representa esta clase. Si para vos es una clase que representa mas datos (tipo DataClass de kotlin y veo q python tiene algunos decorators) q procesamiento, te sentiras mas comodo separando el parseo en otra parte



--
Emanuel Friedrich 

Cel: 3754-442896

Daniel Moros

unread,
Jun 18, 2020, 4:31:48 PM6/18/20
to rub...@googlegroups.com
Buen día! Matías me apuntaría por la opción 1: crear un método privado para realizar la transformación: @c = metodo_privado(c). Usas el callback before_save



--
Lic. Daniel Moros
Soluciones tecnológicas
#ImprimeSoloSiEsNecesario

Juan Matías

unread,
Jun 18, 2020, 6:02:48 PM6/18/20
to rub...@googlegroups.com
La del constructor específico o la de una Factory me gustan. También  puede ayudar pensar en qué momento o capa se valida o transforma una entrada y quién debería hacerlo. Como sucede con los parámetros de un request que terminan siendo un "Hash" (pensando en Rails). 



--
Matías 

Emanuel Gauler

unread,
Jun 18, 2020, 6:30:35 PM6/18/20
to rub...@googlegroups.com
Cómo te escribo, todo depende, y de qué depende? De la responsabilidad de Foo, para el caso que se fabrica Foo. Y hay que determinar cómo incide en el comportamiento de Foo la estructura de "c".

Para mí no hay una opción única y generalizada para todos los casos, hay que ir especificando el comportamiento de Foo, y determinar que és lo esencial para Foo.
Desde mi punto de vista.



Reply all
Reply to author
Forward
0 new messages