Newsgroup: it.comp.lang.visual-basic
Titolo: Consiglio Progettazione classi Three Layer ( lunghetto... )

Ciao a tutti.
Dopo aver letto, spulciato, copiato, ecc ecc vorrei partire a
convertire una mia applicazione NET in una applicazione NET Three
Layer.
 
Partiamo da un aspetto molto semplice
 il popolamento di una combobox da una stored procedure
 
Ho fatto così:
'====================================================================================
nel MODEL definito la classe
Public Class ComboConto 
    Private mCodiceConto As String
    Public Property CodiceConto() As String
        Get
            Return mCodiceConto
        End Get
        Set(ByVal value As String)
            mCodiceConto = value
        End Set
    End Property
 
    Private mDescrizione As String
    Public Property Descrizione() As String
        Get
            Return mDescrizione
        End Get
        Set(ByVal value As String)
            mDescrizione = value
        End Set
    End Property
End Class
 
nel DAL ho scritto la function che va a pescare i dati nel database
Public Class RetrieveCombo
    Shared sConn As String = clsConnessione.strConn
    Public Shared Function LoadComboContoListOfT() As List(Of
ComboConto)
        Dim _combo As ComboConto
        Dim _combos As New List(Of ComboConto)
 
 
        Dim ds As New DataSet
        Dim dt As DataTable
        Try
            ds = SqlHelper.ExecuteDataset(sConn, "sp_Conto")
            dt = ds.Tables(0)
            Using dt
                For Each row As DataRow In dt.Rows
                    _combo = New ComboConto
                    With _combo
                        .CodiceConto = row("CodiceConto")
                        .Descrizione = row("descrizione")
                    End With
                    _combos.Add(_combo)
                Next
 
            End Using
            Return _combos
        Catch ExceptionErr As Exception
            Throw New System.Exception(ExceptionErr.Message, _
           ExceptionErr.InnerException)
            Return Nothing
        End Try
    End Function
End Class
 
 
nello strato BUSINESS
Public Class GetLoadComboListT
    Public Shared Function GetComboConto() As List(Of ComboConto)
        Try
            Dim lista As New List(Of ComboConto)
            lista = DAL.RetrieveCombo.LoadComboContoListOfT
            Return lista
 
        Catch ExceptionErr As Exception
            Throw New System.Exception(ExceptionErr.Message, _
           ExceptionErr.InnerException)
            Return Nothing
 
        End Try
    End Function
End Class
 
Per finire nella parte client chiamo il tutto così nell'evento load
 
Try
  With ComboBox2
	.DataSource = GetLoadComboListT.GetComboConto
        .DisplayMember = "Descrizione"
        .ValueMember = "CodiceConto"
  End With
Catch ex As Exception
        Me.Text = ex.Message
End Try
 
'====================================================================================
 
Che ne pensate?
 
Simona


 
Non male anche se qualcosa si può migliorare.
Dai uno sguardo a questa serie di articoli per 
ASP.NET
 che puoi 
tranquillamente utilizzare nelle tue applicazioni
 
http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1
 
 
Ciao, Vincenzo


Grazie del feedback Vincenzo.
mi guardo il link che mi hai mandato.
 
più che altro mi sembra, continuando per la mia strada, che dovrò
scrivere una quantità notevole di codice pensando di applicare tutta
questa logica per ogni oggetto.
 
O sbaglio?
 
Simona
 
 
 

On Mon, 11 Mar 2013 15:48:45 +0100, "vincepik@work"
<in...@F-U-C-K-S-P-A-M-M-E-R-monkeysoft.it> wrote:
 

mi sono già persa....
 
ma se quando popolo la combo voglio poter aggiungere una riga vuota
alla combo, del tipo "tutti i valori", come faccio?
 
 
 

 alla combo, del tipo "tutti i valori", come faccio?
 
Ciao,
farai un "Add" alla tua lista. Se desideri che sia il primo Item, gli assegni indice "-1".


Ciao.
 
Quindi lo faccio solo nello strato di presentazione?
 

> Quindi lo faccio solo nello strato di presentazione?
Sì, dal momento che ti serve solo in quel contesto.


 
E' un problema esclusivo della presentazione quindi puoi fare come ti ha 
consigliato Fabrizio oppure non aggiungi niente e imposti tutte le combo 
a valore -1 quando inizializzi la form o webform che sia.
In questo modo le combobox appaiono senza nessun elemento e sarà compito 
tuo gestire un'eventuale salvataggio.
 
Ciao, Vincenzo


Ciao
rispondo a te ed a Fabrizio
Il dubbio che ho nel lasciare fare allo strato di presentazione è che
lo stesso in teoria non dovrebbe sapere niente di aggiungere o meno un
elemento vuoto alla lista.
Non dovrebbe essere più corretto, da un punto di vista OOP, che la
parte UI dica alla classe , tramite una proprietà, di aggiungere un
elemento vuoto, che poi effettivamente sarà realizzato dalla
corrispondete classe nell'Data Access Layer?
 
 
 
Simona
 
 

 corrispondete classe nell'Data Access Layer?
 
Dipende.
Ha senso, nella logica *dei dati*, che esista questo elemento che rappresenta <tutti gli elementi>? Secondo me no, è un problema puramente di interfaccia utente... ci saranno schermate in cui serve (ed. interrogazioni) rispetto ad altre in cui non ha senso (es. inserimento, li vorrai immagino che l'utente ne scelga sempre uno specifico)
Il metodo che popola il List(of) non dovrebbe preoccuparsi
 
 
Per inciso, già il fatto stesso che tu abbia chiamato le classi e i metodi 'Combo<qualcosa>', non è il massimo... anche qui, gli strati di accesso ai dati e logica non dovrebbero nemmeno sapere che al mondo esiste il combobox o altro: a loro tu chiedi solo di popolare degli insiemi, e anche il nome di tutte queste funzionalità dovrebbe riflettere questo uso generico
 
Un ultima cosa
Sia per questioni di performance, sia per facilitare tutto il controllo del flusso, personalmente limiterei l'uso massiccio delle eccezioni solo al componente DAL; che 'RetrieveCombo' faccia il trapping delle possibili eccezioni di database, è corretto, ma da li in avanti nella catena, piuttosto che fare Throw in cascata fino al lato UI, sarebbe probabilmente preferibile restituire codici e messaggi attraverso membri delle varie classi.

Concordo con Luca D.
La combo appartiene alla presentazione e l'elemento che vai ad aggiungere, ha la funzione di un button. La stessa combo, rappresenta un insieme di dati fruibili tramite UI.

Sia per questioni di performance, sia per facilitare tutto il controllo del flusso, personalmente limiterei l'uso massiccio delle eccezioni solo al componente DAL; che 'RetrieveCombo' faccia il trapping delle possibili eccezioni di database, è corretto, ma da li in avanti nella catena, piuttosto che fare Throw in cascata fino al
lato UI, sarebbe probabilmente preferibile restituire codici e messaggi attraverso membri delle varie classi.
Qui non ho capito
nello specifico delle classe in Business
Public Class GetLoadComboListT
    Public Shared Function GetComboConto() As List(Of ComboConto)
        Try
            Dim lista As New List(Of ComboConto)
            lista = DAL.RetrieveCombo.LoadComboContoListOfT
            Return lista
 
        Catch ExceptionErr As Exception
            Throw New System.Exception(ExceptionErr.Message, _
           ExceptionErr.InnerException)
            Return Nothing
 
        End Try
    End Function
End Class
 
mi puoi fare un esempio di restituzione dei codici e messaggi
attraverso membri delle varie classi?
 
ciao e grazie
Simona
 
 
 


ok
Avevo proprio cannato il senso allora....
 
grazie
 

 attraverso membri delle varie classi?
 
Ci sono tanti modi.
 
Puoi definire delle proprietà direttamente nella classe Business, oppure usare classi di supporto apposta, ecc...
 
Ad esempio, alcuni componenti che usiamo qui (Chilkat) implementano, in tutte le interfacce pubbliche delle loro classi, le property LastErrorText, LastErrorHTML, LastErrorXML che vengono sempre valorizzate ad ogni chiamata di funzione e a cui si può fare riferimento se il risultato non è quello previsto (Nothing se ritorna un oggetto, negativo se ritorno un numerico, ecc...)
 
Un altro possibile sistema può essere (pseudo-codice)
Class Result(Of T)
  Enum ResultCodes
    OK
    Warning
    Critical
    [ecc...]
  End Enum
 
  Property Code As ResultCodes
  Property Message As String
  Property Item As T
End Class
 
e nella classe business, tutti i metodi ritornano un istanza (tipizzata) di Result, del tipo:
 Public Class GetLoadComboListT
     Public Shared Function GetComboConto() As Result(Of List(Of ComboConto))
         Dim lista As List(Of ComboConto)
         Dim res As New Result(Of List(Of ComboConto))
         Try
             lista = DAL.RetrieveCombo.LoadComboContoListOfT
             res.Code = OK
             res.Item = lista
         Catch ex1 As ExceptionTipo1
             res.Code = Warning
             res.Message = ex2.Message
         Catch ex2 As ExceptionTipo2
             res.Code = Critical
             res.Message = ex1 .Message
         [ecc.. se vuoi discriminare vari tipi di eccezione]
         Finally
             Return res
         End Try
     End Function
 
 End Class
 
 
Lato presentazione, invece di trappare nuovamente l'eccezione, diventa
 
Dim res As Result(Of List(Of ComboConto))
 
res = GetLoadComboListT.GetComboConto
Select case res.code
Case OK
  With ComboBox2 
        .DataSource = res.Item
        .DisplayMember = "Descrizione"
        .ValueMember = "CodiceConto"
  End With
Case Warning
  Me.Text = res.Message
Case Critical
  MessageBox.Show res.Message
  Exit Sub
[ecc..]
End Select


Grazie
mi hai dato molte informazioni utili
 
grazie ancora
 
Simona

 Ha senso, nella logica*dei dati*, che esista questo elemento che rappresenta <tutti gli elementi>? Secondo me no, � un problema puramente di interfaccia utente... ci saranno schermate in cui serve (ed. interrogazioni) rispetto ad altre in cui non ha senso (es. inserimento, li vorrai immagino che l'utente ne scelga sempre uno specifico)
 
 
Dipende, anche in inserimento pu� servire avere un valore "vuoto", per 
esempio nei dati opzionali.
 
ciao
stefano