Tuesday, 2 de June de 2009 por climens

Principios básicos de OOP: SOLID

Últimamente reviso mucho código, tanto mío como de otros y me doy cuenta de que muchas veces se pasan por alto los principios básicos del paradigma de orientación a objetos y en muchos casos porque la formación es deficiente o inexistente.
Así pues, uno de los acrónimos en el mundillo de la programación orientada a objetos (OOP) es SOLID, que sirve de regla mnemotécnica para recordar 5 principios básicos:

SRP: Single Responsibility Principle:
El principio de responsabilidad única nos dice que nunca debe haber más de un motivo para que una clase cambie, o lo que es lo mismo, que una clase solamente debe tener un propósito. Esto parece simple pero en realidad es uno de los principios más fáciles de violar y muchas veces no es fácil distinguir las responsabilidades.

OCP: Open-Closed Principle:
El principio abierto/cerrado implica que las clases de software deben estar abiertas para la extensión pero cerradas para la modificación. Este es el principio por el cual se hacen privadas las variables del miembro o que no se usan variables globales. El truco de este principio está en la abstracción. Las clases abstractas implementan un código inalterable desde fuera pero obligan a extender de ellas para usar este código a parte de que se promueve la reusabilidad.

LSP: Liskov Substitution Principle:
El principio de sustitución de Liskov implica que las clases derivadas deberían poder ser sustituidas por sus clases base. Es decir, es en cierto modo una extensión del principio anterior: mientras que OCP promueve la herencia de clases base, LSP promueve que la herencia se haga de forma transparente, es decir, que heredar es bueno pero no hay que olvidar las raíces. Es decir, no implementemos un método en una clase heredada que no esté en la clase base porque romperemos este principio.

De OCP y LSP se deduce que las clases base (abstractas o no) modelan el aspecto general y las clases heredadas modelan el comportamiento local.

DIP: Dependency Inversion Principle:
Básicamente, el principio de inversión de dependencia promueve que hay que depender de abstracciones, no de concreciones. Dicho de forma más compleja, los módulos de más alto nivel no deben depender de los de más bajo nivel sino que ambos deben depender de abstracciones. Y a su vez, las abstracciones no deben depender de los detalles sino al contrario.

En este caso, el uso de interfaces resulta muy beneficioso y un framework de inversión de control (Castle Windsor, StructureMap, por citar algunos) van a hacer que resulte más obvia la necesidad de abstracciones. Además, el testado unitario resulta mucho más sencillo ya que la independencia entre los distintos módulos es muy elevada.

ISP: Interface Segregation Principle:
Este principio de segregación de interfaces indica que no se debe hacer depender las clases de interfaces que no necesitan y que debe haber granularidad en las interfaces para dotar de aspectos específicos a las distintas implementaciones.

En general, en Java y C# se pueden implementar tantos interfaces como se quiera por lo que es sencillo llevar a cabo este principio. Las interfaces son la forma más práctica de modelar las clases y dotarlas de aspectos particulares así como incluso tratarlas de diferente modo según las interfaces implementadas.

Y estos son básicamente los principios SOLID que aunque llevan ya muchos años siguen siendo vigentes y ayudan a desarrollar un código más reusable, mantenible y claro. Además, con las herramientas actuales de refactorización es muy fácil extraer interfaces y clases abstractas de las ya existentes sin tener que revisar cientos de líneas de código. Y cómo no, tener un buen conjunto de tests unitarios ayudará a que cualquier refactorización se haga sin miedo a romper toda la funcionalidad existente.

Referencias: Principles of OOD

Compartir | meneame | fresqui | del.icio.us | digg | technorati
Tags: , , | Sin comentarios

Friday, 24 de April de 2009 por climens

Apache y Mongrel en Windows

Después de pelear un rato intentando hacer funcionar Ruby on Rails con Apache y Fast-CGI en Windows, me iba bastante más lento que directamente con Mongrel, así que opté por usar este último y hacer un proxy vía Apache con mod_proxy.

Mongrel es bastante fácil de instalar, simplemente se hace un gem install mongrel y cuando pide la versión a seleccionar hay que seleccionar la de x86-mswin32.

Para ver si funciona, hay que ir a la carpeta donde está instalada nuestra aplicación Rails y ejecutar mongrel_rails start que iniciará el servicio en el puerto 3000 y nos dirá si hay algún error.

Una vez comprobado que Mongrel funciona, hay que instalarlo como servicio de Windows, por simple comodidad. Para ello hay que ejecutar gem install win32-service, que además nos instalará una serie de paquetes relacionados con Windows. Seleccionar siempre la versión x86-mswin32 si está disponible.

Ya está todo listo para instalar el servicio. Con el siguiente comando:


mongrel_rails service::install -N AplicacionRails -c RutaDeLaAplicacion -p 3001 -e production --prefix=/subdir

El nombre de la aplicación, en el parámetro -N es la que saldrá en el listado de servicios de Windows. Lo que va en el parámetro -c es la ruta de la aplicación Rails (no la carpeta public, sino la raíz). Luego se indica el puerto en -p (recomiendo que no sea 3000 para no entrar en conflicto si ejecutamos Mongrel independientemente). En el parámetro -e se indica el entorno, en principio "production" y finalmente y lo más importante, en --prefix se indica la subcarpeta donde se va alojar, es decir, si va a ser localhost/subdir, el valor deberá ser /subdir. Esto es sumamente importante para que funcione bien el proxy de Apache. Si va a estar en la raíz, no hace falta poner nada.

En cuanto a la configuración de Apache, tengo algo más o menos así en httpd.conf:


ProxyRequests off
ProxyPass /subdir http://localhost:3001/subdir
ProxyPreserveHost on

<Location /subdir>
ProxyPassReverse /
</Location>

Eso sí, hay que tener mod_proxy activado y mod_rewrite también (seguro que lo usa el .htaccess de la aplicación Rails).

Y esto es todo, así conseguí configurar el Redmine en Windows con Apache. Lo que más costó fue descubrir el parámetro --prefix de Mongrel para que alojase la aplicación en un subdirectorio, no soy ningún experto en Rails.

Espero que os sirva de ayuda.

Links:

Compartir | meneame | fresqui | del.icio.us | digg | technorati
Tags: , , | Sin comentarios

Wednesday, 8 de April de 2009 por climens

Invocar constructores genéricos por reflexión

Explicaré brevemente cómo se puede invocar un constructor genérico por reflexión (del namespace System.Reflection) dado que a veces solamente tenemos el Type del genérico y no se puede pasar entre dado que no es el nombre de una clase.
Para mi caso, es una acción de un método web que me pasa un string con el nombre de la entidad a procesar por lo que el proceso, que es un método genérico, no se podía llamar de este modo:

public void ProcessStuff(Type type, object data)
{
    var processor = new Processor(); // Esto da error

    var results = processor.process(data);
}

Entonces, esto es un problema ya que el método ProcessStuff en este caso no puede ser genérico, lo que solventaría así el problema:

public void ProcessStuff(object data)
{
    var processor = new Processor();

    var results = processor.process(data);
}

Así que el namespace System.Reflection viene en nuestra ayuda y el secreto está en el método MakeGenericType. El método final es algo así:

public void ProcessStuff(Type type, object data)
{
    var constructor = typeof(Processor).MakeGenericType(new[] { type }).GetConstructor(new Type[] {}); // Obtiene el constructor sin parámetros
    var processor = constructor.Invoke(new object[] { });

    var processMethod = processor.GetType().GetMethod("Process", new[] {typeof(object)}); // Obtiene el método del objeto creado
    var results = processMethod.Invoke(processor, new[] {data}); // Llama al método
}

Y eso es todo. Es un poco más engorroso, por supuesto, pero nos puede sacar de más de un lio y ahorrarnos un montón de switches.

Compartir | meneame | fresqui | del.icio.us | digg | technorati
Tags: , , | Sin comentarios