Domanda di design del codice, riferimento circolare tra le classi?

5

Non ho codice qui, poiché si tratta più di una domanda di design (presumo che sia ancora il posto migliore per chiederlo).

Ho un server molto semplice in Java che memorizza una mappatura tra determinati valori e UUID che devono essere utilizzati da molti sistemi su più piattaforme. Accetta una connessione da un client e crea un client socket che memorizza il socket e tutti gli altri dati rilevanti unici per quella connessione. Ogni clientSocket verrà eseguito nel proprio thread e bloccherà sul socket in attesa di una lettura. Prevedo pochissimo sforzo su questo sistema, raramente verrà chiamato, ma quando riceverà una chiamata dovrà rispondere rapidamente e a causa del rischio che abbia un tempo di punta con più chiamate in arrivo in una volta threaded è ancora meglio .

Ogni thread ha un riferimento a una classe Mapper che memorizza la mappatura dell'UUID che sta segnalando ad altri (con una corretta sincronizzazione ovviamente). Tutto funziona fino a quando non devo aggiungere un nuovo UUID all'elenco. Quando ciò accade, voglio segnalare a tutti i clienti che si interessano a quel particolare UUID che ne è stato aggiunto uno nuovo. Non posso eseguire il multicast (limitazione del sistema su cui sto girando), quindi sto verificando che ogni socket invii il messaggio al client attraverso il socket stabilito. Tuttavia, dato che ogni thread conosce solo il socket che sta aspettando, non ho avuto un metodo chiaro per cercare ogni thread / socket che si preoccupa dei dati per informarli del nuovo UUID.

Il polling è principalmente perché sembra un po 'troppo complicato per cercare di mantenere un elenco di UUID appena aggiunto. La mia soluzione è di avere la classe 'genitore' che crea la classe mapper e genera tutti i thread passati come argomento al mappatore. Quindi, quando il mapper crea un nuovo UUID, può effettuare una chiamata alla classe genitore che gli dice di inviare aggiornamenti a tutti gli altri socket che si preoccupano della modifica.

Sono preoccupato che questo possa essere un cattivo progetto dovuto all'uso di un riferimento circolare; il genitore ha un riferimento al mappatore (per passarlo a nuovi thread ClientSocket) e i punti del mappatore al genitore. Per me non mi sembra un cattivo design ma volevo controllare perché i riferimenti circolari sono pessimi.

Nota: mi rendo conto che ciò significa che il thread associato a qualsiasi socket originariamente ricevuto la richiesta che ha generato la creazione di un UUID sta per pagare il "costo" dell'output a tutti gli altri client che si interessano del nuovo UUID. Non mi importa di questo; come ho detto, sospetto che il client riceva solo messaggi intermittenti. È improbabile che un socket possa ricevere più messaggi contemporaneamente e non ci siano così tanti socket, quindi non dovrebbe impiegare troppo tempo per inviare messaggi a ciascuno di essi. Forse più tardi aggiusterò il fatto che sto caricando un carico di lavoro più elevato su qualunque thread sfortunato ottiene la prima richiesta; ma per ora penso che vada bene.

    
posta dsollen 06.09.2012 - 18:57
fonte

2 risposte

9

Un modo generale in cui questi riferimenti vengono interrotti è tramite interfacce. Invece che la classe genitore abbia un riferimento al mappatore, tieni un riferimento a IWhateverParentNeedsFromMapper. Invece che il mapper abbia un riferimento al genitore, tieni un riferimento a IWhateverMapperNeedsFromParent.

Spesso, pensare al problema in questo modo finisce con un bel nome di interfaccia descrittiva e un piccolo insieme di operazioni al suo interno.

Non infrangi il riferimento circolare "reale", ma quel riferimento è un dettaglio di implementazione invece di un requisito fondamentale per il tuo progetto di classe.

Come nota a margine, questo:

I wanted to check since circular references are suppose to be bad

Non pensare in questo modo. :) Ci sono un sacco di cose che dovrebbero essere cattive che alimentano tutto ciò che usi ogni giorno. Il codice di lavoro supera il codice "teoricamente migliore" nella maggior parte dei casi.

    
risposta data 06.09.2012 - 20:03
fonte
1

Non è un cattivo design. I puntatori posteriori sono un meccanismo comunemente usato. Esiste già una dipendenza tra le classi, quindi non stai creando un accoppiamento in cui nessuna esistente. Potresti renderlo un accoppiamento astratto introducendo interfacce, SE scegli tu, ma questo viola YAGNI. Per inciso, si noti che l'istruzione java import supporta le dipendenze circolari e Spring setter injection abilita le dipendenze circolari supportando la costruzione a due fasi.

    
risposta data 06.09.2012 - 22:38
fonte

Leggi altre domande sui tag