Llevo algo de tiempo programando en PHP, al principio mi código era horrible pero poco a poco he ido aprendiendo más y más sobre buenas prácticas, SOLID, naming, uso de herramientas para mejorar el código (PHP Mess detector, PHP code Sniffer…). Además la serie de post sobre refactoring PHP legacy code he podido poner en práctica muchos de estos conocimientos.
Este post es un recopilatorio de buenas prácticas y consejos que he ido aprendiendo en estos últimos meses.
Instalación de PHP
Antes de empezar a desarrollar tenemos que tener bien configurado PHP y el archivo de configuración php.ini es esencial.
- date.timezone -> tener bien definido la zona horaria nos evitará muchos quebraderos de cabeza.
- charset -> trabajar con UTF-8.
- error_reporting -> tener diferentes entornos (producción, desarrollo,…) y que cada uno notifique errores distintos.
- Extensiones -> Instalar extensiones como XDebug,, mycript, intl,Imagemagick.*
Utilizar Composer
Existen miles de librerías en PHP, github esta lleno de componentes que puedes sernos muy útiles para ayudándonos en nuestro día a día. Librerías par manejar CSV, para log, para manejar peticiones HTTP,… Para gestionar todas estas dependencias creo que lo más útil es utilizar composer.
Con composer podemos gestionar las dependencias y el autoload con solo tener un archivo json.
- Definir dependencias es tan facil como:
{ "require": { "twig/twig": "1.8.*" } }
- Para el autoload solo tenemos que añadir
require 'vendor/autoload.php';
Seguir los principios SOLID
SOLID es una regla mnemotécnica para recordar los 5 principios del buen desarrollo software orientado a objetos.
- Single responsability principle
- Open close principle
- Liskov substitution principle
- Interface segregation principle
- Dependency inversion principle
No hay mucho que añadir a estos principios, lo mejor es conocerlos y tenerlos en cuenta para cualquier desarrollo.
guías de estilo
Existen decenas de frameworks (Symfony, Laravel, Yii, Slim,…), librerías para que resuelven pequeños problemas y en los proyectos que desarrollemos podemos combinarlo todo de muy diversas maneras. Por eso es importante que nuestro código y librerías tengan un «estilo de código». La comunidad PHP tiene un serie de recomendaciones de estilo conocidas como PSR-0, PSR-1, PSR-2, PSR-4 así que lo mejor es que nuestro código se acerque a estos estándares. También hay frameworks que tienen sus propias recomendaciones. La máxima aquí es, «cualquier a puede desarrollar código que entienda un ordenador, lo difícil es desarrollar código que entienda otro humano»
Una ayuda para los estándares
Después de mucho utilizarlos acabaremos aprendiendo los estándares, pero apoyarnos en un buen editor con autocompletado es lo mejor. Además existen proyectos como:
- PHP CodeSniffer que sirve para verificar si nuestro código sigue estas recomendaciones.
- PHP Coding Standards Fixer modifica la sintaxis de nuestro código de manera automática.
- PHP Copy/Paste Detector para encontrar el código duplicado en nuestro proyecto.
- PHP Dead Code Detector para encontrar métodos que no estén siendo usados. (Cuidado si utilizamos reflexión)
- PHP Mess Detector
- PHP Depend que nos ayuda a analizar el código y genera métricas software.
BOLA EXTRA
Los chicos de Atrápalo han desarrollado un pequeño Hook para git (http://carlosbuenosvinos.com/write-your-git-hooks-in-php-and-keep-them-under-git-control/) en elq eu antes de cada commit se analiza todo tu código. Aquí puedes encontrar una librería para añadirla a composer (https://github.com/bruli/php-git-hooks).
Aunque estas herramientas nos pueden ayudar la mejor manera, con diferencia, para aportar valor a nuestro proyecto PHP es tener sentido común y pensar antes de escribir. Con esto nos evitaremos muchos quebraderos de cabeza cuando tengamos que escribir nuevas funcionalidades en el proyecto o resolver bugs. Ser cuidadosos a la hora de escribir poniendo buenos nombres a los métodos y las variables, hacer tests (aunque no hagamos TDD) tener test que complementen el código. Hacer métodos pequeños que puedan leerse de un vistazo son unos consejos más que podemos añadir a la lista.
Algunos consejos más
Indentación
Ya hemos visto que hacer métodos pequeños/entendibles es una buena práctica que debemos seguir, pero como sabemos que nuestro método es entendible de un vistazo. Cuando estamos inmersos resolviendo un problema lo vemos el código y nos parece clarísimo, pero meses después cuando lo volvemos a tocar nos encontramos que no entendemos nada.
Algo que nos puede ayudar a saber si un método es demasiado enrevesado es la indentación. Una regla no escrita que podemos seguir es cuantos más niveles de sangría tengamos, más complejo será el método.
veamos un ejemplo:
“código complejo”
public function transformToCsv($data)
{
$csvLines = array();
$csvLines[] = implode(',', array_keys($data[0]));
foreach ($data as $row) {
if (!$row) {
continue;
}
$csvLines[] = implode(',', $row);
}
return $csvLines;
}
Este código es un poco malo, podríamos mejorarlo de muchas maneras y seguramente la más sencilla sea atacando a la indentación e intentando eliminarla.
Podemos mejorar utilizando una función como array_filter
$data = array_filter($data);
foreach ($data as $row) {
$csvLines[] = implode(',', $row);
}
Hemos mejorado un poco la función, ahora es más legible y tan solo hemos eliminado un poco la anidación, pero podríamos llegar más allá y eliminar el bucle de esta manera.
If, else y return
Intentar minimizar el uso de if/else o lo que es lo mismo pensar antes de escribir. Después hay manías como minimizar el numero de return o intentar que las guardas de los if sean en positivo.
public function addThreeInts($first, $second, $third) {
if (is_int($first)) {
if (is_int($second)) {
if (is_int($third)) {
$sum = $first + $second + $third;
} else {
return null;
}
} else {
return null;
}
} else {
return null;
}
return $sum;
}
Podemos reescribir este código de una manera más sencilla siguiendo los consejos anteriores: pensando ante de escribir y minimizando la indentación.
public function addThreeInts($first, $second, $third)
{
if (!is_int($first)) {
return null;
}
if (!is_int($second)) {
return null;
}
if (!is_int($third)) {
return null;
}
return $first + $second + $third;
}
Este ejemplo es mucho más fácil de seguir incluso podríamos crear un solo if con varias guardas.
Test unitarios
Unit testing es una buena práctica de desarrollo de software, eso ya lo sabemos. Los test verifican el comportamiento, son rápidos y nos ayudan a entender mejor el código.De la misma manera nos ayudan a tener un código un poco mejor diseñado, o por lo menos podemos adaptar el diseño para que el código que escribimos sea testeable, es decir, si tenemos un código que es difícil de testear, seguramente ese código no este bien diseñado.
Algunas características que deben tener nuestros tests unitarios son:
- Rápidos, deben ser rápidos y enfocados a una funcionalidad.
- No deben tener dependencias externas, es decir no deben acceder a la red o al sistema de ficheros o a la base de datos.
- Utilizar mocks para evitar las dependencias.
- Un test solo debería fallar por una cosa, es decir un test solo prueba una cosa. Aunque a decir verdad esto es relativo depende de la funcionalidad de nuestra aplicación.
XDebug
Es una de las herramientas más útiles cundo estamos intentando resolver un bug, es cierto que var_dump() muchas veces ayuda, pero nada mejor que poder ir paso a paso debuggeando el código.
Conclusiones
Después de la serie larga de post sobre legacy code quería hace run poco de reflexión sobre todo el camino recorrido ya no solo a la hora de enfrentarnos a refactorizar, sino a la hora de desarrollar nuevo código. Aquí comparto algunas de las buenas prácticas, consejos y herramientas que he ido aprendiendo escribiendo código en PHP. Seguramente me deje atrás miles de librerías y herramientas muy útiles ¿creéis que hay alguna que tenga que mencionar?