Vídeos

Acá pueden encontrar vídeos educativos sobre Ingeniería de Software donde explico, por ejemplo, cuestiones sobre ingeniería de requerimientos, diseño y arquitectura de software (en particular patrones de diseño), especificaciones formales de software y validación y verificación de software.

Todos estos vídeos los pueden encontrar también en mi canal de Youtube.

Introducción a la Ingeniería de Software (01). Presentación de conceptos muy básicos y generales sobre la Ingeniería de Software. Definición de Ingeniería de Software; conocimientos y habilidades del ingeniero de software; las cuatro descripciones fundamentales de un programa; fracasos y éxitos de la Ingeniería de Software; posibles causas del estado actual de la disciplina; introducción a los métodos formales.

Ingeniería de Requerimientos

Principios de la Ingeniería de Requerimientos. Presento los que a mi criterio son los cuatro principios de la Ingeniería de Requerimientos: 1) el negocio detrás del sistema es el criterio para incluir, rechazar y priorizar cada requerimiento; 2) los requerimientos están en el dominio de aplicación y se los debe describir usando el vocabulario de ese dominio; 3) los requerimientos no funcionales, también son requerimientos; y 4) nunca ir a una reunión con el cliente sin un prototipo. Para profundizar en estos temas sugiero la siguiente bibliografía:

Arquitectura y diseño

Conceptos y vocabulario

Conceptos y vocabulario básicos sobre diseño de software (01). Definición de diseño de software; módulo; interfaz de un módulo; principio de diseño para el cambio; ítem de cambio; breve descripción del criterio basado en la ocultación de información para definir módulos y sus interfaces.

Conceptos y vocabulario básicos sobre diseño de software (02). El vídeo incluye una explicación sobre los tres niveles de la descripción estructural de un sistema de software: diseño de componentes o módulos, patrones de diseño y estilos arquitectónicos (arquitectura de software o nivel arquitectónico). Se trata de establecer las diferencias y relaciones entre estos tres niveles.

Conceptos de Herencia y Composición (01). El vídeo explica dos conceptos importantes en el Diseño Orientado a Objetos. En primer lugar se explica el concepto de herencia de interfaces y luego el de composición de objetos. Ambos conceptos son importantes para obtener buenos diseños orientados a objetos y para comprender los patrones de diseño. Estos conceptos los utilizo en muchos de los vídeos. Es importante que vean este vídeo porque otras personas le dan significados diferentes a estos conceptos lo que puede llevar a confusión.

¿Para qué sirve la herencia? (01). En este vídeo explico cuál es el problema que soluciona el concepto de herencia y por lo tanto cuándo la herencia es útil. El problema en cuestión es la duplicación o multiplicación del código cliente. Este problema se produce cuando tenemos módulos con la misma interfaz pero diferentes implementaciones que deben ser pasados a una o más subrutinas externas. Como son módulos (tipos) diferentes deberíamos tener una subrutina por cada módulo. La herencia permite solucionar esto definiendo un padre común a todos los módulos y poniendo este nuevo tipo como parámetro de las subrutinas externas.

¿Para qué sirve la herencia? (02). En este vídeo se relaciona el concepto de herencia con el de ítem de cambio. Se muestra un ejemplo de cómo utilizar la herencia partiendo de un ítem de cambio. Finalmente se generaliza el ejemplo mostrando una metodología muy simple en la cual la herencia se utiliza para resolver cambios previstos en un ítem de cambio.

Introducción a la arquitectura de software (01). Breve introducción a la arquitectura de software. Diseño, arquitectura y estructura de software. Los tres niveles de la estructura de un sistema de software: estilo arquitectónico, patrones de diseño y diseño de componentes. Por qué definir una arquitectura de software. Criterio para seleccionar un estilo arquitectónico.

Introducción a la arquitectura de software (02). En este vídeo muestro dos arquitecturas diferentes (cada una derivada de un estilo arquitectónico distinto) para el mismo sistema. Los estilos arquitectónicos usados son: tubos y filtros (pipes and filters) e invocación implícita (también conocido como publicar y suscribir o tool abstraction u orientación a eventos). Si quieren aprender más sobre estilos arquitectónicos pueden leer mi apunte de clase ``Catálogo incompleto de estilos arquitectónicos'' que pueden descargar de aquí.

Patrones de diseño

Introducción a los patrones de diseño (01). En este vídeo presento una introducción a los patrones de diseño. Comienzo por comentar la definición de diseño de software; luego muestro la ayuda que brindan los patrones de diseño cuando se diseña un sistema de software; a continuación comento la definición de patrón de diseño; también menciono cómo estudiar un patrón de diseño; y para finalizar menciono la posibilidad de combinar o integrar varios patrones de diseño cuando se desarrolla un sistema.

Patrón de diseño Decorador

Aplicación del patrón de diseño Decorador (01). (Envoltorio, Decorator o Wrapper). Agregar control de acceso a las subrutinas de un módulo o clase. No requiere programación orientada a objetos. Diseño muy simple pero limitado.

Aplicación del patrón de diseño Decorador (02). Continuación del vídeo que muestra una aplicación del patrón de diseño Decorador (Envoltorio, Decorator o Wrapper). Agregar control de acceso a las subrutinas de un módulo o clase. No requiere programación orientada a objetos. Versión con la posibilidad de configurar dinámicamente los decoradores.

Aplicación del patrón de diseño Decorador (03). Continuación del vídeo que muestra una aplicación del patrón de diseño Decorador (Envoltorio, Decorator o Wrapper). Agregar control de acceso a las subrutinas de un módulo o clase. Versión Orientada a Objetos.

Aplicación del patrón de diseño Decorador (04) (Envoltorio, Decorator o Wrapper). Implementar nuevos requerimientos sobre una caja de ahorros bancaria. El diseño permite incorporar y retirar la nueva funcionalidad sin afectar el resto del sistema. Comparación con otros diseños que no usan el patrón Decorador.

Patrón de diseño Estrategia

Aplicación del patrón de diseño Estrategia (01). (Política, Strategy o Policy). Implementar control u optimización de inventario (stock) El diseño permite incorporar y retirar algoritmos de control u optimización y mantiene separados los objetos que componen el inventario de los algoritmos que realizan el control u optimización. Permite generar un sistema sin control de inventario y permite cambiar el algoritmo de control en tiempo de ejecución. Comparación con otros diseños que no usan el patrón Estrategia.

Aplicación del patrón de diseño Estrategia (02). (Política, Strategy o Policy). Mostrar en pantalla un catálogo de productos. El diseño permite incorporar y retirar algoritmos de formateado del catálogo y mantiene separados los objetos que componen el catálogo de los algoritmos que realizan el formateado. Permite cambiar el algoritmo de formateado en tiempo de ejecución. Comparación con otros diseños que no usan el patrón Estrategia.

Patrón de diseño Fábrica Abstracta

Aplicación del patrón de diseño Fábrica Abstracta (01). (Abstract Factory o Kit). Creación de objetos de cada modelo de vehículo comercializado por un concesionario. Por el momento tenemos como clientes a tres concesionarios (uno de Ford, otro de Fiat y otro de BMW) pero queremos expandir nuestro negocio a concesionarios de otras marcas. Cada marca comercializa distintos tipos de vehículos (sedan, SUV, cupé, etc.); dentro de cada tipo cada marca vende diversos modelos (EcoSport, Focus, Siena, Serie 3, etc.). El problema es cómo crear los objetos que corresponden a cada modelo de cada marca cuando el programa está instalado en un concesionario de una marca particular. Por ejemplo, si instalamos en el programa en un concesionario Ford querremos que los objetos sean de tipo EcoSport y Focus; y cuando el programa corre en un concesionario Fiat querremos que sean Siena y 500X.

Patrón de diseño Método de Fabricación

Aplicación del patrón de diseño Método de Fabricación (01). En este vídeo se presenta la aplicación del patrón de diseño Método de Fabricación (Factory Method). Una empresa que vende un sistema de sueldos debe implementar una función para exportar los recibos de sueldo a PDF. El problema es que cada cliente define su propio formato de recibo de sueldo y la empresa espera poder vender su sistema a otros clientes. El patrón de diseño Método de Fabricación permite implementar este requerimiento de forma flexible, extensible y minimizando el código a entregar a cada cliente.

Patrón de diseño Puente

Aplicación del patrón de diseño Puente (01). En este vídeo se presentan dos ejemplos simples de aplicación del patrón de diseño Puente (Bridge o Manejador/Cuerpo o Handle/Body). El primer ejemplo consiste en configurar algoritmos de ordenación de manera tal que ordenen de forma ascendente o descendente según lo seleccione el usuario; la configuración se hace en tiempo de ejecución. El segundo ejemplo muestra cómo configurar un producto de manera tal de poder calcular su precio en cuotas según los planes de pago de diferentes tarjetas de crédito y bancos emisores.

Aplicación del patrón de diseño Puente a un vídeo juego muy simple (02). En este vídeo se presenta la aplicación del patrón de diseño Puente (Bridge o Manejador/Cuerpo o Handle/Body). El problema a resolver consiste en implementar un vídeo juego muy simple de forma tal que corra sobre diversas placas gráficas que proveen diferentes APIs. El juego consiste de un circuito, obstáculos y vehículos que lo deben recorrer. Hay diversos tipos de obstáculos y vehículos. Todos los elementos gráficos se construyen a partir de figuras geométricas simples como rectángulos, círculos, rectas, etc. Las APIs de las placas proveen funciones para dibujar estas figuras geométricas pero lo hacen de formas diferentes. Se espera que el vídeo juego pueda correr sobre otras placas gráficas que proveen APIs totalmente desconocidas.

Patrón de diseño Visitante

Aplicación del patrón de diseño Visitante a un vídeo juego muy simple (01). En este vídeo se presenta la aplicación del patrón de diseño Visitante (Visitor). El problema a resolver consiste en agregar funcionalidad a un vídeo juego muy simple de forma tal de no agrandar innecesariamente los módulos que ya están implementados. El juego consiste de un circuito, obstáculos y vehículos que lo deben recorrer. Hay diversos tipos de obstáculos y vehículos. Todos los elementos gráficos se construyen a partir de figuras geométricas simples como rectángulos, círculos, rectas, etc. Lo que ya está implementado son los módulos que dibujan el circuito, los obstáculos y los vehículos. Ahora queremos agregar tres funcionalidades: dibujar un circuito en miniatura de forma tal que el jugador pueda tener una idea global de cómo va la carrera; una tabla de posiciones; y dibujar escenas de choque entre un vehículo y los límites del circuito o los obstáculos.

Especificaciones formales

Introducción a los métodos formales (01). Breve explicación de qué son y para qué sirven los métodos formales para desarrollar software. Aplicación a un ejemplo mínimo que muestra las posibles ambigüedades, inconsistencias e incompletitudes de los requerimientos.

Formalizar o no formalizar esa NO es la cuestión. Analizo brevemente la resistencia de muchos programadores a utilizar lenguajes formales para especificar programas bajo el argumento de que formalizar programas es o muy difícil o ajeno a la programación. Mi punto es: programar ES formalizar. Entonces la especificación formal de software no puede ser ni más difícil ni más ajena a la programación que la programación misma.

Teoría de conjuntos

Matemática para programadores (01). Este es el primer vídeo de una serie donde intento mostrar cómo usar la teoría de conjuntos para escribir especificaciones formales de programas y, a través de esto, mejorar la calidad del código y de los proyectos de desarrollo. En este vídeo se explica el concepto de especificación de software en relación a los requerimientos y la implementación (programa). Además se introduce lo mínimo de la teoría de conjuntos finitos y se da una mínima primera especificación.

Matemática para programadores (02). Introducción a {log} (setlog). Instalación de Prolog y {log}. Escribir una especificación en {log}. Ejecutar casos de pruebas o simulaciones en {log}.

Matemática para programadores (03). Funciones como conjuntos de pares ordenados. Dominio de una función. Pertenencia de un elemento a un conjunto. Traducción a {log} (setlog) de los operadores de dominio y pertenencia. Aplicación al problema de las cuentas bancarias.

Matemática para programadores (04). Ejecución en {log} (setlog) de tests sobre la especificación corregida de la operación que abre una cuenta bancaria. Ejecución de un test que muestra cómo {log} permite obtener entradas a partir de salidas.

Matemática para programadores (05). Especificación de la operación que cierra una cuenta bancaria. Resta o diferencia de conjuntos. Aplicación de una función a su argumento. Traducción a {log} (setlog) de los operadores de resta de conjuntos y aplicación de función.

Matemática para programadores (06). Especificación de la operación que cierra una cuenta bancaria. Restricción y anti-restricción de dominio de un conjunto de pares ordenados.

Matemática para programadores (07). Implementación en {log} de tres versiones diferentes de la especificación de la operación para cerrar una cuenta bancaria usando diferencia de conjuntos y anti-restricción de dominio. Ejecución de algunos tests.

Matemática para programadores (08). Introducción a la unificación conjuntista (set unification). Constructor de conjuntos extensionales. Aplicación de la unificación conjuntista a la especificación de una operación para cerrar una cuenta bancaria.

Matemática para programadores (09). Implementación en {log} de la cuarta versión de la especificación de la operación para cerrar una cuenta bancaria. Esta versión utiliza unificación conjuntista. Ejecución de algunos tests. Comparación con las otras versiones.

Matemática para programadores (10). Demostración de propiedades de especificaciones de programas. Invariantes de estado. Invariantes de estado en el contexto de especificaciones basadas en teoría de conjuntos y lógica de primer orden. Aplicación al ejemplo de cuentas bancarias.

Matemática para programadores (11). Demostración automática de invariantes de estado con {log}. Satisfiability solver, fórmulas válidas (teoremas), satisfacibles e insatisfacibles. Equivalencia entre fórmulas válidas (teoremas) y fórmulas insatisfacibles.

Semántica formal de un lenguaje de programación

Semántica formal de un lenguaje de programación (01). La semántica de un lenguaje de programación establece el significado de los programas; es decir, cómo se comporta un programa o qué hace un programa. Normalmente la semántica de los lenguajes de programación se describe mediante ejemplos o reglas de funcionamiento descriptas en castellano. Formalizar la semántica de un lenguaje de programación significa establecer un modelo matemático preciso que indica de modo exacto cómo se comportan los programas. En este vídeo les presento la semántica formal de un lenguaje de programación (imperativo) muy simple. La semántica es operativa estructural. Es decir, se da una regla matemática para cada instrucción del lenguaje. Inicialmente muestro la gramática del lenguaje de programación y luego explico cómo dar la semántica formalmente. El contenido matemático del vídeo lo pueden ver en este documento PDF.

Semántica formal de un lenguaje de programación (02). Expresiones booleanas. En este vídeo extiendo el lenguaje de programación, presentado en el primer vídeo de la serie, con expresiones booleanas. En particular muestro cómo evaluar expresiones booleanas y cómo ejecutar programas cuyas sentencias condicionales son expresiones booleanas. El contenido matemático del vídeo lo pueden ver en este documento PDF.

Semántica formal de un lenguaje de programación (03). Arreglos. En este vídeo extiendo el lenguaje de programación, presentado en el segundo vídeo de la serie, con arreglos. La inclusión de arreglos implica tener que formalizar la posibilidad de que se trate de acceder a una componente de un arreglo que en realidad no existe. Por ejemplo si el arreglo A tiene 20 componentes, expresiones como A[-3] o A[102] son imposibles de evaluar porque tales componentes no existen (aunque es posible escribirlas porque la gramática las permite). Esto tiene consecuencias sobre la evaluación de expresiones enteras, booleanas y sobre la ejecución de sentencias. El contenido matemático del vídeo lo pueden ver en este documento PDF.

Validación y verificación

Introducción a la Validación y Verificación de Software (01). Las cuatro descripciones fundamentales para construir un software. Proceso continuo de validación y verificación. Diferencias entre validación y verificación. Ejemplo informal sobre prototipación de requerimientos.

V&V de distintos aspectos de un programa (02). Segundo vídeo de la serie Introducción a la Validación y Verificación de Software. Requerimientos funcionales y no-funcionales. V&V de aspectos no-funcionales de un sistema. Ejemplo aplicado a seguridad informática.

Introducción al testing de software (03). Tercer vídeo de la serie Introducción a la Validación y Verificación de Software. Origen del testing. Comparación del testing de software con el testing de productos de otras industrias. Dificultades esenciales del testing de software. El testing solo sirve para mostrar la presencia de errores en el código, nunca su ausencia.

Las 4 dificultades fundamentales del testing de software (04). 1ra dificultad) En la práctica es imposible garantizar la calidad de un software de dimensión industrial usando solo testing; 2da dificultad) Especificar cada caso de test, o sea decidir cada condición en la que testearemos el programa; 3ra dificultad) Encontrar valores concretos para cada caso de prueba; 4ta dificultad) Determinar si la salida que se obtiene para cada caso de prueba corresponde con la salida esperada o no. Esfuerzo de testing; automatización del testing según la industria; verdadera automatización del testing, testing basado en modelos (model-based testing).