Sul serio, qual è il grosso problema di avere alcuni cicli nel proprio grafico di importazione? Lo vedo come un male minore rispetto all'importazione di importazioni a grana fine che tengono traccia di dove cercare il codice di un incubo assoluto.
A seconda dell'ambiente, le dipendenze cicliche tra i moduli possono rendere impossibile il collegamento statico. Il modulo A non può essere collegato fino a quando il modulo B non è collegato; ma il modulo B dipende dal modulo A e non può essere collegato fino a quando il modulo A non è collegato. Questo è il motivo per cui alcuni ambienti, come .NET e Delphi, non consentono affatto questo tipo di cose.
Altri ambienti / compilatori / linker possono essere più indulgenti, ma ciò non rende il design migliore. Anche se sembra essere generalmente accettato che le dipendenze cicliche all'interno delle strutture di dati siano talvolta necessarie (modelli di entità, liste con collegamenti doppi, certi tipi di alberi ... ottieni l'immagine), è quasi sempre un difetto di progettazione serio per avere una dipendenza modulo ciclica.
Perché? Prova a immaginare la fase di inizializzazione di un'applicazione, mentre i moduli sono ancora in fase di caricamento. La maggior parte dei moduli conta sul fatto che tutte le loro dipendenze siano state completamente caricate prima di eseguire qualsiasi codice di inizializzazione. Le dipendenze cicliche invalidano questa ipotesi, perché è fisicamente impossibile (almeno in questo universo) che entrambi i moduli siano caricati l'uno sull'altro. Allo stesso modo, nella fase di teardown, il codice di finalizzazione che fa presupposti perfettamente ragionevoli potrebbe bloccarsi perché un runtime dipendente è già stato scaricato dal runtime.
La parte peggiore è che nella maggior parte dei sistemi operativi, quando si hanno dipendenze da moduli ciclici, l'ordine di caricamento è deterministico ma impossibile da prevedere. Quindi un'ipotesi sull'inizializzazione che risulta essere corretta oggi potrebbe improvvisamente rompersi domani a causa di un cambiamento totalmente innocente in una parte totalmente diversa dell'applicazione. Rintracciare questi bug può essere un processo dolorosamente doloroso.
Le importazioni cicliche all'interno di un singolo pacchetto / modulo / assieme sono in realtà completamente un'altra storia. Una "importazione" può significare tante cose diverse a seconda del contesto. In molti casi sono "considerati dannosi" semplicemente perché i primi compilatori non erano in grado di gestirli, quindi bisognava fare il proprio rilevamento del ciclo con un gruppo di direttive #ifdef
(o simili) e ovviamente, dopo un certo numero di questi, inizi a perdere la testa. Ma nella moderna programmazione orientata agli oggetti è spesso considerata una buona pratica avere un file per classe, il che significa che un'importazione ciclica è semplicemente un segno di una dipendenza da classe ciclica, che come ho già detto non è necessariamente così male cosa a meno che non sia necessario .
Se non è necessario, allora è una brutta cosa semplicemente per il fatto che qualsiasi complessità non necessaria è una brutta cosa e le dipendenze cicliche aggiungono complessità.
Il mio grande sentimento sulle dipendenze dei moduli ciclici è che se questi due moduli dipendono davvero l'uno dall'altro, forse dovrebbero essere un modulo. Non puoi usarne uno senza l'altro, quindi qual è il motivo per dividerli?
Mantenerli separati ti costringe a pensare alle dipendenze del sistema quando aggiungi un nuovo codice. Questa è una buona cosa. Quando devi pensare a tutta l'architettura, è meno probabile che tu prenda una decisione che la ingarbuglia.
Una ragione è che può essere , ma non è sempre , un segnale di avvertimento di una cattiva decisione di progettazione da qualche parte.
Leggi altre domande sui tag modules