¿Podemos facilitar la adición de flujos de datos entre partes distantes de una base de código grande?

10

Cuando realizo cambios en sistemas grandes, a menudo enfrento el problema de que una parte de la funcionalidad necesita obtener algunos datos de otra parte, pero están en diferentes partes de un árbol de llamadas profundo y ramificado, posiblemente fluyendo a través de escuchas de eventos, llamadas diferidas, etc. De esta manera, un simple cambio puede aumentar rápidamente.

Una cita relacionada de la publicación del blog de Yossi Kreinin en http://www.yosefk.com/blog/i-want-a-struct-linker.html :

Tiene algún tipo de estructura de datos que pasa mucho. Pronto, lo más valioso de la estructura no son los datos que guarda, sino el hecho de que está disponible a través de un flujo de control.

Las variables globales son una forma clásica de dejar que el código "grite" a código distante, pero se sabe que son problemáticas. Las variables de ámbito dinámico son una forma más restringida, pero también son problemáticas.

¿Hay alguna investigación de lenguaje de programación dirigida a resolver este problema? ¿Podemos hacer que sea más fácil agregar flujos de datos imprevistos a una gran base de código, sin dejar de tener una comprobación estática, pruebas unitarias sencillas y otras ventajas?

Vladimir Slepnev
fuente
Supongo que tiene en mente el flujo de datos en un solo proceso, no hay comunicación entre procesos. Entonces, ¿qué tipo de problema ves que no puede ser resuelto por los mecanismos estándar de envío / escucha de eventos?
Doc Brown
Un ejemplo artificial: imagine que en el fondo de su sistema hay un código que envía al usuario un mensaje de texto. Y tiene un nuevo requisito de que el texto del mensaje dependa de la hora actual en la zona horaria del usuario. La pila de llamadas tiene este aspecto: un código que conoce la zona horaria del usuario, llama a un método que llama a un método que (... repite 15 veces) llama a un método que genera el texto del mensaje. Este es un ejemplo simple para mis estándares, porque involucra la comunicación solo hacia abajo, pero aún así debe cambiar las firmas de 15 métodos para hacer su cambio trivial.
Vladimir Slepnev
Bueno, supongo que lo que puede ayudar es modelar el flujo de datos explícitamente y separar componentes del flujo de datos. El ingeniero de software alemán está escribiendo mucho sobre este tema, la mayoría de los artículos en alemán. Aquí hay un artículo de entrada en inglés de él: geekswithblogs.net/theArchitectsNapkin/archive/2011/03/19/…
Doc Brown
Creo que una API interna singleton podría ayudar. Sería accesible en toda la aplicación y encapsularía toda la lógica de recuperación de datos.
SuperM

Respuestas:

1

Se está refiriendo a CDI (Inyección de dependencia de contexto) AKA IoC (Inversión de control). Java JSF y Spring Framework son algunos ejemplos. ASP.NET MVC tiene complementos como Unity. Javascript está comenzando a tener estructuras organizadas utilizando bibliotecas como RequireJS, que tiene un comportamiento de inyección visto en muchos marcos JS modernos. Eso es para el cableado de aplicaciones locales y remotas.

Para un acoplamiento flexible en las redes, a las compañías les gusta usar servicios web con SOAP, REST, AJAX o llamadas a métodos remotos regulares con RPC. En Java puede usar JAX-WS o .NET WCF para construir servicios distribuidos. Luego los alinea en un bus de servicio o "flujo de datos" desde cualquier idioma o plataforma como cliente. Ruby, Python, Scala, Java, C #, ... cualquier cosa.

El acoplamiento flexible le permite dividir y conquistar problemas, y los servicios son a menudo el punto de entrada a una base de datos para extraer datos. Subiendo la escalera tenemos a la bestia llamada Message Queue. Ese camino conduce a marcos empresariales y de infraestructura.

Sin embargo, si su proyecto insiste en que no hay red, hay idiomas como Scala, Akka, NodeJS, etc. que están diseñados para un alto flujo de datos dentro de una sola aplicación. También trabajan con algunas o todas las tecnologías mencionadas anteriormente para proyectos complejos. Por ejemplo, Scala se puede usar con los servicios REST JAX-RS para extraer una especie de "datos globales" de una fuente de datos y tener Spring para el cableado interno de IoC. También hay muchos marcos de ejecución de negocios o flujo de trabajo en herramientas JBoss, .NET y GUI como MuleESB. En desarrollo, Eclipse y Netbeans le permiten arrastrar y soltar servicios en una pantalla de diagrama de flujo visual.

Finalmente, Java todavía tiene frijoles Singleton. Para ajustar sus métodos en tiempo de ejecución, use marcos proxy o de reflexión. Pero honestamente, eso es tan 1999.

Si realiza tantas llamadas para enviar un mensaje a un usuario en función de su zona horaria, en mi opinión, probablemente haya una forma de 2 pasos para lograr el mismo efecto que ve el usuario. Pero sí, los marcos existentes son usados ​​por lenguajes existentes como un abrigo que les da todos los poderes flexibles que mencionaste. Me gusta llamarlo subconsciente de mi programa, ocupándome del trabajo sucio sin problemas.

Señor desarrollador
fuente
Las colas de mensajes pueden ser excesivas, pero la mensajería es la manera perfecta de hacer que los eventos se disparen en todos los ámbitos. Java usa beans controlados por mensajes (MDB) y eso debería permitir que su programa envíe o reciba 'conversación' entre ellos. Puedes hacerlo de esta manera por la bonificación asincrónica.
Senor Developer el
Gracias por los punteros! Definitivamente me hace preguntarme cómo se vería un lenguaje si fue diseñado desde cero para admitir la inyección de dependencia y patrones similares.
Vladimir Slepnev
0

La forma más sencilla de hacer esto a gran escala es, de hecho, utilizar algún tipo de API de encapsulación de datos. Esto podría ser un almacén NoSQL o podría ser un RDBMS encapsulado (o de hecho podría estar en diferentes momentos y lugares en la misma aplicación; no hay ninguna razón por la que no pueda tener un RDBMS manejando a largo plazo almacenamiento y un control de estado a corto plazo NoSQL db). Incluso podría ser una serie de objetos únicos.

Sus estructuras de datos pueden estar disponibles en algún tipo de espacio neutral, de una manera algo administrada. Este es el enfoque que tomamos con LedgerSMB (pero con algunas variables semi-globales para lo que son esencialmente singletons escondidos, pero nuevamente estos son administrados, elegimos guardar directamente el objeto porque facilitó un poco la administración de las variables, pero luego hay los 4 de ellos).

Por supuesto, cualquier enfoque tiene compensaciones y no puede evitar esas compensaciones. La clave es observar cuáles son las compensaciones (gestión frente a rendimiento frente a limpieza del código frente a posibles dificultades de codificación) y tomar una decisión basada en lo que es mejor para su aplicación.

Chris Travers
fuente
¡Gracias por la respuesta! Me parece que la investigación del lenguaje de programación podría ayudar con este problema. Por ejemplo, si el código lee algunos datos de una base de datos global o de singletons escondidos, podría haber una garantía estática / declarativa sobre qué datos requiere.
Vladimir Slepnev
-1

Si usa (o cita) las palabras

hairy flow of control

entonces supongo que tu código realmente es un desastre. Deberías dejarlo caer de inmediato. Si utiliza la modularización / separación de preocupaciones, no existe un "flujo de control melenudo". Su código simplemente carece de simplicidad, lo que también es inferible por el hecho de que se refirió a variables globales :-).

usuario127749
fuente
¿Por qué el voto negativo? En la cita faltaba la introducción que respalda exactamente mi punto de vista: "(probablemente está clasificada como" Antipatrón "o" Olor de código "y como tal tiene un nombre en los círculos apropiados, pero no lo sabría, así que dejarlo sin nombre) "
usuario127749
2
Esta no es realmente una respuesta a la pregunta, esa es probablemente la razón del voto negativo
Daniel Gratzer
Entonces permítanme reformular la pregunta: ¿hay algún truco de magia para deshacer el desorden de código que viola uno de los principios más básicos del diseño de software: KISS (que sea simple, estúpido)? El truco no es mágico, es un programador que no puede ser reemplazado porque conoce todos los detalles no tan obvios (que matarán a la compañía a largo plazo) o reestructurar la base del código. Desafortunadamente, muchas empresas inicialmente no se preocupan por el diseño adecuado del código o ni siquiera entienden las consecuencias, luego tienen que reescribir su código al menos una vez, muchas incluso lo reescriben muchas veces ...
user127749