Читать книгу Computación y programación funcional - Camilo Chacón Sartori - Страница 23

2.3 IMPLEMENTACIÓN

Оглавление

Cuando sabemos cómo resolver un problema computacional, entonces podemos buscar la forma de confrontarlo, haciendo uso claro de la tecnología más acorde en cuanto a nuestro tiempo y problema en cuestión. Es importante en esta fase no caer en el error clásico de forzar una tecnología para que resuelva todos los problemas que tengamos. Una cosa es que alguien tenga una afinidad hacia alguna (por ejemplo, Python) y otra es querer resolver todo con Python omitiendo cualquier otra tecnología (a saber, otro lenguaje de programación).

Cuando tratamos con la implementación lo que buscamos es crear un programa computacional. Es aquí donde debemos preocuparnos de aspectos que van al detalle del problema a tratar. Desde elegir correctamente la tecnología, pasando por la elección correcta del paradigma de programación, hasta cómo diseñar el código, por ejemplo: ¿qué estructura de datos o biblioteca podría usar? o ¿cuál es más conveniente, un lenguaje de programación tipado o no? Y si el problema es más complejo, pueden surgir preguntas de arquitectura de software: ¿cómo puedo diseñar el programa para que pueda aumentar la cantidad de datos que maneja en el tiempo sin producir cuellos de botella?, ¿cuáles serán los componentes del software y cómo se comunicarán entre ellos?, ¿cuáles serán las fases de despliegue de mi aplicación en la nube?, ¿cómo debo diseñar el software para que pueda soportar una carga de usuarios que aumentará en el tiempo?, etc.

La implementación no es simple, no se trata de eso. Sin embargo, lo que creemos es que muchas veces vamos directamente a la implementación cegados por la emoción de elegir las tecnologías, y olvidamos pensar cómo podríamos resolver el problema desde una visión mucho más abstracta, amplia y general (que para algunos problemas [los más complejos] suele ser lo importante). Pero también tenemos claro que para esto es necesaria la experiencia, la cual tiende a ser casi nula en desarrolladores novatos.

Una correcta implementación debe venir respaldada de un amplio conocimiento de múltiples herramientas y proyectos de software desarrollados previamente, para ver el bosque y no solo un árbol en particular. Así evitaremos el arrebato hacia la tecnología (aunque esto, lamentablemente, no siempre está asegurado). Con ello, nos aseguramos de reducir el margen de error que conlleva elegir tecnologías inadecuadas para el problema a solucionar.

Ahora definiremos algunos conceptos que son parte de la implementación.

Estructuras de datos. Una estructura de datos como tal es parte de una implementación, porque es una abstracción que permite organizar y manipular datos. Cada una de ellas tiene características para abordar distintos tipos de problemas computacionales de la manera más acorde y eficaz. Muchas veces están agrupadas por la «complejidad algorítmica», que es la forma de medir la eficacia de un algoritmo según los valores de entrada, ya sea por tiempo de ejecución o por espacio a utilizar (disco duro o memoria RAM).

La elección apropiada de las estructuras de datos puede marcar el éxito de un proyecto de software, no tan solo por temas de eficiencia, sino también por temas como la facilidad para expandir y ampliar el propio código. Si, por ejemplo, necesitamos acceder a la información de un cliente que tiene un identificador único, lo correcto sería usar una tabla hash para acceder directamente a su información y no, claro, usar una lista para encontrar ese identificador, ya que se debería recorrer toda la estructura según la cantidad de clientes que se tenga disponible (búsqueda lineal), lo cual es, por definición, ineficiente para ese problema.

Por eso es importante estudiar, analizar, experimentar y comparar las distintas estructuras de datos, para, así, evitar caer en errores como elegir la incorrecta estructura para un problema. (Por añadidura, debemos decir que las estructuras de datos se analizan en conjunto con el algoritmo a utilizar, pues un algoritmo puede estar construido con diversas estructuras de datos.)

En este libro dedicamos el capítulo 13 a diversas estructuras de datos que pueden ser utilizadas siguiendo un enfoque funcional.

Cada lenguaje de programación trae un conjunto de estructuras de datos estándar preestablecidas que nos facilitarán la implementación. Por ejemplo, algunas de ellas son: listas, cola, pila, grafos, árboles, tabla hash, entre otras.

Programa computacional. Un programa computacional existe cuando es ejecutado en un ordenador, es decir, necesita estar escrito en un lenguaje de programación. No es puramente una construcción abstracta sin experimentación (esto lo diferencia de algo escrito en el papel). El programa representa la parte final de la solución a un problema; es ahí donde comprobamos si nuestra solución funciona correctamente en un ambiente real y productivo.

Además, un programa es, a su vez, un proceso, si asumimos que un proceso es un programa que se está ejecutando en otro programa, a saber: un sistema operativo. (No obstante, este nombre podría variar según el sistema operativo que utilice.)

El sistema operativo le asigna al proceso (programa) un identificador único solo cuando se mantiene ejecutando (conocido como PID [process ID]), es decir, si cerramos nuestro programa y lo volvemos a abrir, el identificador cambiará. Al final, el sistema operativo es un programa sofisticado con múltiples componentes que asegura mantener un orden en todos los procesos que se ejecutan. Esto viene dado por la prioridad que este le haya asignado según los recursos disponibles del ordenador, por ejemplo: memoria RAM, espacio de disco y los núcleos libres del CPU.

Para ahondar en la pieza más importante dentro de las tecnologías de computación y que tiene un rol protagonista en la implementación, dedicaremos el siguiente capítulo a los lenguajes de programación.

_________________

6 Leslie Lamport es un ganador del Turing Award (equivalente al Nobel en ciencias de la computación, entregado por ACM en el 2013), por sus aportes a los sistemas concurrentes y distribuidos.

7 Invariante es el concepto fundamental en la verificación formal, nos permite comprobar si una expresión lógica mantiene su estado después de un conjunto de transformaciones.

8 https://www.microsoft.com/en-us/research/project/boogie-an-intermediate-verification-language [revisado en junio del 2020].

9 http://why3.lri.fr [revisado en junio del 2020].

10 https://learntla.com/introduction/ [revisado en junio del 2020].

11 https://coq.inria.fr/ [revisado en junio del 2020].

Computación y programación funcional

Подняться наверх