¿Las dependencias de la clase circular son malas desde el punto de vista del estilo de encoding?

¿Las dependencias de la clase circular son malas desde el punto de vista del estilo de encoding?

Ejemplo:

En una aplicación de base de datos, tenemos dos clases, una que encapsula información sobre una única base de datos ( DBInfo ) y una clase que puede crear una conexión de base de datos. ( ConnFactory )

DBInfo tiene un método getConnection que usa ConnFactory para crear una conexión. Pero ConnFactory necesita un objeto DBInfo para hacerlo.

De esta manera: (Cualquier estilo de encoding descartado por el bien de la legibilidad)

 class DBInfo { String name; String connectionUrl; Connection getConnection() { return ConnFactory.getConnection(this); } } class ConnFactory { Connection getConnection(DBInfo toWhat) { return new Connection(toWhat.connectionUrl); } } 

Mis compañeros de trabajo argumentan que esta es una mala práctica y sería mejor si hubiera una sola dirección de dependencias y no circulares como aquí.

¿Es esta mala práctica, un anti-patrón o un olor a código? ¿Hay algún inconveniente?

    En general, llamaría a las dependencias circulares un olor a código. Tenga en cuenta que el término ‘Olor del código’ indica principalmente que ‘aquí hay un fragmento de código que requiere atención especial y es probable que se beneficie del rediseño’.

    En la mayoría de los casos, consideraría un diseño en el que no sea necesaria una dependencia circular, pero en casos excepcionales, puede estar bien.

    En su ejemplo, el ConnFactory parece redundante, pero puede deberse a que su ejemplo ha sido recortado. Sin embargo, me parece que la lógica de creación de conexión sería mejor si se moviera a la clase DBInfo. Cuando ya tiene una clase que contiene datos sobre una base de datos, parece natural hacerlo responsable de crear una conexión a esa base de datos.

    Sí, generalmente las dependencias circulares son malas, aunque no siempre malvadas. Los problemas con las dependencias circulares incluyen acoplamiento ajustado, módulos mutuamente dependientes y generalmente efecto dominó, cuando los cambios en un módulo se propagan a otros módulos.

    Dicho esto, su código está violando el principio de responsabilidad única en el que DBInfo no solo almacena información sobre la base de datos, sino que también es responsable de obtener objetos de Connection . Elimine esa pieza particular de funcionalidad en una clase separada y todo estará bien.

    No necesariamente

    No creo que las dependencias circulares en el nivel de granularidad de clases sean malas. No veo un problema si dos, tres o tal vez cuatro clases son mutuamente dependientes. (No digo que esto sea algo que quieras, pero puede ser bueno en algunas circunstancias).

    Es un problema si tiene dependencia mutua en el paquete o en el nivel del módulo, por todos los motivos mencionados anteriormente y a continuación.

    Este código solo funciona si ConnFactory.getConnection() es estático. Una mejor solución sería hacer de getConnection() un método de instancia de ConnFactory . Entonces su DBInfo puede tomar un ConnFactory como argumento (posiblemente en un constructor, si tiene un constructor sobrecargado). Sin embargo, creo que el uso del método estático para este caso es más una mala práctica que la referencia circular.

    Sin embargo, si tuviera que ir por esta ruta, también haría una interfaz IConnFactory que DBInfo interactuaría y que ConnFactory implementaría. Entonces no hay referencia circular: tanto DBInfo como ConnFactory dependerían de IConnFactory , lo que no dependería de ninguna de las dos.

    Todo lo que sé es que las dependencias circulares pueden convertirse en un problema cuando comienzas a usar un Marco de dependency injections, como el Mapa de estructuras. La mayoría de estos marcos tienen problemas para manejar dependencias circulares, a veces resultando en una excepción de desbordamiento de stack (perdón por el juego de palabras :-)) Por lo tanto, tiendo a tratar de evitarlo a menos que sea absolutamente necesario y no pueda evitarse.

    ¿Qué pasa con una relación bi-direccional de uno a muchos que es un caso común en cualquier aplicación que use una capa ORM? ¿No es este un caso de dependencia circular?

    ¿Es malo / código malicioso?

    Las dependencias circulares son malas porque:

    • dos dependencias es más de una
    • no se puede probar incrementalmente (sin burlarse de uno de ellos, lo que sería una tontería para cosas pequeñas, estrechamente relacionadas).

    Puede hacer todo el trabajo con interfaces para romper la dependencia circular si es necesario, pero la solución mínima directa es simplemente convertir DBInfo en una clase anidada de ConnFactory. Una unidad que se refiere a sí misma no es circular.