Utilizzo di Java Reflection per disaccoppiare i moduli di codice

1

Sono coinvolto in un progetto con diversi moduli. Ho scoperto che i programmatori hanno progettato un modulo per essere facilmente disaccoppiato dai suoi moduli dipendenti utilizzando Java Reflection. Se altri moduli devono chiamare un metodo in questo modulo, i programmatori si aspettano che usino il reflection per chiamarlo. Ciò ha comportato molti luoghi con le chiamate di riflessione codificate . Con hard-coded, voglio dire che i nomi delle classi e dei metodi sono permanentemente fissati come stringhe, il che sconfigge lo scopo della riflessione che dovrebbe essere per la programmazione dinamica.

Come può essere giustificato? Sento che sono novizio su di esso e uso improprio dell'API di riflessione. Penso che il polimorfismo sia il modo giusto per disaccoppiare un modulo da un altro senza rompere le funzionalità. (Sfortunatamente, cambiare l'intero codice base in polimorfismo è troppo di manutenzione.)

    
posta ADTC 24.09.2013 - 05:15
fonte

4 risposte

6

Se l'unico scopo dell'uso della riflessione è disaccoppiare i moduli (in senso astratto), quindi (IMO) non può essere giustificato.

Perché?

Perché in realtà NON li disaccoppia. Piuttosto sta sostituendo una forma di accoppiamento con un'altra forma. Inoltre, la seconda forma di accoppiamento (vale a dire la classe cablata e le stringhe del nome del metodo) è più difficile da individuare e più suscettibile alla rottura.

OTOH, se l'uso della riflessione è destinato a ottenere altre cose, allora potrebbe essere giustificabile su questa base. Ad esempio, gli esempi nelle altre risposte hanno tutti uno scopo più specifico del semplice "ridurre l'accoppiamento".

    
risposta data 24.09.2013 - 16:40
fonte
5

Sì, a meno che la riflessione non usi alcuni nomi non disponibili al momento della compilazione, di solito dovrebbe essere sostituito da fabbriche o da un'iniezione di dipendenze.

OTOH ci sono sono rari casi in cui sono noti nomi di classi esatti al momento della compilazione, ma le classi nominate non sono disponibili al momento della compilazione. Un classico esempio è JDBC, che usava il paradigma Class.forName("com.vendor...") . Il nome della classe dei driver JDBC è noto al momento della compilazione, ma un .jar con la classe specificata, o spesso diversi per diversi DBMS supportati, non è disponibile.

Questo caso è ancora piuttosto speciale: non solo assume che le classi referenziate da reflection siano distribuite in jar separati, ma presuppone che alcune di tali classi potrebbero non essere affatto disponibili. Questa è una supposizione ragionevole per una biblioteca pubblicamente utilizzata; Non so se è ragionevole nel tuo caso.

Ad ogni modo, i contenitori moderni non richiedono che il codice client utilizzi il reflection, usano l'injection dependency per fornire specifiche implementazioni sostituibili, ad es. Driver JDBC.

Penso che dovresti prendere in considerazione l'utilizzo di un framework di iniezione delle dipendenze nel tuo caso. Il framework DI potrebbe usare la riflessione internamente, ma almeno tutta questa riflessione sarebbe concentrata in uno strato sottile e ben definito.

    
risposta data 24.09.2013 - 06:12
fonte
1

un modo migliore è utilizzare le interfacce e il metodo alcuni per individuare le classi di implementazione

le interfacce anticipano la necessità di riflessione nel codice chiamante, questo è fattibile durante un refactoring, basta estrarre le interfacce (e gli oggetti dati) e metterle dove il codice client può fare riferimento a esso e sostituire tutto il riflesso con una chiamata al interfaccia

ci sono diversi modi per trovare le classi di implementazione: una di queste è usata da Sistema di servizio ImageIO , coinvolge un file nella cartella META-INF del jar contenente il modulo di implementazione e che include il jar nel classpath

    
risposta data 24.09.2013 - 12:13
fonte
0

La riflessione per il disaccoppiamento è sempre una cattiva idea. Le interfacce sono la strada da percorrere. È possibile rilevare dinamicamente le implementazioni usando SPI e / o OSGi o simili. Utilizza una factory per nascondere i dettagli della ricerca.

    
risposta data 25.09.2013 - 10:35
fonte

Leggi altre domande sui tag