Introducción al curso

1

Diseño y Documentación de Arquitectura de Software

Atributos de calidad

2

Atributos de Calidad en Sistemas: Definición y Medición

3

Idoneidad Funcional: Completitud, Exactitud y Pertinencia

4

Eficiencia de Ejecución en Sistemas Informáticos

5

Compatibilidad en Sistemas: Interoperabilidad y Coexistencia

6

Subcaracterísticas de Usabilidad en Desarrollo de Software

7

Confiabilidad de Sistemas: Madurez, Disponibilidad, Resiliencia y Recuperación

8

Seguridad de Usuarios en Desarrollo de Software

9

Subcaracterísticas de Mantenibilidad en Sistemas de Software

10

Medición de Adaptabilidad en Sistemas de Software

11

Relación y Tensión entre Atributos de Calidad en Sistemas de Software

12

Atributos de Calidad en Arquitectura de Software

Patrones de arquitectura

13

Patrones de Arquitectura Monolítica y Distribuida

14

Modelo Vista Controlador: Separación de Responsabilidades en Aplicaciones

15

Arquitectura de Capas: Diseño y Comunicación entre Niveles

16

Patrones de Arquitectura Orientada a Eventos y Event Sourcing

17

Patrón de Arquitectura MicroKernel y su Implementación en IDEs

18

Arquitectura "Comparte Nada": Optimización y Procesamiento de Datos

19

Patrón de Microservicios en Arquitectura de Software

20

Patrón CQRS para Separación de Consultas y Comandos

21

Arquitectura Hexagonal: Diseño y Aplicación Práctica

22

Diseño Orientado al Dominio: Conceptos y Aplicaciones Prácticas

23

Patrones de Arquitectura para Aplicaciones Escalables y Modulares

24

Patrones de Arquitectura en Proyectos de Crecimiento Empresarial

Diseño de una arquitectura

25

Diseño de Arquitecturas a Medida: Herramientas y Estrategias

26

Tipos de Conectores en Arquitectura de Software

27

Conectores Asíncronos y Sincrónicos: Implementación y Uso Práctico

28

Diferencias entre Enrutadores y Difusores en Comunicación de Mensajes

29

Conexión de Productores y Consumidores con Colas de Mensajes

30

Framework de Diseño Orientado a Atributos: Escenarios y Tácticas

31

Tácticas para Mejorar la Disponibilidad de Sistemas

32

Tácticas para Mejorar la Disponibilidad del Sistema

33

Tácticas para Mejorar la Mantenibilidad del Software

34

Prevención de Efectos Dominó en Mantenibilidad de Software

35

Estrategias para Mejorar la Eficiencia de Ejecución en Sistemas

36

Tácticas de Seguridad Informática para Detectar, Resistir y Recuperarse de Ataques

37

Estrategias para Mejorar la Capacidad de Prueba de Software

38

Tácticas de Usabilidad en Diseño de Interfaces de Usuario

39

Validación de Arquitectura con ATAM y Métricas de Calidad

40

Diseño de Arquitectura para Startups y Empresas Escalables

Modelado y documentación de arquitectura

41

Documentación Efectiva de Arquitectura de Software

42

Sincronización de Modelos de Arquitectura y Código Fuente

43

Evaluación de Atributos de Calidad en Arquitectura de Software

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Prevención de Efectos Dominó en Mantenibilidad de Software

34/43
Recursos

¿Cómo prevenir efectos dominó en sistemas de software?

Los efectos dominó en software ocurren frecuentemente cuando un cambio en un módulo genera la necesidad de cambiar muchos otros, impactando potencialmente todo el sistema. Prevenir estos efectos es crucial para mejorar la mantenibilidad del software y se logra principalmente mediante la ocultación de información y el mantenimiento de interfaces.

¿Por qué ocultar información es clave?

Ocultar información es una táctica que promueve la encapsulación, un principio fundamental en la programación orientada a objetos. Al permitir que un módulo o un objeto oculte ciertos elementos de información, se asegura que los agentes externos dependan de una interfaz estable y no de detalles internos que pueden cambiar.

Por ejemplo, si tienes un módulo que calcula impuestos, puedes ofrecer una interfaz pública que maneje este cálculo de manera consistente, independientemente de cómo los detalles del cálculo interno puedan cambiar a lo largo del tiempo. Esto reduce el riesgo de que los cambios internos afecten a otros módulos que dependen de esta funcionalidad.

¿Cómo mantener una interfaz sólida?

Mantener una interfaz implica definir claramente cómo otros componentes o servicios interactúan con tu módulo a través de un conjunto consistente de funciones o métodos. Al establecer una única interfaz que gestione todas las interacciones necesarias, cualquier cambio interno no afectará a los usuarios externos de tu servicio.

Por ejemplo, si tienes que agregar un paso adicional al proceso de cálculo, mientras la interfaz externa no cambie, los clientes del servicio no se verán afectados. Esto es esencial para lograr un sistema más robusto y fácil de actualizar.

¿Cuál es el rol de los intermediarios en la programación?

Los intermediarios actúan como puentes entre módulos o componentes no compatibles, ayudando a gestionar cambios en interfaces o mensajes sin afectar la estabilidad del sistema. En programación orientada a objetos, patrones como FASAD, PROXY o ADAPTER permiten a los desarrolladores desacoplar componentes y facilitar la evolución del sistema a lo largo del tiempo.

¿Qué es la ley de Demeter y cómo aplica?

La ley de Demeter, también conocida como el principio de menor conocimiento, sugiere que un módulo o componente sólo debe conocer los otros módulos directamente relacionados con él, no las dependencias de sus dependencias. Al limitar estas conexiones, se reduce el riesgo de introducir errores cuando un componente intermedio cambia.

Un ejemplo clásico es cuando gestionas órdenes de compra: en lugar de navegar directamente a través de varios objetos conectados para obtener información del vendedor de un producto, puedes preguntar directamente al objeto principal (en este caso, la orden) por los vendedores, manteniendo así el conocimiento limitado y la interacción modular.

¿Cómo aprovechar el polimorfismo y el reemplazo de componentes?

El polimorfismo permite que los objetos cambien su comportamiento sobre la marcha, dependiendo de su estado o tipo de instancia. Usar esta característica, especialmente común en la programación orientada a objetos, es clave para diferir enlaces y ofrecer flexibilidad en la implementación de funcionalidades.

¿Cuándo utilizar el reemplazo de componentes?

El reemplazo de componentes permite la actualización o sustitución de un módulo sin alterar el sistema. Esto es posible si los componentes se enlazan regularmente en tiempo de carga, permitiendo su renovación sin necesidad de detener el sistema.

Imagina una aplicación que utiliza plugins: puedes actualizar o cambiar un componente simplemente instalando un nuevo plugin que cumpla con la misma interfaz, lo que brinda al sistema la capacidad de adaptarse sin comprometer la estabilidad.

¿Qué beneficio aportan los protocolos a la arquitectura de software?

Adherirse a protocolos de comunicación bien definidos, como JSON o XML, es crucial para que los módulos se comuniquen efectivamente sin importar sus cambios internos. Esto no sólo facilita la mantenibilidad, sino que también asegura que los módulos pueden desplegarse de forma independiente, promoviendo una arquitectura de software modular y eficiente.

¿Cómo implementar archivos de configuración efectivamente?

Utilizar archivos de configuración para definir cómo se conectan diferentes partes del sistema es una práctica común. Estos archivos permiten ajustar la configuración y las interacciones entre módulos de forma dinámica, sin necesidad de recompilar el sistema. Son especialmente útiles en arquitecturas de plugins donde las configuraciones pueden dictar qué extensiones o servicios se utilizan en cada caso, proporcionando flexibilidad y control sobre el flujo de trabajo del software.

Aportes 12

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Apuntes:

Prevenir efectos dominó. Trabaja estrictamente con las dependencias. Es decir, cuándo podemos detectar que un cambio generaría problemas en otros módulos u otras dependencias.
• Ocultar información. Cualquier módulo u objeto que diseñemos, tenga la capacidad de ocultar cierta parte de la información para que los agentes externos no dependan de esa información puntual sino de una interfaz clara que no puedan cambiar por más que la información cambie. De esta forma podemos garantizar que, si el cambio de la información es importante, los dependientes no necesiten cambiar porque están pasando por una interfaz que no cambió.
• Mantener la interfaz. Si tengo un servicio que hace algo, la dependencia a ese servicio va a ser a través de una interfaz clara, de lo contrario cualquier acción cuándo cambie puede poner en riesgo el módulo.
• Restringir comunicación. Para generar sistemas que estén acoplados de forma ligeras, en vez de conocer las dependencias de tus dependencias, siempre te limites a tus dependencias directas, de esta forma cualquier cambio en la forma que tus dependencias trabajan no afecta al módulo en el que estás trabajando.
• Intermediarios. Hablamos de un punto dónde podamos compatibilizar a un módulo con otro y si dejan de ser compatibles, estos intermediarios puedan servir como punto de compatibilidad.

Diferir enlace. Habla sobre cómo podemos hacer para que un cambio en nuestro código no requiera desplegar toda la aplicación completa.
• Registro en ejecución. Cuando un módulo o servicio depende de otro, si dependen fuertemente van a requerir estar compilados juntos. Si nosotros podemos diferir esa compilación y que se registre un servicio en momento de ejecución, es decir que se ponga disponible a sus dependencias en el momento de ejecución, podemos hacer que estos servicios se puedan desplegar independientemente.
• Archivos de configuración. Van a servir para en momento de ejecución saber cómo conectar varias partes. Es imprescindible que nuestros módulos dependan de interfaces y no de implementaciones específicas.
• Polimorfismos. Un objeto pueda comportarse de forma diferente en base a su estado. A través del polimorfismo podemos postergar la forma en que se resuelve un problema dependiendo de qué instancia del objeto será.
• Reemplazo de componentes. Tener la capacidad de desplegar un componente y luego desplegar su reemplazo, o quizás otro componente que respete esa interfaz, y que todo el resto de nuestra aplicación no necesite cambiar.
• Adherir a protocolos. Nos permite tener un protocolo claro entre dos módulos y no necesitar saber la instancia específica o el tipo específico de un módulo.

Ley de Demeter o el principio de menor conocimiento, esta ley dice que para generar sistemas que estén acoplados de forma ligera en vez de conocer las dependencias de tus dependencias siempre te limites a hablar con tus dependencias directas. De esta forma cualquier cambio en la forma en la que tus dependencias trabajan no afecta al modulo que estas trabajando.

Escenario: Mantenibilidad

Estimulo: Pedido de cambio / Nuevo requerimiento

  • Prevenir efectos domino
    • Ocultar información
    • Mantener la interfaz
    • Restringir comunicación
    • Intermediarios
  • Diferir enlace
    • Registro en ejecución
    • Archivos de configuración
    • Polimorfismo
    • Remplazo de componentes
    • Adherir a protocolos

Cambios semánticos. Si la semántica de lo que hacemos cambia, el modulo que lo implementa también cambiara. Se relaciona con el sentido. Cambia la lógica.
Cambios sintéticos. Cambios en la secuencia de lo que se hace. Los cambios de “Mantener la interfaz” funcionan aquí. Se relaciona con la estructura.

semantico: que se relaciona con el sentido
sintactico: que se relaciona con la estructura

COMPLETO:
Familias de tácticas:
1.- Confinar modificaciones. Las tácticas van a intentar trabajar sobre nuestros módulos para que cada cambio que nos pidan esté confinado a sólo un módulo. Cuando logramos esto logramos que las dependencias entre módulos sean más ligeras y el cambio que nos proponen no afecte a muchas partes del sistema.
a) Coherencia semántica. Habla de la relación entre las responsabilidades de los módulos. Hablamos de acoplamiento y cohesión. Si logramos encontrar la cohesión en un módulo entonces vamos a poder hacer que ese módulo sea más mantenible. De lo contrario es posible que ese módulo cambie por diferentes razones.
Abstraer servicios comunes. Cuando encontramos que la aplicación tiene servicios más genéricos de no necesario podemos abstraerlos a un punto común y que las dependencias vayan de los módulos cohesivos a un servicio o modulo externo.
b) Generalizar. Al generalizar un módulo podemos separar lo específico de lo genérico.
c) Limitar opciones disponibles. Limitar el rango de modificación nos ayuda a que sea más mantenible.
d) Anticipar cambios. Prepararnos para algún cambio que nosotros mismo sepamos que se deberá de dar en el futuro tomando en cuenta una estrategia sobre como incorporar el nuevo cambio. Los patrones de diseño suelen estar orientados a esto (Patrón estrategia).
2.- Prevenir efectos domino. Trabaja estrictamente con las dependencias, es decir cuando podemos detectar que un cambio generaría problemas en otros módulos o dependencias.
Prevenir efectos dominó. Trabaja estrictamente con las dependencias. Es decir, cuándo podemos detectar que un cambio generaría problemas en otros módulos u otras dependencias.
• Ocultar información. Cualquier módulo u objeto que diseñemos, tenga la capacidad de ocultar cierta parte de la información para que los agentes externos no dependan de esa información puntual sino de una interfaz clara que no puedan cambiar por más que la información cambie. De esta forma podemos garantizar que, si el cambio de la información es importante, los dependientes no necesiten cambiar porque están pasando por una interfaz que no cambió.
• Mantener la interfaz. Si tengo un servicio que hace algo, la dependencia a ese servicio va a ser a través de una interfaz clara, de lo contrario cualquier acción cuándo cambie puede poner en riesgo el módulo.
• Restringir comunicación. Para generar sistemas que estén acoplados de forma ligeras, en vez de conocer las dependencias de tus dependencias, siempre te limites a tus dependencias directas, de esta forma cualquier cambio en la forma que tus dependencias trabajan no afecta al módulo en el que estás trabajando.
• Intermediarios. Hablamos de un punto dónde podamos compatibilizar a un módulo con otro y si dejan de ser compatibles, estos intermediarios puedan servir como punto de compatibilidad.
3.- Diferir enlace. Habla sobre cómo podemos hacer para que un cambio en nuestro código no requiera desplegar toda la aplicación completa.
• Registro en ejecución. Cuando un módulo o servicio depende de otro, si dependen fuertemente van a requerir estar compilados juntos. Si nosotros podemos diferir esa compilación y que se registre un servicio en momento de ejecución, es decir que se ponga disponible a sus dependencias en el momento de ejecución, podemos hacer que estos servicios se puedan desplegar independientemente.
• Archivos de configuración. Van a servir para en momento de ejecución saber cómo conectar varias partes. Es imprescindible que nuestros módulos dependan de interfaces y no de implementaciones específicas.
• Polimorfismos. Un objeto pueda comportarse de forma diferente en base a su estado. A través del polimorfismo podemos postergar la forma en que se resuelve un problema dependiendo de qué instancia del objeto será.
• Reemplazo de componentes. Tener la capacidad de desplegar un componente y luego desplegar su reemplazo, o quizás otro componente que respete esa interfaz, y que todo el resto de nuestra aplicación no necesite cambiar.
• Adherir a protocolos. Nos permite tener un protocolo claro entre dos módulos y no necesitar saber la instancia específica o el tipo específico de un módulo.

Estos temas son un resumen de lo expuesto en este modulo…

 -------------------------------------------------
*)PRINCIPIOS GRASP
  +Encapsulamiento
  +Acoplamiento
  +Cohesion
  +Ley Demeter
  +Separation of Concerns
  +Invertion of Control
  +Don't Repeate Yourself
  +Keep it Simple Stupid
 -------------------------------------------------
*)PRINCIPIOS SOLID
  +Single Responsability Principal
  +Open/Closed Principal
  +Liskov Sustitution Principal
  +Interface Segregation Principal
  +Dependention Invertion Principal
 -------------------------------------------------
*)PATRONES ARQUITECTONICOS
  +Circuit Breaker
  +Publisher/Suscriber
  +Dashboard
  +Plugins
 -------------------------------------------------
*)PATRONES DISEÑO SOFTWARE
  ->CREACIONALES<-
  +Singleton
  +Prototype
  +Builder
  +Factory Method
  +Abstract Factory
  +Object Pool
  ->ESTRUCTURALES<-
  +Adapter
  +Bridge
  +Composite
  +Decorator
  +Facade
  +Flyweight
  +Proxy
->COMPORTAMIENTO<-
  +Iterator
  +Command
  +Observer
  +Tempalte Method
  +Strategy
  +Chain of Responsability
  +Interpreter
  +Mediator
  +Moment
  +Null Object
  +State
  +Visitor
 -------------------------------------------------
<h3>Prevenir efectos Domino:</h3>

Los cambios provocan otros cambios no previstos en el sistema.
Tácticas:

  • Ocultar Información
  • Mantener la Interfaz
  • Restringir Comunicación
  • Intermediarios
<h3>Diferir enlace:</h3>
  • Registro en ejecución
  • Archivos de Configuración
  • Polimorfismo
  • Reemplazo de Componentes
  • Adherir a Protocolos

Cuando hablamos de ocular información hablamos de encapsulamiento? Por ejemplo

### Adherencia a Protocolos #### Definición Utilización de protocolos de comunicación estandarizados para el intercambio de información entre módulos, permitiendo que evolucionen independientemente mientras respeten el contrato establecido. #### Protocolos Comunes * REST, GraphQL para APIs web * gRPC, Thrift para comunicación entre servicios * AMQP, Kafka para mensajería * JSON, XML, Protocol Buffers para serialización #### Beneficios * Desacopla productores y consumidores de servicios * Facilita la evolución independiente de componentes * Mejora la interoperabilidad entre sistemas heterogéneos * Simplifica la integración con sistemas de terceros #### Buenas Prácticas * Versionado explícito de APIs * Documentación detallada (OpenAPI, Swagger) * Compatibilidad hacia atrás cuando sea posible * Diseño de contratos centrado en el dominio, no en la implementación
### Prevenir Efectos Dominó Objetivo: Evitar que un cambio en un módulo cause una cascada de cambios en otros módulos del sistema. #### a) Ocultar Información * **Definición mejorada**: Implementar encapsulación para que los módulos externos dependan solo de interfaces estables y no de detalles de implementación. * **Beneficios**: * Reduce dependencias entre módulos * Permite cambios internos sin afectar a los consumidores * Simplifica el mantenimiento a largo plazo * **Ejemplo práctico**: Un módulo de cálculo de impuestos que expone métodos públicos estables mientras los algoritmos internos pueden cambiar según nuevas regulaciones. * **Principio relacionado**: Encapsulación en programación orientada a objetos. #### b) Mantener Interfaces Estables * **Definición mejorada**: Definir claramente cómo otros componentes interactúan con un módulo mediante un conjunto consistente de funciones. * **Técnicas**: * Contratos de interfaz bien definidos * Versiones de API para cambios significativos * Uso del patrón Fachada para unificar puntos de acceso * **Beneficio clave**: Permite actualizar implementaciones internas sin afectar a los clientes del servicio. * **Ejemplo**: Añadir pasos adicionales a un proceso interno mientras se mantiene la misma firma de método en la interfaz pública. #### c) Uso de Intermediarios * **Definición mejorada**: Implementar componentes que actúen como puentes entre módulos incompatibles o que puedan cambiar independientemente. * **Patrones aplicables**: * Patrón Fachada (FACADE): Simplifica interfaces complejas * Patrón Proxy: Controla acceso a objetos * Patrón Adaptador (ADAPTER): Convierte interfaces incompatibles * **Beneficios**: * Gestiona cambios en interfaces sin propagar efectos * Facilita la evolución independiente de componentes * Mejora la testabilidad de los módulos #### d) Aplicar la Ley de Demeter (Complemento) * **Definición**: Principio de mínimo conocimiento - un objeto debe tener conocimiento limitado sobre otros objetos. * **Regla práctica**: Un método de un objeto debe invocar solo: * Métodos del propio objeto * Métodos de parámetros pasados al método * Métodos de objetos creados dentro del método * Métodos de componentes directos del objeto

⭐️ Excelente ⭐️

⭐️⭐️⭐️⭐️⭐️