Capítulo 1. ¿Qué es un buen código? ¿Qué es un buen código?

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Este libro pretende ayudarte a escribir mejor código. Pero primero, ¿qué hace que un código sea "bueno"? Hay varias formas de pensar en ello: el mejor código podría ser el que se ejecuta más rápido. O podría ser el más fácil de leer. Otra posible definición es que un buen código es fácil de mantener. Es decir, si el proyecto cambia, debería ser fácil volver al código y cambiarlo para reflejar los nuevos requisitos. Los requisitos de tu código cambiarán con frecuencia debido a actualizaciones del problema empresarial que estás resolviendo, nuevas direcciones de investigación o actualizaciones en otras partes de la base de código.

Además, tu código no debe ser complejo, y no debe romperse si recibe una entrada inesperada. Debería ser fácil añadir una nueva función sencilla a tu código; si esto es difícil, sugiere que tu código no está bien escrito. En este capítulo, presentaré aspectos de un buen código y mostraré ejemplos de cada uno de ellos. Los dividiré en cinco categorías: simplicidad, modularidad, legibilidad, rendimiento y robustez.

Por qué es importante un buen código

Un buen código es especialmente importante cuando tu código de ciencia de datos se integra con un sistema mayor. Puede tratarse de poner en producción un modelo de aprendizaje automático, escribir paquetes para una distribución más amplia o crear herramientas para otros científicos de datos. Es más útil para bases de código más grandes que se ejecutarán repetidamente. A medida que tu proyecto crezca en tamaño y complejidad, aumentará el valor de un buen código.

A veces, el código que escribas será único, un prototipo que hay que montar hoy para una demostración mañana. Y si realmente vas a ejecutar el código sólo una vez, entonces no pierdas el tiempo haciéndolo bonito: escribe simplemente un código que haga el trabajo para el que se necesita. Pero, según mi experiencia, incluso el código que escribes para una demostración puntual casi siempre se ejecuta de nuevo o se reutiliza para otro fin. Te animo a que te tomes el tiempo de volver a tu código cuando haya pasado la urgencia y lo pongas en orden para utilizarlo en el futuro.

Un buen código también es más fácil de mantener. Existe un fenómeno conocido como "bit-rot": la necesidad de actualizar el código que no se ha utilizado en algún tiempo. Esto ocurre porque las cosas de las que depende tu código también cambian (por ejemplo, las bibliotecas de terceros o incluso el sistema operativo que utilizas). Si vuelves a un código que no has utilizado durante un tiempo, probablemente tendrás que hacer algún trabajo para modernizarlo. Esto es mucho más fácil si tu código está bien estructurado y documentado.

Nota

La deuda técnica (a menudo abreviada como deuda tecnológica) es un término de uso común para el trabajo aplazado resultante de cuando el código se escribe rápidamente en lugar de correctamente. La deuda técnica puede adoptar la forma de falta de documentación, código mal estructurado, variables mal nombradas o cualquier otro recorte. Esto hace que el código sea más difícil de mantener o refactorizar, y es probable que pases más tiempo en el futuro corrigiendo errores del que habrías pasado escribiendo bien el código en primer lugar. Dicho esto, la deuda tecnológica es a menudo necesaria debido a los plazos y presupuestos de la empresa. No siempre tienes tiempo para pulir tu código.

Adaptarse a las necesidades cambiantes

Escribir código no es como construir un puente, donde el diseño se elabora minuciosamente, se fijan los planos y luego se procede a la construcción. La única constante al escribir código, para un proyecto de ciencia de datos o para cualquier otra cosa, es que debes esperar que las cosas cambien a medida que trabajas en un proyecto. Estos cambios pueden ser el resultado de tus descubrimientos a través de tu proceso de investigación, de cambios en los requisitos empresariales o de innovaciones que quieras incluir en el proyecto. Un buen código puede adaptarse fácilmente para funcionar bien con estos cambios.

Esta adaptabilidad se hace más importante a medida que crece tu base de código. Con un único script pequeño, hacer cambios es sencillo. Pero a medida que el proyecto crece y se divide en varios scripts o cuadernos que dependen unos de otros, puede resultar más complejo y difícil hacer cambios. Unas buenas prácticas desde el principio facilitarán la modificación del código en un proyecto mayor.

La ciencia de datos sigue siendo un campo relativamente nuevo, pero los equipos de ciencia de datos están empezando a encontrarse con situaciones en las que llevan varios años trabajando en la misma base de código, y el código ha sido trabajado por muchas personas, algunas de las cuales pueden haber abandonado la empresa. En esta situación, en la que un proyecto pasa de una persona a otra, la calidad del código adquiere una importancia aún mayor. Es mucho más fácil retomar el trabajo de otra persona si está bien documentado y es fácil de leer.

La ingeniería de software como disciplina lleva décadas enfrentándose a requisitos cambiantes y a una complejidad creciente. Ha desarrollado una serie de estrategias útiles que tú, como científico de datos, puedes tomar prestadas y aprovechar. Si te pones a investigar, es posible que veas referencias a "código limpio", del libro homónimo de Robert C. Martin, o siglas como SOLID.

Como ya he mencionado, en este capítulo he decidido dividir estos principios en cinco características del buen código: simplicidad, modularidad, legibilidad, rendimiento y robustez. Describiré cada una de ellas en detalle en el resto del capítulo.

Simplicidad

Lo simple es mejor que lo complejo.

Tim Peters, El Zen de Python

Si estás trabajando en un proyecto pequeño, tal vez un cuaderno de visualización de datos o un breve script de manipulación de datos, puedes mantener en tu mente todos los detalles a la vez. Pero a medida que tu proyecto crece y se hace más complejo, esto deja de ser factible. Puedes tener en la cabeza los pasos de entrenamiento de tu modelo de aprendizaje automático, pero no la canalización de los datos de entrada ni el proceso de implementación del modelo.

La complejidad dificulta la modificación del código cuando cambian tus requisitos, y puede definirse del siguiente modo:

La complejidad es todo aquello relacionado con la estructura de un sistema que dificulta su comprensión y modificación.

John K. Ousterhout, Una filosofía del diseño de software

No es una definición precisa, pero con la experiencia te harás una idea de cuándo un sistema se vuelve más complejo. Una forma de pensar en ello es que cuando haces un cambio, rompe algo no relacionado de forma inesperada. Por ejemplo, puedes entrenar un modelo de aprendizaje automático en datos de reseñas de clientes para extraer el artículo que el cliente compró utilizando técnicas de procesamiento del lenguaje natural (PLN). Tienes un paso de preprocesamiento independiente que trunca la reseña a 512 caracteres. Pero cuando implementas el modelo, olvidas añadir el paso de preprocesamiento al código de inferencia. De repente, tu modelo arroja errores porque los datos de entrada superan los 512 caracteres. Este sistema está empezando a ser difícil de razonar y se está volviendo complejo.

Cuando hablo de complejidad en el código, ésta suele ser accidental y diferente de la complejidad esencial de un proyecto. Tu proyecto de aprendizaje automático puede ser complejo porque quieres probar muchos tipos diferentes de modelos y muchas combinaciones diferentes de características para ver cuál funciona mejor. Tu análisis puede ser complejo porque los datos que utilizas tienen muchos parámetros diferentes interdependientes. Ninguno de ellos puede simplificarse; la complejidad es sólo una parte del proyecto. En cambio, la complejidad accidental es cuando no estás seguro de qué función dentro de tu código necesitas cambiar para conseguir alguna acción.

Sin embargo, hay herramientas que puedes utilizar para ayudar a disminuir la complejidad de tu código. Hacerlo todo un poco más sencillo a medida que avanzas tiene enormes beneficios cuando el proyecto se hace grande. En la siguiente sección, describiré cómo mantener tu código simple evitando la repetición. Luego hablaré de cómo mantener tu código conciso. También puedes evitar que tu código se vuelva complejo dividiéndolo en piezas reutilizables, como describiré en "Modularidad".

No te repitas (DRY)

Uno de los principios más importantes a la hora de escribir un buen código es que la información no debe repetirse. Todo el conocimiento debe tener una única representación en el código. Si la información se repite en varios lugares, y esa información necesita actualizarse debido a requisitos cambiantes, entonces un cambio significa muchas actualizaciones. Tendrías que recordar todos los lugares en los que hay que actualizar esa información. Esto es difícil de hacer y aumenta la complejidad del código. Además, la duplicación aumenta las posibilidades de que se produzcan errores, y un código más largo requiere más tiempo para leerlo y comprenderlo.

También aumenta el esfuerzo mental cuando ves dos trozos de código que son muy parecidos pero no duplicados exactos. Es difícil saber si los dos trozos de código están haciendo lo mismo o algo diferente.

He aquí un ejemplo sencillo: quieres abrir tres archivos CSV, leerlos en un DataFrame de pandas , hacer algún procesamiento y devolver cada DataFrame. Los datos de este ejemplo proceden de los Objetivos de Desarrollo Sostenible (ODS) de la ONU, y utilizaré datos de este sitio a lo largo de todo el libro. Puedes encontrar más detalles sobre estos datos en "Datos en este libro". El código y los archivos CSV están disponibles en el repositorio GitHub de este libro.

Para una primera pasada, podrías hacer algo así:

import pandas as pd

df = pd.read_csv("sdg_literacy_rate.csv")
df = df.drop(["Series Name", "Series Code", "Country Code"], axis=1)
df = df.set_index("Country Name").transpose()

df2 = pd.read_csv("sdg_electricity_data.csv")
df2 = df2.drop(["Series Name", "Series Code", "Country Code"], axis=1)
df2 = df2.set_index("Country Name").transpose()

df3 = pd.read_csv("sdg_urban_population.csv")
df3 = df3.drop(["Series Name", "Series Code", "Country Code"], axis=1)
df3 = df3.set_index("Country Name").transpose()

Pero esto es innecesariamente prolijo y repetitivo. Una forma mejor de conseguir el mismo resultado sería poner el código repetido dentro de un bucle for. Si esto es algo que vas a utilizar repetidamente, puedes poner el código dentro de una función, como ésta:

def process_sdg_data(csv_file, columns_to_drop):
    df = pd.read_csv(csv_file)
    df = df.drop(columns_to_drop, axis=1)
    df = df.set_index("Country Name").transpose()
    return df

Otros casos más sutiles pueden dar lugar a la duplicación de código. He aquí algunos ejemplos:

  • Puede que te encuentres utilizando código muy similar en varios proyectos sin darte cuenta, por ejemplo, código de procesamiento de datos. Separar el código de procesamiento para que pueda aceptar datos ligeramente variables, en lugar de aceptar rígidamente sólo un tipo exacto de datos, podría ayudarte a evitar esta duplicación.

  • Varias personas que trabajan en proyectos similares pueden escribir un código parecido, sobre todo si no se comunican en qué están trabajando. Facilitar el uso del código a otras personas y proporcionar una buena documentación ayudará a reducir este tipo de duplicación.

  • Los comentarios y la documentación también pueden ser una forma de duplicación. El mismo conocimiento está representado en el código y en la documentación que lo describe. No escribas comentarios que describan exactamente lo que hace el código; en lugar de eso, utilízalos para añadir conocimientos. Describiré esto con más detalle en el capítulo 9.

Es muy importante tener en cuenta el principio DRY a la hora de escribir un buen código. Parece trivial, pero evitar la repetición significa que tu código debe ser modular y legible. Trataré estos conceptos más adelante en este capítulo.

Evita el Código Verborreico

A veces, puedes simplificar tu código teniendo menos líneas de código. Esto significa menos oportunidades de errores y menos código para que otra persona lo lea y lo entienda. Sin embargo, a menudo hay un equilibrio entre hacer tu código más corto y hacerlo menos legible. Hablaré de cómo garantizar que tu código sea legible en "Legibilidad".

Te recomiendo que intentes que tu código sea conciso pero legible. Para ello, evita hacer cosas que alarguen innecesariamente tu código, como escribir tus propias funciones en lugar de utilizar funciones incorporadas o utilizar variables temporales innecesarias. También debes evitar las repeticiones, como se describe en la sección anterior.

Aquí tienes un ejemplo de variable temporal innecesaria:

i = float(i)
image_vector.append(i/255.0)

Esto puede simplificarse a lo siguiente:

image_vector.append(float(i)/255)

Por supuesto, exprimir tu código en menos líneas tiene sus inconvenientes. Si ocurren muchas cosas en una sola línea, puede ser muy difícil que otra persona entienda lo que ocurre. Esto significa que es más difícil que otra persona trabaje en tu código, y esto podría dar lugar a más errores. En caso de duda, te recomiendo que mantengas tu código legible, aunque eso signifique utilizar unas cuantas líneas más.

Modularidad

Escribir código modular es el arte de dividir un gran sistema en componentes más pequeños. El código modular tiene varias ventajas importantes: facilita la lectura del código, es más fácil localizar de dónde viene un problema y es más fácil reutilizar el código en tu próximo proyecto. También es más fácil probar el código dividido en componentes más pequeños, de lo que hablo en el Capítulo 7.

Pero, ¿cómo abordar una tarea de gran envergadura? Podrías simplemente escribir un gran script para hacerlo todo, y esto podría estar bien al principio de un proyecto pequeño. Pero los proyectos más grandes deben dividirse en trozos más pequeños. Para ello, tendrás que pensar en el futuro del proyecto con la mayor antelación posible y tratar de anticipar lo que hará el sistema en su conjunto y cuáles podrían ser los lugares sensatos para dividirlo. Trataré este proceso de planificación con mucho más detalle en el Capítulo 8.

Escribir código modular en es un proceso continuo, y no es algo que vayas a hacer completamente bien desde el principio, aunque tengas las mejores intenciones. Debes esperar cambiar tu código a medida que evolucione tu proyecto. Cubriré técnicas que te ayudarán a mejorar tu código en "Refactorización".

Puedes dividir un gran proyecto de ciencia de datos en una serie de pasos pensando en él como en un diagrama de flujo, como se muestra en la Figura 1-1. Primero extraes algunos datos, luego los exploras, luego los limpias y luego los visualizas.

Breaking down a data science project
Figura 1-1. Desglosar un gran proyecto de ciencia de datos en pasos discretos

Al principio, podría tratarse de una serie de cuadernos Jupyter . Al final de cada uno, podrías guardar los datos en un archivo, y luego cargarlos de nuevo en el siguiente cuaderno. A medida que tu proyecto madure, podrías darte cuenta de que quieres realizar un análisis similar repetidamente. Entonces, puedes decidir cuál debe ser el esqueleto del sistema: tal vez haya una función que extraiga los datos y luego los pase a la función que los limpie. El ejemplo siguiente utiliza la sentencia pass para crear una función vacía. Esto garantiza que cuando llames a esta función, no provocará un error antes de escribirse.

Por ejemplo, podría ser el esqueleto de un sistema que carga unos datos, los limpia recortándolos a una longitud máxima y los traza con unos parámetros de trazado:

def load_data(csv_file):
    pass

def clean_data(input_data, max_length):
    pass

def plot_data(clean_data, x_axis_limit, line_width):
    pass

Al crear este marco, has descompuesto el sistema en componentes individuales, y sabes lo que cada uno de esos componentes debe aceptar como entrada. Puedes hacer lo mismo a nivel de un archivo Python. Utilizar un paradigma de programación como la programación orientada a objetos o la programación funcional puede ayudarte a averiguar cómo dividir tu código en funciones y clases (más sobre esto en el Capítulo 4). Independientemente de cómo dividas tu sistema, cada uno de los componentes debe ser lo más independiente y autónomo posible, de modo que cambiar un componente no modifique otro. Hablaré del código modular con más detalle en el Capítulo 8.

Legibilidad

...el código se lee mucho más a menudo de lo que se escribe...

PEP8

Cuando escribes código, es importante que otras personas también puedan utilizarlo. Puede que pases a otro proyecto, o incluso a otro trabajo. Si dejas un proyecto durante un tiempo y vuelves a él dentro de un mes, seis meses o incluso seis años, ¿seguirás entendiendo lo que hacías en el momento en que lo escribiste? Escribiste ese código por una razón, para una tarea que era importante, y hacer que tu código sea legible le dalongevidad.

Entre los métodos para hacer que tu código sea más legible se incluyen la adhesión a las normas y convenciones de tu lenguaje de programación, la elección de buenos nombres, la eliminación del código no utilizado y la redacción de documentación para tu código. Resulta tentador tratar estos métodos a posteriori y concentrarse más en la funcionalidad del código, pero si prestas atención a que tu código sea legible en el momento de escribirlo, escribirás código menos complejo y más fácil de mantener. Presentaré estos métodos en esta sección, y los trataré con mucho más detalle en los Capítulos 6 y 9.

Normas y Convenios

Las normas de codificación y el formato pueden parecer los temas menos apasionantes que trataré en este libro, pero son sorprendentemente importantes. Hay muchas formas de expresar el mismo código, incluso hasta en pequeños detalles como el espaciado alrededor del signo + al sumar dos enteros. Las normas de codificación se han desarrollado para fomentar la coherencia entre todos los que escriben código Python, y el objetivo es que el código resulte familiar aunque lo haya escrito otra persona. Esto ayuda a reducir el esfuerzo que supone leer y editar código que no has escrito tú mismo. Trataré este tema con más detalle en el Capítulo 6.

Python es intrínsecamente muy legible en comparación con muchos lenguajes de programación; ceñirse a una norma de codificación hará que sea aún más fácil de leer. La principal norma de codificación para Python es PEP8 (Python Enhancement Proposal 8), establecida en 2001. El ejemplo siguiente muestra un extracto de PEP8, y puedes ver que hay convenciones incluso para los detalles más pequeños de tu código. Guías de estilo como la Python Style Guide de Google complementan la PEP8 con orientaciones e información adicionales.

Aquí tienes un ejemplo de los detalles que especifica PEP8, mostrando las formas correctas e incorrectas de dar formato a los espacios entre paréntesis:

# Correct:
spam(ham[1], {eggs: 2})

# Wrong:
spam( ham[ 1 ], { eggs: 2 } )

Afortunadamente, hay muchas formas automatizadas de comprobar que tu código se ajusta a las normas de codificación, lo que te ahorra el aburrido trabajo de repasar y comprobar que cada signo + tiene un solo espacio alrededor. Linters como Flake8 y Pylint resaltan los lugares en los que tu código no se ajusta a PEP8. Los formateadores automáticos como Black actualizarán tu código automáticamente para que se ajuste a las normas de codificación. Veré cómo utilizarlos en el Capítulo 6.

Nombres

Al escribir código para la ciencia de datos, tendrás que elegir nombres en muchos puntos: nombres de funciones, variables, proyectos e incluso herramientas enteras. Tu elección de nombres afecta a la facilidad de trabajar en tu código. Si eliges nombres que no son descriptivos o precisos, tendrás que guardar su verdadero significado en tu cabeza, lo que aumentará la carga cognitiva de tu código. Por ejemplo, podrías importar la biblioteca pandas como p y nombrar tus variables x y f, como se muestra aquí:

import pandas as p

x = p.read_csv(f, index_col=0)

Este código se ejecuta correctamente, sin errores. Pero aquí tienes un código de ejemplo que es más fácil de leer porque los nombres de las variables son más informativos y siguenlas convenciones estándar:

import pandas as pd

df = pd.read_csv(input_file, index_col=0)

Hay más detalles sobre cómo escribir buenos nombres en el capítulo 9.

Limpieza

Otra forma de hacer que tu código sea más legible es limpiarlo después de haber terminado de crear una función. Una vez que la hayas probado y estés seguro de que funciona, debes eliminar el código que haya sido comentado y suprimir las llamadas innecesarias a la función print() que hayas podido utilizar como una forma sencilla de depuración. Es muy confuso ver secciones comentadas en el código de otra persona.

Cuando ves secciones de código desordenadas, se envía el mensaje de que la mala calidad del código es aceptable en un proyecto. Esto significa que hay menos incentivos para que otros colaboradores escriban buen código. El código desordenado también puede ser copiado y adaptado en otras partes del proyecto. Esto se conoce como la Teoría de la Ventana Rota. Establecer normas estrictas en un proyecto anima a todos los que trabajan en él a escribir buen código.

Si quieres mejorar la calidad de tu código, puedes decidir refactorizarlo. Refactorizar significa cambiar el código sin cambiar su comportamiento general. Puede que se te hayan ocurrido formas de que tu código sea más eficiente, o que hayas pensado en una forma mejor de estructurarlo que permita a tu compañero de equipo utilizar partes del código en otro proyecto. Las pruebas son esenciales en este proceso, porque comprobarán que tu nuevo código sigue teniendo el mismo comportamiento general. Trataré la refactorización en "Refactorización".

Documentación

La documentación también ayuda a otras personas a leer tu código. El código puede documentarse con múltiples niveles de detalle, empezando por simples comentarios en línea, pasando pordocstrings que explican toda una función, pasando por la página README que aparece en un repositorio de GitHub e incluso tutoriales para enseñar a los usuarios a utilizar un paquete. Todos estos aspectos de la documentación ayudan a explicar a otras personas cómo utilizar tu código. Incluso podrían explicarte tu código en el futuro (¡un público muy importante!). Si quieres que otras personas utilicen tu código, debes ponérselo fácil escribiendo una buena documentación.

Escribir una gran documentación es una cosa, pero también hay que mantenerla actualizada. La documentación que hace referencia a una versión obsoleta del código es peor que la ausencia total de documentación. Causará una confusión que llevará más tiempo resolver. Hablaré de todas las formas de documentación con mucho más detalle en el Capítulo 9.

Rendimiento

Un buen código debe ser eficaz. Esto se mide tanto en el tiempo de ejecución del código como en el uso de memoria. Cuando tomas decisiones sobre cómo escribir tu código, es útil saber qué estructuras de datos y algoritmos son más eficientes. Es muy bueno saber cuándo estás haciendo cosas que ralentizarán significativamente tu código, especialmente cuando hay una alternativa fácilmente disponible. También debes ser consciente de qué partes de tu código tardan mucho.

El rendimiento es especialmente importante cuando escribes código de producción que va a ser llamado cada vez que un usuario realice una acción determinada. Si tu base de usuarios crece, o tu proyecto tiene éxito, tu código podría ser llamado millones de veces cada día. En este caso, incluso pequeñas mejoras en tu código pueden ahorrar muchas horas a tus usuarios. No querrás que tu código sea el punto lento de una gran aplicación. Te explicaré cómo medir el rendimiento de tu código en el Capítulo 2, y te mostraré cómo elegir las mejores estructuras de datos para optimizar el rendimiento de tu código en el Capítulo 3.

Robustez

Un buen código también debe ser robusto. Con esto quiero decir que debe ser reproducible: debes poder ejecutar tu código de principio a fin sin que falle. Tu código también debe ser capaz de responder con elegancia si las entradas del sistema cambian inesperadamente. En lugar de lanzar un error inesperado que podría provocar el fallo de un sistema mayor, tu código debe estar diseñado para responder a los cambios. Tu código puede hacerse más robusto gestionando adecuadamente los errores, registrando lo ocurrido y escribiendo buenas pruebas.

Errores y registro

Un código robusto no debería comportarse de forma inesperada cuando recibe una entrada incorrecta. Debes elegir si quieres que tu código se bloquee ante una entrada inesperada, o manejar ese error y hacer algo al respecto. Por ejemplo, si a tu archivo CSV le faltan la mitad de las filas de datos que esperabas, ¿quieres que tu código devuelva un error o que continúe evaluando sólo la mitad de los datos? Debes hacer una elección explícita para dar una alerta de que algo no es como debería ser, manejar el error o fallar silenciosamente. Trataré los errores con más detalle en el Capítulo 5.

Si se gestiona el error, puede seguir siendo importante registrar que se ha producido para que no falle silenciosamente, si no es eso lo que quieres que ocurra. Éste es un caso de uso del registro; exploraré otros usos del registro en el Capítulo 5.

Prueba

Las pruebas son fundamentales para escribir código robusto. La ingeniería de software utiliza dos tipos principales: las pruebas de usuario, en las que una persona utiliza un programa para confirmar que funciona correctamente, y las pruebas automatizadas. Un método habitual de prueba automatizada consiste en enviar una entrada de ejemplo a un fragmento de código y confirmar que la salida es la esperada. En este libro sólo trataré las pruebas automatizadas.

Las pruebas son necesarias porque aunque tu código funcione perfectamente en tu máquina, eso no significa que vaya a funcionar en la máquina de otra persona, ni siquiera en tu propia máquina en el futuro. Los datos cambian, las bibliotecas se actualizan, y máquinas diferentes ejecutan versiones diferentes de Python. Si otra persona quiere utilizar tu código en su máquina, puede ejecutar tus pruebas para confirmar que funciona.

Hay varios tipos diferentes de pruebas. Las pruebas unitarias comprueban una única función, las pruebas de extremo a extremo comprueban todo un proyecto, y las pruebas de integración comprueban un trozo de código que contiene muchas funciones, pero que sigue siendo más pequeño que todo un proyecto. En el Capítulo 7 describiré en detalle las estrategias de pruebas y las bibliotecas. Pero una buena estrategia para empezar, si tienes una gran base de código sin pruebas, es escribir una prueba cuando algo se rompe para asegurarte de que no vuelva a ocurrir lo mismo.

Puntos clave

Escribir un buen código te ayudará de muchas maneras: será más fácil que otras personas utilicen tu código; te ayudará a entender lo que estabas haciendo cuando vuelvas a tu trabajo seis meses después de haberlo tocado por última vez; y ayudará a que tu código se amplíe y se interconecte con un sistema mayor. Un buen código también te hará la vida mucho más fácil si necesitas añadir funciones a tu código que no estaban en el plan original del proyecto.

Si quieres leer más sobre los principios para escribir un buen código, te recomiendo estos libros:

  • El Programador Pragmático, Edición 20 Aniversario, de David Thomas y Andrew Hunt (Addison-Wesley Professional)

  • Una filosofía de la arquitectura del software, de John Ousterhout (Yaknyam Press)

En resumen, he aquí algunas formas de pensar sobre cómo escribir un buen código:

Simplicidad

Tu código debe evitar la repetición, la complejidad innecesaria y las líneas de código innecesarias.

Modularidad

Tu código debe descomponerse en funciones lógicas, con entradas y salidas bien definidas.

Legibilidad

Tu código debe seguir la norma PEP8 en cuanto a formato, contener nombres bien elegidos y estar bien documentado.

Rendimiento

Tu código no debe tardar innecesariamente en ejecutarse ni consumir más recursos de los disponibles.

Robustez

Tu código debe ser reproducible, emitir mensajes de error útiles y manejar entradas inesperadas sin fallar.

En el próximo capítulo, examinaré con más detalle un aspecto del buen código: el rendimiento.

Get Ingeniería de Software para Científicos de Datos now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.