Correggi il modello, non i muri
Percepire la necessità di avere questi marcatori sembra un odore di codice . Non mi sembra una questione di convenzione di denominazione ma di design architettonico (e comportamentale). Anche se ovviamente avere una buona convenzione di denominazione sarà importante per rendere utilizzabile quel design.
Soluzioni
Ci sono vari approcci, ma qui ci sono 2 opzioni possibili.
1 Class per DB Usage Approach (facile da fare, ma non raccomandato)
Avere 2 classi separate per affrontare entrambi gli scenari, in modo efficace prendendo la distinzione di un livello più in alto nella catena. Ad esempio, qualcosa di simile (in nessuna lingua particolare):
class CustomerDirectDAO {
save() {}
}
class CustomerIndirectDAO {
save(Connection c) {}
}
Come accennato, questo ti consentirebbe di affrontare il problema della selezione del problema giusto a un livello superiore della catena di progettazione. Tuttavia, puoi ovviamente sembrare noioso e hai ancora bisogno di una distinzione per ogni approccio. Inoltre, la prima classe probabilmente fa essenzialmente ciò che la seconda classe fa con il passo in più per creare la connessione e invocarla.
Questo non è eccezionale.
1 Data Class e 1 DB Connection Supplier / Factory
Sarebbe meglio avere una classe che richiede sempre di passare un oggetto di connessione e un'altra classe che li costruisce e li fornisce. Sembrerebbe un modo migliore e consentirebbe di scambiare le implementazioni degli oggetti di connessione che potrebbero provenire da diversi fornitori.
Un wrapper L'oggetto Connection può anche essere fornito una sola volta al costruttore, dove il wrapper controlla lo stato della connessione e ne ricrea uno se necessario.
Ad esempio (in nessuna lingua particolare):
class Customer {
save(ConnectionWrapper c) {}
// (or pass the wrapper object only once to the constructor,
// as the wrapper would automatically check to reconnect the
// connection if invalid)
}
class ConnectionWrapper<T extends Connection> {
T get() {}; // gets the wrapped connection or returns a newly created one
}
class ConnectionFactory<T extends Connection> {
ConnectionWrapper<T> create() {}
}
Ci sono dozzine di modi per raggiungere questo obiettivo e puoi scegliere quello che sembra più applicabile a te.
L'approccio sopra riportato utilizza una singola classe di rappresentazione dei dati che consente di cambiare classe utilizzata per l'archiviazione. Ma un altro approccio è quello di prendere il problema dall'angolo inverso, per instnace con questo DAO schema , in cui è possibile visualizzare un approccio simile per consentire implementazioni swappable del back-end senza utilizzare i prefissi dei metodi, ma richiedono 2 implementazioni concrete del proprio oggetto dati:
Maggioriinformazionisull'argomentoconapprocciper DAO su Wikipedia e DAO per JEE applicazioni.