+ All Categories
Home > Technology > Code Smell

Code Smell

Date post: 03-Jul-2015
Category:
Upload: avature
View: 913 times
Download: 0 times
Share this document with a friend
44
Code smell Alternative classes with different interfaces Qué es? Diferentes posibles soluciones Donde lo podemos encontrar en el iATS? Solución a los casos encontrados en el iATS
Transcript
Page 1: Code Smell

Code smellAlternative classes with

different interfaces

Qué es?

Diferentes posibles soluciones

Donde lo podemos encontrar en el iATS?

Solución a los casos encontrados en el iATS

Page 2: Code Smell

Que es?

Code smell: Alternative classes with different interfaces

Code smell:

Un code smell es un indicio de que algo esta mal en alguna parte en el código y que este necesita un refactor para

corregir dicho problema.

Page 3: Code Smell

Que es?

Code smell: Alternative classes with different interfaces

Alternative classes with different interfaces:

Si 2 clases son similares o iguales internamente, pero diferentes externamente, hablamos de clases alternativas con una interfaz diferente, y claramente estamos ante un

code smell.

Page 4: Code Smell

Que es?

Code smell: Alternative classes with different interfaces

Que problema nos genera esto?

Si las clases similares tienen diferencias en sus interfaces, quien las use, tendrá diferencias en la interacción con cada una de las ellas. En cambio si las clases contaran con una

interface común, quienes las usen podrían trabajar con cualquiera de las clases de forma uniforme, lo que significa una importante reducción de código duplicado y de posibles

problemas.

Page 5: Code Smell

Diferentes posibles soluciones

Rename methods

Mode methods

Extract Sub or Super Class

Code smell: Alternative classes with different interfaces

Page 6: Code Smell

Diferentes posibles soluciones

Code smell: Alternative classes with different interfaces

Para solucionar este problema primero podemos comenzar con el renombrado de métodos asegurandonos que los

métodos se llamen como lo que realmente hacen y que su nombre sea realmente descriptivo.

Tambien podremos utilizar otras metodologías como “Mover métodos” y “Extracción de clases”

Page 7: Code Smell

Rename methods

Code smell: Alternative classes with different interfaces

Cuando queremos ver lo que hace una clase con exactitud, o a la hora de iniciar el refactor si los nombres de los métodos

no son claros, se nos puede generar un inconveniente grande ya que tendremos que seguir todo el código para ir

entendiendo.

Renombrar los métodos de una clase nos puede ayudar a entender de una forma mas simple el código, que este sea mas legible, que no sea necesario ver dentro del método

para saber que es lo que hace, y encontrar problemas (necesidad de small refactors) entre otros beneficios.

Page 8: Code Smell

Rename methods

Code smell: Alternative classes with different interfaces

Por ejemplo, nos podemos encontrar en una clase con un método que sirve para obtener los botones que se agregaran

en una toolbar de acciones, llamado “getBttns” que para saber lo que hace es necesario leer el código dentro del método si o si. Si en cambio nosotros renombramos este

método a “getActionsToolbarButtons” con solo ver el nombre nos alcanzaría para entender de que se trata dicho método.

Page 9: Code Smell

Rename methods

Code smell: Alternative classes with different interfaces

Otra cosa que debemos tener en cuenta a la hora de renombrar los métodos, para poder llegar a una solución de

este code smeel, es asegurarse que los nombres de los métodos que realizan una misma acción dentro de las clases

similares que vamos a refactorear, sean llamados de una misma forma, para que entonces quien use las clases, no deba conocer mas de una interfaz de comunicación con ambas, para evitar el duplicado de código a la hora de

usarlas.

Page 10: Code Smell

Code smell: Alternative classes with different interfaces

Como renombrar métodos sin romper todo

Para llevar a cabo esta tarea sin destruir nuestro código, o correr riesgos de dejar cosas mal hechas, la metodología a

seguir es la siguiente:

Volvamos al ejemplo anterior. Supongamos que tenemos 1 clase que maneja las toolbars de nuestra aplicación, también

supongamos que tenemos 2 posibles toolbars a mostrar, dependiendo de algún factor externo (diferentes niveles de

usuarios, etc).

Page 11: Code Smell

Code smell: Alternative classes with different interfaces

Como renombrar métodos sin romper todo

Si las clases “Toolbars” tienen una interfaz diferente, la clase que se encargue de implementar una u otra deberá conocer las 2 interfaces, y tener contemplado en su código el uso de ambas, generando el doble de código, y un aumentando la

posibilidad de error.

Page 12: Code Smell

Para corregir esto podemos empezar por hacer que los métodos de una de las clases sean igual a los de la otra, pero usando métodos nuevos que sean llamados por los

viejos.

Como renombrar métodos sin romper todo

Code smell: Alternative classes with different interfaces

Page 13: Code Smell

Como renombrar métodos sin romper todo

Por ejemplo, creamos en ActionsToolbarForUser un método nuevo, poniéndole como nombre el que deseamos que

quede. Movemos todo el código del método viejo al nuevo, y hacemos una llamada desde ahí al método nuevo.

setButtonSelected = function() { // código que había antes en setSelected

}

setSelected = function() { setButtonSelected();

}

Code smell: Alternative classes with different interfaces

Page 14: Code Smell

Como renombrar métodos sin romper todo

Luego hacemos lo mismo en la otra clase:

setButtonSelected = function() { // código que había antes en setButtonSel }

setButtonSel = function() { setButtonSelected(); }

Code smell: Alternative classes with different interfaces

Page 15: Code Smell

Como renombrar métodos sin romper todo

Ahora cambiamos en la clase que instancia estas otras dos:

if (algo) { clase1.setButtonSel(); } else { clase2.setSelected(); }

por:

claseHija.setButtonSelected();

Code smell: Alternative classes with different interfaces

Page 16: Code Smell

Como renombrar métodos sin romper todo

Por último eliminamos los métodos de las clases hijas que ya no usaremos mas:

setButtonSel y setSelected

Code smell: Alternative classes with different interfaces

Page 17: Code Smell

Add or remove parameters

Como agregado a “Rename method” podemos hablar de agregar o remover parámetros, usando la mismo

metodología que comentamos anteriormente.

Cabe destacar que cuando necesitemos mas información en un método, y para ello queramos agregar un parámetro,

siempre debemos buscar si no hay otra alternativa a esto, ya que agregar parametro nunca es conveniente, por que hace que la clase mas difícil de utilizar, ya que debemos conocer mas sobre esta por que deberemos recordar los parámetros

que necesitan sus métodos.

Code smell: Alternative classes with different interfaces

Page 18: Code Smell

Add or remove parameters

Si no tenemos mas alternativa que agregar un parámetro, deberemos al igual que al momento de renombrar un método, crear un método nuevo que reciba el nuevo

parámetro, que este sea llamado desde el método viejo, agregando el nuevo parámetro en la llamada, y luego desde quien utilice a clase llamar al nuevo método con el parámetro

agregado.

En el caso de remover un parámetro la metodología también es la misma.

Code smell: Alternative classes with different interfaces

Page 19: Code Smell

Move methodsCuando encontramos un método que es usado en mas por

otra clase que por la clase donde esta declarado, o internamente usa demasiadas propiedades o llamadas a

otros métodos de una clase externa, es evidente que estamos ante la necesidad de mover este método a dicha

clase externa.

Utilizar esta metodología hace que nuestras clases terminen siendo mas simples, y tengan menor posibilidad de fallas, ya

que tienen menos responsabilidades.

Muchas veces es difícil tomar la decisión de cambiar de lugar un método, y normalmente, cuando la decisión es difícil de

tomar, significa que en esos momentos no es tan importante el mover ese método.

Code smell: Alternative classes with different interfaces

Page 20: Code Smell

Move methods

En este caso debemos realizar algo parecido a lo que ya habíamos visto.

Para dar el ejemplo en este caso voy a usar algo que hice hace 2 días en el iATS.

Code smell: Alternative classes with different interfaces

Page 21: Code Smell

Ejemplo dentro del iATS

Tenemos una clase AttachmentList y una clase AttachmentRecord.

El problema con el que me encontré es que había en AttachmentList un link para agregar un nuevo attachment que cuando hacíamos click y elegíamos la opción “From Record” este inmediatamente instanciaba un AttachmentRecord, lo

ponía en la UI, pero vacío, y era esta clase la que se encargaba de abrir el popup para elegir cual era el

attachment a elegir. Una vez seleccionado el attchment, se actualizaba el link agregado en la UI poniéndole los datos del

attachment agregado.

Code smell: Alternative classes with different interfaces

Page 22: Code Smell

Solución al ejemplo

Esto provocaba que si el attachment elegido por alguna razón necesitaba ser mostrado/usado de otra forma a la

normal, termine siendo muy fea su implementación, ya que debía agregar una condición para ver que attachment había sido elegido y en base a eso o solo actualizábamos el link, o

había que redibujar toda la UI de ese widget.

La solución era mover todo el código de selección del attachment afuera de la clase AttachmentRecord, y que esta funcionalidad sea implementada por AttachmentList, y que una vez que se seleccionaba el attachment, recién hay se instancie la clase hija, solo que esta vez, instanciábamos AttachmentRecord para los attachments normales, o una

clase nueva, para el caso especial que se había presentado.

Code smell: Alternative classes with different interfaces

Page 23: Code Smell

Solución al ejemplo

Para realizar este cambio de forma correcta, se debe como primera instancia, controlar que métodos son los que

necesitan ser movidos, ver quien mas puede estar usándolos de forma externa y por ultimo, ver que cosas de la propia

clase donde estaban declarados usaban y que al moverlos no íbamos a tener disponibles en forma directa.

En ese análisis encontré que nadie mas usaba esos métodos de forma externa, ni que tampoco usaban propiedades o

otros métodos de la clase donde estaba declarados, por lo que estos puntos no eran un problema que me traben o

compliquen en el momento de mover el/los métodos.

Code smell: Alternative classes with different interfaces

Page 24: Code Smell

Solución al ejemplo

También vi que los métodos a mover eran 3, el que abría el popup en cuestión, y 2 callers que eran usados al elegir un

attachment, o al cancelar y cerrar el popup.

Una vez terminado ese análisis es hora de empezar a mover los métodos. Como primera medida, se declaran los 3

nuevos métodos en la clase donde se van a poner, acomodando si es necesario los nombres para que

concuerden con su nuevo entorno.

Code smell: Alternative classes with different interfaces

Page 25: Code Smell

Solución al ejemplo

Luego copiamos todo el código de los métodos de la clase hija a la clase que los va a recibir, y acomodamos las

llamadas a otros métodos, o uso de propiedades según sea necesario para que funcionen en la nueva clase.

Una vez hecho esto podemos hacer que la clase que recibió los nuevos métodos haga uso de estos, y que la clase que

aun los tiene (pero que va a dejar de tenerlos) deje de usarlos.

Cuando vemos que esta todo ok a este punto, podemos eliminar de la clase original los métodos que copiamos en la clase externa, así como todo lo relacionado a su uso (calls y

properties).

Code smell: Alternative classes with different interfaces

Page 26: Code Smell

Resultado de la solución

Clases originales

Asi quedarían

Code smell: Alternative classes with different interfaces

Page 27: Code Smell

Extract super or sub classes

Extraer super classes o sub classes, es a mi parecer la mejor forma de hacer limpieza y mejora del código. Si bien de las 3 metodologías que hablamos en esta charla podría ser la que mas trabajo nos de, creo que es la que mejor resultado nos

aporta.

Usar esta metodología nos sirve cuando 2 o mas clases cuentan con funcionalidades iguales o similares, y que por

ser parte de diferentes clases el código esta duplicado, además de que las clases son mas grandes (cantidad de

lineas de código), tienen mayores responsabilidades/funcionalidades por lo que son mas

propensas a fallos, que como venimos hablando, es lo que siempre trataremos de evitar.

Code smell: Alternative classes with different interfaces

Page 28: Code Smell

Extract super or sub classes

Extract super class:

Vamos a extraer parte del código de 2 o mas clases como una super class, cuando estas hacen cosas similares de una

forma similar.

Extract sub classes:

Vamos a extraer parte del código de 1 o mas clases como una sub class, cuando estas hacen cosas similares, pero de una forma diferente, o cuando consideramos que una clases esta haciendo demasiadas cosas y estas podrían ser hechas

por 2 o mas clases.

Code smell: Alternative classes with different interfaces

Page 29: Code Smell

Extract super class

Supongamos que tenemos 2 clases: SingleLineInput y MultiLineInput.

Ambas clases comparten parte de su funcionamiento, ya que tenemos muchos métodos que son iguales para ambas,

como por ejemplo, getValue, setValue, show, hide, setDisable, etc.

Si tenemos implementado cada uno de estos métodos en las 2 clases, tendremos no solo un montón de código duplicado, si no que ambas clases son mas difíciles de entender, son mas propensas a fallas, y además el día que necesitemos

cambiar o agregar algo, deberemos hacer el doble de trabajo.

Code smell: Alternative classes with different interfaces

Page 30: Code Smell

Extract super class

En este caso podemos extraer de estas 2 clases, 1 clase que se

encargue de hacer todo lo que es común a las 2 (los métodos que

mencionamos mas arriba).

Podríamos por ejemplo, crear una nueva clase que tenga los métodos setValue, getValue, etc, y que las

otras 2 hereden de esta, y solo tengan declarados los métodos que

son específicos para cada una.

Code smell: Alternative classes with different interfaces

Page 31: Code Smell

Como hacer la separacion de la clase

Primero debemos crear la nueva clase en blanco y hacer que las clases que tenemos actualmente hereden de esta.

Una vez hecho esto deberemos ir viendo en las clases que estamos refactoreando cuales son los métodos que

comparten funcionalidad, para ir pasándolos a la clase nueva.

Code smell: Alternative classes with different interfaces

Page 32: Code Smell

Como hacer la separacion de la clase

En este punto podemos si los métodos que vamos a mover tienen diferentes nombres usar la metodología que vimos al

principio “Rename classes”. (osea.. primero las renombramos, después las movemos).

Tenemos que fijarnos los métodos que vamos a dejar en la clases que heredan que tengan el mismo nombre, para lo

que volveremos a usar “Rename methods”

Code smell: Alternative classes with different interfaces

Page 33: Code Smell

Como hacer la separacion de la clase

Una vez que tenemos esto hecho, podemos controlar los métodos que hacen cosas similares que quedaron en las clases que heredan, para ver si tienen código que puedan

compartir, en este caso, pondremos ese código en un método separado en la clase padre, y que los métodos que

quedan en las clases que heredan lo llamen.

Code smell: Alternative classes with different interfaces

Page 34: Code Smell

Extract sub class

Cuando 1 o mas clases tienen demasiadas lineas de código, o tienen muchas funcionalidades, es seguro que debemos

extraer parte de ese código como una sub clase.

Por ejemplo supongamos que tenemos una clase ViewContactInfo, y que la usamos para mostrar los datos de

contacto de una entidad de nuestra aplicación.

Code smell: Alternative classes with different interfaces

Page 35: Code Smell

Extract sub class

Esta clase podría tener un montón de código extra, ya que debe conocer como mostrar los diferentes datos según el tipo

de contacto que es.. Phone, Email, Website, etc.

Nosotros podríamos extraer como se muestra cada ítem en particular en una clase diferente, y así hacer que cada una

solo tenga una responsabilidad, y poco código.

Code smell: Alternative classes with different interfaces

Page 36: Code Smell

Como extraer las sub clases

Para llevar a cabo esto, teniendo como ejemplo lo que comentamos sobre una clase ViewContactInfo, primero deberemos, analizar que partes de la clase, podemos

separar, teniendo en cuenta que su funcionalidad, no sea especifica de la clase padre, si no que sea un pedasito

especifico de esta.

Code smell: Alternative classes with different interfaces

Page 37: Code Smell

Como extraer las sub clases

Esto significa que si un metodo trabaja sobre todos los items a mostrar por ejemplo, sin importar de que tipo es, ese

método es de la clase padre, y no podremos sacarlo en una clase nueva. En cambio si tenemos un método que solo tiene

código para ver como se muestra un phone, en ese caso podremos sacarlo en una nueva subClase llamada por

ejemplo PhoneContactInfoItem.

La clase ViewContactInfo, deberá implementar internamente las nuevas subclases que creemos.

Code smell: Alternative classes with different interfaces

Page 38: Code Smell

Donde lo podemos encontrar en el iATS

Advaced Searches

Task and Event editors

ResultItems del search page

EmailSender.php y MailSender.php

Inputs del DOM e Inputs nuestros (.getValue and .value)

Diferentes tipos de tests (de ui, unit)

Tags Manager

Code smell: Alternative classes with different interfaces

Page 39: Code Smell

Advanced searches

En los advance search en varios caso se podría usar “Extract Sub Class”, ya que tenemos casos por ejemplo de clases que tienen métodos: updateLocation1, updateLocation2,

updateLocation3

Code smell: Alternative classes with different interfaces

Page 40: Code Smell

Result Items de Search Page

Acá tenemos varias veces ifs grandes controlando de que tipo es el ítem. Nosotros podríamos Extraer una Clase nueva

que se encargue de instanciar el tipo de ítem

Code smell: Alternative classes with different interfaces

Page 41: Code Smell

Inputs del DOM e inputs nuestros

Todavía quedan algunos inputs del DOM en la app, esto significa que nuestra app debe conocer las 2 interfaces

.value y .getValue.

Acá la solución es eliminar por completo el uso de inputs del DOM y en todos los casos usar de los nuestros para tener

una sola interfaz de comunicación posible.

Code smell: Alternative classes with different interfaces

Page 42: Code Smell

SendEmail and MailSender

EmailSender y MailSender son para lo mismo, pero tienen interfaces diferentes, acá hay que eliminar MailSender que

es el mas incompleto y usar siempre el otro.

Code smell: Alternative classes with different interfaces

Page 43: Code Smell

Sistema de Tests

Sistema de Tests, tenemos diferentes tipos de tests y sus interfaces no son iguales (Test de UI, Unit Test de UI, Unit

Test de PHP). Mi conocimiento es demasiado básico en esta parte, y además el problema es muy grande, por lo que no

podría nombrar así nomas una solución, solo nombro el problema y la solución la podemos charlar entre todos.

Code smell: Alternative classes with different interfaces

Page 44: Code Smell

Tag Manager

El TagManager funciona tal cual lo haría un Datasource, por ende lo que hay que hacer es usar un Datasource en su

lugar.

Code smell: Alternative classes with different interfaces


Recommended