ammirate / at-silo

Automatically exported from code.google.com/p/at-silo
0 stars 1 forks source link

Implementazione Classi Storage #48

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Volevo chiedere a che punto siamo con lo storage, cioè dovrei occuparmi 
dell'implementazione delle classi DBnomeBeans... 
Ma non so se posso ancora metterci mano! 
Cioè non so se la struttura dello Storage  è definitiva, e quindi posso 
iniziare a lavorare senza fare cose che poi non serviranno! :)

Original issue reported on code.google.com by FabioNapoli34 on 23 Nov 2012 at 1:33

GoogleCodeExporter commented 9 years ago

Original comment by FabioNapoli34 on 23 Nov 2012 at 1:35

GoogleCodeExporter commented 9 years ago
Allora. Possiamo seguire questa organizzazione. 
1) Rivedere tutte le classi in modo da capire se necessitano di altri metodi.
2) Iniziare ad implementare i metodi ereditati dalla classe DBBeans(in fase di 
modifica)
3) Implementare i metodi specifici delle classi.

Ovviamente c'è da fare in primis la javadoc.

Original comment by lomastol...@gmail.com on 23 Nov 2012 at 1:46

GoogleCodeExporter commented 9 years ago
Aspetto News da Giulio  e Luigi

Original comment by FabioNapoli34 on 23 Nov 2012 at 3:25

GoogleCodeExporter commented 9 years ago
Credo che possiate incominciare. La classe DBBeans ha un interfaccia che credo 
sia stabile, ed è documentata in modo, secondo me, abbastanza buono.
Quindi, trasformo questo in un task, e vi do le istruzioni per farlo: 
https://groups.google.com/d/topic/at-silo/M34qfJP_6Hc/discussion

Original comment by blunotte...@gmail.com on 23 Nov 2012 at 4:16

GoogleCodeExporter commented 9 years ago
Giulio_Franco: Bisognerebbe modificare i nomi degli attributi delle classi del 
package entity. Se ricordi ci sono parecchi nomi che non vanno. Ho trovato 
anche userName e passWord... non so se vanno bene.

Original comment by lomastol...@gmail.com on 24 Nov 2012 at 9:41

GoogleCodeExporter commented 9 years ago
I nomi tra database e Java devono coincidere, fatte salve le convenzioni.
In pratica, se hai userName in java, devi avere user_name nel database. Oppure 
puoi fare username e username.
Se hai password nel database, devi avere password in Java. Oppure fai pass_word 
e passWord.

Original comment by blunotte...@gmail.com on 24 Nov 2012 at 1:19

GoogleCodeExporter commented 9 years ago
Ho completato e committato le mie benedette classi di storage!
Devo solo mettere alcuni set di liste in creaBeans per Genitore e registro

Original comment by ferdi...@gmail.com on 28 Nov 2012 at 7:04

GoogleCodeExporter commented 9 years ago
In merito al problema individuato da Luigi sulle entità deboli:
se la chiave primaria contiene una chiave esterna, inserite nel mapping un 
campo fittizio, il cui nome inizia con "-" (es. "-bambino"), e che mappa sulla 
colonna di cui avete bisogno (es: "-bambino" -> "Bambino") e inserite questo 
campo fittizio anche nella List restituita da getKeyFields.
Infine, sovrascrivete il metodo getAssegnazioni, in modo da restituire 
l'Assegnazione corretta per la colonna della chiave primaria.

Original comment by blunotte...@gmail.com on 28 Nov 2012 at 7:20

GoogleCodeExporter commented 9 years ago
Quale è lo status delle classi storage? Avete realizzato le classi JUnit 
associate per testare ciò che avete implementato?

Original comment by funfor...@gmail.com on 30 Nov 2012 at 3:02

GoogleCodeExporter commented 9 years ago
Stavamo io e luigi cercando di capire come usare Junit. 

Original comment by FabioNapoli34 on 30 Nov 2012 at 3:05

GoogleCodeExporter commented 9 years ago
l'implementazioni delle classi test ancora non è iniziata.

Original comment by lomastol...@gmail.com on 30 Nov 2012 at 3:05

GoogleCodeExporter commented 9 years ago
Sto vedendo alcune cose che non vanno nel codice. Le dico in generale, così lo 
capiscono tutti.

1) Accesso a variabili null-----------------------------------------
Il seguente codice non va bene:
----------------------BUGGY-JAVA-CODE------------------------------------
Psicopedagogo p = null;  //p inizializzato a null
        if(r.next()){
            p.setNumeroClassi(r.getInt("numero_classi")); //p vale ancora null
-------------------------------------------------------------------------

perché se eseguito, lancerà sicuramente una NullPointerException.
Le variabili vanno sempre inizializzate. La versione corretta del codice è:
----------------------JAVA-CODE------------------------------------------
Psicopedagogo p = new Psicopedagogo();  //p inizializzato
        if(r.next()){
            p.setNumeroClassi(r.getInt("numero_classi"));
-------------------------------------------------------------------------

2) Database.directQuery--------------------------------------------------
Come è scritto nella documentazione del metodo, "Utilizzare con molta cautela, 
solo quando i metodi forniti da Tabella e DBBeans sono insufficienti, e non e' 
possibile aggiungervi funzionalità."

Il seguente codice non va bene:
----------------------BUGGY-JAVA-CODE------------------------------------
ResultSet res = tabella.getDatabase().directQuery(
    "SELECT * FROM " + tabella.getNomeTabella()
    + "WHERE username =" + user);
-------------------------------------------------------------------------

La colonna username è una stringa. La query, così formattata, verrebbe: 
"WHERE username = nomeutente". Invece, dovrebbe essere "WHERE username = 
'nomeutente'". Inoltre, eventuali apici singoli e doppi presenti nella stringa 
dovrebbero essere sottoposte ad escape.
Per ovviare al problema, la cosa più semplice è utilizzare i metodi messi a 
disposizione da Tabella:

----------------------JAVA-CODE------------------------------------------
PreparedStatement stmt = tabella.prepareStatement(
    "SELECT * FROM " + tabella.getNomeTabella() + "WHERE username = ?");
tabella.setParam(stmt, 1, "username", user);
ResultSet res = stmt.executeQuery();
-------------------------------------------------------------------------

3) colonne inesistenti---------------------------------------------------
q.setListaGenitori((List<Genitore>)r.getObject("lista_genitori"));

La colonna lista_genitori non esiste da nessuna parte,
in tutta la documentazione del sistema.
-------------------------------------------------------------------------

4) getObject-------------------------------------------------------------
Questo codice non va bene:
----------------------BUGGY-JAVA-CODE------------------------------------
protected Attivita creaBean(ResultSet r) throws SQLException {
    Attivita a = new Attivita();
    if(r.next())
    {
        a.setCategoria(r.getString("categoria"));
        a.setDescrizione(r.getString("descrizione"));
        a.setProgramma_educativo_settimanale(
                (ProgrammaEducativoSettimanale)r.getObject("programma_educativo_settimanale"));
        //....
-------------------------------------------------------------------------
La documentazione di getObject dice: "Il tipo concreto dell'oggetto Java 
restituito sarà il tipo Java predefinito corrispondente al tipo della colonna 
SQL".
In questo caso, programma_educativo_settimanale è un ID intero. Quindi, 
getObject, restituirà una variabile di tipo Integer, non certo un 
ProgrammaEducativoSettimanale bello e fatto (se bastasse fare così, le classi 
di storage sarebbero inutili).

La cosa giusta da fare è istanziare un nuovo programma educativo, inserendovi 
solo i campi disponibili nella chiave esterna:
----------------------JAVA-CODE------------------------------------------
protected Attivita creaBean(ResultSet r) throws SQLException {
    Attivita a = new Attivita();
    if(r.next())
    {
        a.setCategoria(r.getString("categoria"));
        a.setDescrizione(r.getString("descrizione"));
        a.setProgramma_educativo_settimanale(
                new ProgrammaEducativoSettimanale());
        a.getProgramma_educativo_settimanale().
                setId(r.getInt("programma_educativo_settimanale"));
        //....
-------------------------------------------------------------------------

5) Nomi------------------------------------------------------------------
Le variabili e i metodi Java si chiamano con le convenzioni Java.
Le colonne del database si chiamano con le convenzioni del database.
Come descritto nelle convenzioni di codifica, il cui mancato rispetto incide 
sulla valutazione finale da parte dei PM.

Se la colonna del database si chiama programma_educativo_settimanale, la 
variabile Java deve chiamarsi programmaEducativoSettimanale, ed il metodo 
accessore deve chiamarsi 
getProgrammaEducativoSettimanale/setProgrammaEducativoSettimanale.
Se i nomi lunghi non vi piacciono, potete pure chiamarli getPES e setPES, per 
quanto mi riguarda. L'importante è che la documentazione chiarisca ogni dubbio 
e che il nome rispetti le convenzioni.

A questo proposito, dovreste tutti installare in Eclipse il plugin di 
validazione che vi ho già indicato: 
http://eclipse-cs.sourceforge.net/downloads.html
-------------------------------------------------------------------------

6) Documentazioni assenti------------------------------------------------
C'è gente che deve USARE i vostri metodi. Possibilmente, dovrebbe essere in 
grado di farlo SENZA andarsi a leggere il codice. Quindi, dovete documentare i 
metodi che implementate in modo esaustivo.
-------------------------------------------------------------------------

6) Documentazioni carenti------------------------------------------------
Questa non è una documentazione sufficiente (però è una delle poche 
presenti):
----------------------BUGGY-JAVADOC--------------------------------------
/**
 * 
 * @param user
 * @return un account con username=a oppure null
 * @throws SQLException
 */
public Account ricercaPerUsername(String user) throws SQLException
-------------------------------------------------------------------------

- Cosa rappresenta la stringa user?? Uno username?
- Che succede se la stringa user è null?
- Che succede se la connessione al database fallisce?
- Che succede se nel database non è presente l'utente indicato?
- Che succede se nel database è presente più di un utente che corrisponde ai 
criteri?
- In che circostanze il metodo restituisce un account piuttosto che null?
- In che circostanze viene lanciata una SQLException?
- Come sono avvalorati i campi interni all'Account?

Una versione più esaustiva della documentazione potrebbe essere come segue:
----------------------------JAVADOC--------------------------------------
/**
 * Ricerca e restituisce, se presente, un Account il cui username
 * corrisponde a quello passato in input.
 * @param user   Username dell'Account ricercato.
 * @return l'unico Account esistente con username==user
 *        oppure null, se tale Account non esiste.
 *        L'Account restituito include un'istanza di {@link Utente},
 *        in cui l'unica proprietà avvalorata e' CodiceFiscale.
 * @throws SQLException se si verifica un'eccezione nella comunicazione
 *        con la base di dati.
 */
public Account ricercaPerUsername(String user) throws SQLException
-------------------------------------------------------------------------

Original comment by blunotte...@gmail.com on 30 Nov 2012 at 3:45

GoogleCodeExporter commented 9 years ago
Per una versione più leggibile, vedete qui: 
https://groups.google.com/d/topic/at-silo/ZEtX07nNy-Y/discussion

Original comment by blunotte...@gmail.com on 30 Nov 2012 at 3:53

GoogleCodeExporter commented 9 years ago
Mi sono appena accorto che in atsilo Storage non ci sono implementate, nè 
create le relazioni N a N che vengono a crearsi con lo schema Logico

Original comment by FabioNapoli34 on 30 Nov 2012 at 4:28

GoogleCodeExporter commented 9 years ago
Le relazione N a N dovrebbero essere state risolte con una tabella di 
smistamento.
Sarà compito delle classi che fanno riferimento alla relazione (non quindi 
alla tabella di smistamento) prendere le info relative alla tabella nuova.
Spero di essere stata chiara

Original comment by hilin...@gmail.com on 30 Nov 2012 at 7:34

GoogleCodeExporter commented 9 years ago
in alternativa, potete fare un'altra classe derivata di DBBeans e metterla 
package protected.

Original comment by blunotte...@gmail.com on 30 Nov 2012 at 10:13

GoogleCodeExporter commented 9 years ago
giulio potresti dircelo in modo piu dettagliato ? :D

Original comment by FabioNapoli34 on 30 Nov 2012 at 10:18

GoogleCodeExporter commented 9 years ago
potete fare una classe di pacchetto (senza public) che estende DBBeans e si 
lega alla tabella di smistamento. Come bean associato, potreste usare una 
classe interna

class DBRelazioneNAN extends DBBeans<DBRelazioneNAN.Relazione> {
    static final class Relazione {
        private PrimoBean primoBean;
        private SecondoBean secondoBean;

        //getter e setter di Relazione
    }
}

È solo un'altra opzione. Sinceramente, non so quale sia meglio.

Un'altra opzione potrebbe essere quella di inserire una ulteriore Tabella in 
uno o entrambi i DB-Manager coinvolti nella relazione.

Original comment by blunotte...@gmail.com on 30 Nov 2012 at 10:29

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Dopo una discussione con Luigi , abbiamo pensato di procedere in questo modo 
per le cosiddette tabelle di smistamento:
Nel mio esempio abbiamo la relazione Compila tra genitore e questionario
Quindi procederò così:
Creo prima un Bean in atsiloEntity chiamato CompilaQuestionario con i get e i 
set, 
quest'oggetto conterrà un campo int : idQuestionario( chiave del questionario)
e un campo String : codiceFiscale (chiave del genitore che compila)
Poi in atsiloStorage creo una classe che estende DBBeans chiamata 
DBCompilaQuestionario che sarà la tabella del DB che conterrà  gli oggetti 
CompilaQuestionario
COsa ne pensate?

Original comment by FabioNapoli34 on 1 Dec 2012 at 11:12

GoogleCodeExporter commented 9 years ago
secondo me può andare, aspetto però l'intervento di qualcuno più anziano di 
me per sarerne un po' di più :-)

Original comment by cesarano...@gmail.com on 1 Dec 2012 at 12:41

GoogleCodeExporter commented 9 years ago
Non dire Anziano potrebbero offendersi :D

Original comment by FabioNapoli34 on 1 Dec 2012 at 12:42

GoogleCodeExporter commented 9 years ago
Cosa ho detto l'altro giorno?? Terzo anno della triennale potete programmare, 
non serve nessuno più anziano.
Personalmente, non metterei il bean in atsilo.entity, perché non è una vera 
entity, ma solo un metadato, quindi propenderei per il metterlo come classe di 
pacchetto dentro atsilo.storage. L'idea è che le classi fuori dal pacchetto 
storage non hanno bisogno di sapere che questa classe esiste.

Però alla fine non è sbagliato se la mettete in entity.

Original comment by blunotte...@gmail.com on 1 Dec 2012 at 10:45

GoogleCodeExporter commented 9 years ago
Per il testing, vorrei farvi notare che ho creato una classe 
test.storage.DBUtil, che contiene un metodo utile per eseguire uno script SQL 
sul database.
Questo è utile in associazione al metodo di setUp del test. In pratica, l'idea 
è che, prima di ogni metodo di test, resettate il database allo stato 
iniziale, in modo da annullare eventuali modifiche (corrette o errate che 
siano) apportate dai test precedenti (principio di isolamento dei test).

Per un esempio su come usarlo, potete guardare i metodi setUp e tearDown della 
classe test.storage.TestDBBeans, però fate attenzione al fatto che lo script 
testDB.sql NON è adatto ai vostri test, perché usa un db di prova giocattolo 
con una struttura logica diversa dal db di @silo. Più probabilmente, a voi 
interesserà usare "SDD/Dati Persistenti/atsilo popolato.sql".

Original comment by blunotte...@gmail.com on 1 Dec 2012 at 11:56