Programación orientada a componentes

Programación orientada a componentes
Información sobre la plantilla
Diagrama.gif

Programación orientada a componentes. Extensión natural de la programación orientada a objetos (POO) en los sistemas de aplicación abiertos, que tiene como propósito contrarrestar las limitaciones de esta, como la falta de una unidad concreta de composición independiente en las aplicaciones, y la definición de interfaces a bajo nivel, que dificultan la reutilización comercial de objetos.

Objetivo

El objetivo de la programación orientada a componentes (POC) es construir un mercado global de componentes software, en donde los usuarios son los desarrolladores de las aplicaciones que necesitan reutilizar componentes ya hechos y testeados para construir sus aplicaciones de forma más rápida y robusta.

En general, puede verse como una extensión natural de la programación orienta a objetos dentro del ámbito de los sistemas de aplicación abiertos y distribuidos.

Las entidades básicas de la POC son los componentes, estos pueden interpretarse como cajas negras que encapsulan cierta funcionalidad y que son diseñadas sin saber quién los utilizará, ni cómo, ni cuándo. Los servicios de los componentes son conocidos mediante sus interfaces y requisitos.

La POC es un paradigma de programación que se centra en el diseño e implementación de componentes, y en particular en los conceptos de encapsulación, polimorfismo, composición tardía y seguridad.

Conceptos básicos de la POC

Existe un conjunto de conceptos básicos que intervienen en la POC y que permiten diferenciarla del resto de los paradigmas de programación. Entre ellos se encuentran:

  • Composición tardía: composición que se realiza en un tiempo posterior al de la compilación del componente, puede ser durante su enlazado, carga o ejecución, y por alguien ajeno a su desarrollo, es decir, que sólo conoce al componente por su interfaz o contrato, sin necesidad de conocer detalles de implementación, ni la forma en que fue creado.
  • Eventos: mecanismo de comunicación por el que se pueden propagar las situaciones que ocurren en un sistema de forma asíncrona. Emitidos para avisar a los componentes de su entorno de cambios en su estado.
  • Reutilización: posibilidad de utilizar un componente software en contextos distintos a aquellos para los que fue diseñado (reutilizar no significa usar más de una vez).
  • Contratos: especificación que se añade a la interfaz de un componente y que establece las condiciones de uso e implementación que ligan a los clientes y proveedores del componente. Los contratos cubren aspectos tanto funcionales (semántica de las operaciones de la interfaz) como no funcionales (calidad de servicio, prestaciones, fiabilidad o seguridad).
  • Polimorfismo: posibilidad de que un mismo componente se muestre de diferentes formas, dependiendo del contexto; o bien la capacidad de distintos componentes de mostrar un mismo comportamiento en un contexto dado. En POC muestra tres nuevas posibilidades:

1. La reemplazabilidad (inclusión), o capacidad de un componente de reemplazar a otro en una aplicación, sin romper los contratos con sus clientes.
2. El polimorfismo paramétrico, o implementación genérica de un componente. Este no se resuelve en tiempo de compilación (generando la típica explosión de código), sino en tiempo de ejecución.
3. El polimorfismo acotado, para indicar restricciones sobre los tipos sobre los que se puede parametrizar un componente.

  • Seguridad: garantía que debe ofrecer un componente de respetar sus interfaces y contratos:

1. Seguridad a nivel de tipos: asegura que las invocaciones usen los parámetros adecuados (o supertipos) y que los valores que devuelven son del tipo adecuado (o subtipos).
2. Seguridad a nivel de módulo: asegura que solo se utilizan los servicios ajenos al componente que se han declarado.

  • Reflexión: habilidad para conocer y modificar el estado de un componente.

Problemas típicos de la POC

La POC es una disciplina muy joven y por tanto en la que los resultados obtenidos se centran más en la identificación de los problemas que en la resolución de los mismos. Algunos de los retos y problemas con los que se enfrenta son:

  • Clarividencia: se refiere a la dificultad con la que se encuentra el diseñador de un componente al realizar su diseño, pues no conoce ni quién lo utilizará, ni cómo, ni en qué entorno, ni para qué aplicación. Este problema está muy ligado a la composición tardía y reusabilidad de los componentes.
  • Evolución de los componentes: la gestión de la evolución es un problema serio, pues en los sistemas grandes han de poder coexistir varias versiones de un mismo componente.
  • Percepción del entorno: posibilidad de un componente de descubrir tanto el tipo de entorno en donde se está ejecutando (de diseño o de ejecución), como los servicios y recursos disponibles en él.
  • Particularización: cómo particularizar los servicios que ofrece un componente para adaptarlo a las necesidades y requisitos concretos de la aplicación, sin poder manipular su implementación.
  • Falta de soporte formal: la dificultad que encuentran los métodos formales para trabajar con sus peculiaridades, como puede ser la composición tardía, el polimorfismo o la evolución de los componentes.
  • El problema de la clase base frágil (FBCP): este problema ocurre cuando la superclase de una clase sufre modificaciones. El FBCP existe a dos niveles, sintáctico y semántico. A nivel sintáctico ocurre cuando las modificaciones de la superclase son puramente a este nivel. A nivel semántico ocurre cuando lo que se altera es la implementación de los métodos de la superclase.
  • Asincronía y carreras de eventos: problema que se presenta por los tiempos de comunicación en los sistemas abiertos (no se pueden despreciar retrasos). Es muy difícil garantizar el orden relativo en el que se distribuyen los eventos. El proceso de difusión de eventos es complicado cuando los emisores y receptores pueden cambiar con el tiempo.
  • Interoperabilidad: los contratos de los componentes se reducen a la definición de sus interfaces a nivel sintáctico, y la interoperabilidad se reduce a la comprobación de los nombres y perfiles de los métodos. Sin embargo, es necesario ser capaces de buscar los servicios que se necesitan por algo más que sus nombres, y poder utilizar los métodos ofrecidos en una interfaz en el orden adecuado.

Fuente

  • Fuentes, L., Troya, José M. & Vallecillo, A. 2001. Desarrollo de software basado en componentes. Universidad de Málaga.
  • Metodología de desarrollo de software basada en componentes, trabajo de cátedra.