Pensieri sul refactoring di un DAO generico

3

Ho progettato un DAO generico in Java e sto avendo confusione sul fatto di rifattorizzarlo con un design diverso o meno.

PS Non dire di usare il framework per terze persone già esistente. So che ci sono alcuni presenti ma sto imparando Java e schemi di progettazione, quindi ho bisogno di tutta la pratica che posso ottenere.

Se c'è qualche confusione, per favore chiedi e ti chiarirò.

L'attuale architettura

DAOFactory.java

  • Contiene i metodi abstract per la creazione di DAODelete , DAOUpdate e altre 2 interfacce che devono essere implementate da classi di implementazione concrete
  • public Metodo di classe per la creazione del calcestruzzo Fabbriche per la produzione dell'attuazione concreta delle interfacce menzionate in precedenza.

DAORead.java

public abstract <T> T getPojoForPrimarKey(Connection con,
        TableName tableName, String primaryKey) throws SQLException;

Analogamente nelle altre mie interfacce ho metodi generici.

  • Qui Connection viene passato dal livello di servizio e chiuso lì per la gestione delle transazioni.
  • TableName è un enum che sto usando per avere un caso switch nel livello inferiore di DAO per chiamare le funzioni specifiche della tabella. Anche usare un enum mi sta aiutando nel controllo dei tipi.

OracleRead.java

@Override
    public <T> T getPojoForPrimarKey(Connection con, TableName tableName,
            String primaryKey) throws SQLException {
        T currentPojo = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            String queryString = OracleSpecifics.queryString(tableName,
                    primaryKey, QueryType.READ);
            ps = con.prepareStatement(queryString);
            rs = ps.executeQuery();
            if (rs.next()) {
                currentPojo = OracleSpecifics.getPojoFromResultSet(tableName, rs);
            }
        } finally {
            DAOFactory.closeAll(ps, rs);
        }
        return currentPojo;
    }

Ecco come ho implementato la funzione deleteFrom dall'interfaccia nella classe concrete.

Qui OracleSpecifics è il livello inferiore di DAO di cui stavo parlando. In pratica contiene% casi diswitch per verificare la tabella specifica.

OracleSpecifics.java

// These functions call table-specific functions
    @SuppressWarnings("unchecked")
    static <T> T getPojoFromResultSet(TableName tableName, ResultSet rs)
            throws SQLException {

        switch (tableName) {
        case ASEEM_MASTER:
        case ASEEM_MASTER_TEMP:
            return (T) SpecAseemMaster.getPojo(rs);
        case AUTHENTICATE_TABLE:
            return (T) SpecAseemRole.getPojo(rs);
        default:
            return null;
        }
    }

Qui SpecAseemMaster e SpecAseemRole sono livelli specifici di tabella (in particolare dello schema) che producono i campi richiesti

SpecAseemRole.java

public static AuthenticationDetails getPojo(ResultSet rs)
            throws SQLException {
        AuthenticationDetails cur = new AuthenticationDetails();
        cur.setUserName(rs.getString(1));
        cur.setPassWord(rs.getString(2));
        cur.setRole(rs.getString(3));
        return cur;
    }

Nel livello di servizio

Il tipo con cui viene chiamato il metodo DAO è il Pojo che rappresenta i campi dati dello schema. per es.

myFactory.getDAORead().<AuthenticationDetails> getPojoForPrimarKey(con, CUR_TABLE, primaryKey);

Qui AuthenticationDetails è il mio Pojo aka DTO per la comunicazione tra il mio controller e il livello di servizio (nel modello).

Nota che sto dando solo una panoramica nel modo più semplice. Ci sono 4 interfacce nei DAO astratti contenenti un totale di metodi di 8 abstract implementati da 4 classi concrete. Tutte queste classi generiche dipendono da un livello inferiore in DAO per ottenere query specifiche, PreparedStatement s ecc., Che chiama inoltre funzioni nelle funzioni della classe di utilità ausiliaria in base al tableName trasmesso su questa gerarchia. Il livello inferiore è specifico dello schema.

La mia confusione sul refactoring

  • Sono soddisfatto degli strati superiori di DAO, ma penso che al livello più basso, in particolare a OracleSpecific , le cose che dovrebbero avere un accoppiamento strong abbiano un accoppiamento debole. per esempio. ci sono diversi metodi per ottenere PreparedStatement per l'inserimento e l'aggiornamento. Ognuno di questi a sua volta ha switch per chiamare le funzioni nella classe di utilità inferiore.
  • Sebbene i metodi schema-specific siano legati insieme in diverse classi di utilità, il metodo si chiama in OracleSpecifics.java non ha alcun accoppiamento.
  • Sto pensando se dovrei cambiare l'enum TableName per contenere uno stato specifico . Lo stato che sto pensando per le classi di utilità di livello più basso specifiche dello schema.
  • Questi specific states contenuti nelle enumerazioni possono essere utilizzati per modificare lo stato di DAO e DAO può quindi chiamare le funzioni specifiche basate su un'interfaccia implementata da tutti questi stati. Quindi, a seconda dello stato, il comportamento può cambiare automaticamente.

  • Questa decisione di progettazione è corretta o sarebbe priva di significato?

  • Qualunque altra cosa che potrei aver trascurato?
  • Qualche idea sul design stesso?
  • Perderò la sicurezza del tipo introdotta dai generici a causa di questa modifica?
posta Aseem Bansal 01.12.2013 - 08:49
fonte

1 risposta

3

La prima domanda a cui devi rispondere è se intendi creare un framework di accesso ai dati veramente generico o se lo desideri su misura per il particolare progetto su cui stai lavorando.

Un framework generico ha il vantaggio di essere portabile e abbastanza liberamente collegato allo schema DB + sottostante, ma a costo di spingere le informazioni a livello di schema più avanti nel framework. Più generico crei il framework, più questa conoscenza ti spinge.

Un framework su misura allevia i livelli più alti dell'applicazione dal preoccuparsi dello schema o dei dettagli del DB, ma al costo del costo di essere meno riutilizzabile in altri ambienti. Come corollario, più specifico crei il framework, meno è facile estenderlo altrove.

Se non sei sicuro su quale di questi scegliere, il framework generico ha senso se sospetti che ci saranno cambiamenti a livello di DB o dello schema. Allo stesso modo, se quelli sono abbastanza ben bloccati, allora il framework su misura è l'approccio migliore. In definitiva, stai ottimizzando il sistema per gestire più facilmente dove pensi che il cambiamento si verificherà.

Per quanto riguarda la necessità o meno di refactoring, la risposta è No a meno che tu non abbia riscontrato un problema specifico.

Preoccuparsi del grado di accoppiamento è bello, suppongo, ma non necessariamente affronta un problema specifico che potresti vedere. Il refactoring basato su presunti problemi nell'accoppiamento è più probabile che crei per te un problema piuttosto che lasciarlo da solo.

Allo stesso modo con l'espressione dello stato. Se il meccanismo attuale di enum è sufficiente e non presenta un problema apparente, allora non cambiare quello che hai.

Nel complesso, sembra che tu abbia progettato un metodo di accesso ai dati ragionevolmente affidabile per il dominio che stai valendo. La tua domanda non elenca problemi specifici che frenano il tuo sviluppo, quindi la definirei buona e passare alla fase successiva dello sviluppo.

    
risposta data 27.12.2014 - 20:55
fonte

Leggi altre domande sui tag