Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código...

60
Herramienta para romper dependencias en ensamblados .NET mediante la refactorización de su código intermedio. Presentado por: Jair Cazarin Villanueva Bajo la supervisión de: Dr. Mauricio Osorio. Dr. Mircea Trofin. Universidad de las Américas, Puebla

Transcript of Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código...

Page 1: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Herramienta para romper dependencias en ensamblados .NET

mediante la refactorización de su código intermedio.

Presentado por:Jair Cazarin Villanueva

Bajo la supervisión de:Dr. Mauricio Osorio.

Dr. Mircea Trofin.

Universidad de las Américas, Puebla

Page 2: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Agenda.

• Contexto del Problema.– Programación Orientada a Objetos.– Dependencias.

• Objetivos.• Alcances y Limitaciones.• Análisis del Problema.• Diseño e Implementación.• Resultado y Pruebas.• Conclusiones.

Page 3: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Programación Orientada a Objetos

Page 4: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

“El paradigma de la programación orientada a objetos, también conocida como POO, es la que usa objetos y sus interacciones para diseñar aplicaciones.”

Page 5: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.
Page 6: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Características Principales

Page 7: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.
Page 8: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.
Page 9: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Flexible

Page 10: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Fácil de mantener.

Page 11: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.
Page 12: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependencias.

Page 13: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Tipos de dependencias.

Page 14: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Solución: Refactorizar.

“Refactorizar es el proceso de cambiar un software de tal forma que el comportamiento externo no cambia, más bien, se mejora su estructura interna.”

Page 15: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

• Desafortunadamente, la refactorización es un proceso que se aplica cuando se tiene acceso al código fuente.

• Ignorando las veces cuando:

Page 16: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Objetivo General.

• Investigar la refactorización de ensamblados binarios con el objetivo de mejorar la reusabilidad y capacidad de resolución de frameworks

Page 17: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Objetivo General.

• Para lograr lo anterior, se desarrolló una herramienta que refactoriza ensamblados existentes, con el objetivo de romper las dependencias contenidas entre distintas clases, y de esta forma hacer posible satisfacer estas dependencias con otros tipos, mediante la mejora de la modularización y extensibilidad de los componentes.

Page 18: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Afterex = Extensibility after-the-fact.

Page 19: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Alcances y Limitaciones.

• .NET Framework y ensamblados .NET.• Dependencias contenidas y directas.• Solución completa para el escenario de

dependencias contenidas.• En el caso de las dependencias directas solo se

abordó el tema y se hicieron los primeros experimentos con los casos de parámetros.

• Aplicación basada en consola.

Page 20: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Análisis del problema.

• Metodología ágil.• Definición de enfoques y tecnologías a usar.

Page 21: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependencia Contenida.

• Si tenemos un DLL D con una clase d, y un DLL C con una clase c, una dependencia contenida de D a C, sería si encontráramos instrucciones como al siguiente en clases de d:

• c someVariable = new c(…Parameters…);• ic someVariable = new c(…Parameters…);

Page 22: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependencia Directa.

• C someMethod(…);• SomeType someOtherMethod(…,C parameter,

…);• C.someStaticMember(…);• class Cls:C (<-if C wasn’t sealed)• class Cls:SomeGeneric<C>

Page 23: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

.NET Framework.

Page 24: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

CLR

Page 25: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Ejecución de código administrado.

Page 26: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

CIL.

.method static void main(){ .entrypoint .maxstack 1 ldstr "Hello world!" call void [mscorlib]System.Console::WriteLine(string) ret}

Page 27: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Ensamblados.

Page 28: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

CECIL.

Page 29: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependency Injection.

• Dependency Injection es un patrón de diseño de objetos en los cuales estos son colocados por entidades externas.

• No se usa el operador new para construir objetos.

• Una forma de implementarlo es usando factories.• Esto nos da la flexibilidad de crear

implementaciones alternas especificándola usando un archivo de configuración.

Page 30: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Implementación

Page 31: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Capa de Framework.

Page 32: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Capa de Framework.

• El framework fue desarrollado siguiendo las mejores prácticas dictadas por el Framework Design Guidelines.

Page 33: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Capa de implementación.

Page 34: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependency Injection Container.

Page 35: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Rompiendo dependencias contenidas.

Tipo abstracto.

public Interface ISort{ void Sort(int[] list();}

Page 36: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Rompiendo dependencias contenidas.

Implementación concreta.

public class BubbleSort : ISort{ public void Sort(int[] list) { …

Implementation goes here…}}

Page 37: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Rompiendo dependencias contenidas.

Tipo dependendiente.

public class DependentType { void m1() { ISort sorter = new BubbleSort(); … sorter.Sort(numbers) …. }}

Page 38: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

• Propiedad

private static Func<ISort> sortBaseTypeFactory = null;

Page 39: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Implementación del Factorypublic static Func<ISort> SortBaseTypeFactory{ get { if (null == SortBaseTypeFactory) { SettingsReader settingsReader = new SettingsReader(); string assemblyName = settingsReader.GetValue("Assembly"); string typeName = settingsReader.GetValue("Type"); string methodName = settingsReader.GetValue("Method"); string assemblyFullName =Path.Combine(Directory.GetCurrentDirectory(), assemblyName); MethodInfo method =

Assembly.LoadFile(assemblyFullName).GetType(typeName).GetMethod(methodName); sortBaseTypeFactory = () => (String)(method.Invoke(null, null)); } return baseTypeFactory; } set { sortBaseTypeFactory = value; }}

Page 40: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Factory Method:

public static ISort GetBubbleSortInstance()

{ return new BubbleSort();}

Page 41: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

XML de configuración.

<Settings> <Assembly>SortFactory.dll</Assembly>

<Type>SortFactory.Factory</Type><Method>SomeMethod</Method></Settings>

Page 42: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Ahora instanciamos así:

ISort sorter = Factory.SortBaseTypeFactory();

En lugar de:

ISort sorter = new BubbleSort();

Page 43: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Nuevo componente.

public class QuickSort : ISort{ public void Sort(int[] list) { …Implementation goes here… }}

Page 44: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Factory Method

public static ISort GetQuickSortInstance(){ return new QuickSort();}

Page 45: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

XML de configuración.

<Settings> <Assembly>newComponent.dll</Assembly>

<Type>QuickSortComponent</Type><Method>GetQuickSortInstance</Method></Settings>

Page 46: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Refactorizando instanciaciones.RefactorInstantiations(baseType, concreteType, targetAssembly)1 Foreach Type t in targetAssembly.Types2 Foreach Method m in t.Methods3 If method doesn’t has a body4 Continue5 If method doesn’t contain a variable of type6 baseType7 Continue8 Foreach Instruction i in m.Body9 If perform a new instantiation of10 concreteType11 Replace the instruction to call12 the property instead of new.

Page 47: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

public class DependentType { void m1() { BubbleSort sorter = new

BubbleSort(); … sorter.Sort(numbers) …. }}

Page 48: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Refactorizando instanciaciones concretas.

RefactorInstantiations(concreteType, targetAssembly)1 newInterface ← new Interface2 Declare the operations of concreteType in

newInterface3 Change concreteType to implemente newInterface4 Perform RefactorConcreteImplementations5 the property instead of new

AND6 change the variable to be

baseType.

Page 49: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Dependencias Directas.

• Se logró crear una capa más abstracta para el API que define.

• Sin embargo, aún no sabemos cómo romper la dependencia completamente.

• Tampoco sabemos cómo desarrolladores terceros puedan utilizar esta capa más abstracta o tomar ventaja de ella.

Page 50: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Refactorizando Parámetros.RefactorParameters(baseType, concreteType, targetAssembly)1 Foreach Type t in target.AssemblyTypes2 Foreach Method m in t.Methods3 If m contain parameter of type concreteType4 Change the parameter to be baseType6 mbody ← m.MethodBody5 Make the method protected and abstract.6 Make the type to be abstract.7 Create a new type tAbstract8 Create a new assemblyAbstract9 Make tAbstract inherits from t10 Implement abstract methods of t with

mbody.11 Add tAbstract to assemblyAbstract

Page 51: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Renombramiento.

AssemblyRenameApproach(originalAssembly, newAssembly, originalType, Type newType)

1 oname ← originalAssembly.Name2 originalAssembly.name ← newAssembly.Name3 newAssembly.name ← oname4 otype ← originalType.name5 originalType ← newType.Name6 newType ← otype

Page 52: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Refactorizando Parámetros de retorno.

RefactorReturnParameters(baseType, concreteType, targetAssembly)

1 Foreach Type t in target.AssemblyTypes2 Foreach Method m in t.Methods3 If return type of m is of type concreteType4 Find which methods calls m5 Move m to the new assembly and

type.6 If the list of method that calls m > 17 Move all methods to the new

assembly8 Update calls to m.

Page 53: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Capa de aplicación.

Page 54: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Capa de aplicación.

• Extensible. Se pueden cargar nuevas reglas de refactorización.

• Fácil de cambiar a otra implementación. Ejemplo: Una interfaz gráfica.

• Genera un archivo XML con un resumen de las reglas aplicadas.

Page 55: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Pruebas y Resultados.

Page 56: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Escenario 2.

Page 57: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Resumiendo

• La aplicación ya no es responsable de encontrar sus dependencias.

• El contenedor se encarga de encontrar esas dependencias.

• Añadimos flexibilidad a la aplicación para futuros cambios.

• Promovimos la disminución del acoplamiento entre componentes, por lo cual facilitamos las pruebas de unidad.

Page 58: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Conclusiones.

Page 59: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

Trabajo a Futuro.

• Terminar un escenario completo de las dependencias directas.

• Estudiar las dependencias indirectas y ocultas.• Crear un contenedor de dependencias para

aplicaciones existentes más robusto.• Mejorar la complejidad de los algoritmos.• Extender el API y fusionarlo con CECIL.

Page 60: Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.

?