sábado, 13 de abril de 2013

Segunda: «Apply Functional Programming Principles»

En su esencia este segundo aspecto, consiste básicamente en comprender y convertir en herramienta la programación funcional en el proceso de análisis y diseño de algoritmos. Además, desde mi consideración, así como resultan útiles y prácticos todos los principios de diseño orientados a objetos, los principios de la programación funcional son sumamente relevantes a la hora de escribir un algoritmo para alcanzar propiedades deseables que garanticen un código óptimo, corto y preciso.

Edward Garson, presenta en 97 Things Every Programmer Should Know recomendaciones que deberían ser consideradas por los programadores que deseen escribir código legible, funcional, extendible, etc. Entre los puntos que se tratan en Apply Functional Programming Principles se tratan los siguientes:

  1. Programación multinúcleo:

    Procesamiento multi-núcleo
    [Fuente: http://www.techmissile.com/]

    Gracias a las capacidades de procesamiento simultáneo de los microprocesadores modernos, la programación funcional se ve fortalecida al permitirse dividir un problema en distintas partes independientes que es posible asignar a los núcleos o hilos de ejecución.

    Lo anterior representa una oportunidad para la escritura de algoritmos eficientes en consumo de tiempo de procesador, debido a las bondades que ofrece el multiprocesamiento llevado por los cores (núcleos) integrantes.

    Recomendaciones para alcanzar paralelismo en una aplicación:

    Aunque el sistema operativo puede hacer un buen trabajo para explotar los recursos físicos del sistema, como permitir la ejecución de diferentes procesos de sistema y/o de aplicaciones en los diferentes cores de que disponga el chip principal; también resulta relevante la participación del programador en el diseño de algoritmos que incluyan estas variantes para aumentar en la mayor medida el aprovechamiento de los N cores de la arquitectura:

    - Incrementar el número de threads por procesos, o
    - Incrementar el número de procesos que se ejecutan en paralelo, o finalmente
    - Realizar ambos incrementos.
  2. Transparencia funcional:

    Esta es una de las propiedades más deseables para un programa diseñado a partir del enfoque funcional. A continuación, explico desde mi perspectiva el significado de esta propiedad, e introduzco unos ejemplos sencillos.

    2.1 Definición: «An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program (in other words, yielding a program that has the same effects and output on the same input).»[Wikipedia: Referential transparency] Lo que nos está dando a entender esta definición es que para que una expresión o función posea transparencia referencial debe generar los mismos resultados independiente del lugar que sea invocada, o cuándo sea invocada. Adicionalmente, se debe considerar los datos de entrada y salida, que necesariamente deben ser los mismos bajo las dos condiciones anteriores.

    2.2 Ejemplos

    Ejemplo 2.2.1:



    Obsérvese que en la expresión hay dos subexpressiones equivalentes: (5*2).  Hay que destacar, como ocurre en la definición, que la función o expresión siempre generará el mismo valor sin tener en cuanto el lugar donde sea invocada.

    Ejemplo 2.2.2:

    Si tenemos f() + f() vemos que es equivalente a 2 * f().

    Volviendo a la equivalencia: f() + f() = 2 * f() es correcto apuntar que
    f() se trata de una función que posee transparencia referencial. En el contraejemplo 2.3.1 se puede ver como en programación, a diferencia en matemáticas, la transparencia referencial no se cumple.

    Resulta evidente que al hacer: f() + f() obtenemos 6 + 7 = 13 y 2 * f() = 12. Al contraejemplo, o caso contrario de la transparencia referencial, se le conoce como opacidad referencial.

  3. Mitigación de variables mutables

    A través de la visiblidad de la semántica (Semantics visibility) [Definición: La Visibilidad de la semántica está relacionado con los principios de la programación orientada a objetos, y consiste en comprender el alcance o ámbito de las variables de clase, de métodos, namespaces, módulos, etc.] En muchos lenguajes de programación (v.gr.: C#, Java, C++, Objective-C, etc) existen elementos de que definien la visibilidad de una variable: protected, public, private, default, package, y otros.

    La comprensión y uso de los elementos de visibilidad, facilita o ayuda a mitigar el efecto insidioso de las variables mutables.
    Conceptualmente, en eso consiste el proceso de establecer la visibilidad de la semántica; y como fin propio de este proceso el de mitigar o remover definitivamente el problema inherente de las variables mutables.

    Este principio a pesar de que hace un buen trabajo para mitigar los problemas relacionados con las variables mutables, es contrario a lo que dictamina la interacción implícita de la programación orientada objetos: donde el intercambio de mensajes entre objetos integrantes del mundo del problema, promueve un diseño donde la mutabilidad es un efecto inherente: el cambio de estado de un objeto es prueba evidente.
  4. Otros enfoques

    En Mock Objects, Not Objects se aprecia un enfoque donde la prueba o abstracción de un objeto del mundo del problema se realiza de manera aislada, lo cual permite deshacerce de la mutabilidad no necesaria generada entre los objetos que interactúan con el intercambio de mensajes para cumplir con un objetivo específico.

    Más acerca de Mock Objects y Test-Driven Development y Need-Driven Development (inglés).
  5. Conclusiones

    Así como la programación orientada objetos cuenta con principios de diseño, la programación funcional está fundamentada por principios (como los tratados en este artículo) que fomentan la creación de programas más consistentes, completos y optimizables. La programación multinúcleo, la transparencia referencial, mitigación de variables mutables, han sido considerados y resumidos en este artículo a través de la definición, ejemplificación y demostraciones.
  6. Referencias