domingo, 6 de mayo de 2012

Tests unitarios en PHP

Los tests en un proyecto sirven para poder "asegurarnos" de si la aplicación está funcionando correctamente pese a haber echo una modificación/refactorización. Esto nos permite evitar regresiones en el código o si las tenemos detectarlas fácilmente y encontrar rápidamente una solución.

En este articulo hablaremos sobre que son los tests unitarios y veremos un ejemplo sencillo de como funcionan.

Tests unitarios

Los tests unitarios, como su propio nombre indica, se basan en comprobar si una unidad de código funciona de la forma que nosotros esperamos. Normalmente la unidad de código se considera la clase, por lo que los tests unitarios se dedican a probar a fondo una sola clase de forma que sepamos que esa clase funciona como esperamos.

Un ejemplo de test unitario podría ser:
<?php
 class Calculadora{
  public function suma( $a, $b )
  {
   return $a + $b;
  }
 }

 $calculadora = new Calculadora();
 if( $calculadora->suma(1,2) === 3 )
 {
  echo 'Test1. Resultado correcto.';
 }
 else
 {
  echo 'Test1. Resultado incorrecto.';
 }
?>

Como puede verse en el ejemplo, únicamente prueba la clase Calculadora y prueba que dadas unas entradas se produce la salida esperada. Es muy importante que el test no tenga ningún tipo de lógica y los resultados esperados no sean calculados, ya que un test que realiza las mismas operaciones que lo que está probando no es un test.

Esto sería un ejemplo de un test incorrecto:
<?php
 class Calculadora{
  public function suma( $a, $b )
  {
   return $a + $b;
  }
 }

 $calculadora = new Calculadora();
 for ( $a = 0; $a < 10; ++$a )
 {
  for ( $b = 0; $b < 10; ++$b )
  {
   if ( $calculadora->suma( $a, $b ) === $a + $b )
   {
    echo "Test $a+$b correcto";
   }
   else
   {
    echo "Test $a+$b incorrecto";
   }
  }
 }
?>

Como puede verse el código tiene mucha lógica, teniendo dos bucles y operaciones algorítmicas. Si analizas el código te das cuenta de que este test no está probando nada, ya que el test realiza la misma operación que la función probada ( $a + $ b ). Eso significa que si la función probada está mal, también lo estará la del test y el error no se detectará. Por eso siempre que hagas un test, debes hacer los cálculos a mano y establecer que en dichas entradas el resultado debe ser el que tu has calculado.

Estos dos ejemplos, son muy sencillos y esto casi nunca se da en un entorno real. Aún pese a ser sencillos escribir el test ha sido engorroso y además se sitúa en el mismo archivo que la clase, por lo que este archivo no puede ir a producción. Para facilitarnos la tarea en la creación de tests y hacerlos la vida más sencilla, existen los frameworks para tests, que es lo que utilizaremos a partir de ahora.

Tests unitarios en PHP con PHPUnit

En PHP, el estándar para la realizar los tests es el framework PHPUnit. Este framework nos proporciona todo lo necesario para poder realizar los tests que nos dirán si nuestra aplicación está funcionando como nosotros esperamos de una forma mucho más sencilla que la vista anteriormente.

Para ver el funcionamiento de PHPUnit, nada mejor que ver un ejemplo y explicar paso a paso como funciona. Os recuerdo que este será un ejemplo sencillo y lo iremos complicando en los siguientes artículos.

Para empezar, tenemos nuestra clase calculadora, que se almacenará en un archivo llamado "calculadora.php":
<?php
 //calculadora.php
 class Calculadora{
  public function suma( $a, $b )
  {
   return $a + $b;
  }
 }
?>

Ahora que tenemos nuestra clase, vamos a probarla con PHPUnit, el código para probar esta clase sería el siguiente:
<?php
 //CalculadoraTest.php
 require_once( 'calculadora.php' );

        /**
         * Los nombres de las clases tiene que terminar por *Test y el nombre del archivo debe ser el mismo
         * que el de la clase.
         */
        class CalculadoraTest extends PHPUnit_Framework_TestCase{
                /**
                 * Objeto a probar, en nuestro caso la calculadora.
                 *
                 * @var Calculadora
                 */
                protected $obj;

                /**
                 * Este método es ejecutado antes de cada ejecución de test, de forma
                 * que todo lo que tengas que inicializar en todos los tests, lo puedes
                 * centralizar aquí.
                 */
                public function setUp()
                {
                        $this->obj = new Calculadora();
                }

                /**
                 * Este método se ejecuta después de cada test ejecutado, por lo que
                 * se dedicará a limpiar los restos de la ejecución del test.
                 */
                public function tearDown()
                {
                        $this->obj = null;
                }

                /**
                 * Test para comprobar la funcionalidad del objeto
                 */
                public function testSuma()
                {
                        $this->assertEquals( 3, $this->obj->suma( 1, 2 ), 'El resultado de 1 + 2 debe ser 3.' );
                }
        }
?>

El nombre de la clase de testing debe terminar por Test y el mismo nombre de la clase debe ser el mismo nombre del archivo. Esto lo utiliza PHPUnit para buscar las clases a ejecutar y saber que nombre tienen. Además esta clase extiende de PHPUnit_Framework_TestCase, que es la clase que nos aportará todas las herramientas necesarias para el test.

Una vez entramos dentro de la clase, vemos un par de métodos mágicos llamados setUp y tearDown. Este par de métodos son opcionales y se dedican a inicializar y limpiar respectivamente los tests. Esto nos permitirá que todas las acciones repetitivas de dentro de los tests, extraerlas y que los tests solo contengan realmente la lógica de comprobación. Además esto nos permite respetar otra regla importante de los tests y es que un test no puede ser nunca dependiente de otro, por lo que el orden de ejecución de los tests nunca debería de importar, y es por esa razón que el tearDown borra el objeto creado para el test anterior, por si este ha hecho alguna modificación al objeto que podría hacer fallar al siguiente test.

Todos los métodos que empiecen por la palabra test son los que se van a ejecutar y deben comprobar el funcionamiento de la clase deseada. En nuestro caso, el método testSuma comprueba que si sumo 1 y 2, el resultado sea 3. Como podeis ver, la forma en que se comprueba si todo a ido bien es con la función assertEquals.

Las función assertEquals lo que permite es que dado el primer parámetro, que es lo que espero como resultado y un segundo parámetro donde indico el resultado real de la operación, saber si los resultados coinciden. Además a esta función se le puede pasar un tercer parametro para que en el caso de que la comparación falle, me muestre dicho mensaje de error. Como puedes ver es mucho más sencillo usar esta simple función que la lógica if/else utilizado en nuestro primer ejemplo sin framework.

A estas comparaciones para saber si algo ha ido bien, se le llaman aserciones y assertEquals es solo una de las muchas que tiene PHPUnit para poder comprobar que un resultado ha sido correcto. En el framework tienes disponibles desde aserciones para comprobar si un número es mayor que otro, hasta comprobar si el atributo de un objeto es igual a lo que tu quieres, pasando por saber si un array tiene un cierta clave. Os aconsejo darle una mirada a la gran cantidad de aserciones de las que dispone en su manual.

Finalmente para ejecutar los tests de phpunit, es tan sencillo como ejecutar la orden:
$phpunit --colors CalculadoraTest.php

Esto nos mostrará un resultado, que será verde en caso de que todo haya ido bien y rojo en caso contrario.

Os dejo los archivos del articulo adjuntos en el mismo y en los siguientes artículos veremos más a fondo el funcionamiento del framework y como abordar casos más complejos.

Referencias

  1. PHPUnit

Descargar scripts del artículo.

domingo, 18 de marzo de 2012

Como utilizar APC

¿Que es APC?

APC es un sistema de cache NO distribuido, que nos permite almacenar en memoria RAM los datos que necesitamos, además de un acelerador de PHP, por lo que también aumentará el rendimiento de nuestros scripts.

¿Como funciona APC?

APC una vez instalado, puede tener dos usos:
Acelerador de PHP
PHP es un lenguaje interpretado, por lo que no es el sistema operativo quien arranca nuestros scripts, si no que es PHP el que se encarga de interpretar lo que hemos escrito e interpretarlo generando su propio código máquina (opcode).
Ejecutando un script sin APC Cada vez que se ejecuta un script, sucede lo que se puede ver en la imagen superior. Si os fijáis, en un entorno de producción el paso de compilar el script no es necesario, ya que sabemos que ese archivo no va a cambiar, por lo que nos podríamos ahorrar la compilación del código y obtener siempre el mismo opcode compilado la primera vez. En este punto es donde entra APC. APC lo que hace por defecto es almacenar el opcode generado por el PHP y cuando PHP pide nuevamente el archivo, en vez de tenerlo que compilar de nuevo, APC se lo sirve directamente ahorrándonos todo el proceso de compilación, ahorrando así CPU y aumentando la velocidad de ejecución y respuesta de nuestros scripts.
Ejecutando un script con APC Por defecto APC cada vez que PHP le pide el opcode de un archivo el comprueba si el archivo ha sido modificado desde la última vez que obtuvo su opcode. De esta forma este sistema nos puede servir también en un entorno de desarrollo, ya que no tenemos que ir eliminando manualmente el opcode de la versión anterior de nuestro script. Esto nos trae un inconveniente, y es que como se puede ver en el gráfico, APC necesita realizar por cada petición un acceso a disco para comprobar la fecha de modificación del archivo y pese a que aún así es más rápido que compilar de nuevo nuestro script, es una operación completamente innecesaria en un entorno de producción donde sabes que los archivos no van a cambiar, y en caso de cambiar puedes hacer manualmente una limpieza de caché. Por eso APC nos provee del flag "stat", representado también en el flujo, que nos permite activar o desactivar ese comportamiento.

Sistema de caché
Desde PHP puedes decirle a APC que almacene un valor en memoria RAM, de tal forma que cuando queramos podemos volver a obtener ese dato de forma muy rápida. Esto puede servir por ejemplo para almacenar un resultado de una consulta que sea idéntica a todos los usuarios y que no queramos repetirla por cada conexión. De esta forma el primer usuario que ejecutaría la página haría la consulta a base de datos y almacenaría el resultado en APC. A partir de ese momento, todos los usuarios que accedieran al sitio no necesitarían obtener el resultado de base de datos, si no que lo obtendrían directamente de memoria RAM, por lo que la obtención del dato será muchísimo más rápida que obtenerla desde Mysql.

¿Como se usa?

Apc es una extensión de PHP, por lo que instalarla es tan sencillo como configurarla. Si tienes un sistema operativo linux basado en debian, es algo ran sencillo como:
$ sudo apt-get install php-apc
Para usarla, disponemos de una API que se puede consultar en la documentación oficial de PHP y que permite básicamente almacenar datos en memoria y obtenerlos. El funcionamiento es muy sencillo, ya que de forma básica solo necesitas utilizar las funciones apc_fetch para la recuperación de datos y apc_store para el almacenamiento de datos.
Os dejo un ejemplo para que veáis un uso muy básico, pero que cubre la gran mayoría de los casos
<?php
// Aquí solo se accede la primera vez
if ( !apc_exists( 'calculo_super_complicado' ) 
{
 $resultado = hacerCalculoMuyLentoYComplicado();
 apc_store( 'calculo_super_complicado', $resultado );
 echo $resultado;
}
//El resto de usuarios ejecutan esta parte
else 
{
 echo apc_fetch( 'calculo_super_complicado' );
}
?>

Al usar APC como sistema de caché, se tiene que tener en cuenta que por defecto APC tiene configurado un tamaño de caché de 32mb, por lo que cuando llegue a ese límite automáticamente las entradas menos usadas se irán descartando a medida que se añadan de nuevas. Si deseas borrar algo manualmente, solo tienes que usar la instrucción apc_delete y si quieres ampliar el tamaño de almacenamiento, solo debes modificar la configuración correspondiente.

Gestión de APC

APC dispone además de un entorno web muy útil para ver información sobre el uso que está teniendo el sistema de caché. Para poderlo usar simplemente debes copiar el archivo apc.php a una carpeta que apache pueda tener acceso. El usuario y contraseña para acceder a la página se encuentra dentro del propio archivo php, por lo que es muy fácil de editar y poner los que más te convengan.
Os dejo unas captura de como es actualmente este panel.
Esto ha sido un acercamiento a los sistemas de cache, el opcode y concretamente a APC. Existen otros sistemas de caché y APC puede hacer más de lo explicado en esta entrada, pero se han cubierto sus características básicas.

Actualización:
El archivo apc.php, puede encontrar en las distribuciones ubuntu en la ruta "/usr/share/doc/php-apc/apc.php.gz". Solo se tiene que descomprimir y listo.



miércoles, 14 de marzo de 2012

Patrones de diseño IV - Inyección de dependencias


En la anterior entrada, vimos como crear un adaptador, pero no llegamos a ver como podemos utilizar esos adaptadores para sacar toda su utilidad. Para eso vamos a ver el patrón de inyección de dependencias.

Este patrón nos ayudará a que nuestra aplicación tenga un bajo acoplamiento y una alta cohesión. Para los que no estén familiarizados, decir que eso significa que dos piezas de software no deben ser dependientes entre ellas, pero deben definir correctamente una unidad de software. Para más detalles os dejo una referencia al final de la entrada(1).

Si programas una clase sin utilizar este patrón, la clase resultante puede ser parecida a la del ejemplo, donde se crean objetos dentro de la propia clase y eso hace que haya un fuerte acoplamiento, que es algo que queremos evitar.
class my_class
{
 public function obtenerDatos()
 {
  $base_de_datos = new Mysqli(); //Fuerte acoplamiento

  $base_de_datos->connect();
  $result = $base_de_datos->query( 'SELECT * FROM tabla' );

  return $result;
 }
}

$instancia = new my_class(); 
$instancia->obtenerDatos();

Si utilizamos el patrón, la dependencia se inyecta de forma externa, por lo que la propia clase ya no necesita saber que objeto va a utilizar (realizar un new Objeto), si no solamente la interfaz que va a utilizar de ese objeto, y ahí es cuando entran en juego los adaptadores.

Los adaptadores, tal y como explicamos en la anterior entrada, tienen una interfaz en común que nos asegura que esos objetos tienen un conjunto común de métodos. De esta forma se puede inyectar en la clase cualquier objeto que posea la interfaz que el requiera y olvidarse de que objeto concreto usa.
class my_class
{
 //Inyección de un objeto del tipo InterfazBaseDeDatos
 public function obtenerDatos( InterfazBaseDeDatos $base_de_datos )
 {
  $base_de_datos->connect();
  $result = $base_de_datos->query( 'SELECT * FROM tabla' );

  return $result;
 }
}

$base_de_datos = new AdaptadorMysqli(); //Creamos la dependencia de forma externa.
$instancia = new my_class(); 
$instancia->obtenerDatos( $base_de_datos ); //Inyectamos la dependencia.

En el ejemplo puede verse que la clase ya no requiere el objeto Mysqli, si no que requiere un objeto que tenga la interfaz InterfazBaseDeDatos. Esto permitirá nuestra clase utilizar cualquier objeto que disponga del adaptador.

La dependencia, en el ejemplo anterior, se ha inyectado en el mismo método en el que se utiliza la dependencia externa, pero la inyección de dependencia se puede realizar en otros lugares como por ejemplo el constructor o un método específico para la inyección de dependencias.

Tipos de inyecciones alternativas


Constructor

//Inyección de dependencia en el constructor.
class my_class
{
 //Código de la clase
 public function __construct( InterfazBaseDeDatos $base_de_datos )
 {
  $this->base_de_datos = $base_de_datos;
 }
 //Código de la clase

}

Método específico

//Inyección de dependencia en un método concreto.
class my_class
{
 //Código de la clase
 public function establecerConectorBaseDeDatos( InterfazBaseDeDatos $base_de_datos )
 {
  $this->base_de_datos = $base_de_datos;
 }
 //Código de la clase

}

Por último decir, que si leéis más cosas sobre inyección de dependencias y os encontráis con algo llamado "Contenedor de inyección de dependencias", decir que no es lo mismo que explicado en esta entrada.

Referencias

  1. Acoplamiento y Cohesión

lunes, 5 de marzo de 2012

Patrones de diseño III - Adaptadores

Los adaptadores son un tipo de clase que nos permiten unificar una interfaz para poder cambiar fácilmente entre distintas librerías, haciéndolas así compatibles con nuestra aplicación.

Para ejemplificar este patrón, consideraremos que tenemos una aplicación con la que queremos tener acceso a base de datos con el conector Mysqli, pero queremos dejar la aplicación preparada para poder cambiar de conector fácilmente.

Para empezar a realizar un adaptador, lo primero que tenemos que definir es un interfaz. Pese a que no es un requisito obligatorio, definir un interfaz hará que sea más fácil la implementación del adaptador, evitando así muchos problemas. Para quien no sepa lo que es una interfaz (interface en inglés), le aconsejo que se lea la documentación oficial de php sobre interfaces.

La interfaz que definiremos será un método para poder conectar a la base de datos y otro método para poder ejecutar las consultas y que además nos devuelva su resultado. Un posible código para la interfaz podría ser el siguiente:
<?php
/**
 * Interfaz para la conexión a una base de datos
 */
interface conexionBd
{
        /**
         * Permite al usuario conectarse a la base de datos indicada.
         *
         * @param string $servidor Dirección del servidor.
         * @param string $usuario Nombre de usuario.
         * @param string $contrasena Contraseña.
         * @param string $base_de_datos Nombre de la base de datos a conectar.
         * @return boolean Devuelve TRUE si todo ha ido bien, si no FALSE.
         */
        public function conectar( $servidor, $usuario, $contrasena, $nombre_base_de_datos );

        /**
         * Realiza una petición al motor sql y devuelve el resultado
         * de su ejecución.
         *
         * @param string $sql Petición SQL.
         * @return mixed
         */
        public function peticion( $sql );
}
?>

Como puedes ver, aquí no definimos ningún tipo de implementación, por lo que los métodos están vacíos. Será la clase que implemente esta interfaz, la que deberá programar su lógica.

Ahora que ya tenemos una interfaz común para el acceso a todo tipo de conectores de bases de datos, vamos a crear una clase adaptador que adapte el objeto Mysqli original a  la interfaz genérica que hemos definido.

El código de nuestra clase adaptador es:
<?php
/**
 * Adaptador para Mysqli
 */
class AdaptadorMysqli implements conexionBd
{
        /**
         * Conexión a la base de datos.
         *
         * @var Mysqli
         */
        protected $conexion;

        /**
         * Permite al usuario conectarse a la base de datos indicada.
         *
         * @param string $servidor Dirección del servidor.
         * @param string $usuario Nombre de usuario.
         * @param string $contrasena Contraseña.
         * @param string $base_de_datos Nombre de la base de datos a conectar.
         * @return boolean Devuelve TRUE si todo ha ido bien, si no FALSE.
         */
        public function conectar( $servidor, $usuario, $contrasena, $nombre_base_de_datos )
        {
                $this->conexion = new Mysqli( $servidor, $usuario, $contrasena, $nombre_base_de_datos );
        }

        /**
         * Realiza una petición al motor sql y devuelve el resultado
         * de su ejecución.
         *
         * @param string $sql Petición SQL.
         * @return mixed
         */
        public function peticion( $sql )
        {
                $resultado = $this->conexion->query( $sql );
                if ( $resultado->num_rows > 0 )
                {
                        $datos = array();
                        while( $row = $resultado>fetch_assoc() )
                        {
                                $datos[] = $row;
                        }

                        return $datos;
                }

                return $resultado;
        }

}
?>


Como puedes ver lo primero que hace el código es decir que la clase que implementa la interfaz que hemos definido.
class AdaptadorMysqli implements conexionBd 
De esta forma ahora PHP nos obligará a crear en nuestra clase  todas las funciones que se indiquen en la interfaz que implementa.

En él método de conectar hemos implementado como se realiza la conexión a Mysqli, mientras que en él método de petición hemos implementado una petición más una obtención de resultados. Como ves, no es necesario, ni práctico, que la interfaz se adapte a Mysqli, si no que es al revés, Mysqli debe adaptarse a la interfaz, ya que ahora mismo es Mysqli el que es adaptado, pero al día siguiente puede ser PDO el que quieras adaptar y la misma interfaz te debe servir para cualquiera.

Con todo esto, ya hemos terminado nuestro adaptador pero, ¿esto que nos aporta?. Ahora podemos utilizar en toda nuestra aplicación objetos del tipo conexionBd sin que nos importe que conector a base de datos haya detrás, ya que todos se accederán de la misma forma por la aplicación.

Os dejo el código completo del ejemplo para descargar.

miércoles, 29 de febrero de 2012

Patrones de diseño II - Singleton

Aquí venimos de nuevo con un nuevo patrón de diseño, el denominado singleton. Este patrón nos servirá para cuando queremos que un objeto tenga una sola y única instancia en toda la aplicación, como por ejemplo al conexión a la base de datos.
La conexión a bases de datos consume muchos recursos del servidor, por lo que nos interesa, conectar una sola vez y realizar todas las consultas necesarias, además de esta forma, nos evitamos tener que crear múltiples objetos que también hacen que la aplicación ocupe más memoria.

A continuación podéis ver la estructura básica de un singleton y después lo explicaremos detalladamente.

/**
 * Objeto del cual deseamos tener una sola instancia
 * en toda la aplicación.
 */
class mi_objeto
{
        /**
         * Aquí se almacenará la única instancia existente
         * del propio objeto.
         *
         * @var mi_objeto
         */
        private static $instancia;

        /**
         * Constructor para la creación de una instancia
         * del objeto.
         */
        private function __construct(){}

        /**
         * Método que siempre devuelve la misma instancia
         * del objeto.
         */
        public static function getInstance()
        {
                if ( !self::$instancia )
                {
                        self::$instancia = new self;
                }

                return self::$instancia;
        }
}


La primera parte y fundamental del código es la variable $instancia.
private static $instancia;
Esta variable almacenará la única instancia disponible en toda la aplicación. Esta variable es estática, ya que debe estar siempre accesible. Si no sabéis que es o para que sirve una variable estática, os recomiendo ver los ejemplos disponibles en la documentación oficial de php.

Más adelante nos encontramos con algo que al principio parece extraño y es que el constructor de la clase es privado. Como hemos dicho solo queremos una instancia en toda la aplicación y es por eso que el constructor es privado, para que nadie pueda realizar por desconocimiento o despiste algo como
$variable = new mi_objeto();
ya que al ser el constructor privado, esto lanzaría un error en la aplicación y evitaría la creación descontrolada de objetos.

Llegados a este punto muchos se preguntarán como se hace entonces para poder crear una un objeto, teniendo el operador new bloqueado. Pues la respuesta es sencilla como ejecutar el método getInstance.
$obj = mi_objeto::getInstance();
Como puede verse en el código del método getInstance, lo que hace es primero que todo comprobar si el objeto ha sido creado anteriormente y en caso de que no haya sido creado anteriormente lo crea y lo devuelve. A partir de este momento, todas las veces que queramos obtener un objeto de la clase mi_objeto, ya no se devolverá una nueva instancia, si no que se obtendrá la generada por primera vez.

A continuación dejo un ejemplo práctico de una clase singleton, con un ejemplo de su funcionamiento. Probad a jugar un poco con ella y pensar posibles usos.
/**
 * Objeto del cual deseamos tener una sola instancia
 * en toda la aplicación.
 */
class mi_objeto
{
        /**
         * Aquí se almacenará la única instancia existente
         * del propio objeto.
         *
         * @var mi_objeto
         */
        private static $instancia;

        /**
         * Variable para almacenar un número
         */
        public $numero;

        /**
         * Constructor para la creación de una instancia
         * del objeto.
         */
        private function __construct(){}

        /**
         * Método que siempre devuelve la misma instancia
         * del objeto.
         */
        public static function getInstance()
        {
                if ( !self::$instancia )
                {
                        self::$instancia = new self;
                }

                return self::$instancia;
        }
}

//Creo un objeto y le asigno un numero
$var = mi_objeto::getInstance();
$var->numero = 23;

//Elimino el contenido de la varible.
$var = null;

//Vuelvo a obtener una instancia del objeto.
//Al ser un singleton lo que se obtendrá es la
//misma instancia que estaba en $var
$nueva_var = mi_objeto::getInstance();

//Imprimirá el número 23
echo $nueva_var->numero;

Os dejo tanto el código base del singleton como del ejemplo para su descarga.

domingo, 26 de febrero de 2012

Patrones de diseño I - MVC


Este es el primer articulo de una serie de artículos que haré sobre patrones de diseño ,que considero todo el mundo debería conocer. Empezaré por el MVC, ya que es uno de los más importantes y es utilizado por todos los frameworks más famosos en la actualidad, como por ejemplo Symfony.

El patrón Modelo, Vista, Controlador o en sus siglas (MVC), es un patrón de arquitectura, por lo que nos ayudará a que nuestra aplicación sea mantenible y respete varios principios como DRY (Don't Repeat Yourself) y KISS (Keep It Simple Stupid). Para los que no conozcan estos principios aconsejo que se queden con sus ideas, ya que son principios muy sencillos e incluso obvios, siendo muy útiles para el día a día.

La característica principal del MVC es que divide nuestra aplicación en tres capas, de forma que cada una de ellas se ocupa de una sola cosa. En la siguiente imagen podemos ver gráficamente como es la estructura del MVC y como se comunican las capas. 
Comunicación entre capas

No os preocupéis si no entendéis el gráfico, ya que se irá explicando cada parte, para que quede claro su funcionamiento. Mientras explicamos las distintas capas, veremos como crear una calculadora básica, con las operaciones de suma y resta, para que se entienda mejor el funcionamiento del patrón. Esta calculadora está pensada para propósitos académicos por lo que no debe utilizarse este código en un entorno de producción.

El modelo

Es la capa encargada de almacenar y procesar datos. No debemos caer en el pensamiento de que esta capa es únicamente para el acceso a la base de datos, ya que tareas tal como hacer una suma o formatear datos deben ir también en esta capa.

En el caso de la calculadora que ponemos en el ejemplo, las operaciones con datos que se realizan son las de suma y las de resta.

/**
 * Clase encargada del tratamiento de los datos.
 */
class Modelo
{
	/**
 	 * Realiza una suma.
	 */
	public function sumar( $a, $b )
	{
		return $a+$b;
	}

	/**
	 * Realiza una resta.
	 */
	public function restar( $a, $b )
	{
		return $a-$b;
	}
}

Como puede verse en el ejemplo en la clase del modelo solo recibimos datos, realizamos operaciones y devolvemos el resultado, por lo que tendremos todas las operaciones centralizadas en esta clase, cumpliendo así con el principio DRY.

La vista

Es la encargada de mostrar los datos al usuario, de manera que será el único punto de salida de información hacia el navegador del usuario. En esta capa se puede usar tanto un gestor de plantillas como Twig o usar directamente PHP + HTML como haremos en nuestro ejemplo.

/**
 * Clase encargada de mostrar al usuario el formulario y el resultado de la operación.
 */
class Vista
{
	/**
 	 * Método que envía al usuario el html/xml/.../json correspondientes
	 */
	public function render( $resultado )
	{
		echo <<<HTML
<!doctype html>
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>Mi calculadora</title>
	</head>
	<body>
		El resultado de la operación es: $resultado
		<form>
			<p>
				Número: <input type="text" name="a"/>
			</p>
			<p>
				Número: <input type="text" name="b"/>
			</p>
			<p>
				Operación: <input type="radio" name="action" value="sumar" checked="checked"/> Sumar <input type="radio" name="action" value="restar"/> Restar
			</p>
			<p>
				<input type="submit" name="submit" value="Calcular"/>
			</p>
		</form>
	</body>
</html>
HTML;
	}
}

Como podemos ver, tiene un método que permite mostrar un HTML por pantalla que contiene el resultado de la operación. Esta capa es la única que tiene permitido enviar datos directamente al usuario y es de lo único que se encarga.

El controlador

Este es el único punto de entrada a la aplicación y es el que se encarga de pedir los datos necesarios al modelo y enviárselos a la vista, para que el usuario pueda visualizarlos.

/**
 * Único punto de entrada de la aplicación y quien decide que acciones se van a
 * realizar y que se le mostrará al usuario.
 */
class Controlador
{
	/**
	 * Método que arranca nuestra aplicación
	 */
	public function run()
	{
		$resultado = 0;
		switch( $_GET['action'] )
		{
			case 'sumar':
				$modelo = new Modelo();
				$resultado = $modelo->sumar( $_GET['a'], $_GET['b'] );
				break;
			case 'restar':
				$modelo = new Modelo();
				$resultado = $modelo->restar( $_GET['a'], $_GET['b'] );
				break;
		}

		$vista = new Vista();
		$vista->render( $resultado );				
	}
}

En el código vemos como la función run es la que se encarga de recoger los datos del navegador, pedir los cálculos al modelo y finalmente con el resultado del modelo decirle a la vista que envíe la respuesta a nuestro usuario.

El flujo completo de la petición para una suma sería el siguiente:

Finalmente, para ejecutar la aplicación, bastaría con ejecutar las siguientes lineas:
$aplicacion = new Controlador();
$aplicacion->run();


Dejo el código completo del ejemplo para su descarga y que lo podáis probar.

Esta es mi primera entrada en un blog, por lo que espero que os haya gustado, en caso de encontrar erratas o estéis en desacuerdo en algún concepto, agradecería que lo comentarais.