Sie sind auf Seite 1von 44

Code smell Alternative classes with different interfaces

Qu es? Diferentes posibles soluciones Donde lo podemos encontrar en el iATS? Solucin a los casos encontrados en el iATS

Que es?

Code smell: Un code smell es un indicio de que algo esta mal en alguna parte en el cdigo y que este necesita un refactor para corregir dicho problema.

Code smell: Alternative classes with different interfaces

Que es?

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.

Code smell: Alternative classes with different interfaces

Que es?

Que problema nos genera esto? Si las clases similares tienen diferencias en sus interfaces, quien las use, tendr diferencias en la interaccin con cada una de las ellas. n cambio si las clases contaran con una interface com!n, quienes las usen podr"an traba#ar con cualquiera de las clases de forma uniforme, lo que significa una importante reduccin de cdigo duplicado y de posibles problemas.

Code smell: Alternative classes with different interfaces

Diferentes posibles soluciones

Rename methods Mode methods Extract Sub or Super Class

Code smell: Alternative classes with different interfaces

Diferentes posibles soluciones


$ara 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. &ambien podremos utilizar otras metodolog"as como '(over m%todos) y ' xtraccin de clases)

Code smell: Alternative classes with different interfaces

Rename methods
*uando 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 cdigo para ir entendiendo. +enombrar los m%todos de una clase nos puede ayudar a entender de una forma mas simple el cdigo, 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.

Code smell: Alternative classes with different interfaces

Rename methods

$or e#emplo, 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 'get.ttns) que para saber lo que hace es necesario leer el cdigo dentro del m%todo si o si. Si en cambio nosotros renombramos este m%todo a 'get/ctions&oolbar.uttons) con solo ver el nombre nos alcanzar"a para entender de que se trata dicho m%todo.

Code smell: Alternative classes with different interfaces

Rename methods
0tra cosa que debemos tener en cuenta a la hora de renombrar los m%todos, para poder llegar a una solucin de este code smeel, es asegurarse que los nombres de los m%todos que realizan una misma accin 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 comunicacin con ambas, para evitar el duplicado de cdigo a la hora de usarlas.

Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo


$ara llevar a cabo esta tarea sin destruir nuestro cdigo, o correr riesgos de de#ar cosas mal hechas, la metodolog"a a seguir es la siguiente1 2olvamos al e#emplo anterior. Supongamos que tenemos 3 clase que mane#a las toolbars de nuestra aplicacin, tambi%n supongamos que tenemos 2 posibles toolbars a mostrar, dependiendo de alg!n factor externo ,diferentes niveles de usuarios, etc-.

Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo

Si las clases '&oolbars) tienen una interfaz diferente, la clase que se encargue de implementar una u otra deber conocer las 2 interfaces, y tener contemplado en su cdigo el uso de ambas, generando el doble de cdigo, y un aumentando la posibilidad de error.
Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo

$ara 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 vie#os.

Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo


$or e#emplo, creamos en /ctions&oolbar4orUser un m%todo nuevo, poni%ndole como nombre el que deseamos que quede. (ovemos todo el cdigo del m%todo vie#o al nuevo, y hacemos una llamada desde ah" al m%todo nuevo. set.uttonSelected 5 function,- 6 77 cdigo que hab"a antes en setSelected 8 setSelected 5 function,- 6 set.uttonSelected,-9 8
Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo


:uego hacemos lo mismo en la otra clase1

set.uttonSelected 5 function,- 6 77 cdigo que hab"a antes en set.uttonSel 8 set.uttonSel 5 function,- 6 set.uttonSelected,-9 8

Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo


/hora cambiamos en la clase que instancia estas otras dos1 if ,algo- 6 clase3.set.uttonSel,-9 8 else 6 clase2.setSelected,-9 8 por1 clase;i#a.set.uttonSelected,-9
Code smell: Alternative classes with different interfaces

Como renombrar mtodos sin romper todo

$or !ltimo eliminamos los m%todos de las clases hi#as que ya no usaremos mas1 set.uttonSel y setSelected

Code smell: Alternative classes with different interfaces

Add or remove parameters


*omo agregado a '+ename method) podemos hablar de agregar o remover parmetros, usando la mismo metodolog"a que comentamos anteriormente. *abe destacar que cuando necesitemos mas informacin en un m%todo, y para ello queramos agregar un parmetro, 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 parmetros que necesitan sus m%todos.

Code smell: Alternative classes with different interfaces

Add or remove parameters


Si no tenemos mas alternativa que agregar un parmetro, deberemos al igual que al momento de renombrar un m%todo, crear un m%todo nuevo que reciba el nuevo parmetro, que este sea llamado desde el m%todo vie#o, agregando el nuevo parmetro en la llamada, y luego desde quien utilice a clase llamar al nuevo m%todo con el parmetro agregado. n el caso de remover un parmetro la metodolog"a tambi%n es la misma.

Code smell: Alternative classes with different interfaces

Move methods
*uando 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. (uchas veces es dif"cil tomar la decisin de cambiar de lugar un m%todo, y normalmente, cuando la decisin 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

Move methods

n este caso debemos realizar algo parecido a lo que ya hab"amos visto. $ara dar el e#emplo en este caso voy a usar algo que hice hace 2 d"as en el i/&S.

Code smell: Alternative classes with different interfaces

Ejemplo dentro del iA !


&enemos una clase /ttachment:ist y una clase /ttachment+ecord. l problema con el que me encontr% es que hab"a en /ttachment:ist un lin< para agregar un nuevo attachment que cuando hac"amos clic< y eleg"amos la opcin '4rom +ecord) este inmediatamente instanciaba un /ttachment+ecord, lo pon"a en la U=, 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 lin< agregado en la U= poni%ndole los datos del attachment agregado.
Code smell: Alternative classes with different interfaces

!oluci"n al ejemplo
sto provocaba que si el attachment elegido por alguna razn necesitaba ser mostrado7usado de otra forma a la normal, termine siendo muy fea su implementacin, ya que deb"a agregar una condicin para ver que attachment hab"a sido elegido y en base a eso o solo actualizbamos el lin<, o hab"a que redibu#ar toda la U= de ese >idget. :a solucin era mover todo el cdigo de seleccin del attachment afuera de la clase /ttachment+ecord, y que esta funcionalidad sea implementada por /ttachment:ist, y que una vez que se seleccionaba el attachment, reci%n hay se instancie la clase hi#a, solo que esta vez, instancibamos /ttachment+ecord para los attachments normales, o una clase nueva, para el caso especial que se hab"a presentado.
Code smell: Alternative classes with different interfaces

!oluci"n al ejemplo
$ara 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 usndolos 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. n ese anlisis 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 el7los m%todos.
Code smell: Alternative classes with different interfaces

!oluci"n al ejemplo
&ambi%n vi que los m%todos a mover eran ?, el que abr"a el popup en cuestin, y 2 callers que eran usados al elegir un attachment, o al cancelar y cerrar el popup. Una vez terminado ese anlisis es hora de empezar a mover los m%todos. *omo primera medida, se declaran los ? 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

!oluci"n al ejemplo
:uego copiamos todo el cdigo de los m%todos de la clase hi#a 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 de#ar de tenerlos- de#e de usarlos. *uando vemos que esta todo o< 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

Resultado de la soluci"n

Clases originales

Asi quedaran

Code smell: Alternative classes with different interfaces

E#tract super or sub classes


xtraer super classes o sub classes, es a mi parecer la me#or forma de hacer limpieza y me#ora del cdigo. Si bien de las ? metodolog"as que hablamos en esta charla podr"a ser la que mas traba#o nos de, creo que es la que me#or 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 cdigo esta duplicado, adems de que las clases son mas grandes ,cantidad de lineas de cdigo-, tienen mayores responsabilidades7funcionalidades 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

E#tract super or sub classes


Extract super class: 2amos a extraer parte del cdigo de 2 o mas clases como una super class, cuando estas hacen cosas similares de una forma similar. Extract sub classes: 2amos a extraer parte del cdigo de 3 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

E#tract super class


Supongamos que tenemos 2 clases1 Single:ine=nput y (ulti:ine=nput. /mbas clases comparten parte de su funcionamiento, ya que tenemos muchos m%todos que son iguales para ambas, como por e#emplo, get2alue, set2alue, sho>, hide, set@isable, etc. Si tenemos implementado cada uno de estos m%todos en las 2 clases, tendremos no solo un montn de cdigo duplicado, si no que ambas clases son mas dif"ciles de entender, son mas propensas a fallas, y adems el d"a que necesitemos cambiar o agregar algo, deberemos hacer el doble de traba#o.
Code smell: Alternative classes with different interfaces

E#tract super class


n este caso podemos extraer de estas 2 clases, 3 clase que se encargue de hacer todo lo que es com!n a las 2 ,los m%todos que mencionamos mas arriba-. $odr"amos por e#emplo, crear una nueva clase que tenga los m%todos set2alue, get2alue, 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

Como hacer la separacion de la clase


$rimero 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 pasndolos a la clase nueva.

Code smell: Alternative classes with different interfaces

Como hacer la separacion de la clase


n este punto podemos si los m%todos que vamos a mover tienen diferentes nombres usar la metodolog"a que vimos al principio '+ename classes). ,osea.. primero las renombramos, despu%s las movemos-. &enemos que fi#arnos los m%todos que vamos a de#ar en la clases que heredan que tengan el mismo nombre, para lo que volveremos a usar '+ename methods)

Code smell: Alternative classes with different interfaces

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 cdigo que puedan compartir, en este caso, pondremos ese cdigo 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

E#tract sub class

*uando 3 o mas clases tienen demasiadas lineas de cdigo, o tienen muchas funcionalidades, es seguro que debemos extraer parte de ese cdigo como una sub clase. $or e#emplo supongamos que tenemos una clase 2ie>*ontact=nfo, y que la usamos para mostrar los datos de contacto de una entidad de nuestra aplicacin.

Code smell: Alternative classes with different interfaces

E#tract sub class

sta clase podr"a tener un montn de cdigo extra, ya que debe conocer como mostrar los diferentes datos seg!n el tipo de contacto que es.. $hone, mail, Aebsite, etc. Bosotros 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 cdigo.

Code smell: Alternative classes with different interfaces

Como e#traer las sub clases

$ara llevar a cabo esto, teniendo como e#emplo lo que comentamos sobre una clase 2ie>*ontact=nfo, 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

Como e#traer las sub clases


sto significa que si un metodo traba#a sobre todos los items a mostrar por e#emplo, sin importar de que tipo es, ese m%todo es de la clase padre, y no podremos sacarlo en una clase nueva. n cambio si tenemos un m%todo que solo tiene cdigo para ver como se muestra un phone, en ese caso podremos sacarlo en una nueva sub*lase llamada por e#emplo $hone*ontact=nfo=tem. :a clase 2ie>*ontact=nfo, deber implementar internamente las nuevas subclases que creemos.

Code smell: Alternative classes with different interfaces

Donde lo podemos encontrar en el iA !

/dvaced Searches &as< and vent editors +esult=tems del search page mailSender.php y (ailSender.php =nputs del @0( e =nputs nuestros ,.get2alue and .value@iferentes tipos de tests ,de ui, unit&ags (anager
Code smell: Alternative classes with different interfaces

Advanced searches

n los advance search en varios caso se podr"a usar ' xtract Sub *lass), ya que tenemos casos por e#emplo de clases que tienen m%todos1 update:ocation3, update:ocation2, update:ocation?

Code smell: Alternative classes with different interfaces

Result $tems de !earch %a&e

/c tenemos varias veces ifs grandes controlando de que tipo es el "tem. Bosotros podr"amos xtraer una *lase nueva que se encargue de instanciar el tipo de "tem

Code smell: Alternative classes with different interfaces

$nputs del D'M e inputs nuestros


&odav"a quedan algunos inputs del @0( en la app, esto significa que nuestra app debe conocer las 2 interfaces .value y .get2alue. /c la solucin es eliminar por completo el uso de inputs del @0( y en todos los casos usar de los nuestros para tener una sola interfaz de comunicacin posible.

Code smell: Alternative classes with different interfaces

!endEmail and Mail!ender

mailSender y (ailSender son para lo mismo, pero tienen interfaces diferentes, ac hay que eliminar (ailSender que es el mas incompleto y usar siempre el otro.

Code smell: Alternative classes with different interfaces

!istema de

ests

Sistema de &ests, tenemos diferentes tipos de tests y sus interfaces no son iguales ,&est de U=, Unit &est de U=, Unit &est de $;$-. (i conocimiento es demasiado bsico en esta parte, y adems el problema es muy grande, por lo que no podr"a nombrar as" nomas una solucin, solo nombro el problema y la solucin la podemos charlar entre todos.

Code smell: Alternative classes with different interfaces

a& Mana&er

l &ag(anager funciona tal cual lo har"a un @atasource, por ende lo que hay que hacer es usar un @atasource en su lugar.

Code smell: Alternative classes with different interfaces