Apache Kafka

Miércoles, 15 julio 2015, 20:31 Deja un comentario

kafka_logo

Apache Kafka es un sistema de procesado de mensajes. Los mensajes se publican por los productores (producers) en colas denominadas topics  y se consumen de la cola por los consumidores (consumers) suscritos a dicha cola. Es una solución al problema de los productores-consumidores concurrentes. En este problema existen uno o más actores (productores) que generan los mensajes que son procesados por uno o más actores (consumidores) de manera concurrente.

El sistema de encolado y procesado de mensajes es distribuido y particionado en diferentes instancias denominadas brokers que conforman el clúster de Kafka. Dentro del clúster, en cada broker, cada topic o cola está dividida en particiones en las que los mensajes se almacenan de manera secuencial. Las particiones de un topic permiten:

  • Distribuir la carga de trabajo entre diferentes brokers y consumidores
  • Tener tolerancia a errores de los brokers, al poder tener replicadas la misma partición en brokers distintos (aunque solo una es la activa, pueden tomar el sitio de la activa si ésta cae)

Apache Kafka Diagram

El productor es quien encola los mensajes en cada partición, que mantiene estos mensajes de manera secuencial y ordenada. Es el propio productor quien decide en qué partición específica del topic se almacena el mensaje. De esta manera el balanceado de los mensajes en las diferentes particiones queda en manos del productor, no del clúster, que puede basarse en criterios de balanceado de carga o de lógica de negocio.

El modo en que se distribuyen los mensajes a los consumidores es también bastante flexible. Los consumidores se agrupan en grupos de consumidores. El clúster distribuye los mensajes de cada partición a un único consumidor del grupo, pero si hubiese más de un grupo de consumidores lo haría para cada grupo. De esta manera nos encontramos en un cola clásica con la carga balanceada entre varios consumidores si solo hay un grupo, y en un modelo de suscripción si tuviésemos más de un grupo.

Apache Kafka Distribution

El único modo de garantizar que los mensajes se consumen en el orden en que se crean es teniendo una única partición por topic y un solo consumidor por grupo. El único modo de garantizar que los mensajes se consumen una sola vez es teniendo un único grupo de consumidores.

El consumidor de cada partición es el que decide el orden en que se procesan los mensajes y los mensajes que se procesan. El consumidor tiene libertad para moverse en la partición accediendo a los mensajes de manera indexada (offset desde comienzo) y en sentido y con el criterio que quiera, y es quién lleva constancia de si han sido consumidos o no.  Esto permite que la política o lógica de procesado de mensajes sea mucho más flexible que la cola tradicional, permitiendo el reprocesado de mensajes, el procesado en cualquier orden o el consumo de mensajes en la misma partición por diferentes consumidores (si están en distintos grupos).

Los mensajes se mantienen en la partición, con independencia de si han sido consumidos o no, durante el tiempo indicado por la política de retención de mensajes. No hay borrado de los mensajes. Esto se debe a una decisión de diseño muy eficiente, puesto que el acceso al disco secundario es siempre secuencial y no aleatorio, con las ventajas de rendimiento que supone.

Mi opinión es que Apache Kafka es un solución muy versátil y sencilla para consumir o transformar elementos de información que se generan a un ritmo no constante o mantenido, sino poissoniano, como son eventos, mensajes, peticiones… Siguiendo la documentación, que por cierto es muy buena y completa, los ejemplos de aplicación más comunes son como sistema de mensajería tradicional, monitor de actividad web o monitor de métrica de operaciones, agregador de log, gestor de eventos, procesador de streams de datos…

apache-logo

Apache ZooKeeper

Jueves, 23 abril 2015, 23:50 Deja un comentario

zookeeper

Apache ZooKeeper es un servicio de datos en estructura de árbol. El servicio es centralizado, replicado, de alta disponibilidad y escalable; y garantiza la integridad en accesos concurrentes y el orden de modificación de los datos de manera secuencial. El sistema está formado por un conjunto distribuido de instancias denominado quorum que sirven la misma información.

El servicio es centralizado porque solo una de las instancias en ejecución hace las veces de instancia maestra, es la única que puede modificar los datos y que los replica al resto de las instancias. Esto garantiza el orden de los cambios, la atomicidad transaccional y la integridad concurrente de la información. Cuando la instancia maestra cae, el algoritmo de elección de líder, decide qué instancia es la nueva instancia maestra. El acceso de lectura, sin embargo, puede hacerse a cualquiera de las instancias levantadas del sistema. Esto por un lado garantiza la disponibilidad, al poder cualquier nodo convertirse en líder, y el rendimiento y la escabilidad, al permitir poder añadir todas las instancias que queramos al quorum para repartir la carga. Este diseño lo hace más adecuado para situaciones en que la lectura de datos es mucho más habitual que la escritura (al menos 1:10 según la documentación).

El servicio es rápido porque los datos se encuentran en memoria de cada instancia y solo se replican a disco para garantizar su persistencia. También es muy sencillo, tanto en el modo en que almacena la información; como en el modo en que se accede a la misma, con un conjunto de operaciones que son muy básicas y reducidas en número.

La forma en que se estructuran, organizan y acceden los conjuntos de datos es en estructura de árbol. Muy parecido a lo que sería un sistema de ficheros clásico pero siendo todos los nodos iguales, sin que haya distinción entre directorios y ficheros: todos los nodos son accesibles, pueden contener datos y pueden tener nodos hijos. Cada nodo puede contener cualquier tipo de información ya que el acceso es binario, pero el sistema está diseñado para que sean de un tamaño moderado, unos pocos kilobytes como mucho.

Los clientes tienen configuradas una o varias de las instancias del quorum, que no tienen por qué ser todas los integrantes, y que son los que se encargan de presentar al cliente al líder en ese momento.

Los usos más habituales de este servicio es como repositorio de información de configuración y nombres, o para proveer mecanismos de sincronización (lock, mutex,…) para soluciones distribuidas.

Un ejemplo de uso que me parece muy apropiado puede ser como repositorio de configuración de un conjunto de componentes muy numeroso, por ejemplo los sistemas de red de una gran organización o los diferentes servicios de una granja de servidores. Cada nodo hoja de la estructura de árbol puede ser un sistema o servicio y la información que contiene su configuración o estado. Los nodos rama nos permiten organizar, agrupar y clasificar los sistemas o servicios de la manera más adecuada para la organización. La configuración de todos los sistemas o servicios se gestiona de manera centralizada (solo hay una configuración aún estando replicada), la solución es muy escalable y tiene alta disponibilidad (levantando más instancias podemos servir a más clientes) y es también deslocalizable (al permitir desplegar instancias en diferentes lugares buscando la idoneidad específica para cada cliente).

Es también común verla como mecanismo de sincronización o como monitor de soluciones distribuidas como en Druid, por ejemplo.

apache-logo

Docker

Martes, 24 marzo 2015, 13:16 Deja un comentario

Docker

Docker es una plataforma para la virtualización de entornos a nivel de aplicación o software base en lugar de sistema operativo o máquina virtual. Docker permite definir las diferentes unidades de despliegue de la solución software, con sus componentes distribuidos y sus límites de interconexión con otras unidades, para permitir su despliegue apilado de tal manera que representen las diferentes capas de las soluciones.

La idea es que, en lugar de crear una máquina virtual completa para cada entorno con sus recursos virtuales y sistema operativo, sea el propio sistema operativo el que aísle y compartimente la ejecución de cada entorno, denominado container. El propio sistema operativo crea un entorno de ejecución aislado a nivel de sistema de ficheros, de red, de seguridad y ejecución; de tal manera que los diferentes entornos, aún ejecutando en el mismo sistema operativo, están aislados entre ellos o solo compartiendo aquellas partes que se deseen.

Docker para implementar su funcionalidad se basa en dos características del kernel de Linux, cgroups y namespaces, que permiten establecer criterios de prioridad de CPU, limitación de memoria o de operaciones de I/O o control de facturación en el primer caso; o aislar procesos, entornos de red, usuarios, sistemas de ficheros entre los diferentes entornos en el segundo.

Cada entorno en Docker en ejecución es un container, que se corresponde con el despliegue de una imagen, que contiene la definición del entorno, sus límites, puntos de interconexión con terceros y componentes software. Los containers pueden apilarse de tal manera que cada uno represente una capa de la solución final. La combinación apilada de containers se produce mediante la definición de los puntos de interconexión de los container, como pueden ser puertos de red, y la sobreposición de los sistemas de ficheros uno sobre otro, mediante UnionFS.

La posibilidad de dividir los diferentes componentes distribuidos y capas del aplicativo en diferentes containers apilables supone una gran ventaja tanto para desarrolladores como para técnicos de explotación. Por un lado las dependencias se resuelven dentro de los propios container de la solución por lo que dentro de un mismo sistema no hay incompatibilidades entre versiones y dependencias. Por otro, el proceso de despligue se modulariza y la nivelación de entornos de integración y productivos es mucho más sencilla, al basarse en el despliegue secuencial de estas unidades.

Las imágenes que se despliegan como containers pueden registrarse en directorios públicos o privados (dentro del ámbito de la organización) con Docker Hub. El servicio en la nube que registra, almacena, distribuye y da soporte social y colaborativo a la tarea de gestión de las diferentes imágenes. Este es el servicio que monetiza toda la idea. Secundo la opinión de D’Oh de que puede ser una excelente alternativa o mecanismo en el que basarse las futuras tiendas de aplicaciones o sistemas de paquetes de los sistemas operativos.

Aunque la tecnología está basada en características propias de Linux, existen versiones portadas a Windows o iOS, pero con un componente adicional de virtualización para dar soporte a estas funcionalidades de compartimentación que no existen, al menos de manera idéntica, en estos sistemas. Las plataformas de virtualización en la nube Amazon EC2 y Google Cloud también soportan de manera nativa Docker.

Categorías:Arquitectura, Píldoras, Sistemas Etiquetas:

“Best and bad practices” del desarrollo software

Lunes, 9 marzo 2015, 14:23 Deja un comentario
Categorías:Desarrollo

gRPC y Proto 3

Domingo, 8 marzo 2015, 1:24 Deja un comentario

Google hace público el protocolo o mecanismo RPC que utiliza en alguno de sus sistemas, gRPC:

https://github.com/grpc/grpc-common

Para el envío de mensajes utiliza el protocolo Protocols Buffers en su versión 3:

https://github.com/google/protobuf

Google asegura que son ligeras, rápidas y muy eficientes en cuanto al consumo de recursos. La verdad es que los ejemplos aparentan que es muy sencillo integrarlo.

Ambas opciones son multilenguaje/multiframework soportando C++, Java, Python, Go y Ruby entre otros (incluyendo la posibilidad de invocarse entre plataformas distintas). Pero sobre todo me llama la atención la opción de Android, porque hace tiempo buscando soluciones para RPC en este entorno no encontré ni muchas opciones, ni muy buenas.

Categorías:Desarrollo, Píldoras Etiquetas:

Consejos y buenas prácticas en la gestión de errores: recopilación y comunicación de información

Lunes, 17 noviembre 2014, 1:37 Deja un comentario

Error

Los errores ocurren y son parte de la fase de servicio del ciclo de vida de toda aplicación. No hay ni que verlos de manera trágica, pues son las singularidades propias de la explotación de la aplicación, ni con excesiva indulgencia, porque son una medida clave de la calidad del servicio que estamos dando.

Pero lo que sí es relevante es que, desde el primer momento de la incidencia, tengamos información suficiente para disparar todos lo mecanismos de análisis y resolución del error. Es necesario que tengamos una recolección de datos automática y eficaz; y esa eficacia sobre todo va a depender, dado la variado e impredecible de los errores, de lo completos que sean esos datos.

Más importante que la información recopilada para el análisis del problema, es la información y mensajes transmitidos al usuario de la aplicación que sufre el error. Factores como la usabilidad, funcionalidad, gestión del riesgo reputacional o la propia operativa de gestión de incidencias dependen fundamentalmente de este aspecto.

El proceso completo  de identificación, clasificación, investigación, resolución y cierre (pasos de la gestión de incidencias según ITIL) es especialmente elaborado y largo como para poder cubrirlo en una sola entrada. Esta entrada pretende solo abordar la primera etapa o paso en la gestión de las incidencias (Identification and Logging según ITIL), y en parte sólo, entrando más en aspectos prácticos que en los formalismos del proceso. El objetivo es cubrir cómo se identifica el incidente, cómo se informa de él y cómo se recopila información que sea útil para su resolución.

La dualidad de actores: usuario y operador

Cuando se produce el incidente hay dos actores interesados o relacionados: por un lado el usuario que no puede resolver de manera normal la operativa, y por otro, el equipo de soporte o de resolución de incidencias que tiene que darle una solución.

Ambos actores necesitan información muy distinta. Por un lado, el usuario no necesita información técnica de qué lo que ha pasado; de hecho, por motivos de seguridad se debería evitar que se revelase o fuese deducible. Por el otro, el soporte debe tener información detallada relativa a la incidencia, pero con un acceso muy limitado y controlado a la propia transacción, si esta tuviese información sensible o confidencial.

Afortunadamente, los canales por lo que se envía la información suelen ser distintos y solo tenemos que tener cuidado en recopilar toda la información necesaria a ambos y mostrar a cada uno la que le corresponde.

No conozco referencias relativas a este asunto, por lo que me he permitido llamar a una la visión del usuario, y a la otra la visión del técnico.

La visión del usuario

Cuando ocurre un error en la aplicación no hay que perder de vista lo más importante: que el usuario estaba intentando hacer algo que podría ser valioso o importante para él. Por eso la visión del usuario (sobre todo cuando estemos hablando de una actividad crítica, relevante o de valor para el usuario o cuando el nivel de calidad de servicio así lo exija) tiene que centrarse en trasmitir muy claramente:

  • ¿Qué ha pasado con la operación que estaba haciendo? ¿En qué situación se ha quedado? ¿Qué consecuencias puede tener?
  • ¿Qué puedo hacer ahora? ¿Cuáles son los pasos a seguir ahora que estamos en una situación anómala (o no) desde el punto de vista de la experiencia de usuario?

Por otro lado, las formas y el contenido en el que se comunica la información del error y de la situación al usuario es especialmente relevante para la usabilidad de la aplicación. Al ser, el error, una situación excepcional, a veces descuidamos esta usabilidad; pero es justamente esa excepcionalidad, la que nos obliga a tener especial cuidado en los mensajes y cómo se los transmitimos a los usuarios, así como el guiado para que puedan encauzar la operativa. Una buena opción es considerar los errores, al igual que las excepciones en el código, como vías de escape del flujo normal de navegación de la aplicación y considerarlas en su diseño. De esta manera ayudaremos a que en caso de error la aplicación esté en un estado y posición estables y conocidos (la pantalla de error “tal” dentro del proceso funcional “tal”) y que sea más usable (el usuario puede utilizar los mismos criterios y flujos de navegación que en el resto de la aplicación).

Información relativa a la operación del usuario

Ya sea escribir un mail, hacer una transferencia o confirmar el pago del carrito de la compra; el usuario está haciendo una operación o transacción importante para él y lo primero de lo que tiene que informarse al usuario es de qué ha pasado con lo que estaba haciendo. Por eso en la información del error que se muestra al usuario se deberían tener en consideración los siguientes puntos:

  • Si la transacción se ha finalizado correctamente: ¿se llegó a enviar el mail? ¿se efectúo la transferencia? ¿se ha cobrado en la tarjeta la compra?; o si por el contrario se canceló la operación: el mail no se envió y la transferencia y el pago no se hicieron efectivos
  • En cualquier caso, si existe operativa de soporte o ticketing, debe definirse un identificador único que permita al usuario poder identificar su caso. Aunque esa identificación pueda y deba llevarse de manera interna por el procedimiento de soporte, en mi opinión, debe ser comunicada al usuario por motivos de transparencia
  • Si la operación no es recuperable, es muy importante indicar al usuario qué va a pasar con la información que ha introducido. Por ejemplo: no he podido finalizar mi compra pero he introducido información sensible como es mi dirección o mi tarjeta. En este caso es conveniente:
    • Informar al usuario de qué información va a almacenarse y de cuál se va a eliminar
    • Indicar qué criterios se utilizarán para gestionarla. Como puede ser el almacenar dicha información por 30 días por si es necesaria para el equipo de soporte, por ejemplo
    • Si estamos obligados por imperativo legal o de cualquier otro tipo a mantenerla, no está de más mencionar estas exigencias u obligaciones
    • Informar al usuario de cómo puede verificar y eliminar esos datos. Desde su perfil o poniéndose en contacto con nosotros, por ejemplo

Pasos a tomar y opciones de resolución

Ahora que el usuario tiene ya una idea clara de qué ha pasado con su operación, es necesario indicarle cómo puede completar dicha operación

  • Si no quedó claro o no se pudo verificar el estado en que quedó la operación, debemos informar al usuario de cómo puede verificar la operación o dónde o con quién puede ponerse en contacto, como puede ser el equipo de soporte
  • Si tenemos cierta certeza de que el fallo es transitorio, podemos invitar a reintentar la operación al usuario pasado un tiempo o cuando podamos contrastar que el problema ha remitido
  • Si es posible continuar la operación o recuperarla en un punto en concreto, debemos indicar al usuario cómo y cuándo (más tarde por mail, por ejemplo) hacerlo; facilitando lo máximo posible este reintento y evitando todo lo posible la repetición de pasos ya realizados. Este punto es importante por varios motivos estratégicos:
    • Porque mejoramos el servicio y funcionalidad ofrecida al usuario y con ello la percepción que tiene de nuestro producto y reducimos el daño reputacional del error
    • Porque evitamos el tedioso proceso de repetir toda la transacción mejorando la experiencia de usuario
    • Porque reducimos el impacto del fallo o caída de servicio habilitando el que de los servicios perdidos algunos se puedan recuperar
    • Porque evitamos que parte de los usuarios afectados migren a la competencia buscando el mismo servicio
  • En la medida de lo posible debe ser parte del flujo normal de navegación y seguir los mismos criterios de navegación, forma y contenido de la información que en el resto de la aplicación. Esto transmite la sensación de ser un situación controlada al usuario, con lo que se limita la pérdida reputacional y se atenúa la sensación de gravedad; además de facilitar el guiado para la resolución del problema.

La visión del técnico

Los mecanismos de log pueden ser de gran ayuda, y son el referente normal en estos casos; pero para que puedan ser manejables desde el punto de vista operativo, suelen ser muy poco detallados. Lo singular e infrecuente del error nos permite que la recolección de información de incidencias pueda ser mucho más exhaustiva, elaborada y detallada. Esta información de mucho más volumen, pero de menor frecuencia.

Es muy importante recordar que esta información es altamente sensible y que su divulgación podría desvelar vulnerabilidades y patrones de ataque. De hecho, una parte fundamental que precede a los ataques informáticos, es el análisis de estas vulnerabilidades. El forzar situaciones de error puede permitir, si no se controla con cuidado, que se pueda obtener información muy sensible y relevante, vulnerabilidad, para luego poder ser explotada.

El siguiente es un checklist de información que puede ser útil recopilar para la visión del técnico:

  • Entorno
    • Hora y fecha
    • Posición geográfica, en especial en entornos móviles o distribuidos
    • Conectividad, también cobra especial importancia en entornos móviles
    • Host o instancia de máquina, para entornos distribuidos
    • Servicio o contenedor de la aplicación
    • Hebra o proceso del sistema operativo
    • Paths y parámetros de configuración del servicio
    • Cliente
      • Navegador, a través de las cabeceras HTTP o recopilando esa información desde la ejecución de código en el mismo navegador
      • Dispositivo, sea un móvil, equipo informático clásico, smartwatch, sistema empotrado…
      • Periféricos de los que hagamos uso
  • Usuario
    • Parametrizacion o personalización del usuario
    • Idioma, zona horaria y configuración regional
    • Credenciales, roles y autorizaciones
  • Transacción
    • Tipo de operación
    • Parámetros de la operación
    • Estado actual de la transacción
  • Aplicación
    • Componente software en el que se produjo el error o salida del flujo normal de ejecución
    • Stack trace de ejecución con los parámetros en el flujo de llamada
    • Variables de estado, de sesión, de ejecución, volcados de memoria, registros del micro…

Hay que tener especial cuidado cuando la información recabada sea relativa a sistemas que no son de nuestra propiedad y que lo puedan ser del usuario, como por ejemplo: la información del propio equipo del usuario, de su móvil o la obtenida relativa al navegador. En este caso, es ético y recomendable informar al usuario de qué información se obtiene de una manera explícita y concreta (aunque sin ser apabullante con detalles). Mejor si le permitimos, incluso, decidir si quiere compartirla con nosotros o no.

Referencias

La foto de cabecera ha sido tomada de https://www.flickr.com/photos/sissou/8432968631 y se está usando bajo licencia CC.

Licencia Creative Commons
Esta entrada de Juan Francisco Adame Lorite está publicada bajo una licencia Creative Commons Atribución-CompartirIgual 3.0 Unported.
Categorías:Arquitectura, Desarrollo, UI Etiquetas:

Checklist de requisitos no funcionales

Lunes, 15 septiembre 2014, 10:30 Deja un comentario

La presente entrada pretende ser un pequeño recopilatorio o lista de control de requisitos no funcionales. No es una entrada definitiva, y de hecho la idea es que vaya creciendo y actualizándose con el tiempo. Invito a todo el que quiera a que aporte correcciones, añadidos y observaciones.

Aunque me gustaría que fuese completa, no pretendo que sea exhaustiva. En las diferentes áreas y aspectos existen grupos de trabajo, estándares y procedimientos suficientemente completos si se quiere profundizar. Por ejemplo, el apartado de la seguridad, por su propia sensibilidad, está muy trabajado en este sentido y existen estándares como el  ISO 27002 o la iniciativa OWASP que contienen checklists y mecanismos de certificación muy completos y detallados. De igual manera, algunos aspectos como Usabilidad son especialmente ambiguos y poco detallados debido a mi falta de experiencia en ellos.

Requisitos

Un requisito es una propiedad física o funcional de un sistema o solución que representa la necesidad, con sus restricciones y detalles, que debe cumplir por diseño, para que cumpla el fin o utilidad con el que fue creado. Es, junto con el alcance, lo que nos dice “qué tiene que hacer y cómo” nuestra solución para que sea útil y tenga valor.

Si nos ceñimos a la norma ISO/IEC/IEEE 29148:2011 los requisitos deben ser:

  • Necesarios. Deben definir una capacidad, característica o restricción sin la cuál el objeto del proyecto o producto sería incompleto. Aunque también pueden documentarse como opcional, deseables, negociables…
  • De libre implementación. Aún siendo suficientemente completo su definición debería ser completamente independiente del modo en que se implemente. En la medida que independicemos la fase de diseño de la de análisis, daremos más libertad a la implementación y obtendremos un mejor producto.
  • Unívocos. Que su definición solo pueda interpretarse de una única manera.
  • Consistentes. Que no entren en conflicto con otros requisitos.
  • Completos. Describe de manera completa, sin deficiencias ni necesidad adicional de información, el requisito. También es necesario especificar el nivel y alcance del requisito, no es lo mismo que el sistema por diseño sea capaz de cumplir el requisito, que verificar de manera continuada y rigurosa que el requisito se cumple durante la explotación del sistema.
  • Singulares. La definición incluye un único requisito. Lo que luego nos puede ayudar a auditar y validar cada requisito de manera única y sencilla.
  • Posibles. Que sean técnicamente posibles, dentro de las restricciones propias del proyecto. Esto incluye que sean posibles bajo los análisis de riesgo o coste-beneficio.
  • Referenciable. Que pueda ser referenciado o identificado de manera única, ordenada y estructurada. Que tenga una codificación correcta y unívoca.
  • Verificables. Que existan mecanismos que permitan verificar que realmente el requisito se cumple y criterios definidos para validarlo

Aunque me gustaría también añadir una propiedad que se mencionaba en el estándar original de esta norma (IEEE 830)

  • Modificable/gestionable. Que existan mecanismos para, cuando sea necesario y dentro de los procedimientos y formalismos establecidos para la gestión del producto o proyecto, poder modificar la definición del requisito, su eliminación o la inclusión de nuevos requisitos siguiendo los criterios anteriores.

Los requisitos pueden ser funcionales o no funcionales:

  • Funcionales. Hacen referencia a funciones o resultados esperados del sistema, enfocados en resolver el problema o la operativa para el que fueron creados. Responden a la pregunta de qué debe hacer el sistema.
  • No funcionales. Hacen referencia a detalles, aspectos, atributos o propiedades del sistema enfocados en cómo se debe resolver el problema o la operativa objeto del sistema. Responden a la pregunta de cómo lo debe hacer el sistema.

Se podría decir que los requisitos funcionales representan la parte del mundo real que toca al sistema y los no funcionales la parte tecnológica.

El análisis completo de los requisitos funcionales es relativamente sencillo. Si se nos pasa alguno, es muy seguro que estemos olvidando una funcionalidad relevante del sistema. Los cambios, añadidos y eliminaciones de requisitos funcionales suelen tener impacto en el alcance del proyecto. Además, son aquellos donde el usuario o los no especialistas en tecnología aportan mucho más, siendo el feedback practicamente suyo por completo.

Sin embargo, hacer un análisis completo de los requisitos no funcionales es más complicado. Primero, porque los actores que más feedback pueden dar en el análisis de los requisitos no funcionales son necesariamente aquellos con conocimientos técnicos; y normalmente no están en el conjunto de actores que conocen la naturaleza del problema, sino en el de los analistas.

En segundo lugar y más importante, porque se confunden con facilidad con decisiones propias del diseño. Algo, que aparentemente, parece una restricción o exigencia técnica, es solamente un efecto de una decisión de diseño tomada, y su obligación se debe a la vinculación con este diseño. Si cambiamos el diseño, muy posiblemente el requisito cambie o pierda consistencia. Si un requisito no funcional puede cambiarse por otro o cambia si cambiamos el diseño, es muy probable que estemos hablando de una consecuencia del diseño de la solución, y no de un requisito como tal. Este aspecto es importante, porque los requisitos no deben condicionar la implementación (solo su resultado o producto). Por eso, el exceso de definición en este aspecto, no es todo lo beneficioso que pensamos.

Desgraciadamente un requisito no funcional pasado por alto puede tener efectos catastróficos en un diseño o implementación ya iniciados. Esta lista, como checklist que es, tiene como único objetivo facilitar que el análisis de requisitos sea completo y evitar que se nos pase por alto algún aspecto que podría ser útil a nuestro análisis. La gran mayoría de los requisitos de esta lista no van a aplicar ni tener sentido para el problema que estemos analizando, pero lo importante es que no se nos pase aquel requisito que sí es relevante, beneficioso o imprescindible.

Por último, el conjunto de los requisitos no funcionales tienen unos efectos en el reparto de la carga de trabajo de implementación que, por lo general, son mayores que el de los requisitos funcionales. Cada diferente requisito no funcional debe abordarse como una solución separada, heterogénea y poco acoplada con las de otros requisitos, con las consecuencias que esto tiene en el desempeño y en la curva de aprendizaje. Las plataformas más generalizadas como son Java o Microsoft .net, han infravalorado este aspecto de manera habitual. En Java suelen ser implementados por librerías de terceros, que aveces tienen su clon en versiones oficiales posteriores de la plataforma; en el caso de .net, es común que cambien bastante de versión en versión. Nuevas plataformas como Django o Ruby on Rails, se centran precisamente en la reusabilidad del código relativo estos requisitos con bastante acierto, facilitando y focalizando el trabajo del desarrollador en lo funcional.

Checklist

  • Seguridad
    • Seguridad física tanto de los sistemas como los medios de almacenamiento, líneas de comunicación, copias de respaldo.
    • Cifrado de datos, tanto en las comunicaciones, como medios de almacenamiento, copias de respaldo.
    • Auditabilidad, qué información y mecanismos existen para revisar la operativa de la solución, qué mecanismos garantizan la fiabilidad e integridad de esa información.
    • Control de acceso, cómo se autentican los usuarios, cuál es el modelo de autorización, cuál es el ciclo de vida de las credenciales y sesiones
    • Qué información está disponible en el acceso anónimo, qué damos a conocer de la organización, cómo protegemos nuestros sistemas del fingerprinting
    • Cómo protegemos la integridad de la información, cómo validamos que sea correcta, cómo impedimos su manipulación no autorizada
    • Cómo se gestionan los errores para que sean siempre controlados y no desvelen información no autorizada
    • Cómo impedimos la operativa no autorizada, cómo protegemos la manipulación de peticiones o servicios qué información es insertable mediante formularios, servicios o uploads de ficheros
    • Cómo se van a gestionar los incidentes de seguridad
    • Si nos vamos a ceñir a algún tipo de guía de seguridad o si va a ser necesario certificar el sistema contra algún estándar u obligación legal, bien por criterios de calidad o por exigencia externa
  • Capacidad y Escalabilidad
    • Qué niveles de rendimiento se necesitan:
      • Nivel mínimo aceptable para no mermar la experiencia de usuario
      • Número de usuarios concurrentes
      • Operaciones o transacciones por unidad de tiempo
    • Qué niveles de capacidad se necesitan:
      • Requisitos de memoria principal
      • Requisitos de memoria secundaria, terciaria y offline
      • Cachés de memoria intermedios
      • Requisitos de capacidad de la copia de respaldo
      • Tamaños de colas de mensajes y de servidores antes del desbordamiento o descarte de la petición
      • Número máximo de peticiones concurrentes por servicio
    • Si el sistema debe estar preparado para la escalabilidad vertical (más recursos por nodo) u horizontal (más nodos simultáneos por nivel)
    • Plan de capacidad o cómo se espera que evolucionen los requisitos anteriores con el tiempo
  • Disponibilidad
    • Qué componentes están replicados de manera activa o pasiva
    • Ciclo de vida de la información
      • Cómo discurre la información desde que se procesa hasta que se almacena en la copia de respaldo
      • En qué componentes se almacena de forma persistente y en cuáles volátil
      • Dónde se pueden introducir sondas para extraer información, bajo qué criterios o restricciones
      • Cómo y cuándo se historifica la información, cómo se borra, soft-delete (marcado del registro como borrado) o hard-delete (borrado físico de la información)
      • Qué estados de la información pueden considerarse estables o coherentes (¿un rollback destruye la transacción o la devuelve a un punto estable intermedio anterior?)
    • Cuál es el nivel de detalle o de precisión de la información
    • Si las operaciones y servicios son idempotentes o puras
    • La  copia de respaldo:
    • Plan de continuidad
      • Ante una caída de servicio cómo se espera continuar la actividad sin el sistema
      • Cuál es el tiempo máximo admisible de esta caída o cómo afecta a la actividad en función de este tiempo
    • Plan de recuperación
      • Ante una caída de servicio cómo se espera recuperar el sistema para que dé servicio
      • Cuál es el tiempo de recuperación estimado
  • Mantenibilidad
    • Qué arquitectura, framework, infraestructura de hardware o software base
    • Qué metodologías de trabajo
    • Qué estándares de codificación, nomenclaturas o convenciones
    • Qué herramientas de ciclo de vida de producto, de construcción del producto, de integración continua o de chequeo de software
    • Qué sistemas de versionado y nombrado de versiones, así como las políticas de versionado
    • Qué políticas de adopción/integración de librerías y de software de terceros
    • Qué políticas de gestión y configuración de entornos, qué políticas de gestión del cambio
    • Cómo se gestionan de logs y trazas y con qué herramientas
    • Qué políticas, procedimientos y herramientas de gestión de incidencias
    • Qué documentación se va a generar y en qué formato
    • Qué indicadores o estadísticas se monitorizan para conocer el estado o salud del sistema
  • Ciclo de vida
    • Cómo se despliega/repliega
    • Cómo se realizan las intervenciones o paradas del sistema
    • Cómo se realizan el upgrade de componentes, así como de los datos y parametrizaciones del aplicativo
  • Robustez y estabilidad
    • Cómo se gestionan los errores del sistema
      • qué información muestran al usuario
      • cómo se informa al usuario de la situación actual de su transacción y de cuáles son los siguientes pasos a seguir
      • qué información almacenan para la identificación y el análisis del error
    • Cómo se recupera el sistema de los errores, cómo vuelve a un punto estable parcial (punto de recuperación intermedio) o total
    • Cómo se gestionan los bugs desde su descubrimiento hasta su resolución, cómo se incluyen en las pruebas de regresión del sistema
  • Integridad y Consistencia
    • Qué es una transacción, qué componentes comprende, cuál es su alcance
    • Si se permiten faltas de sincronismo en la replicación de la información entre componentes (porque tarda en llegar de uno a otro) o de integridad (porque se permiten inconsistencias entre componentes)
    • Qué controles de integridad y coherencia de datos
  • Integración
    • Qué interfaces se definen con otras aplicaciones, de qué tipo
    • Qué componentes ya existentes en la organización se utilizan, cuál es la política de reusabilidad
    • Cómo de divide en módulos diferenciados, cómo se integran entre sí
  • Configuración
    • Cómo se configura y parametriza
    • Qué es parametrizable
    • Cuál es el alcance de cada parámetro: del sistema, por entorno, por usuario, por región…
    • Cuáles son los valores por defecto
  • Internacionalización
    • Cómo se soporta el uso de múltiples idiomas, qué idiomas se soportan, cómo se traduce la solución a otros idiomas
    • Cómo se parametrizan los diferentes aspectos regionales de formato numérico, fechas, aspecto…
    • Cómo se soportan las zonas y usos horarios, cómo se gestionan los cambios de horario, qué convenciones tiempo se utilizan
  • Legales
    • Cuál es la licencia o condiciones de uso de la aplicación
    • Cuáles son y cómo afectan las licencias y condiciones de uso del software de terceros
    • Qué requisitos o exigencias legales deben tenerse en cuenta
  • Usabilidad
    • Navegabilidad
      • Cuál es el mapa de navegación
      • Cuáles son los criterios de navegación (adelante, atrás, histórico, menus, error…)
      • Cómo se indica en todo momento en qué lugar nos encontramos
    • Ayuda en pantalla
      • Cuál es el nivel de detalle de esa ayuda
      • Cuál es la terminología utilizada
      • Cómo se referencia a las diferentes partes del manual o documentación
    • Aspecto
      • Colores, fuentes y maquetación
        • Cómo se usan para que estén acorde al sentido o significado de lo que muestran
        • Guía corporativa de diseño y estilo
        • Cómo se adapta el interfaz a dispositivos con poco tamaño o monocromo
      • Contenido
        • Cómo se maqueta y distribuye
        • Cómo es de legible el texto
        • Cómo se introducen y validan valores y formularios
        • De dónde se pueden obtener imágenes (banco corporativo de imágenes)
    • Responsible design
      • Cómo se adecua, transforma y maqueta el contenido en los diferentes dispositivos y tamaños
    • Qué estándares de formateado o visualización se siguen
    • Qué cliente se utiliza
      • Qué navegadores son soportados
    • Usabilidad
      • Cuál es el glosario de términos y comandos
      • Cómo se informa al usuario del estado actual de su operación:
        • En espera o ejecutando una acción, del estado  de dicha operación y del tiempo estimado de espera
        • En la llegada de eventos
        • Del resultado de una operación
      • Cómo se avisa de errores, alertas y se solicitan confirmaciones
      • Cómo se adapta el UI para mostrar las opciones posibles
      • Cómo se definen los atajos y el uso del teclado
      • Cómo se define el uso del ratón o de un dispositivo multitáctil
      • Cómo se habilita el deshacer/rehacer de operaciones, cómo se gestiona ese default

Referencias

http://leadinganswers.typepad.com/leading_answers/2009/03/nonfunctional-requirements-minimal-checklist.html

http://thoughts-agile.blogspot.com.es/2013/09/non-functional-requirements.html

http://www.eyefodder.com/2011/06/quality-software-non-functional-requirements.html

http://www.utdallas.edu/~chung/RE/IEEE830-1993.pdf

Licencia Creative Commons
Esta entrada de Juan Francisco Adame Lorite está publicada bajo una licencia Creative Commons Atribución-CompartirIgual 3.0 Unported.
Categorías:Arquitectura, Desarrollo
A %d blogueros les gusta esto: