Buenas Prácticas de Programación en Python

En toda disciplina del saber humano la experiencia práctica es fundamental, de la práctica se derivan lecciones muy importantes que difícilmente se olvidan. Estas lecciones generalmente se convierten en los que podríamos llamar “buenas prácticas”. Cuando nos dedicamos a la programación en Python, también podemos encontrar estas buenas prácticas. Veamos algunas de ellas sin pretender ser exhaustivos o creer que tenemos en la mano la verdad absoluta, pues simplemente no hay nada absoluto, lo que hoy es considerado bueno, mañana puede no ser adecuado, todo depende del contexto y hasta del individuo, además, Python es un ente vivo que evoluciona todos los días. La ciencia avanza y con este avance cambia nuestra percepción de las cosas. Finalmente, sin más preámbulo, les dejo un intento de resumir algunas “buenas prácticas de programación en Python”:

Organización del Código

  • La estructura general de un módulo debería ser como se muestra en la Figura 1

Figura 1. Estructura General (Recomendada) de un Módulo Python

  • Si tus módulos pueden ser importados y/o ejecutados como script emplea siempre el fragmento de código if __name__ == '__main__':, para evitar la ejecución innecesaria del código cuando importes el módulo (Figura 1)

  • Agrupa en módulos el código con objetivos y funcionalidades similares o relacionadas, luego importa los módulos desde el módulo principal o desde donde los necesites

  • Emplea nombres cortos y descriptivos para tus módulos y paquetes

  • Crea tu propio conjunto de módulos utilitarios, modifica tu PYTHONPATH y úsalos regularmente en tus proyectos

  • Emplea una estructura de paquetes y directorios coherente en tus proyectos, la Figura 2 podría servirte de guía general, con la observación de que el paquete principal (mypackage) debería tomar el mismo nombre de tu proyecto o aplicación

  

Figura 2. Estructura Básica Recomendada de un Proyecto Python

Entorno de Trabajo y Herramienta

  • Consigue un buen editor de texto o un buen IDE para Python, configúralo atendiendo a tus necesidades y domínalo a la perfección para que seas más productivo. Mi recomendación: PyCharm IDE

  • Has uso de entornos virtuales (virtual environments) para evitar convertir tu sistema base en un lío

  • Emplea un sistema de control de versiones para trabajar tus proyectos de manera consistente y evitar pérdidas irreparables. Mi recomendación: Git

  • Si pretendes hacer que tu proyecto o aplicación sea Software Libre u Open Source y que otros desarrolladores colaboren, debes valorar la Gestión de Proyecto con GitHub.com

  • Automatiza tus pruebas de código, empleando herramientas como unittest, doctest, nose o pytest

  • Automatiza la creación de documentación con herramientas como Sphinx

Estilo de Codificación (Coding Style)

  • Aprende a leer y escribir en inglés y usa siempre el inglés en tu código, en tus comentarios y en tus docstrings, más aún si pretendes que tu código tenga alcance internacional

  • Asume un estilo de codificación y sé consecuente con él a lo largo de todo el proyecto. El PEP 8 es un excelente lugar por donde comenzar

  • Comenta el código siempre que lo creas necesario, aunque un código bien escrito y legible no requiere de muchos comentarios

  • Si actualizas tu código, actualiza también tus comentarios; no hay peor comentario que uno desactualizado

  • No comentes lo obvio

>>> # Sumando x + y

>>> x + y

  • En lo personal los comentarios siempre me han parecido trabajo doble, por eso trato de que mi código sea lo más legible posible y así los evito. Cuidado con los comentarios, a veces denotan la necesidad de refactorizar el código

  • No te repitas a ti mismo, aplica el principio DRY (Don’t Repeat Yourself). Cuando identifiques código repetitivo o similar o cuando te sorprendas copiando y pegando fragmentos de código, extrae el fragmento, conviértelo en una función o en un método y llámalo desde los lugares donde lo requieras

  • Usa coherentemente la indentación del código, esto mejora notablemente la legibilidad del mismo y en Python es parte de la sintaxis del lenguaje

  • Para la indentación es recomendable usar espacios (de preferencia 4) en lugar de caracteres de tabulación, debido a que diferentes sistemas/editores pueden tener diferentes configuraciones de tabulación

  • Nunca mezcles espacios con caracteres de tabulado en la indentación

  • Emplea nombres cortos y descriptivos para tus variables, funciones, clases y atributos. Los nombres son clave para la legibilidad de tu código, selecciónalos adecuadamente

  • No emplees como nombres para tus variables y atributos, las palabras reservadas o los nombres de estructuras propias del lenguaje (built-ins), si esto fuera estrictamente necesario para garantizar la legibilidad de tu código, añade un guión bajo al final del nombre para diferenciarlo, ejemplo: list_ = [1, 2, 3, 4]

  • Evita usar la sentencia from module import *, conocida como Wildcard imports, que además de poblar tu espacio de nombres con atributos que no vas a emplear, resulta contraproducente en términos de legibilidad de código. Recuerda, “la legibilidad cuenta”

  • Evita las abreviaturas

  • Mantén el código simple, aplica el principio KISS (Keep It Simple Stupid). Recuerda que “Simple es mejor que complejo”

  • No emplees el operador “==” para comparar objetos de tipo singleton como None, en su lugar emplea el operador is/is not, como en: if var is not None:

Pruebas al Código (Testing)

  • Desarrolla un conjunto automatizado de pruebas para tu código. Crea casos de prueba con valores típicos o esperados y con valores en la frontera o límite, incluso con valores absurdos

  • Escribe los casos de prueba antes que el propio código, esto te ayudará a definir mejor el problema y los requisitos de la solución y de seguro incrementará la calidad de tu código (Test Driven Development)

  • Emplea el Ciclo Red/Green/Refactor para tus pruebas, es decir, Red: escribe tu prueba y córrela (no pasa), Green: escribe el código necesario para pasar la prueba (pasa), Refactor: modifica tu código para que quede mejor escrito, sea más legible y más eficiente, pero manteniendo sus resultados finales. Corre nuevamente las pruebas

  • Realiza pruebas de lo que estás codificando a cada momento. Asegúrate de que funciona correctamente antes de incluirlo en tu código final, para esto te puedes auxiliar del una sección interactiva en el intérprete de Python, o de otras herramientas como IPython

  • Realiza pruebas al código que se relacione con el código que estás modificando (no solo al código modificado), para asegurarte de que toda tu base de código continúa funcionando correctamente y evitar las regresiones

  • Cada prueba debe ser independiente; en otra palabras, los resultados de una prueba no deben depender de los resultados de otras

Manejo de Errores

  • Lanza excepciones a bajo nivel y atrápalas a alto nivel, así podrás tener un código más fácil de mantener, pues las modificaciones/actualizaciones serán en solo unos poco lugares

  • Como regla general, es mejor ser específico que genérico a la hora de manejar las excepciones, por ejemplo: evita usar la clase Exception en un bloque try/except, Exception es una clase de excepción muy amplia, lo que significa que atraparías lo que quiere atrapar y lo que no. Recuerda que los “errores no deben pasar silenciosamente

  • Usa siempre excepciones basadas en clases, para garantizar compatibilidad con otras versiones de Python

  • Implementa tus propias excepciones solo cuando creas que las disponibles en Python no satisfacen tus necesidades específicas

Optimización

  • Regresa a tu código algún tiempo después y revísalo en busca de mejoras, posibles errores y oportunidades de optimización, pero ojo, no te obsesiones con la optimización, este afán puede romper tu código y hacerte perder horas de tu tiempo en vano

  • Antes de pensar en optimizar tu código, asegúrate de que has logrado que funcione correctamente, esto es lo más importante

  • Considera usar un generador (generator expression) siempre que estés trabajando con una función que devuelva una secuencia o que trabajes en un ciclo

  • Minimiza el número de llamadas a funciones en tu código

  • Importa nombres específicos con la sentencia from module import attribute, esto incluye el nombre del atributo en tu espacio de nombres en tiempo de importación y mejora el desempeño en tiempo de ejecución

Seguridad

  • Valida siempre los datos de entrada suministrados por el usuario antes de realizar cualquier operación con ellos

  • Nunca manejes/transmitas datos sensibles del usuario en forma de texto plano u otra forma no segura

  • Desarrolla un conjunto consistente de pruebas para tu código que te garanticen que todos funciona tal y como debería. Corre estas pruebas sistemáticamente

  • Cuando emplees código de terceros, asegúrate de que ha sido ampliamente probado y que funciona correctamente, y que además, mantiene un desarrollo activo

  • Mantén todo el código de terceros actualizado siempre que sea posible

  • Como de seguro no tendrás el tiempo y/o la habilidad de escribir código perfecto, concéntrate en los fragmentos de tu código que se encargan de recibir y procesar información del exterior, no solo del usuario, sino también de archivos, de sitios web, de otras aplicaciones, etc.

  • Si pretendes incluir extensiones escritas en C/C++ en tus proyectos, sé cuidadoso con el manejo de memoria y otras vulnerabilidades clásicas de estos lenguajes

  • Evita por todos los medios que tus aplicaciones requieran correr con privilegios de administración y si es imprescindible hacerlo, minimiza el tiempo de empleo de estos privilegios. Recuerda que esto puede comprometer la seguridad del sistema completo

Programación Orientada a Objetos

  • Aprende y plantéate siempre emplear la Programación Orientada a Objetos (OOP por sus siglas en Inglés), esto mejorará la mantenibilidad y la extensibilidad de tu código, y te ahorrará mucho tiempo de desarrollo y de depuración de errores (debugging)

  • Evita la herencia múltiple (multiple inheritance): Puede no funcionar como esperas

  • Emplea la técnica del Duck Typing para evitar el uso de la herencia cuando sea posible

  • Favorece la Composición en lugar de la Herencia, la primera es mucho más flexible y controlable

  • Favorece el Polimorfismo en lugar de la comprobación de tipos

  • Aplica el principio Open/Close, procurando que tu código quede abierto a la extensión y cerrado a la modificación

  • El uso de la función incluida super() debe ser consistente, es decir, en una jerarquía de clases, super() debe ser usada en todos o en ningún lugar. Mezclar super() y la llamada clásica es una práctica confusa

  • No mezcles old-style y new-style clases: tener un código base con ambos estilos de clases resulta en un comportamiento MRO (Method Resolution Order) variable

  • Aprende patrones de diseño orientado a objetos y empléalos para mejorar la mantenibilidad y el diseño de tu código

  • Emplea coherentemente las convenciones de nombrado: self para identificar al objeto concreto en la definición de clases, cls para identificar la clase en los métodos de clase, guión bajo al inicio del nombre de atributos privados y doble guión bajo para invocar el name mangling de Python y evitar la colisión de nombre en jerarquías de clases

  • No accedas a atributos o miembros de clases que hayan sido definidos como privados, desde fuera de la clase en cuestión

Bien, esto es todo por ahora, si este artículo te resultó interesante y/o útil, compártelo para que otros también puedan acceder a él. Déjanos tus comentarios y podremos mejorar nuestros contenidos.

Gracias de antemano,

lpozo

2 comentarios

    • yrh on 10 enero, 2018 at 9:05 pm

    Hola quiero iniciarme en la programación con Python y creo que este sitio es muy bueno. Ojalá lo mantengan actualizado y no muera como otros de la plataforma.

    1. Eres bienvenido. Nuestro objetivo es mantenerlo y que sirva a todos los que se inician o ya están usando Python.
      saludos,
      lpozo

Los comentarios han sido desactivados.