Pecesama.Net [weblog]

Programación web y TI

Continuando con la serie de patrones de diseño en PHP5, veamos ahora uno de los patrones que más me llaman la atención: el strategy pattern (patrón estrategia).

Este patrón se usa generalmente cuando se desea cambiar entre diferentes versiones de un algoritmo. Es decir, si tenemos un código que genera un archivo comprimido, bajo ciertas circunstancias, podemos querer un archivo .ZIP y bajo circunstancias diferentes, queremos crear un archivo .TAR.GZ.

Para implementar este patrón debemos declarar una interface (o bien una clase abstracta) base con un método para el algoritmo, el cual es implementado heredando desde las clases concretas.

En el código de nuestro sistema, debemos decidir cual estrategia concreta es la relevante, la cual debe ser instanciada para ser usada.

El ejemplo que usaré para mostrar este patrón, es la selección del idioma del contenido al abrir una página Web. Por simplicidad, asumiré que si la palabra “es” existe en $_SERVER["HTTP_ACCEPT_LANGUAGE"], estamos frente a un usuario que habla español, de otra forma, estamos frente a un usuario que prefiere el inglés.

PHP:
  1. < ?php
  2. interface langStrategy {
  3.         public function helloWorld();
  4. }
  5.  
  6. class enLang implements langStrategy {
  7.     public function helloWorld() {
  8.         return "Hello World";
  9.     }
  10. }
  11.  
  12. class esLang implements langStrategy {
  13.     public function helloWorld() {
  14.         return "Hola Mundo";
  15.     }
  16. }
  17.  
  18. $ln = explode(';',$_SERVER[HTTP_ACCEPT_LANGUAGE]);
  19. if (preg_match('/es/',$ln[0])) {
  20.     $langObj = new esLang();
  21. } else {
  22.     $langObj = new enLang();
  23. }
  24.  
  25. echo $langObj->helloWorld();
  26. ?>

El patrón estrategia es usado a menudo al mismo tiempo que el patrón factory, el cual se encargaría de elegir la estrategia correcta. La siguiente entrega vendrá con este patrón.




El Domain Model Pattern (algo así como ”Patrón del Modelo de Dominio”), consiste en una clase que representa objetos o responsabilidades particulares en nuestro software.

Por ejemplo, para trabajar con usuarios, cada usuario sería una instancia de una clase “Usuario”.

Normalmente al usar el Domain Model se representan los datos en una o más tablas de una base de datos. Por ejemplo, para la tabla de usuarios de un sistema.

SQL:
  1. CREATE TABLE `usuarios` (
  2.   `id_usuario` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3.   `nombre` varchar(100) DEFAULT NULL,
  4.   `login` varchar(100) NOT NULL DEFAULT '',
  5.   `password` varchar(64) NOT NULL DEFAULT '',
  6.   `email` varchar(100) DEFAULT NULL,
  7.   PRIMARY KEY  (`id_usuario`)
  8. ) ENGINE = MYISAM ;

Entonces escribimos una clase que represente a cada usuario y sus atributos; es decir el Domain Model:

PHP:
  1. < ?php
  2. class Usuario {
  3.     public $id_usuario;
  4.     public $nombre;
  5.     public $login;
  6.     public $password;
  7.     public $email;
  8.  
  9.     // metodos para obtener de la BD
  10.     // los datos y asignarlos a las propiedades.
  11. }
  12. ?>

Para usarla debemos instanciarla:

PHP:
  1. < ?php
  2. $fulano = new Usuario();
  3. echo $fulano->nombre;
  4. ?>

De esta forma dispondremos de las propiedades de los usuarios en nuestros objetos.

Este patrón es el que usamos principalmente en la actual arquitectura de gelato. Pero es importante tener especial cuidado en no caer en el anti-patrón Anemic Domain Model que como todos los anti-patrones hace que se pierdan los beneficios del uso de patrones en nuestro diseño.




Continuamos con la serie de patrones, en esta ocasión vamos a extender la funcionalidad del patrón Singleton para que sea más simple su utilización en nuestros sistemas PHP5.

En el post anterior vimos como implementar el patrón Singleton en nuestras clases. Pero cuando tenemos nuestro sistema con muchas clases que requieren hacer uso de este patrón se vuelve complejo y a la vez más lento el implementar clase por clase todo el código que necesita el patrón para funcionar.

Vamos a mejorar eso utilizando una de las características más importantes de la POO: la herencia.

Paso número 1: Debemos definir la clase base (clase padre); es decir la clase Singleton:

singleton.class.php

PHP:
  1. < ?php
  2. class singleton {
  3.         private static $instances = array();
  4.  
  5.         public static function getInstance($class) {
  6.                 if (!isset(self::$instances[$class])) {
  7.                         self::$instances[$class] = new $class();
  8.                 }
  9.                 return self::$instances[$class];
  10.         }
  11.  
  12.         private final function __clone() { }
  13. }
  14. ?>

Paso número 2: Crear las clases que vayamos a necesitar extendiendo (heredando) de la clase Singleton.

ejemplo.class.php

PHP:
  1. < ?php
  2. class ejemplo extends singleton {
  3.         public static function getInstance() {
  4.                 return parent::getInstance(get_class());
  5.         }
  6.  
  7.         public function accion() {
  8.                 echo "Objeto unico";
  9.         }
  10. }
  11. ?>

Paso número 3: Ahora veamos como utilizarlo.

index.php

PHP:
  1. < ?php
  2. include("singleton.class.php");
  3. include("ejemplo.class.php");
  4.  
  5. $prueba = ejemplo::getInstance();
  6. $prueba->accion();
  7. ?>

De esta forma basta con heredar la clase Singleton en cada una de las clases donde la necesitemos y con hacer polimorfismo del método getInstance() tenemos un Singleton en nuestras clases.

Nos leemos en la siguiente entrega :)




Como Jorge mencionó en su último post, andamos re-diseñando la arquitectura de gelato cms, para en un par de versiones mudarlo completamente a PHP5 para obtener ventaja de su poderoso motor de OOP y poder hacer un mejor uso de los patrones de diseño.

Por lo que comenzaré con una serie de posts sobre como implementar patrones de diseño con PHP5 y un par de ejemplos un poco más adelante de como aplicarlos en “la vida real” de nuestros proyectos.

El primer patrón con el que iniciaré es el patrón Singleton, el cual considero como la base de la implementación exitosa de muchos patrones.

La teoría nos dice lo siguiente:

El patrón de diseño Singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.

Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.

Por lo que al usar el patrón Singleton nos aseguramos que SOLO tendremos una misma instancia de nuestra clase.

¿Cómo hacerlo con PHP5?

PHP:
  1. < ?php
  2. class Singleton {
  3.  
  4.     // Una propiedad para tener la instancia de la clase
  5.     private static $instancia;   
  6.  
  7.     // Desde aqui se obtiene la instancia OJO con el static
  8.     public static function getInstance () {
  9.         if (!isset(self::$instancia)) {
  10.             $obj = __CLASS__;
  11.             self::$instancia = new $obj;
  12.         }
  13.         return self::$instancia;
  14.     }
  15.  
  16.     // Se crean los metodos requeridos
  17.     public function accion() {
  18.         echo "Objeto unico";
  19.     }   
  20.  
  21.     // Privado se previene la creacion via new
  22.     private function __construct() { }   
  23.  
  24.     // Para evitar la clonacion de este objeto
  25.     private function __clone() {
  26.         throw new Exception('No se permite clonar');
  27.     }
  28. }
  29. ?>

Y para utilizarlo:

PHP:
  1. < ?php
  2. include("singleton.php");
  3. $prueba = Singleton::getInstance();
  4. $prueba->accion();
  5. ?>

Nos leemos en la siguiente entrega :P




Actualización: He modificado el post para agregar documentación más detallada sobre el uso de la clase.

En gelato estamos usando una clase para pocesar los themes de los tumblelogs, una clase heredada de esta versión alpha de Códice CMS (versión que solo quedó en el SVN) y mejorada para procesar bloques en gelato.

Creé este motor porque requeria algo ligero, que tuviera sólo lo que se necesita y nada más, por eso no utilicé ninguno de los tantos ya existentes y muy buenos.

La dejo aquí por si a alguien le interesa para algo:

La clase: themes.class.php

Modo de utilización

Para utilizar la clase debemos seguir los siguientes pasos:

La estructura de directorios para utilizar el template engine es la siguiente:

  • ./themes <– Se deben agregar los themes SIEMPRE dentro de la carpeta themes.
  • ./themes/nombreTheme/ <– Por cada theme se debe crear una nueva carpeta.
  • ./themes/nombreTheme/plantilla.htm <– dentro de la carpeta del theme se pueden agregar tantas plantillas como queramos.

Paso número 1: Crear la plantilla a utilizar, para esto debemos indicar entre llaves { } el nombre de la variable que va a sustituir el template engine. Debemos ponerle extensión .htm

post.htm (ruta: ./themes/gelato/post.htm)

HTML:
  1. <div class="post">
  2. <div class="regular">
  3.         <a href="{Permalink}">{Title}</a>
  4.     </h2>
  5.  
  6.     {Body}
  7.   </div>
  8. </div>

Paso número 2: Crear archivo PHP que creará una instancia del template engine para procesar la plantilla.

index.php (ruta: ./index.php)

PHP:
  1. require_once("themes.class.php");
  2. // instancia con nombre del theme.
  3. $template = new plantillas("gelato");
  4. // variables a sustituir.
  5. $input = array("{Permalink}", "{Title}", "{Body}");
  6. // Valores reales.
  7. $output = array("http://www.gelatocms.com/", "Titulo", "Cuerpo");
  8. // cargamos la plantilla post y asignamos los valores.
  9. $template->cargarPlantilla($input, $output, "post");
  10. // mostramos la plantilla.
  11. $template->mostrarPlantilla();

Cualquier duda, favor de usar los comentarios del post.




iPod Touch Buscaminas

Tengo desde el viernes con mi iTouch en esta posición, ¿alguna idea?

Buscaminas




Como me ha causado gracia el post de Ignacio sobre el algoritmo del PR, ahora me quedan la cosas claras ;)

Para muestra un fragmento (ir al post para verlo completo):

PHP:
  1. //Sergey said good news sites have
  2. // lots of nested tables
  3. tablesOnPage = getTagCount('table');
  4. if (tablesOnPage >= 50) {
  5. pagerank += 2;
  6. }

Via lo de Diego.




Feliz Navidad 2007!!

Feliz Navidad

Foto: Feliz Natal por Breno Peck con licencia (cc).

Gelato Navideño donado por Rochas Design.




¿Qué es un Weblog?

En el blog de Marcos me he encontrado este video bastante claro que explica con lenguaje simple (como su nombre indica) lo que es un blog.




Here Comes Another Bubble

Genial vídeo




« Previous Entries