Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean code: sobre el uso de métodos privados en paradigma de EDD #26

Open
Dafnemami opened this issue Apr 16, 2024 · 13 comments
Open

Clean code: sobre el uso de métodos privados en paradigma de EDD #26

Dafnemami opened this issue Apr 16, 2024 · 13 comments

Comments

@Dafnemami
Copy link

Holis!,

Haciendo la entrega me surge la duda si está estrictamente prohibido que las clases bajo el paradigma de EDD tengan métodos privados. Esto pensando en qué veo cierto caso, en mi código de clase Unit/Character, en que necesito preparar ciertos datos antes de retornarlos. Ejemplo: un método público que llama a uno privado. Es eso posible?

La segunda duda que me surge es respecto es si además estos métodos públicos de la EDD son meramente para mostrar los atributos de forma más fácil, como se hace referencia en la cápsula, o si se puede también realizar cálculos dentro de ellos como por ejemplo para calcular el daño que una unidad le inflige a otra. Sumo a la pregunta, que no me hace sentido la definición de método abordada en la cápsula, porque me estaría sugiriendo dos formas de acceder a un atributo.

Gracias 🙉 🙉 🙉 🙉

@franciscogazitua
Copy link
Owner

Hola

Si bien nada esta estrictamente prohibido mientras tenga una muy buena razón para existir en tu código, la creación de híbridos no es estrictamente necesaria (y será penalizada) en este proyecto.

Para entender esto, es importante entender el como queremos comunicar la información de nuestras clases a distintas clases que las usan. Generalmente, queremos esconder la implementación de nuestras clases y exponer solo abstracciones que nos permitan trabajar con nuestros datos. Esto no es lo mismo que esconder nuestra implementación con getters y setters, sino que implica diseñar nuestra solución de tal manera que otras partes de nuestro código no dependan de la representación concreta de nuestros datos. En efecto, una clase que expone todos sus atributos con getters y setters sigue siendo una Estructura de Datos.

Imagen de WhatsApp 2024-04-17 a las 08 05 51_b8eadbe0

Ahora, la distinción más importante entre el paradigma orientado a objetos y el paradigma orientado a estructuras de datos es que ambas estructuras son las opuestas de la otra. Los objetos esconden su implementación mediante abstracciones, mientras que las estructuras de datos exponen su implementación. Dado que una estructura de datos quiere exponer su implementación, no debería tener métodos complejos, ya que estos cumplen la función de esconder la implementación mediante abstracciones.

Imagen de WhatsApp 2024-04-17 a las 08 05 51_be4142f0

Si bien, tiene mucho sentido que la clase Unit sea una estructura de datos, no tiene mucho sentido que esta estructura haga operaciones complejas sobre sus datos, porque su objetivo sería exponer estos datos para que otras clases puedan trabajar con estos (lo que incluye hacer operaciones complejas con estos).

Cuando tomes la decisión de si una clase debiese ser una estructura de datos o un objeto, recuerda que es importante entender las ventajas de cada una de estas estructuras y como estas se relacionan. En particular, creo muy importante la siguiente parte del libro:

Imagen de WhatsApp 2024-04-17 a las 08 05 51_bf57a9d8

Dado lo anterior, si tu clase Unit expone su implementación, pero al mismo tiempo la esconde mediante funciones, esta caería en al categoría de hibrido. Es importante evitar construir híbridos porque estos combinan las peores partes de los paradigmas orientados a objetos y orientados a estructuras de datos:

Imagen de WhatsApp 2024-04-17 a las 08 05 50_6b3d908b

En resumen, no crees híbridos, no solo se considerará descuento por estos, sino que también hará que sea más difícil para ti escalar tu solución en las siguientes entregas.

Saludos,

@cahinostroza
Copy link
Collaborator

Bueno, después de la cátedra que dió @franciscogazitua, sólo me queda agregar que si puedes tener métodos privados en una EDD, la parte clave es cómo son esos métodos. El libro nos dice que una EDD no debe tener "meaningful functions", a esto se refiere con lógica de negocio y en este caso en particular, con lógica del juego.

@cahinostroza
Copy link
Collaborator

Por lo tanto, puede que haya un caso en que haga sentido tener un método privado en una EDD, pero por lo general no.

@Dafnemami
Copy link
Author

Hola @franciscogazitua, @cahinostroza . Muchas gracias ambos por sus respuestas, se complementaron bacán!

Sigue siendo confusa para mi cierta idea: Las EDD tienen sus atributos públicos. Entonces, cada vez que por alguna razón algún método -público- lo muestre, cómo puedo manejar ese caso? Pensando que quiero asegurar solo una forma de acceder al atributo. Forma 1: Hago el atributo privado (mal porque es una EDD) Forma 2: No hacer ese método (mala idea también jajaja)

Saludos!

@cahinostroza
Copy link
Collaborator

Una EDD no necesariamente debe tener sus atributos públicos, puedes exponer su datos a través de métodos públicos. Por ejemplo:
image

@Dafnemami
Copy link
Author

Ahhh comprendo. Al final el core es que tenga públicos, de alguna forma, todos sus atributos, pero el cómo lo hacemos (si es a través de un método o el atributo mismo) es elección nuestra. Si lo anterior es correcto, creo comprender bacán. Muchas gracias! Me es mucho más claro ahora!!

@franciscogazitua
Copy link
Owner

Quizas la confusión viene porque estas intentando hacer cosas complejas en tu EDD.

Tiene sentido tener atributos públicos y usarlos en métodos públicos para preparar los datos. En un caso sencillo, podrías tener una EDD con un atributo string X1 y un atributo string X2, si en algun punto necesito retornar un string que use ambas variables, tiene sentido hacer una función pública que haga return $"Tengo {X1} y {X2}". Sin embargo la clase dejaría de ser una EDD si hace cosas más complejas, como, por ejemplo, operar con X1 y X2 para determinar algun elemento del juego.

En ese sentido, estaría mal que una EDD que represente la unidad también calcule el daño que esta realizará. Esto porque calcular el daño depende no solo de los atributos de Unit

@siescobedo
Copy link

Entonces una EDD puede "calcular cosas" para entregar data de sus atributos de alguna otra manera con algún método público, pero no se le puede entregar ningún parámetro a sus métodos porque debería poder solo interactuar con sus propios atributos?

@Dafnemami
Copy link
Author

Sobre lo primero sofi me parece que no se puede operar de ninguna forma entre los atributos que ya tiene, sino más bien presentarlos de otra forma (como return $"Tengo {X1} y {X2}"). Lo segundo que dices me parece oki, como que probablemente hacer eso implicaría que estaríamos ocupando lógica del juego en la edd que no es la idea.

@siescobedo
Copy link

En ese caso, en el ejemplo visto en clases

Screenshot 2024-04-17 122155

Esto es un objeto o una EDD? Ya que en la segunda implementación para mostrar el porcentaje está interactuando con sus atributos, mostrándolos de otra forma.

@franciscogazitua
Copy link
Owner

Hola

La definición de EDD no tiene nada que ver con la composición los argumentos de sus funciones o con el como esta se construye a nivel de código, sino que tiene que ver con el objetivo de la clase en si. Una EDD expone su estructura interna, permitiendo a otras entidades acceder a sus implementación, mientras que un objeto esconde su estructura interna y provee abstracciones para que otras entidades puedan interactuar con el.

En eses sentido, un objeto es como una caja negra, en el sentido que yo no se que es lo que hace por adentro, solo se cuales son sus entradas y sus salidas. Por otro lado, una EDD es lo contrario, ya que esta me permite acceder a su implementación. En ese sentido, un objeto opera sobre sus datos y expone abstracciones, mientras que una EDD expone sus datos para que otros operen sobre ellos.

Lo anterior no habla de implementaciones especificas en tu código. Podrías tener una EDD con todos sus atributos privados y exponerlos mediante métodos o podrías tener una EDD sin métodos y con todos sus atributos públicos, ambas opciones son válidas.

Como señala @Dafnemami, la idea es que tu EDD no contenga lógica compleja del juego, sino que exponga sus datos para que otros elementos de tu solución puedan ocuparlos para realizar dicha lógica. Si la razón por la que le estas pasando un atributo externo a tu EDD es porque quieres que esta maneje la lógica del juego con estos, entonces tu clase no sería una EDD, sino que sería un híbrido.

En cuanto al segundo ejemplo de la clase (que es el que se discute en el comentario de @siescobedo), este sería un objeto, no una estructura de datos. Esto porque no expone su estructura interna, sino que expone sus datos como una abstracción. Lo bueno de esa implementación es que es irrelevante si Vehicle guarda sus atributos en galones, litros u otra unidad de medida, double GetPercentFuelRemaining() solo expone la abstracción en términos de porcentajes. Esto sería cierto incluso si Vehicle guardara su atributo en porcentaje, lo importante es que la clase que utiliza el método double GetPercentFuelRemaining() no lo puede saber.

Por favor, no entender lo anterior como que siempre es mejor hacer objetos, estructuras que se componen de agrupaciones de datos (como probablemente sería Unit) tienen mucho más sentido como EDD que como objetos.

Lo importante es que sepan como manejar sus estructuras tal que haga su solución fácil de mantener y que separe correctamente sus responsabilidades. Recuerden siempre que una EDD y un objeto responden a necesidades distintas y tienen ventajas y desventajas distintas:

Imagen de WhatsApp 2024-04-17 a las 08 05 51_bf57a9d8

@Dafnemami
Copy link
Author

Gracias @franciscogazitua! Me es mucho más clara ahora la flexilibidad de las definiciones.

@siescobedo
Copy link

muchas gracias!! me quedo muy claro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants