domingo, 31 de agosto de 2014

Es necesaria la inyección de dependencias en lenguajes de tipado dinámico?


Porque utilizamos la inyección de dependencias en lenguajes como java o C# pero no lo utilizamos en lenguajes como Ruby, Python o PHP?

He leído en varios lugares que la inyección de dependencia puede ser útil para los lenguajes dinámicos y en otros sitios que es una tontería:

DI frameworks are unnecessary. In more rigid environments, they have value. In agile environments like Ruby, not so much. The patterns themselves may still be applicable, but beware of falling into the trap of thinking you need a special tool for everything. Ruby is Play-Doh, remember! Let’s keep it that way.
– Jamis Buck

Veamos un ejemplo de no utilizar un framework de inyección de dependencia en Ruby, supongamos que tengo un DAO que necesita de la conexión a la base de datos, en java sería así:

class Repository {
    private Connection connection;
    public Repository(Connection connection) {
        this.connection = connection;
    }
    public Something find(Integer id) {
        return this.connection.execute("SELECT ...");
    }
}

En java si necesitamos el objeto connection en varios lugares lo vamos inyectando y a la vez si queremos testear el dao vamos a utilizar un mock, es decir que para los tests vamos a inyestar un objeto que simule la base de datos. Pero en Ruby existe otro modo de organizar este código y es por medio de módulos.

module ConnectionProvider
  def connection
    # open a database connection and return it
  end
end

Gracias a estos modulos podemos utilizar en varios lugares ConnectionProvider, reutilizando código. Y a la vez Ruby nos brinda la posibilidad de reabrir una clase por lo que podemos reabrirla y utilizar la base de datos real o una base de datos en memoria o mock para los test.

# connection_provider.rb

module ConnectionProvider
  def connection
    # open a database connection and return it
  end
end

# reopening the class to mix the module in
class Repository
  include ConnectionProvider
end

Esto provee una capacidad similar a la inyección de dependencia sin utilizar un framework.