Discusion Arquitectura 4.0

De OrfeoWiki

Tabla de contenidos

[editar] DOCUMENTO GUÍA PARA DISCUSIONES DE IMPLEMENTACIÓN DE ORFEO

[editar] 1Conceptos

[editar] 1.1 Rendimiento

Es la velocidad de respuesta percibida por el usuario, en general un usuario considera que una aplicación tiene buen rendimiento si las peticiones que hace al sistema son respondidas rápidamente (en el orden de segundos).

Otra característica asociada es el llamado throughput que sirve para medir el máximo de peticiones concurrentes manejadas por el sistema, es decir está asociado a condiciones de carga extrema.

[editar] 1.2 Escalabilidad

Es la capacidad del sistema de ajustarse a aumentos en la carga impuesta sobre el mismo, es decir, un sistema es escalable si puede exponer el mismo rendimiento al doblarse por ejemplo el número de usuarios que acceden al mismo.. Un sistema áltamente escalable estará en capacidad de responder por igual cuando tiene 10 usuarios o 10000. Evidentemente, el escalar un sistema por lo general involucra la adición de recursos de hardware a medida que la carga del sistema crece, la escalabilidad consiste en que el sistema pueda acomodar y aprovechar eficientemente este aumento en los recursos de hardware.

Un sistema puede tener un rendimiento mejor que otro pero si no es igual de escalable, cuando el número de usuarios crezca el rendimiento del segundo terminará siendo mayor.

Por lo general, la escalabilidad se ataca creando sistemas distribuidos tipo cluster que permita la adición transparente de recursos de hardware representados en máquinas adicionales conectadas por red.

[editar] 1.3 Mantenibilidad

Un sistema es mantenible cuando el proceso de modificar y añadir funcionalidad o de corrección de errores es limpio y rápido, se dice que la mayoría de los costos asociados a una aplicación corresponden a gastos de mantenimiento

[editar] 1.4 Modularidad

Un sistema es modular si la implementación de su funcionalidad está claramente separada en módulos independientes y bien definidos que colaboran entre sí.

Un concepto relacionado es la separación de roles que propende por que los distintos módulos tengan bien definidas las responsabilidades asignadas, se busca en general que cada módulo tengo un pequeño número de responsabilidades para evitar conflictos entre sí.

La modularidad promueve el concepto de reuso ya que los módulos pueden ser combinados para crear nuevas funcionalidades, obviamente estos módulos pueden provenir de fuentes externas

Además un sistema modular es mucho más mantenible ya que permite localizar los problemas y cambiar solo aquellos módulos que fallan.

El costo de la modularidad es rendimiento ya que al hacer un programa modular puede conllevar a que se pierda la posibilidad de realizar optimizaciones.

[editar] 1.5 Sistemas multicapas

La mayoría de aplicaciones Web actuales son multicapas, que no son otra cosa que la aplicación de los conceptos de separación de roles.

Cada una de las capas se encarga de una responsabilidad en especial, de esta forma es posible cambiar separadamente cada una de ellas si se requiere alterar la funcionalidad sin tener que alterar todo el sistema.

Las capas se soportan unas en otras y en general solo se permite la comunicación entre capas adyacentes

El esquema de multicapas más común en la actualidad incluye tres capas principales, presentación, negocio y persistencia.

Los beneficios más evidentes incluyen el cambio de la interfaz de usuario sin alterar el esquema de persistencia y viceversa o proporcionar distintas interfaces de usuario con base en una sola capa de negocio.

Otros beneficios menos explícitos son la capacidad de implementar esquemas de alta disponibilidad y desempeño en cada una de las capas.

Aunque las capas estén bien separadas, sigue existiendo la necesidad de crear esquemas de comunicación entre capas por medio de patrones, los patrones más utilizados son:

  • Patrón MVC (Modelo Vista Controlador) que estructura y facilita la comunicación entre la capa de presentación y la de negocio
  • DTO: Data Transfer Objects. Objetos ligeros que contienen la información a pasar entre capas
  • Dependency Injection: Automatiza la creación e instanciación de DTOs y otros objetos
  • DAOs: Abstraen el acceso a los repositorios persistentes para que la información persistente pueda ser accedida por la capa de negocios de una manera fácil e independiente del repositorio
  • OR-Mappings: Cumplen la misma función de los DAOs pero mapean automáticamente entre artefactos relacionales (Tablas, Vistas, Secuencias) y objetos utilizando esquemas declarativos y de fácil cambio, así mismo incluyen funciones de transaccionalidad local y distribuida (esta última se presenta cuando se manejan varios repositorios).

Texto en cursiva

[editar] 1.6 Interoperabilidad

La interoperabilidad se refiere a la capacidad del sistema de conectarse e interactuar con sistemas externos, esta propiedad es cada vez más deseable y aunque potencialmente siempre se puede realizar, para que un sistema sea áltamente interoperable debe seguir estándares abiertos y de amplia aceptación. Entre más interoperable es un sistema, más se extiende su cobertura y su utilidad

[editar] 1.7 Confiabilidad

La confiabilidad indica que tanto tiempo el sistema se comporta según las especificaciones propuestas. Un sistema es altamente confiable si no presenta fallas inesperadas la máyoria del tiempo.

Estas fallas abarcan un gran rango, incluyendo desde fallas fatales (que hacen caer totalmente el sistema) hasta errores de comunicación y de manejo de datos. En este último aspecto un punto importante es la transaccionalidad del sistema que garantiza el manejo de datos concurrente de una forma confiable.

[editar] 1.8 Disponibilidad

La disponibilidad se puede incluir en la confiabilidad y se refiere a que tanto tiempo el sistema está operando y puede ser utilizado. Los esquemas de alta disponibilidad garantizan que el sistema funcione de una manera 7x24.

Por lo general los esquemas de alta disponibilidad involucran el uso de componentes redundantes en hardware, software y comunicaciones.

[editar] 1.9 Seguridad

Una aplicación es segura si protege los datos y las operaciones que realiza contra ataques malintencionados o incluso errores involuntarios que puedan comprometer a la organización que utiliza el sistema.

Las propiedades principales de un sistema seguro son

  • Autenticación: Verifica que los usuarios del sistema sean quien dicen ser
  • Autorización: Garantiza que los recursos, operaciones y datos de la aplicación solo sean accedidos por los usuarios que tienen permisos sobre ellos (según las políticas de la organización)
  • Auditoría: Registra todos los eventos del sistema para poder hacer seguimiento y eventualmente computación forense.
  • Confidencialidad: Garantiza que los datos manejados por el sistema solo puedan ser accedidos por usuarios autorizados, la confidencialidad se asocia a menudo a sistemas de criptografía y son aplicados principalmente a nivel de redes de comunicación.

La seguridad es un aspecto que debe ser aplicado en todo el sistema, por ejemplo en un sistema multicapa la seguridad debe ser aplicada en cada una de las capas.

[editar] 1.10 Componentes con estado y sin estado

Aunque esta es una característica de los componentes de un sistema más bien que una propiedad, se menciona aquí por las implicaciones que tiene en cuanto a las propiedades ya expuestas.

Un sistema puede incluir componentes con estado mezclados con componentes sin estado, sin ir más allá, las aplicaciones WEB se basan en el protocolo HTTP que fue planeado inicialmente para no manejar estado pero que tuvo que acomodar estrategias adicionales para manejarlo como son las cookies y la rescritura de URLS.

A medida que el sistema presente un comportamiento que tiende a ser más sin estado, la escalabidad, modularidad, interoperabilidad y el desempeño tiende a ser más facil de manejar, obviamente, este comportamiento está definido por las especificaciones iniciales del sistema.

[editar] 1.11 Portabilidad

Un sistema es portable si puede operar en distintas combinaciones de plataformas de hardware, sistemas operativos, redes y servidores. Entre más portable sea un sistema más fácil será su migración a una plataforma distinta. Al igual que la interoperabilidad, la portabilidad se beneficia del uso de estándares o por lo menos de que las plataformas den soporte al lenguaje de implementación y a los protocolos de comunicación utilizados.

[editar] 2 Guía de discusión sobre lenguaje

Para discutir entonces sobre el lenguaje de implementación se propone tener en cuenta las siguientes cuestiones. En cada una de ellas se hace un pequeño análisis respecto a los posibles lenguajes de implementación propuestos y que son Java, PhP, Python y Ruby.

[editar] 2.1 Orientación a objetos y características del lenguaje

Un paradigma de programación dicta la manera de construir programas, los lenguajes de programación se adhieren a uno o más paradigmas de los cuales el más exitoso es el paradigma de programación orientado a objetos debido principalmente a que ataca los problemas de una forma más real. (El mundo está compuesto de objetos y como tal es más fácil modelar en términos de objetos).

Aunque la discusión se puede ampliar a que paradigma de programación se va a utilizar, en aras de acelerar el proceso de escogencia de lenguaje se recomienda utilizar objetos, en este sentido, todos los lenguajes de programación propuestos soportan el paradigma, aunque PhP solo soporta objetos fuertemente a partir de Php 5.

Los lenguajes no suelen tener una orientación a objetos pura, por ejemplo Python y Php mezclan la orientación a objetos con la programación procedimental, un buen cuadro de comparación se encuentra en

así mismo un buen artículo sobre el soporte de objetos de PhP se encuentra en

y en http://www.devx.com/webdev/Article/10007/1954

Como se observa Ruby es el lenguaje más puramente orientado a objetos seguido por Java, Php y Python son más lenguajes híbridos o multiparadigma.

Además de las propiedades básicas de orientación a objetos como encapsulamiento, herencia, polimorfismo y abstracción se destacan las siguientes características como posibles diferenciadoras en la escogencia de un lenguaje u otro (ver cuadro de comparación)

  • Reflexión
  • Funciones de alto orden y closures
  • Clases genéricas
  • Recolectores de basura
  • Multithreading
  • Expresiones regulares
  • Seguridad integrada (SandBoxes)

[editar] 2.2 Desempeño

Aunque el desempeño de un sistema depende básicamente de la forma como se desarrolla y de los recursos de hardware que utiliza, existe una amplia discusión a nivel global sobre si un lenguaje es inherentemente más rápido que otro.

Como regla de oro, entre más cerca esté un lenguaje de programación del lenguaje de máquina, más rápida será su ejecución, esto obviamente, tiene contraprestaciones en cuanto a la velocidad de desarrollo y la portabilidad del lenguaje.

Siguiendo este razonamiento es de común aceptación asegurar que los lenguajes compilados son más rápidos que los interpretados justamente por que los lenguajes compilados producen en la fase de construcción de software un código (binario) que corresponde o por lo menos está más cercano al código de máquina. Por el contrario, los lenguajes interpretados deben hacer algo similar pero en tiempo de ejecución.

Es necesario aclarar que no siempre se produce código de máquina (como lo hace c o assembler) sino que existen puntos intermedios como las máquinas virtuales o llamadas a librerías del sistema operativo o del servidor.

El costo de esta ganancia en velocidad de ejecución es el nivel de abstracción que puede proporcionar el lenguaje, en general, entre más alto nivel tenga el lenguaje, menos rápida será su ejecución. Como siempre esto es discutible y actúan muchas más variables.

El rendimiento de los lenguajes compilados puede ser mejorado notablemente mediante el uso de compiladores y precompiladores eficientes que pueden llegar a incluir técnicas de inteligencia artificial, esto también aplica a los lenguajes interpretados pero la optimización está más restringida puesto que solo puede hacerse en tiempo de ejecución donde no se puede asignar mucho tiempo a esta actividad. Lo mismo aplica para el enlazado de librerías que puede ser dinámico o estático, el estático realiza el enlazado en tiempo de compilación pero suele aumentar el tamaño del código generado.

Finalmente, otra actividad que puede ser llevada a cabo en tiempo de compilación o de ejecución es la verificación de tipos, un lenguaje fuertemente tipeado hará una verificación muy exhaustiva en tiempo de compilación mientras que uno débil hará esta verificación en su mayoría en el tiempo de ejecución. Aunque los lenguajes siempre realicen verificación en tiempo de ejecución, el hecho de que sean fuertemente tipeados hará que esta verificación sea más sencilla en tiempo de ejecución, obviamente, un lenguaje fuertemente tipeado requiere de mayor disciplina al escribir programas puesto que generará mucho más errores al momento de compilar, sin embargo, estos errores se presentarán menos al momento de ejecutar.

Es conveniente reiterar que el desempeño de un sistema viene dado por una combinación de muchos factores, sin embargo citamos aquí las características de cada uno de los lenguajes propuestos.

  • Java: Lenguaje compilado, aunque el resultado de la compilación son bytecodes que se encarga de ejecutar la máquina virtual, a partir de 1.4 se creo la máquina virtual con hotspots que mejora el rendimiento al permitir generar código binario nativo para ciertas operaciones de uso común (como ciclos).
  • PHP: Lenguaje interpretado, puede mejorar el rendimiento notablemente utilizando un acelerador (como ACP) para almacenar temporalmente el código binario generado previamente.
  • Python: Lenguaje interpretado, puede mejorar el rendimiento notablemente utilizando un acelerador (como psyco) para almacenar temporalmente el código binario generado previamente.
  • Ruby: Lenguaje interpretado (No se encontró acelerador)

[editar] 2.3 Escalabilidad, confiabilidad y disponibilidad

Las características orientadas a la escalabilidad, confiabilidad y disponibilidad en uno u otro lenguaje van más de la mano de la infraestructura que se utilice para ejecutar el sistema, en realidad se puede lograr estas propiedades utilizando métodos más generales como por ejemplo utilizar clusters de balanceo de carga como LVS lo cual haría el mecanismo independiente del lenguaje y más bien ubicado a nivel del sistema operativo.

Es así como por ejemplo una aplicación Php puede hacerse escalable mediante la adición de computadores a un cluster cada uno corriendo una copia del sistema y balanceados a nivel de red, el principal problema aquí consiste en el manejo de estado compartido entre las diferentes máquinas del cluster.

Este problema surge porque un sistema como Orfeo depende del concepto de sesión de usuario, es decir, si todas las interacciones del usuario con el sistema fueran independientes entre sí, cada máquina del cluster podría atender una solicitud sin preocuparse de las demás máquinas, si es necesario por el contrario, que las peticiones tengan asociado un estado, este estado debe ser compartido y replicado entre las diferentes máquinas utilizando librerías de comunicación de grupos, sistemas de archivos distribuidos o virtuales (por ejemplo NFS o GFS) o replicación de sesión a nivel de base de datos. De estos tres métodos solo el primero es dependiente del lenguaje, los otros dos pueden ser configurados a nivel del sistema operativo o de la base de datos.

La escalabilidad es considerada más en los frameworks empresariales de uno u otro lenguaje, al respecto parece que el lenguaje que más ha progresado es Java ya que su framework empresarial incluye soporte para componentes distribuidos como los EJB y librerías de comunicación de grupos como JavaGroups y JavaSpaces. Más aún, la especificación J2EE incluye normativas para la clusterización de componentes y así los diferentes fabricantes tienen servidores de aplicaciones (Jboss, Geronimo, GlassFish, Oracle IAS, WebLogic entre otros) que manejan estos temas de escalabilidad uniformemente permitiendo que una aplicación J2EE pueda ser ejecutada de la misma forma en cualquiera de estos servidores de aplicaciones que se ajustan a la especificación J2EE.

Otra característica importante incluída en J2EE es el manejo de transacciones, la especificación J2EE proporciona mecanismos de manejos de transacciones locales y globales que permiten el uso de bases de datos distribuidas o incluso de varias bases de datos o repositorios consistentemente.

Aunque la especificación J2EE era enormente compleja e ineficiente en cuanto al manejo de componentes distribuidos (EJB), la última versión simplifica enormemente la producción de estos componentes los cuales pueden ser generados a partir de objetos muy simples (POJO Plain Old Java Object) mediante la inclusión de anotaciones muy sencillas, en contraprestación este cambio ha limitado un poco las propiedades de distribución de los componentes aunque aún se conservan gran parte de estas propiedades.

A nivel de los otros lenguajes de programación, es necesario revisar si existen prestaciones similares, se agradece colaboración para completar esta información en este documento.

[editar] 2.4 Mantenibilidad, Modularidad y capas

Este aspecto depende más bien de las habilidades del equipo de desarrollo, sin embargo, este aspecto debe incluir necesariamente el uso de un FrameWork de desarrollo bueno, se incluye una lista y comparación de frameworks de desarrollo Web para distintos lenguajes.

http://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks

Es importante sobretodo que el framework incluya tres componentes

  • Patrón modelo-vista-controlador
  • Mapeo Relacional-Objetos
  • Seguridad transversal

Además es deseable que el framework incluya

  • Integración entre capas (Dependency Injection, Annotations)
  • Manejo de transacciones
  • Patrón Fachada o equivalente
  • Soporte de Web Services
  • Soporte de Portlets
  • Componentes de interfaz de usuario Out of the Box (Componentes listos para ser utilizados)
  • Caches


Se requiere de un estudio más detallado de los diferentes frameworks pero a priori Ruby, Java y Phyton pueden llegar a proporcionar más facilidades debido a sus características de reflexión pero teniendo en cuenta que Php está áltamente orientado a aplicaciones Web.

[editar] 2.5 Interoperabilidad

Debido a la misma definición de interoperabilidad, esta propiedad no debe depender de ningún lenguaje de programación en particular, de hecho, lo que se busca es que el sistema interactúe con sistemas escritos en diversos lenguajes de programación y ejecutándose en plataformas distintas. Al respecto se sugiere el uso de WebServices com

[editar] 2.6 Portabilidad

La portabilidad en los lenguajes interpretados depende de la disponibilidad de interpretadores en las distintas plataformas, en el caso de Java depende de la disponibilidad de implementaciones de máquinas virtuales.

A decir verdad Phyton y Ruby también incluyen máquinas virtuales la diferencia es que los bytecodes son generados en tiempo de ejecución (al interpretar el código).

La portabilidad no es relevante en la escogencia del lenguaje debido a que se han creado interpretadores o máquinas virtuales para todas las plataformas principales.

[editar] 2.7 Seguridad

La seguridad es manejada más a nivel de framework y de redes de comunicación, sin embargo la máquina virtual de Java proporciona conceptos de seguridad básica como la verificación de bytecodes y el concepto de SandBox que controla que el bytecode se ejecute en un ambiente aislado con acceso a recursos restringidos,el más claro ejemplo es la ejecución de applets que requiere de archivos jar firmados y automáticamente solicita al usuario que autorice permisos sobre recursos críticos como acceso al disco duro (obviamente muchos usuarios simplemente obvian esta verificación de permisos dando Ok a todo lo que ven!). Ruby también implementa conceptos similares

El tema de seguridad debe ser revisado por un experto, existen evidencias de huecos de seguridad encontrados en frameworks como Ruby on Rails y php puede llegar a ser vulnerable debido a que proporciona acceso a muchas librerías nativas (al igual que Java con JNI) pero debido a la facilidad de uso de Php, estas llamadas son más frecuentes. En general, este tipo de vulnerabilidades son evitables utilizando el criterio común del desarrollador pero se recomienda la revisión de este punto por parte de un experto.

Por último, es recomendable que el lenguaje de implementación incluya librerías para manejo de certificados X.509, algoritmos Hash (MD5, SHA), encriptación (SSL) y directorios LDAP.

[editar] 3 Guía de discusión en Orfeo

Utilizando toda la información anterior, la escogencia del lenguaje se debería basar en los siguientes puntos

  • Características del lenguaje y nivel de abstracción
  • Desempeño del lenguaje
  • Simplicidad y rapidez de desarrollo
  • Experticia de los programadores (se recomienda hacer encuesta)
  • Frameworks disponibles y sus prestaciones
  • Facilidades de escalabilidad y alta disponibilidad
  • Transacciones
  • Existencia de módulos reusables (En particular el motor de BPM es esencial y el repositorio de contenido es recomendado)

Se propone crear un cuadro comparativo y asignar pesos según la importancia que se quiera asignar a estos factores. De igual forma es necesario crear un mecanismo de consolidación de las opiniones respecto a la conformación del cuadro.

[editar] Cuadro Comparativo

Criterio Java Php Python Ruby
Características del lenguaje y nivel de abstracción 7 5 8 9
Desempeño 8 7 5 5
Simplicidad y rapidez de desarrollo 7 8 9 9
Experticia Consulta 10 Consulta Consulta
Frameworks 10 7 6 6
Escalabilidad 8 5 5 5
Transacciones 10 No se sabe No se sabe No se sabe
Módulos 10 No se sabe No se sabe No se sabe
Herramientas personales