En programación informática , la programación orientada a funciones ( FOP ) o el desarrollo de software orientado a funciones ( FOSD ) es un paradigma de programación para la generación de programas en líneas de productos de software (SPL) y para el desarrollo incremental de programas.
Historia
FOSD surgió a partir de diseños basados en capas y niveles de abstracción en protocolos de red y sistemas de bases de datos extensibles a fines de la década de 1980. [1] Un programa era una pila de capas. Cada capa agregó funcionalidad a capas previamente compuestas y diferentes composiciones de capas produjeron diferentes programas. No es sorprendente que existiera la necesidad de un lenguaje compacto para expresar tales diseños. El álgebra elemental encajaba perfectamente: cada capa era una función (una transformación de programa ) que agregaba nuevo código a un programa existente para producir un nuevo programa, y el diseño de un programa se modelaba mediante una expresión, es decir, una composición de transformaciones (capas). La figura de la izquierda ilustra el apilamiento de las capas i, j y h (donde h está en la parte inferior e i está en la parte superior). Las notaciones algebraicas i (j (h)), i • j • h e i + j + h se han utilizado para expresar estos diseños.
Con el tiempo, las capas se equipararon a características, donde una característica es un incremento en la funcionalidad del programa. Se reconoció que el paradigma para el diseño y la generación de programas era una consecuencia de la optimización de consultas relacionales, donde los programas de evaluación de consultas se definían como expresiones de álgebra relacional y la optimización de consultas era la optimización de expresiones. [2] Una línea de productos de software es una familia de programas donde cada programa está definido por una composición única de características. Desde entonces, FOSD se ha convertido en el estudio de la modularidad de características, herramientas, análisis y técnicas de diseño para respaldar la generación de programas basados en características.
La segunda generación de investigación FOSD se centró en las interacciones de características, que se originaron en las telecomunicaciones. Más tarde, se acuñó el término programación orientada a funciones ; [3] este trabajo expuso interacciones entre capas. Las interacciones requieren que las características se adapten cuando se componen con otras características.
Una tercera generación de investigación se centró en el hecho de que cada programa tiene múltiples representaciones (por ejemplo, fuente, archivos MAKE, documentación, etc.) y agregar una característica a un programa debería elaborar cada una de sus representaciones para que todas sean consistentes. Además, algunas de las representaciones podrían generarse (o derivarse) de otras. En las secciones siguientes, se describen las matemáticas de las tres generaciones más recientes de FOSD, a saber, GenVoca , [1] AHEAD , [4] y FOMDD [5] [6] , y enlaces a líneas de productos que se han desarrollado utilizando herramientas de FOSD. están provistos. Además, cuatro resultados adicionales que se aplican a todas las generaciones de FOSD son: metamodelos FOSD , cubos programa FOSD , y las interacciones entre características FOSD.
GenVoca
GenVoca (un acrónimo de los nombres génesis y Avoca) [1] es un paradigma de composición para la definición de programas de líneas de productos. Los programas base son funciones 0-arias o transformaciones llamadas valores :
f - programa básico con función f h - programa básico con función h
y las características son funciones / transformaciones unarias que elaboran (modifican, extienden, refinan) un programa:
i + x - agrega la característica i al programa x j + x - agrega la función j al programa x
donde + denota la composición de la función. El diseño de un programa es una expresión con nombre, por ejemplo:
p 1 = j + f - el programa p 1 tiene características j y f p 2 = j + h - el programa p 2 tiene características j y h p 3 = i + j + h - el programa p 3 tiene las características i, j y h
Un modelo GenVoca de un dominio o línea de productos de software es una colección de programas y características base (consulte MetaModelos y Cubos de programas ). Los programas (expresiones) que se pueden crear definen una línea de productos. La optimización de expresiones es la optimización del diseño de programas y la evaluación de expresiones es la generación de programas .
- Nota: GenVoca se basa en el desarrollo gradual de programas: un proceso que enfatiza la simplicidad y la comprensibilidad del diseño, que son clave para la comprensión y la construcción automatizada de programas. Considere el programa p 3 anterior: comienza con el programa base h, luego se agrega la característica j (lea: la funcionalidad de la característica j se agrega al código base de h), y finalmente se agrega la característica i (lea: la funcionalidad de la característica i es agregado a la base de código de j • h).
- Nota: no todas las combinaciones de funciones son significativas. Los modelos de características (que pueden traducirse en fórmulas proposicionales) son representaciones gráficas que definen combinaciones legales de características. [7]
- Nota: Una formulación más reciente de GenVoca es simétrica : solo hay un programa base, 0 (el programa vacío), y todas las características son funciones unarias. Esto sugiere la interpretación de que GenVoca compone estructuras de programa por superposición , la idea de que las estructuras complejas se componen superponiendo estructuras más simples. [8] [9] Otra reformulación más de GenVoca es como un monoide : un modelo de GenVoca es un conjunto de características con una operación de composición (•); la composición es asociativa y hay un elemento de identidad (es decir, 1, la función de identidad). Aunque todas las composiciones son posibles, no todas son significativas. Esa es la razón de los modelos de funciones .
Las características de GenVoca se implementaron originalmente usando #ifdef feature ... #endif
técnicas de preprocesador de C ( ). Una técnica más avanzada, llamada capas mixtas , mostró la conexión de características con diseños basados en colaboración orientados a objetos.
ADELANTE
Las ecuaciones jerárquicas algebraicas para el diseño de aplicaciones ( AHEAD ) [4] generalizaron GenVoca de dos maneras. Primero reveló la estructura interna de los valores de GenVoca como tuplas. Cada programa tiene múltiples representaciones, como fuente, documentación, código de bytes y archivos MAKE. Un valor de GenVoca es una tupla de representaciones de programas. En una línea de productos de analizadores, por ejemplo, un analizador base f se define por su gramática g f , fuente Java s f y documentación d f . El analizador f está modelado por la tupla f = [g f , s f , d f ]. Cada representación de programa puede tener subrepresentaciones, y también pueden tener subrepresentaciones, de forma recursiva. En general, un valor de GenVoca es una tupla de tuplas anidadas que definen una jerarquía de representaciones para un programa en particular.
Ejemplo. Suponga que las representaciones de terminales son archivos. En AHEAD, la gramática g f corresponde a un solo archivo BNF, la fuente s f corresponde a una tupla de archivos Java [c 1 … c n ], y la documentación d f es una tupla de archivos HTML [h 1 … h k ]. Un valor de GenVoca (tuplas anidadas) se puede representar como un gráfico dirigido: el gráfico para el analizador f se muestra en la figura de la derecha. Las flechas denotan proyecciones, es decir, asignaciones de una tupla a uno de sus componentes. AHEAD implementa tuplas como directorios de archivos, por lo que f es un directorio que contiene el archivo g f y los subdirectorios s f y d f . De manera similar, el directorio s f contiene archivos c 1 … c n , y el directorio df contiene archivos h 1 … h k .
- Nota: Los archivos se pueden descomponer jerárquicamente aún más. Cada clase de Java se puede descomponer en una tupla de miembros y otras declaraciones de clase (por ejemplo, bloques de inicialización, etc.). La idea importante aquí es que las matemáticas de AHEAD son recursivas.
En segundo lugar, AHEAD expresa características como tuplas anidadas de funciones unarias llamadas deltas . Los deltas pueden ser refinamientos del programa (transformaciones que conservan la semántica), extensiones (transformaciones que extienden la semántica) o interacciones (transformaciones que alteran la semántica). Usamos el término neutral "delta" para representar todas estas posibilidades, ya que cada una ocurre en FOSD.
Para ilustrar, suponga que la característica j extiende una gramática por g j (se agregan nuevas reglas y tokens), extiende el código fuente pors j (se agregan nuevas clases y miembros y se modifican los métodos existentes), y extiende la documentación pord j . La tupla de deltas para la característica j está modelada por j = [g j ,s j ,d j ], que llamamos tupla delta . Los elementos de las tuplas delta pueden ser ellos mismos tuplas delta. Ejemplo:s j representa los cambios que se realizan en cada clase en s f por la característica j, es decir,s j = [c 1 …c n ]. Las representaciones de un programa se calculan de forma recursiva mediante la suma de vectores anidados. Las representaciones para el analizador sintáctico p 2 (cuya expresión GenVoca es j + f) son:
p 2 = j + f - expresión GenVoca = [g j , s j , d j ] + [g f , s f , d f ] - sustitución = [ g j + g f , s j + s f , d j + d f ] - componer tuplas por elementos
Es decir, la gramática de p 2 es la gramática base compuesta con su extensión (g j + g f ), la fuente de p 2 es la fuente base compuesta con su extensión (s j + s f ) y así sucesivamente. Como los elementos de las tuplas delta pueden ser ellos mismos tuplas delta, la composición se repite, por ejemplo,s j + s f = [c 1 …c n ] + [c 1 … c n ] = [c 1 + c 1 …c n + c n ]. Resumiendo, los valores de GenVoca son tuplas anidadas de artefactos de programa, y las características son tuplas delta anidadas, donde + las compone de forma recursiva mediante la adición de vectores. Esta es la esencia de AHEAD.
Las ideas presentadas anteriormente exponen concretamente dos principios de FOSD. El principio de uniformidad establece que todos los artefactos del programa se tratan y modifican de la misma manera. (Esto se evidencia por deltas para diferentes tipos de artefactos arriba). El principio de escalabilidad establece que todos los niveles de abstracciones se tratan de manera uniforme. (Esto da lugar al anidamiento jerárquico de tuplas arriba).
La implementación original de AHEAD es AHEAD Tool Suite y el lenguaje Jak, que exhibe los Principios de Uniformidad y Escalabilidad. Las herramientas de próxima generación incluyen CIDE [10] y FeatureHouse. [11]
FOMDD
El diseño basado en modelos orientado a características ( FOMDD ) [5] [6] combina las ideas de AHEAD con el diseño basado en modelos ( MDD ) (también conocido como Arquitectura basada en modelos ( MDA )). Las funciones AHEAD capturan la actualización sincronizada de los artefactos del programa cuando se agrega una función a un programa. Pero existen otras relaciones funcionales entre los artefactos del programa que expresan derivaciones. Por ejemplo, la relación entre una gramática g f y su fuente de analizador s f se define mediante una herramienta compilador-compilador, por ejemplo, javacc. De manera similar, la relación entre la fuente Java s f y su código de bytes b f está definida por el compilador javac. Un diagrama de desplazamiento expresa estas relaciones. Los objetos son representaciones de programas, las flechas hacia abajo son derivaciones y las flechas horizontales son deltas. La figura de la derecha muestra el diagrama de desplazamiento para el programa p 3 = i + j + h = [g 3 , s 3 , b 3 ].
Una propiedad fundamental de un diagrama de desplazamiento es que todas las rutas entre dos objetos son equivalentes. Por ejemplo, una forma de derivar el bytecode b 3 del analizador p 3 (objeto inferior derecho en la figura de la derecha) a partir de la gramática g h del analizador h (objeto superior izquierdo) es derivar el bytecode b hy refinar ab 3 , mientras que otra forma refina g h ag 3 , y luego deriva b 3 , donde + representa la composición delta y () es la función o aplicación de herramienta:
b 3 =b j + b i + javacc (javac (g h )) = javac (javacc ( g i + g j + g h ))
Existen posibles caminos para derivar el bytecode b 3 del analizador p 3 a partir de la gramática g h del analizador h. Cada ruta representa un metaprograma cuya ejecución genera el objeto objetivo (b 3 ) a partir del objeto inicial (g f ). Hay una optimización potencial: atravesar cada flecha de un diagrama de desplazamiento tiene un costo. La ruta más barata (es decir, la más corta) entre dos objetos en un diagrama de desplazamiento es una geodésica , que representa el metaprograma más eficiente que produce el objeto de destino a partir de un objeto dado.
- Nota: Una "métrica de costos" no tiene por qué ser un valor monetario; el costo puede medirse en tiempo de producción, requisitos máximos o totales de memoria, consumo de energía o alguna métrica informal como "facilidad de explicación", o una combinación de lo anterior (por ejemplo, optimización multiobjetivo ). La idea de una geodésica es general y debe entenderse y apreciarse desde este contexto más general.
- Nota: Es posible que haya m objetos iniciales y n objetos finales en una geodésica; cuando m = 1 yn> 1, este es el problema del árbol de Steiner dirigido , que es NP-difícil.
Los diagramas de desplazamiento son importantes por al menos dos razones: (1) existe la posibilidad de optimizar la generación de artefactos (por ejemplo, geodésicas) y (2) especifican diferentes formas de construir un objeto objetivo a partir de un objeto inicial. [5] [12] Una ruta a través de un diagrama corresponde a una cadena de herramientas: para que un modelo FOMDD sea consistente, debe probarse (o demostrarse a través de pruebas) que todas las cadenas de herramientas que mapean un objeto a otro de hecho producen resultados equivalentes . Si este no es el caso, entonces hay un error en una o más de las herramientas o el modelo FOMDD es incorrecto.
- Nota: las ideas anteriores se inspiraron en la teoría de categorías . [5] [6]
Aplicaciones
- Protocolos de red
- Sistemas de bases de datos extensibles
- Estructuras de datos
- Simulador de apoyo de fuego distribuido del ejército
- Compilador del sistema de producción
- Línea de productos Graph
- Preprocesadores extensibles de Java
- Portlets web
- Aplicaciones SVG
Ver también
- MetaModelos de FOSD: líneas de productos de líneas de productos
- Origami FOSD
- Cubos del programa FOSD: líneas de productos multidimensionales
- Lenguaje de programación de muy alto nivel
Referencias
- ^ a b c "Diseño e implementación de sistemas de software jerárquicos con componentes reutilizables" (PDF) .
- ^ "Selección de ruta de acceso en bases de datos relacionales" .
- ^ "Programación orientada a funciones: una nueva mirada a los objetos" . Archivado desde el original el 3 de agosto de 2003 . Consultado el 16 de diciembre de 2015 .
- ^ a b "Escalado del refinamiento paso a paso" (PDF) .
- ^ a b c d "Desarrollo basado en modelos orientados a funciones: un estudio de caso para portlets" (PDF) .
- ^ a b c Trujillo, Salvador; Azanza, Maider; Díaz, Óscar (octubre de 2007). "Metaprogramación generativa" . GPCE '07: Actas de la 6ª conferencia internacional sobre programación generativa e ingeniería de componentes : 105-114. doi : 10.1145 / 1289971.1289990 .
- ^ "Modelos de funciones, gramáticas y fórmulas proposicionales" (PDF) .
- ^ "Un álgebra para características y composición de características" (PDF) .
- ^ "Superposición: un enfoque independiente del lenguaje para la composición de software" (PDF) .
- ^ "Garantizar la corrección sintáctica para todas las variantes de la línea de productos: un enfoque independiente del idioma" (PDF) .
- ^ "FeatureHouse: composición de software automatizada, independiente del idioma" (PDF) .
- ^ "Pruebas de líneas de productos de software mediante generación de pruebas incrementales" (PDF) .