domingo, 20 de mayo de 2007

Inversion of Control - Dependency Injection

Para empezar, clarifiquemos algo: Inversion of Control no es lo mismo que Dependency Injection. Inversion of control estamos haciendo en montañas de lugares, en Visual Basic cuando las aplicaciones dejaron de controlar la UI y permitieron a un tercero hacerlo por ellas y decirle que me "avise" (en ese ejemplo mediante eventos) cuando tengo que hacer algo estabamos "invirtiendo el control" y delegando el manejo de la UI.

Dependency Injection

Veamos un ejemplo para entender de que estamos hablando.

Estamos escribiendo un componente que nos devuelve la lista de películas dirigidas por un director en particular.

La implementación del método es extremadamente ingenua pero nos sirve para nuestro fin.


class MovieLister...

private MovieFinder finder;

public MovieLister() {
finder = new ColonDelimitedMovieFinder("movies1.txt");
}

public Movie[] moviesDirectedBy(String arg) {
List allMovies = finder.findAll();
for (Iterator it = allMovies.iterator(); it.hasNext();) {
Movie movie = (Movie) it.next();
if (!movie.getDirector().equals(arg)) it.remove();
}
return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
}
Lo importante de este método es el finder ya que nuestro algoritmo es independiente de como se persisten las películas.

En este caso, en el constructor de MovieLister estamos instanciado una implementación de MovieFinder que podría levantar un archivo delimitado.

La interface MovieFinder es bien simple:


public interface MovieFinder {
List findAll();
}
Lo que tenemos hasta acá lo podemos ver representado en el siguiente diagrama, MovieLister conoce tanto a la interface MovieFinder como a la implementación MovieFinderImpl.




La IoC en este caso está dada por "tercerizar" la obtención de la implementación real de la interface. De esta manera el componente MovieLister se independiza de las posibles implementaciones del MovieFinder. Esto lo vemos en el siguiente diagrama

La Dependency Injection puede hacerse de tres maneras:

  1. Constructor Injection: En este caso la clase MovieLister tiene un constructor que recibe un MovieFinder.
  2. Setter Injection: Aquí la clase MovieLister posee un método setFinder(MovieFinder finder). Este es el caso de Spring.
    Aquí viene la mejor parte, como hacemos para que todo esto funcione al unisono:

    En el archivo de configuración de spring definimos lo siguiente (también estamos haciendo que ColonMovieFinder reciba mediante spring el nombre del archivo de donde tomar los datos):

    <beans>
    <bean class="spring.MovieLister" id="MovieLister">
    <property name="finder">
    <ref local="MovieFinder">
    </property>
    </bean>
    <bean class="spring.ColonMovieFinder" id="MovieFinder">
    <property name="filename">
    <value>movies1.txt</value>
    </property>
    </bean>
    </beans>
  3. y un ejemplo de uso sería:
    public void testWithSpring() throws Exception {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");
    MovieLister lister = (MovieLister) ctx.getBean("MovieLister");
    Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
    assertEquals("Once Upon a Time in the West", movies[0].getTitle());
    }
  4. Interface Injection: este caso lo veremos en otro momento ya que no es muy utilizado.

En resumen, lo principal es que se agrega un nuevo administrador, en el cual se definen para cada interface, una implementación y en tiempo de ejecución se le solicitan a él los beans.

Verano, Otoño, Invierno y .... Spring

El principal motivo por el cual empecé a buscar información sobre Spring es porque todo el mundo lo nombra, dice que lo usa, intenta explicarme lo maravilloso que es y lo superlativos que son los servicios que brinda, y yo no logro entender absolutamente nada... así que vayamos por partes.

La búsqueda empieza obviamente preguntandole al oráculo (AKA Google), lo que nos lleva a http://www.springframework.org.

Publicitada como una de las grandes características de Spring, "Inversion of Control" y "Dependency Injection" me dejan más perdido que antes... Ya no sólo no conozco una tecnología (en este caso framework) sino que tampoco entiendo sus bondades...; esta vez estaba decidido en entender de que me estaban hablando así que busqué una explicación sobre Dependency Injection. Encontré una página muy interesante y clarificadora sobre el tema de Martin Fowler http://www.martinfowler.com/articles/injection.html. En la próxima entrada explicaré mi versión del tema...

sábado, 19 de mayo de 2007

Patrones de diseño

Empezamos el camino explorando los patrones de diseño básicos.

Un buen sitio que tiene ejemplos (aunque en c#) es http://www.dofactory.com/Patterns/Patterns.aspx

También empecé a leer el libro Head First Desing Patterns. El enfoque es bastante informal, pero permite comprender claramente cada uno de los conceptos.

Otro sitio en que encontré bastante información sobre patrones empresariales (J2EE Patterns) es
http://www.corej2eepatterns.com/Patterns2ndEd/index.htm