Reemplazo de dependencias directas con mensajería

A veces, un módulo solo necesita notificar a otros que se han producido algunos eventos/cambios en él, y no importa lo que suceda con esta información más adelante.

En este caso, los módulos no necesitan "conocerse" en absoluto, es decir, contener enlaces directos e interactuar directamente, pero es suficiente solo para intercambiar mensajes (mensajes) o eventos (eventos).

A veces parece que la comunicación del módulo a través de mensajes es mucho más débil que la dependencia directa. De hecho, debido a que no se llama a los métodos, no hay información sobre las clases. Pero esto no es más que una ilusión.

En lugar de nombres de métodos, la lógica comienza a vincularse a tipos de mensajes, sus parámetros y datos transmitidos. La conectividad de dichos módulos está manchada.

Solía ​​ser como: llamamos métodos - hay conectividad, no llamamos métodos - no hay conectividad. Ahora imagine que el módulo A comenzó a enviar datos ligeramente diferentes en sus mensajes. Y al mismo tiempo, todos los módulos que dependen de estos mensajes no funcionarán correctamente.

Supongamos, anteriormente, al agregar un nuevo usuario, el módulo de autorización envió el mensaje USER_ADDED, y después de la actualización, comenzó a enviar este mensaje al intentar registrarse y adicionalmente indicar registro exitoso o no en los parámetros.

Por lo tanto, es muy importante implementar el mecanismo de mensajes de manera muy competente. Hay varias plantillas para esto.

Observador. Se utiliza en el caso de dependencia de uno a muchos, cuando muchos módulos dependen del estado de uno, el principal. Utiliza el mecanismo de correo, lo que significa que el módulo principal simplemente envía los mismos mensajes a todos sus suscriptores, y los módulos interesados ​​​​en esta información implementan la interfaz de "suscriptor" y se suscriben a la lista de correo.

Este enfoque se usa ampliamente en sistemas con una interfaz de usuario, lo que permite que el núcleo de la aplicación (modelo) permanezca independiente mientras informa a sus interfaces asociadas que algo ha cambiado y debe actualizarse.

Aquí el formato de los mensajes está estandarizado a nivel de sistema operativo, cuyos desarrolladores deben cuidar la retrocompatibilidad y una buena documentación.

La organización de la interacción a través de la distribución de mensajes tiene una "bonificación" adicional: la existencia opcional de "suscriptores" a los mensajes "publicados" (es decir, enviados). Un sistema bien diseñado como este permite agregar/eliminar módulos en cualquier momento.

autobús de mensajería

Puede organizar el intercambio de mensajes y usar el patrón Mediador para esto de una manera diferente .

Se usa cuando hay una dependencia de muchos a muchos entre módulos. El mediador actúa como intermediario en la comunicación entre módulos, actuando como un centro de comunicación y eliminando la necesidad de que los módulos se refieran explícitamente entre sí.

Como resultado, la interacción de los módulos entre sí ("todos con todos") se reemplaza por la interacción de los módulos solo con un intermediario ("uno con todos"). Se dice que el mediador encapsula la interacción entre múltiples módulos.

autobús de mensajería

Este es el llamado intermediario inteligente . Es allí donde los desarrolladores suelen comenzar a agregar sus muletas, que influyen en el comportamiento de los módulos individuales al activar / desactivar la recepción de ciertos mensajes.

Un ejemplo típico de la vida real es el control de tráfico del aeropuerto. Todos los mensajes de las aeronaves van a la torre de control del controlador en lugar de enviarse directamente entre aeronaves. Y el controlador ya toma decisiones sobre qué aviones pueden despegar o aterrizar y, a su vez, envía mensajes a los aviones.

¡Importante! Los módulos pueden enviarse entre sí no solo mensajes simples, sino también objetos de comando. Dicha interacción se describe en la plantilla de Comando . El resultado final es encapsular una solicitud para realizar una acción específica como un objeto separado.

De hecho, este objeto contiene un único método de ejecución () , que luego le permite pasar esta acción a otros módulos para su ejecución como un parámetro y, en general, realizar cualquier operación con el objeto de comando que se pueda realizar en objetos ordinarios.

Ley de Deméter

La Ley de Demeter prohíbe el uso de dependencias implícitas: "El objeto A no debe poder acceder directamente al objeto C si el objeto A tiene acceso al objeto B y el objeto B tiene acceso al objeto C".

Esto significa que todas las dependencias en el código deben ser "explícitas": las clases/módulos solo pueden usar "sus dependencias" en su trabajo y no deben pasar de ellas a otras. Un buen ejemplo es una arquitectura de tres niveles. La capa de interfaz debe funcionar con la capa lógica, pero no debe interactuar directamente con la capa de base de datos.

Brevemente, este principio también se formula de esta manera: "Interactuar solo con amigos inmediatos, y no con amigos de amigos". Con ello se consigue una menor coherencia del código, así como una mayor visibilidad y transparencia de su diseño.

La Ley de Deméter implementa el ya mencionado “principio de conocimiento mínimo”, que es la base del bajo acoplamiento y consiste en que un objeto/módulo debe conocer la menor cantidad de detalles posible sobre la estructura y propiedades de otros objetos/módulos y cualquier cosa en general, incluidos sus propios componentes .

Una analogía de la vida: si quieres que el perro corra, es estúpido ordenarle las patas, es mejor darle la orden al perro, y ella misma se encargará de sus patas.

Composición en lugar de herencia

Este es un tema muy amplio e interesante y merece al menos una conferencia aparte. Se rompieron muchas copias sobre este tema en Internet hasta que se llegó a un consenso: usamos herencia al mínimo, composición, al máximo.

El punto es que la herencia en realidad proporciona la conexión más fuerte entre clases, por lo que debe evitarse. Este tema está bien cubierto en el artículo de Herb Sutter " Preferir composición sobre herencia ".

Cuando comience a aprender patrones de diseño, se encontrará con un montón de patrones que gobiernan la creación de un objeto o su estructura interna. Por cierto, puedo aconsejar en este contexto que presten atención al patrón Delegado/Delegado y al patrón Componente , que provienen de los juegos .

Hablaremos más sobre patrones un poco más tarde.

undefined
3
Опрос
Software architecture, client-server architecture, MVC,  14 уровень,  9 лекция
недоступен
Software architecture, client-server architecture, MVC
Software architecture, client-server architecture, MVC