Escribiendo código limpio en PHP

Pocos lenguajes han pasado por tantas polémicas y debates como lo ha hecho PHP. Y es que todos los problemas que se le atribuyen no son solo por su uso, sino también por su funcionamiento interno.

PHP ha evolucionado a un punto en donde es imposible reconocerlo si se toma una pequeña mirada a sus primeras versiones, lo que originalmente era un sistema de plantillas de HTML, se ha convertido en un lenguaje de programación estructurado, para luego pasar a seguir un paradigma orientado a objetos para luego implementar detalles de la programación funcional. Es increíble pensar que PHP ni siquiera era un lenguaje de programación en sus inicios, y que parte del código que mueve hoy en día su intérprete, está escrito sobre el código original.

Pero aquí estamos para hablar sobre cómo escribir código limpio en este lenguaje, no sobre sus problemas, ya que sobre eso hay mucha información en internet.

Y si, es posible escribir código limpio en PHP, lo único que evita que el código sea más agradable a la vista es la sintaxis del lenguaje que a muchos puede disgustar por cosas como el uso del dólar $ para las variables, o las flechas -> y los doble dos puntos :: para acceder a propiedades.

Los puntos tratados aquí se enfocan al lenguaje de PHP, y son adicionales a los puntos tratados por el libro de Clean Code los cuales son agnósticos en lo que respecta al lenguaje de programación que se use.

Seguir un estándar

En el ecosistema de PHP existe lo denominado PSR, siglas en español de Recomendaciones Estándar de PHP. Este es un conjunto de reglas que se pueden seguir para estandarizar la programación en este lenguaje.

El PSR es publicado por el PHP Framework Interop Group.

Muchas de las reglas del PSR no me parecen esenciales e incluso me parecen que fuerzan demasiado el seguimiento una denominada estructura. Pero hay dos reglas que si me parecen importantes y que deberían de seguirse, esas son el PSR 2 y PSR 4.

El PSR 2 puede implementarlo todo el mundo ya que este solo indica el estilo a seguir al escribir código, o sease lo típico, la posición de las llaves, donde usar un salto de línea, la cantidad de espacios a usar entre identificadores, entre otros detalles...

El PSR 4 es, en cambio, un regla que indica cómo se deben de cargar las clases, en lugar de usar el clásico require "archivoConClase.php" para luego instanciar la clase, se pide usar la función de spl_autoloader_register, que mapea una clase a un archivo, lo cual viene siendo algo así:

index.php:

<?php

spl_autoload_register(function($class) {
    include_once $class . '.php';
});

$car = new Car();

Car.php:

<?php

class Car 
{
	//...
}

De esta forma al instanciar la clase Car se devolverá la clase contenida en el archivo Car.php en el mismo directorio. Para organizar mejor el código y evitar colisiones con los nombres de las clases puedes agruparlas por espacios de nombre o namespaces.

Por suerte si usas un manejador de dependencias como Composer, este ya implementa el PSR 4.

Escoger el paradigma correcto

Puede sonar un poco contraproducente el escribir código estructurado en PHP teniendo las posibilidades de escribir código orientado a objetos, es cierto que la POO ayuda en la escalabilidad pero no me parece un paradigma que sea necesario de implementar en todos los casos de uso.

Por supuesto que es importante conocer sobre el paradigma orientado a objetos y temas de gran valor como los patrones de diseño, pero, al crear una aplicación mínima o de tamaño muy reducido (y me refiero realmente a muy reducido), muchas veces beneficia más el seguir la programación estructurada ya que puede significar menos código por escribir y mantener (a pesar de que parezca que no es así).

Al final, PHP es un lenguaje que sigue varios paradigmas, así que ¿Por qué no sacar provecho de cada uno según sea el caso?

Usar las herramientas correctas

PHP es ese tipo de lenguaje en donde hay muchas maneras de solventar un mismo problema, y es que algunas de estas son mejores que otras, sea porque son más seguras o sencillamente porque al menos tienen soporte.

Antes de continuar se recomienda enormemente ejecutar la última versión estable del lenguaje al menos en producción, porque en caso contrario es posible que estés usando funciones o características que ya no tienen soporte sin darte cuenta.

Recomiendo leer la documentación del lenguaje y curiosear su API pública y sus métodos, gracias a eso he logrado descubrir varias herramientas y características ofrecidas por el lenguaje que me han ayudado a mejorar la calidad de mi código. Aquí dejo alguna de ellas:

PDO para la base de datos

En caso de que no uses una librería para conectarte a la base de datos, la extensión de PDO (PHP Data Objects) es la mejor solución, permite conectarte a varios gestores de base de datos y tiene muchas opciones, las extensiones como la de mysqli no solo tienen problemas de seguridad sino que ya no se les ofrece soporte.

Mbstring para unicode

Lamentablemente este lenguaje no viene con un soporte total para caracteres Unicode, o sease que no sean ASCII o sease que usen más de un byte para representar un carácter, y justamente por eso, si piensas manejar cadenas de texto con caracteres especiales, la extensión de mbstring es la indicada.

Password_hash para contraseñas

Si deseas manejar un sistema de login de usuarios con sus respectivas contraseñas, la combinación de la función de password_hash junto a password_verify es la más indicada. Juntas, estas funciones no solo son lo suficientemente seguras de usar en producción, sino que también se puede indicar el algoritmo y las opciones de encriptación.

Evitar la magia

Algo que siempre he criticado de los grandes frameworks y librerías que existen en PHP (como Laravel), es el uso de toda la "magia" de PHP.

En este caso por magia me refiero a muchas cosas, mas que todo a un conjunto de funciones y métodos con los cuales puedes hacer cosas que en otros lenguajes es imposible, cómo acceder a la pila de llamadas del lenguaje y modificar así los objetos que han llamado a la función actual, o redirigir todas las llamadas hechas a métodos inexistentes a un modelo en específico.

Aprovecharse de estas características del lenguaje no es necesariamente malo, al menos con la intención de debuggear, pero por favor evita poner ese mismo código en un entorno productivo. Cabe resaltar que esto no aplica para todos los métodos mágicos del lenguaje, ya que hay un número limitado de estos cuyo uso es beneficio y hace más expresivo el código.

En este ejemplo la función func es capaz de volver null la propiedad data de sea cual sea el objeto que está llamando a esta función. Incluso se podría modificar para acceder al objeto que llama al objeto que llama a la función (una locura).

<?php

function func() 
{
    $trace = debug_backtrace();
    $trace[1]['object']->data = null;
}

class Obj 
{
    public $data;

    public function __construct() 
	{
        $this->data = [1,2,3];
        func();
        // Aqui $this->data ahora es null
    }
}

new Obj();

Si la declaración de func está en otro archivo, un programador jamás pensaría que una función global es la que está volviendo null la propiedad de un objeto cuando ni siquiera se le está pasando esa propiedad como argumento.

Otra magia del lenguaje es el operador @, el cual oculta cualquier error o excepción en donde se use.

<?php

@lanzarExcepcion();

Si la función lanzarExcepcion lanza una excepción, no pasará nada gracias al uso del @, esto si deberias de evitarlo usar en producción a toda costa, siempre es mejor manejar las excepciones y casos parecidos de la manera convencional.

Para concluir, si deseas leer más sobre el código limpio en PHP y las buenas prácticas, recomiendo enormemente leer PHP: La Manera Correcta, ahi hay infinidad de consejos, tips y guias sobre el uso correcto del lenguaje.