SQL Query e Java Constant Abuse?

6

Attualmente sono incaricato di rilevare un sacco di codice scritto con nomi di campi posizionati nella costante Java nella parte superiore del file e quindi le query SQL create utilizzando la concatenazione di stringhe con i nomi dei campi. Nella parte superiore del file è presente il seguente blocco:

private static final String TABLE_VALID_USER = "valid_user_table";
private static final String TABLE_USER_MANAGEMENT = "V1_USER_MANAGEMENT_TABLE";
private static final String TABLE_ROLE_DEFINITION = "V1_ROLE_DEFINITION_TABLE";
private static final String TABLE_ROLE_MANAGEMENT = "V1_ROLE_MANAGEMENT_TABLE";
private static final String TABLE_USER_STATUS_DEF = "V1_USER_STATUS_DEFNITION";

private static final String COLUMN_NAME_OPEN_ID = "hashed_open_id";

private static final String COLUMN_NAME_INTERNAL_USER_ID = "internal_user_id";
private static final String COLUMN_NAME_USER_ID = "hashed_open_id";
private static final String COLUMN_NAME_USER_NAME = "name";
private static final String COLUMN_NAME_ROLE_ID = "role_id";
private static final String COLUMN_NAME_ROLE_NAME = "role_name";
private static final String COLUMN_NAME_USER_STATUS_CODE = "status_code";
private static final String COLUMN_NAME_USER_STATUS_NAME = "status_name";

private static final String DEFAULT_USER_STATUS = "Pending";

private static final String AS_NAME_COUNT = "cnt";

Più avanti nel codice, ci sono query SQL costruite in questo modo usando queste costanti nella costruzione delle stringhe.

Quello che devi ricordare è che questi sono molto distanti nel codice, quindi per scoprire che cos'è un nome di campo, devi scorrere su e giù per tutto il tempo. Per essere in grado di leggere la query, richiede un sacco di esercizio mentale. Mi rendo conto che per il programmatore originale questo non è un grosso problema, perché la colonna potrebbe essere hashed_open_id ma quel programmatore ha ritenuto che il nome costante COLUMN_NAME_USER_ID fosse un sostituto perfettamente accettabile per quello. La buona notizia è che questo è spiegato come id utente.

La cattiva notizia è che la colonna effettiva nel database è chiamata hashed_open_id che non è ovvia. Quando leggi il codice, impari questo nuovo simbolo arbitrario COLUMN_NAME_USER_ID e devi ricordare che in realtà significa hashed_open_id e devi farlo per ogni colonna della tabella! Sembrerebbe raddoppiare la quantità di cose che devi imparare per leggere il codice.

Per comprendere la query, è necessario avere conoscenza del database. Quando si utilizza il database, è necessario tenere a mente i nomi delle colonne reali. I simboli delle costanti Java non sono utili quando si ha a che fare con il browser dati SQL.

String sql = 
    "SELECT "
    + "COUNT(" + COLUMN_NAME_OPEN_ID +") as " + AS_NAME_COUNT + ", " 
    + "FROM "
        + TABLE_VALID_USER + " " 
    + "WHERE "
        + COLUMN_NAME_OPEN_ID + "= ? "
        + ";";

Non sarebbe meglio usare solo i nomi delle tabelle reali e i nomi delle colonne reali direttamente? Se lo facevi, la query sarebbe nel codice come:

    String sql = 
        "SELECT COUNT(hashed_open_id) as cnt, " 
        + "FROM valid_user_table " 
        + "WHERE hashed_open_id= ? ;";

Quest'ultima query è chiaramente più facile da leggere e comprendere, soprattutto se si conosce la struttura della tabella effettiva. Puoi facilmente vedere esattamente come viene manipolato il nome della tabella e quali colonne sono coinvolte. Torna all'originale e prova a cercare i valori nelle costanti per arrivare alla stessa comprensione. E DEVI conoscere la struttura della tabella perché è manipolata da altre classi e altri programmi. Qualcuno crede davvero che usare le costanti come un ulteriore livello di reindirizzamento dei simboli in questo modo sia un vantaggio?

In teoria, se decidi di cambiare il nome di una colonna, vai in un punto e si propaga attraverso l'intero codice. Ehi, è bello, ma quanto spesso lo fai? E cambia solo questa classe ... ci sono altre classi e programmi, alcuni scritti in lingue diverse, che manipolano il tavolo. Un cambiamento della costante non cambierà mai tutto.

La leggibilità è importante. Non è la capacità di leggere, esaminare e comprendere rapidamente il codice da parte dei programmatori che manterranno il codice più importante della rara comodità di cambiare una colonna? Considera il codice che vive per 10 anni. Quanti nuovi programmatori dovranno leggere questo codice? Quante volte cambia il nome di una colonna?

E, immagina che hai bisogno di cambiare il nome di una colonna da hashed_open_id a standard_user_id è davvero così difficile fare una ricerca e sostituirla? Probabilmente dovevi fare la stessa cosa in alcuni script SQL usati per creare la tabella. La costante non è un simbolo universale per il nome della colonna. Il nome della colonna è un simbolo universale per il nome della colonna. Perché non usarlo direttamente ovunque? Il punto di un nome di colonna deve essere un simbolo per i dati nella colonna.

Qualcuno può pensare a qualche ragione che un ulteriore livello di riferimento per rendere le costanti Java per ogni colonna valga i problemi che provoca?

    
posta AgilePro 08.03.2016 - 04:12
fonte

4 risposte

1

Sono d'accordo con quello che dici. Avendo lavorato in diverse aziende su una varietà di piattaforme, non ho visto il livello di astrazione che descrivi. Occasionalmente scriverò snippet di codice e costruirò SQL da loro, ma formulato in termini di termini di applicazioni e problemi, non in termini di progettazione di DB. Ad esempio
where-cluase-for-employee = "<several lines of SQL>"
mentre
where-clause-for-contractor="<a different complex predicate>" .

SQL è un linguaggio di programmazione. Nessuno considererebbe la procedura migliore per costruire una chiamata al metodo Java come stringa, quindi eseguirla. Perché dovrebbe essere fatto per SQL?

Anche la manutenibilità e la facilità di cambiamento sono importanti. Credo che il codice dovrebbe essere scritto con considerazione per lo sfortunato interlocutore che deve ripararlo alle 3 del mattino, senza averlo mai visto prima. Rendi il codice efficiente e compatto con tutti i mezzi, ma non tanto che lo scrittore sia l'unica persona in grado di capirlo.

Esiste un approccio diverso che può astrarre i nomi di tabelle e colonne da Java e mantenere SQL come un blocco compatto. Può anche migliorare i tempi di esecuzione, in base al carico di lavoro delle applicazioni. Metti l'SQL in una stored procedure. Le buone convenzioni di denominazione SP diranno esattamente che cosa fa ( read_count_by_user per l'esempio nella domanda) e il contratto tra l'applicazione e SQL è definito. Se le colonne restituite cambiano, anche l'applicazione deve cambiare, ma questo è un problema che si deve affrontare al momento. L'analisi di impatto è una ricerca testuale del codice sorgente. La modularità è migliorata. L'ottimizzazione e la riscrittura possono essere eseguite in base alla procedura.

Se l'unica lamentela degli sviluppatori è con la convenzione di denominazione dei DB, chiedere una serie di viste da definire con nomi di sviluppatori per tabelle e colonne. Per i semplici casi d'uso mostrati questi non avranno alcun impatto sulle prestazioni.

    
risposta data 22.08.2016 - 01:39
fonte
0

Solo per informazioni. Poiché i campi sono costanti (statico finale), posso dirti che il codice byte risultante dalla compilazione sarà esattamente quello che desideri.

La compilazione sostituirà ogni costante al suo valore, quindi la tua query sarà una stringa (potrebbe essere una concatenazione di String, non proprio sicura).

Uso dei tuoi esempi

Questo è il file java:

String sql = 
    "SELECT "
    + "COUNT(" + COLUMN_NAME_OPEN_ID +") as " + AS_NAME_COUNT + ", " 
    + "FROM "
        + TABLE_VALID_USER + " " 
    + "WHERE "
        + COLUMN_NAME_OPEN_ID + "= ? "
        + ";";

Ed ecco il byte code, il file di classe:

String sql = 
    "SELECT COUNT(hashed_open_id) as cnt, " 
    + "FROM valid_user_table " 
    + "WHERE hashed_open_id= ? ;";

Questo approccio al codice ha il vantaggio di essere più sicuro se si cambiano i campi, non è necessario controllare tutto il codice. Ho usato questo disegno a volte ... Questo è probabilmente il motivo per cui hai qualche difficoltà a capire perché user_id è in realtà il hashed_open_id , probabilmente in un punto, la colonna user_id dove presente ma alcuni aggiornamenti rimuovono questa colonna il hashed_open_id uno. È più semplice leggere se il nome costante è ben scelto.

EDIT:

Ti invito a provare un codice generico sulle costanti per scoprire che puoi aggiornare il valore costante senza problemi, ma ogni posto che utilizzerai manterrà il valore nella compilation.

    
risposta data 22.08.2016 - 13:13
fonte
0

L'IMO che pratica ha senso solo se tentano di creare un generatore di query grafico e point-and-click ad-hoc per gli utenti finali , e anche in questo caso utilizzerei JDBC metadati per estrarre i nomi delle colonne.

Altrimenti non vedo vantaggi pratici, solo svantaggi.

    
risposta data 22.08.2016 - 14:19
fonte
0

L'anwer: probabilmente per il codice del modello, da centuplo essere copiato e personalizzato'.

Il refactoring ha bisogno di cure. Refactoring per rendere il codice un po 'migliore, spesso non paga. Un refactoring più radicale è migliore.

Qui: semplicemente compilando le costanti (che potrebbero essere automatizzate), specialmente manualmente, dà solo lavoro.

Il vecchio stato è cattivo, e suppongo che il codice sia il risultato di query copiate, codice copiato. Sarebbe un buon momento, per controllare le copie del codice. Questi non saranno più facilmente trovati dopo il refactoring. Non puoi ripetere te stesso? Come vengono generate le chiavi generate dal codice?

Sarebbe un buon momento per vedere se le cose possono essere migliorate, try-with-resources, JPA, forse SQL come dati dichiarativi o altro.

Anche questo tipo di refactoring non deve essere mescolato con le modifiche della logica di business. Pensa a quanto sarebbe inutile se la sostituzione manuale del nome di una colonna sostituisse la colonna sbagliata. Buon debug del nuovo codice.

    
risposta data 22.08.2016 - 16:55
fonte

Leggi altre domande sui tag