El post que buscas se encuentra eliminado, pero este también te puede interesar

Code smell (¿a que huele tu código?)

Code smell (¿a que huele tu código?)

Programacion

Los code smells vienen a ser algo así como malas practicas a la hora de programar. Cosas que no están buenas hacer y que ensucian nuestro código. Probablemente el código compila y se ejecuta perfecto, pero se hace difícil de entender y de seguir. No hay ningún programa que lo hagamos totalmente solos por lo que es bueno mantener cierto orden en el código para que todo el que requiera usarlo lo pueda entender mas fácilmente.

poo

Un refactor es un cambio en el código, pero este cambio no agrega funcionalidad a lo que ya estaba, sino que se hace con el objetivo de ordenar las cosas y que sean mas entendibles. Son muy útiles para realizar rediseños. No es el objetivo del post hablar de refactores pero seguramente haga mención sobre ellos por lo que es importante saber que son.

orientado a objetos

No, hay muchas cuestiones que entran en juego a la hora de decidir refactorizar. Sobre todo el criterio de cada uno. Probablemente estemos cortos de tiempos, como es muy normal que suceda, por lo que no seria bueno tocar código en un modulo que ya esta terminado y no vamos a volver a usar. También puede pasar que si nos tomamos un poco de tiempo arreglando el código el día de mañana nos ahorramos ese tiempo en entenderlo, o explicárselo a otra persona, o incluso puede ser mas fácil agregar funcionalidad sobre el nuevo código.

También es importante saber que un método no se convierte en un long method al superar tantas lineas de código, sino que acá entra en juego un grado de subjetividad para decidir cuando estamos frente a un code smell.

refactor

code smell

Un long method es un método que se extiende mas de lo necesario. No hay una formula mágica para reconocerlo, como dije antes no es un long method por superar las 10 lineas de código. Para mantener un método lo mas sencillo posible es bueno seguir estos 2 consejos.

-Que el método haga una y solo una cosa
-Que su nombre indique que hace y no como lo hace

Los métodos que hacen varias cosas resultan mas complicados que los que realizan solo una, ¿parece obvio no? Pero no siempre resulta sencillo diferenciar una tarea de la otra porque pueden estar muy relacionadas entre si. Si tenemos un método que realiza 2 tareas es buena idea separarlos en 2 métodos distintos.

Con respecto al nombre se puede decir que, si indica lo que esta haciendo en vez del como podemos abrir juego al polimorfismo, por ejemplo en vez de ponerle “buscarBinario” podemos llamarlo solo “buscar” y si mas adelante queremos implementar otro tipo de búsqueda como la secuencial las clases que implementen las búsquedas no deberían ser tocadas porque llamarían al método buscar.

Code smell (¿a que huele tu código?)

Cuando una clase se empieza a hacer muy extensa es síntoma que se esta convirtiendo en una god class. Por lo general tienen muchas variables de instancia y asumen responsabilidades que en realidad deberían estar delegadas en otra clase. Es normal caer en la god class para los que están dejando la programación estructurada para empezar con la orientada a objetos.

En general las god class tienen estas características
-Son difíciles de testear
-Presenta conjuntos de métodos no relacionados que trabajan con distintas variables de instancia
-Es difícil reutilizar debido a las variadas características que contempla
-Hacer un cambio en la clase puede resultar dificultoso por no poder diferenciar las partes que son afectadas
-Muchos de los cambios en el sistema repercuten en esta clase

Para solucionarlo lo mas recomendable es buscar las variables de instancia que se relacionan y extraerlas en otra clase junto con todos los métodos que actúen sobre esas variables. Es importante que las nuevas clases tengan nombres que identifiquen bien que hacen y que responsabilidades tienen. De esta manera dividimos la god class en varias clases mas pequeñas con responsabilidades bien definidas.

Programacion

Es común ver como va creciendo la lista de parámetros de un método a medida que requerimos pasarle nuevos datos. Por lo general las clases que implementen este método deberían reunir todos los parámetros necesarios resultando en un código para nada lindo.

Nos podemos encontrar con algo así.

Tenemos un hotel, cuando una persona llega se debe registrar con su nombre, apellido, edad, dni, domicilio y habitación donde se va a hospedar

class Hotel {

void registrarPersona(nombre, apellido, edad, dni, domicilio, nroHabitacion);

}


y para invocarla haríamos algo así


unHotel.registrarPersona(unaPersona.getnombre(), unaPersona.getApellido(), unaPersona.getEdad(), unaPersona.getDni(), unaPersona.getDomicilio(), nroHabitacion);


Muchos de los datos son sacados de la misma persona. Por lo que podemos hacer algo como.


Class Hotel {

void registrarPersona(unaPersona, nroHabitacion);

}


No siempre es tan fácil de identificar la solución, hay que estudiar cada caso particular y ver el por que requiere tantos parámetros y de donde se obtienen.

poo

Este code smell se da cuando un método parece estar mas interesado en otra clase que a la que le pertenece. Nos deberíamos preguntar ¿El método esta en la clase correcta? Por lo general estos métodos usan muchos setters y getters de la otra clase.

La solución mas sencilla es la de mover el método a la otra clase. También puede pasar que solo una parte del método sea la que debe ser movida a la otra clase.

Una excepción a esta regla se da en los patrones de diseño strategy y visitor, no es el objetivo del post hablar sobre patrones de diseño, quizás mas adelante lo haga.

orientado a objetos

Las data class son justamente clases que tiene unas cuantas variables de instancia y sus setters y getters, pero no presenta comportamiento propio. Esto se debe a una mala distribución de las responsabilidades de cada clase. Seguramente tenemos el comportamiento que le corresponde a esta clase distribuida entre las clases que la implementan.

Esta fuertemente atada al Feature envy, ya que es un método de otra clase la que manipula los atributos de la data class. La solución es mover los métodos que usen los setters y getter injustificadamente a la clase que corresponde. También nos podemos encontrar con el caso de que sea solo una parte del método la que esta implicada por lo que deberíamos separarla del resto del método y luego moverla.

refactor

Un message chain vendría a ser algo como esto.


unaCosa.getXXX ().getYYY().getZZZ().hacerAlgo();


O sea partimos desde unaCosa le pedimos un atributo a este le pedimos otro y cuando llegamos al ultimo le mandamos el mensaje que realmente importa. Esto nos trae aparejado que todas las clases que intervienen terminan fuertemente acopladas a la estructura de navegación. Se pierde el encapsulamiento, porque a una clase no debería importarle como esta armada otra y viceversa.

Lo mas seguro es que el comportamiento que queremos modelar corresponda a unaCosa de esa manera al llamar el mensaje quedaría algo así.


UnaCosa.hacerAlgo();


y en el método hacerAlgo se delega a XXX la tarea.


void hacerAlgo() {
this.getXXX ().hacerAlgo();
}


Y así hasta llegar a alguien que en realidad pueda completar la tarea. Parecería que la solución hace las cosas mas complicadas de lo que eran antes, pero hay que notar que si hacemos un cambio en la estructura de la clase no tendríamos que cambiar en todas las clases que lo implementen porque ahora las clases están menos acopladas.

La regla de Demeter nos dice que una clase solo debería invocar métodos de:
-si mismo (this, self)
-de sus parametros
-de cualquier objeto que él cree o instancie
-de sus colaboradores directos

La aparición de message chains son claras violaciones a la regla de Demeter.

code smell

Casi todos los lenguajes de programación tienen tipos de datos primitivos. La primitive obsession es justamente abusar de estos tipos de datos primitivos. Es muy común para los que se están iniciando en el paradigma de objetos caer en este code smell. A veces es bueno representar, por ejemplo una clase Money que convine una cantidad y una moneda. Si en cambio usáramos los tipos de datos primitivos para esto nos veríamos en la obligación de repetir ciertos controles en todas las clases que requieran utilizar monedas.

Otro ejemplo podría ser usar en una clase una colección, no es malo usar colecciones, pero por ejemplo si tenemos una serie de métodos a realizar sobre esa colección no es mala idea crear una nueva clase que contenga a la colección y delegar en ella todo el comportamiento que al manejo de la colección se refiera.

Code smell (¿a que huele tu código?)

El problema al realizar un switch o una serie de ifs es la duplicación. Es normal que tengamos que repetir el switch o los ifs en otra parte del programa y cuando tengamos que agregar una clausula al switch nos veríamos en un problema, ya que hay que buscar en todos los lugares donde se haga y agregarlo. Para solucionarlo la mejor herramienta que nos da el paradigma de objetos es el polimorfismo.

Esto es porque la mayoría de las veces el swich esta hecho sobre un tipo de código. En general tendríamos que crear tantas clases como clausulas del switch que hereden de la misma el comportamiento común y que cada una redefina el método haciendo lo que le corresponde. También puede pasar que podemos delegar ese comportamiento en otra clase como sucede con el patrón strategy, pero como dije antes no es el objetivo del post hablar de patrones.

Programacion

A veces creamos una clase que en un principio tiene sentido, pero luego de unos refactors nos damos cuenta que perdió su responsabilidad porque tenemos otra clase que las adquirió. Lo mas común es que traslademos el comportamiento que quedo en la lazy class a la otra clase, no es bueno tener 2 clases con la misma responsabilidad.

poo

Este code smell aparece cuando nos planteamos “yo creo que tendríamos que abarcar este tipo de cuestiones por si se nos presentan el día de mañana” y así querer contemplar todos los casos posibles que puedan surgir y no son requeridas en este momento. Esto nos da un código mas complicado y difícil de mantener y si el día de mañana nos llega un nuevo requerimiento que no teníamos contemplado, porque es imposible contemplar todas las situaciones, nos veremos en un gran problema.

orientado a objetos

Es simplemente cuando creamos una clase que hereda de otra cierto comportamiento que queremos reutilizar, pero también comportamiento que no requerimos. Lo mas fácil en estos casos es crear una clase hermana que tenga todo el comportamiento que no queremos que las otras hereden.

refactor

Los comentarios muchas veces ayudan a explicar un poco mejor el código. Pero deberíamos preguntarnos ¿Por que es difícil de entender esta parte del código? En una de esas podemos detectar lo que buscamos y agrupando una parte del método en otro se vuelve mas entendible por lo que el comentario deja de tener sentido. Sin embargo hay muchas veces que comentar el código es la mejor salida.

code smell

Para el final dejo el code smell que probablemente mas apesta, el código duplicado. Cuando nos encontramos con que repetimos la misma estructura de código en varias partes del código debemos pensar que estamos duplicando código y lo mejor es buscar una forma de unificarlo. Lo normal es que no sea exactamente el mismo método, hay que saber identificar la parte que se repite y separarla en un nuevo método para luego poder invocarlo desde donde sea requerido.

Si el código se repite en varias clases es probable que tengamos que crear una clase nueva que tenga el comportamiento que se repite. O también podemos detectar que la parte repetida corresponde a una clase en particular y las otras deberían invocarlo.

Code smell (¿a que huele tu código?)

-Wikipedia http://en.wikipedia.org/wiki/Code_smell
-Clases de técnicas avanzadas de programación (UTN-FRBA)
-Experiencia personal

3 comentarios - Code smell (¿a que huele tu código?)

edd96 -1
Teen spirit