Rompiendo dependencias contenidas en ensamblados .NET mediante la refactorización de su código Intermedio.
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 2,086 views

 

Statistics

Views

Total Views
2,086
Views on SlideShare
2,013
Embed Views
73

Actions

Likes
0
Downloads
7
Comments
0

1 Embed 73

http://jaircazarin.blogspot.com 73

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Muy buenas tarde a todos, mi nombre es Jair Cazarin, y estoy aquí para presentarles la tesis que desarrollé a lo largo de estos meses, como requisito parcial para obtener el título en la Licenciatura en Ingeniería en Sistemas Computacionales. El título de mi tesis es “Herramienta para romper dependencias en ensamblados .NET mediante la refactorización de su código intermedio.”

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

  • 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
  • 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.
  • Programación Orientada a Objetos
    • “ 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.”
  •  
  • Características Principales
  •  
  •  
  • Flexible
  • Fácil de mantener.
  •  
  • Dependencias.
  • Tipos de dependencias.
  • 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. ”
    • Desafortunadamente, la refactorización es un proceso que se aplica cuando se tiene acceso al código fuente.
    • Ignorando las veces cuando :
  • Objetivo General.
    • Investigar la refactorización de ensamblados binarios con el objetivo de mejorar la reusabilidad y capacidad de resolución de frameworks
  • 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.
    • Afterex = Ex tensibility aft er-the-fact.
  • 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.
  • Análisis del problema.
    • Metodología ágil.
    • Definición de enfoques y tecnologías a usar.
  • 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…);
  • Dependencia Directa.
    • C someMethod(…);
    • SomeType someOtherMethod(…,C parameter,…);
    • C.someStaticMember(…);
    • class Cls:C (<-if C wasn’t sealed)
    • class Cls:SomeGeneric<C>
  • .NET Framework.
  • CLR
  • Ejecución de código administrado.
  • CIL.
    • . method static void main ()
    • {
    • . entrypoint
    • . maxstack 1
    • ldstr &quot;Hello world!&quot;
    • call void [ mscorlib ] System . Console :: WriteLine ( string )
    • ret
    • }
  • Ensamblados.
  • CECIL.
  • 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.
  • Implementación
  • Capa de Framework.
  • Capa de Framework.
    • El framework fue desarrollado siguiendo las mejores prácticas dictadas por el Framework Design Guidelines.
  • Capa de implementación.
  • Dependency Injection Container.
  • Rompiendo dependencias contenidas.
    • Tipo abstracto.
    • public Interface ISort
    • {
    • void Sort ( int [] list ();
    • }
  • Rompiendo dependencias contenidas.
    • Implementación concreta.
    • public class BubbleSort : ISort
    • {
    • public void Sort ( int [] list ) { …Implementation goes here… }
    • }
  • Rompiendo dependencias contenidas.
    • Tipo dependendiente.
    • public class DependentType
    • {
    • void m1 () {
    • ISort sorter = new BubbleSort ();
    • sorter . Sort ( numbers ) … .
    • }
    • }
    • Propiedad
    • private static Func < ISort > sortBaseTypeFactory = null ;
  • Implementaci ón del Factory
    • public static Func < ISort > SortBaseTypeFactory
    • {
    • get
    • {
    • if ( null == SortBaseTypeFactory )
    • {
    • SettingsReader settingsReader = new SettingsReader ();
    • string assemblyName = settingsReader . GetValue ( &quot;Assembly&quot; );
    • string typeName = settingsReader . GetValue ( &quot;Type&quot; );
    • string methodName = settingsReader . GetValue ( &quot;Method&quot; );
    • 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 ;
    • }
    • }
    •  
    • Factory Method:
    • public static ISort GetBubbleSortInstance ()
    • {
    • return new BubbleSort ();
    • }
  • XML de configuración.
    • <Settings> <Assembly> SortFactory.dll </Assembly>
    • <Type> SortFactory.Factory </Type>
    • <Method> SomeMethod </Method>
    • </Settings>
    • Ahora instanciamos así:
    • ISort sorter = Factory . SortBaseTypeFactory() ;
    • En lugar de:
    • ISort sorter = new BubbleSort ();
  • Nuevo componente.
    • public class QuickSort : ISort
    • {
    • public void Sort ( int [] list )
    • {
    • … Implementation goes here…
    • }
    • }
  • Factory Method
    • public static ISort GetQuickSortInstance ()
    • {
    • return new QuickSort ();
    • }
  • XML de configuración.
    • <Settings> <Assembly> newComponent.dll </Assembly>
    • <Type> QuickSortComponent </Type>
    • <Method> GetQuickSortInstance </Method>
    • </Settings>
  • Refactorizando instanciaciones.
    • RefactorInstantiations(baseType, concreteType, targetAssembly)
    • 1 Foreach Type t in targetAssembly.Types
    • 2 Foreach Method m in t.Methods
    • 3 If method doesn’t has a body
    • 4 Continue
    • 5 If method doesn’t contain a variable of type
    • 6 baseType
    • 7 Continue
    • 8 Foreach Instruction i in m.Body
    • 9 If perform a new instantiation of
    • 10 concreteType
    • 11 Replace the instruction to call
    • 12 the property instead of new.
    • public class DependentType {
    • void m1 ()
    • {
    • BubbleSort sorter = new BubbleSort ();
    • sorter . Sort ( numbers ) … .
    • }
    • }
  • Refactorizando instanciaciones concretas.
    • RefactorInstantiations(concreteType, targetAssembly)
    • 1 newInterface ← new Interface
    • 2 Declare the operations of concreteType in newInterface
    • 3 Change concreteType to implemente newInterface
    • 4 Perform RefactorConcreteImplementations
    • 5 the property instead of new AND
    • 6 change the variable to be baseType.
    •  
  • 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.
  • Refactorizando Parámetros.
    • RefactorParameters(baseType, concreteType, targetAssembly)
    • 1 Foreach Type t in target.AssemblyTypes
    • 2 Foreach Method m in t.Methods
    • 3 If m contain parameter of type concreteType
    • 4 Change the parameter to be baseType
    • 6 mbody ← m.MethodBody
    • 5 Make the method protected and abstract.
    • 6 Make the type to be abstract.
    • 7 Create a new type tAbstract
    • 8 Create a new assemblyAbstract
    • 9 Make tAbstract inherits from t
    • 10 Implement abstract methods of t with mbody.
    • 11 Add tAbstract to assemblyAbstract
  • Renombramiento.
    • AssemblyRenameApproach(originalAssembly, newAssembly, originalType, Type newType)
    • 1 oname ← originalAssembly.Name
    • 2 originalAssembly.name ← newAssembly.Name
    • 3 newAssembly.name ← oname
    • 4 otype ← originalType.name
    • 5 originalType ← newType.Name
    • 6 newType ← otype
  • Refactorizando Par ámetros de retorno.
    • RefactorReturnParameters(baseType, concreteType, targetAssembly)
    • 1 Foreach Type t in target.AssemblyTypes
    • 2 Foreach Method m in t.Methods
    • 3 If return type of m is of type concreteType
    • 4 Find which methods calls m
    • 5 Move m to the new assembly and type.
    • 6 If the list of method that calls m > 1
    • 7 Move all methods to the new assembly
    • 8 Update calls to m.
  • Capa de aplicación.
  • 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.
  • Pruebas y Resultados.
  • Escenario 2.
  • 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.
  • Conclusiones.
  • 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.
    • ?