Newsletter para devsEntra

Refactorizar una aplicación legacy. Parte II: Desenredando la madeja

En el artículo anterior veíamos cómo enfretarnos a refactorizar una aplicación legacy puede convertirse en un verdadero embrollo. Podéis leer el artículo aquí:

Cómo refactorizar una aplicación legacy

Hoy nos ponemos manos a la obra para desenredar este fragmento de hilo que hemos dejado por ahí tirado y que ahora nos hace falta. También se me ocurre otro símil con el cable de unos auriculares.

Mangas arriba y… ¡Vamos a al lío!

La importancia de un gestor de librerías

Paso 1: la gestión de librerías.

Si bien los que somos de la vieja escuela estamos acostumbrados a descargarnos las librerías en un archivo ZIP desde el repositorio de costumbre, esto conlleva varios problemas:

  • Es muy complicado recordar la versión de la librería instalada.
  • Si decidimos nombrar las carpetas de las librerías con sus correspondientes versiones, nos toca destruir la carpeta obsoleta, crear una nueva y realizar el cambio en el include en todos los archivos en los que hayamos hecho referencia a la misma.
  • Retroceder en la versión conlleva realizar la tediosa tarea que hemos realizado en el paso anterior.

Hay muchisimos inconvenientes más, pero creo que os podéis hacer una idea.

Para librarnos de todas estas tareas viene al rescate el gestor de librerías.

Todo lenguaje de programación tiene su gestor oficial de librerías, en nuestro caso, como estamos hablando de PHP, el gestor de librerías oficial es Composer. No dudéis en vistar su página oficial.

Los gestores de librerías suelen apoyarse en una carpeta donde realizan la gestión de las mismas. En este caso se trata de una carpeta en el raíz llamada vendor.

Por otro lado existe un archivo que se encarga de tener un índice de las librerías instaladas en nuestra aplicación y la versión de las mismas. En el caso de composer: composer.json.

Cómo estructurar las carpetas

Todos los lenguajes de programación tiene una forma de establecer cómo funcionan sus carpetas, cómo es su estructura.

Esto es sumamente importante para la inclusión de las llamadas a las clases externas, ya que así evitaremos la colisiones con los nombres de las clases o métodos.

En el caso de PHP tenemos PSR (PHP Standard Recommendation). PSR comprende muchas recomendaciones, la que se refiere a la estructura de carpetas es la PSR-4.

La inclusión de un estandar de estructura de carpetas nos obliga a tener una estructura muy concreta y la carpeta que contendrá todo nuestro almacén de controladores propios (estas son las clases que nosotros mismos programaremos, las que tienen toda la lógica del negocio de nuestra aplicación) viene referenciada en este caso en el archivo composer.json.

Además nos obligará a tener un espacio de nombres para poder hacer una declaración al inicio de todos los archivos que se rijan por este espacio de nombres.

No voy a entrar en detalles de cómo se realiza la inclusión de este estandar en nuestro aplicativo, pero tenéis un ejemplo en este artículo:

Cómo evitar los require_once en nuestra aplicación Web.

A partir de aquí surge toda la magia. Si decidimos que nuestra carpeta de controladores sea /src (nombre elegido por costumbre), a partir de ahora tan sólo tendremos que incluir nuestras clases dentro de esta carpeta.

Es aquí donde se nos hace necesaria la programación orientada a objetos, ya que a partir de ahora haremos referencia a los archivos que teníamos en el artículo anterior con un modelo de clases que contiene propiedades (carácteristicas del objeto) y métodos (acciones del objeto).

El paso de procedural a orientación a objetos

Como veíamos en el artículo anterior, cada una de nuestras funcionalidades estaban separadas en archivos independientes.

Así, teníamos:

  • contactos.php: contiene un listado de contactos.
  • annadir.php: es utilizado para añadir clientes.
  • borrar.php: usado para borrar clientes.
  • modificar.php: se utiliza para la modificación de clientes.
  • funciones.php: declaración de funciones que utiliza la aplicación: cambio de formatos de fecha, funciones de cadena propias, etc.

Pues bien, todo esto cambia con la POO, y esque todas las funcionalidades estarán contenidas en un mismo archivo: src/Contacts.php.

Recordad que es una buena práctica nombrar todos los archivos, variables, etc. en inglés, ya que nunca sabemos el idioma que hablará el programador que en un futuro puede tocar nuestro código.

También es bueno decir que las clases y los archivos de controlador deben nombrarse con la primera letra en mayúscula

Ahora nuestro archivo con toda la lógica de programación contendría la declaración de nuesto espacio de nombres (ourAPP en este caso), la declaración de la clase y sus propiedades. Vamos a ver cómo quedaría el código:

<?php
namespace ourAPP;

class Contacts{
    private $name;
    private $lastName;
    private $email;
}

Los archivos que contendrán las acciones contra los contactos, pasan a ser métodos.
Vamos a declarar los mismos:

<?php
namespace ourAPP;

class Contacts{
    
    private $name;
    private $lastName;
    private $email;
    private $phone;
    
    public function add();
    public function delete();
    public function update();
    
}

No he incluido el código funcional de cada uno de los métodos porque en este caso no es el objetivo del artículo.

Ahora sólo es cuestión de instanciar esta clase y llamar a cada uno de sus métodos para ejecutar cada una de las acciones que antes teniamos por separado.

Quizás no os convezca la utilidad de haber incluido todos esos archivos independientes en uno sólo, pero imaginaros una aplicación dónde no exista sólo una entidad (la de contactos), sino que tengamos más entiedades. En ese caso el número de archivos crecerá considerablemente (y no hablemos ya de la cantidad de includes que tendríamos que cruzar entre todos esos archivos).

En cuanto al archivo funciones.php, ¿porqué no incluirlo dentro de nuestra carpeta /srctambién?

Este archivo que contiene funciones independientes de tratamiento de verificación de campos, conversión de fechas, etc. (utilidades en definitiva), podría contener un código como este:

<?php
namespace ourAPP;

class Functions{

    public static function checkEmailFormat($email);
    public static function checkPhoneFormat($phone);    

}

Si os habéis dado cuenta, los métodos de esta clase vienen precedido de public static, ¿qué quiere decir esto?

Los métodos estáticos no necesitan una instanciación de la clase y pueden ser atacados directamente de esta forma:

<?php
Functions::checkeEmailFormat('jhon@doe.com');

Conclusión

Como habéis podido apreciar hemos pasado por tres pasos de la refactorización que son muy importantes:

  • Mantenimiento de librerías con un gestor.
  • Estructura de carpetas estandar.
  • Evolución de una metodología de programación funcional a programación orientada a objetos.

Estos tres simples cambios que a priori pueden parecer tediosos nos brindan una serie de ventajas que harán nuestro código mucho más mantenible (ya que ahora sólo tenemos que acudir a un lugar para modificar nuestro código), mucho más legible (debido a que podemos nombrar los métodos de una forma que expliquen lo que hacen) y nos facilitará la inclusión de ficheros y referencias entre ellos.

Si queréis ampliar la información sobre los conceptos vistos en este artículo, os aconsejo que escuchéis el episodio de la Academia online de Daniel Primo en el que Dani nos explica cómo refactorizar correctamente una aplicación legacy.

También os dejo por aquí un fragmento del episodio del podcast por si preferís escucharlo en formato video:

¡Nos vemos en el siguiente fragmento de conocimiento, equipo!

Escrito originalmente por: Juan José Ramos

Imagen de Daniel Primo

Daniel Primo

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. @delineas en twitter y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.