Rifattore su livello n
-
03-07-2019 - |
Domanda
Sono un programmatore vb6 autodidatta che utilizza DAO. Di seguito è riportato un esempio di un tipico codice che potrei sfornare:
Sub cmdMultiplier_Click() 'Button on form, user interface '
dim Rec1 as recordset
dim strSQL as string
strSQL = "select * from tblCustomers where ID = " & CurrentCustomerID 'inline SQL '
set rec1 = GlobalDataBase.openrecordset(strSQL) ' Data access '
if rec1.bof <> true or rec1.eof <> true then
if rec1.fields("Category").value = 1 then
PriceMultiplier = 0.9 ' Business Logic '
else
priceMultiplier = 1
end if
end if
End Sub
Fingi che quanto sopra sia l'intero codice sorgente di un'applicazione CRUD. So che questo design è cattivo, tutto è confuso. Idealmente dovrebbe avere tre livelli distinti, interfaccia utente, logica aziendale e accesso ai dati. Ho capito perché questo è desiderabile, ma non so come sia fatto e sospetto ecco perché non capisco perfettamente perché una tale separazione sia buona. Penso che sarei molto più avanti se qualcuno potesse ridicolizzare quanto sopra ridicolmente banale esempio in 3 livelli.
Soluzione
un esempio banale, sì, ma con tutti gli elementi di base - appartengono solo a 3 classi diverse (vedi sotto). La ragione principale di ciò è la "separazione delle preoccupazioni". principio, ovvero la GUI riguarda solo le cose della GUI, il livello Biz Logic riguarda solo le regole aziendali e il livello di accesso ai dati riguarda solo le rappresentazioni dei dati. Ciò consente a ciascun livello di essere gestito in modo indipendente e riutilizzato tra le applicazioni:
'in Form class - button handler
Sub cmdMultiplier_Click()
PriceMultiplier = ComputePriceMultiplier(CurrentCustomerId)
End Sub
'in Biz Logic class
Function ComputePriceMultiplier(custId as Integer) as Double
Dim cust as Customer = GetCustomer(custId)
if cust.Category = 1 then 'please ignore magic number, real code uses enums
return 0.9
end if
return 1
End Function
'in Data Access Layer class
Function GetCustomer(custId as Integer) as Customer
Dim cust as Customer = New Customer 'all fields/properties to default values
Dim strSQL as String = "select * from tblCustomers where ID = " & custId
set rec1 = GlobalDataBase.openrecordset(strSQL) ' Data access '
if rec1.bof <> true or rec1.eof <> true then
cust.SetPropertiesFromRecord(rec1)
end if
return cust
End Function
[un'applicazione 'reale' memorizzerebbe nella cache il cliente corrente, avrebbe costanti o stored procedure per la query del cliente, ecc .; ignorato per brevità]
Contrasta questo con il tuo originale esempio di gestore di tutto il pulsante (che è terribilmente comune nel codice VB perché è così facile farlo in quel modo) - se avevi bisogno della regola del moltiplicatore di prezzo in un'altra applicazione, dovresti copiare, incollare e modificare il codice nel gestore di pulsanti dell'applicazione. Ora ci sarebbero due posti per mantenere la stessa regola aziendale e due posti in cui è stata eseguita la stessa query del cliente.
Altri suggerimenti
Qual è lo scopo del pulsante?
I miei primi passi sarebbero:
- estrae la parte che accede al database. (avviso: codice aereo in avanti)
funzione getCustomer (CurrentCustomerID come Long)
strSQL = " select * da tblCustomers dove ID = " & Amp; CurrentCustomerID set rec1 = GlobalDataBase.openrecordset (strSQL) risultato = 1
se rec1.recordcount > 0 allora getCustomer = rec1 altro getCustomer = false finisci se fine funzione
- componi la funzione di logica aziendale:
funzione getCustomerDiscount (customerID as Long)
customer = getCustomer (customerID)
res = 1 se cliente allora se il cliente (" categoria ") = 1), allora res = .9 finisci se endif
getcustomerdiscount = res
fine funzione
- quindi, cambia il pulsante:
Sotto cmdMultiplier_Click () pricemultiplier = getcustomerdiscount (currentcustomerid) fine sub
In genere il tuo codice UI risponderà agli eventi generati dall'utente, in questo caso il Clic sul pulsante.
Dopodiché dipende davvero da come è stato progettato il programma, la progettazione più semplice sarebbe quella di fare riferimento a un'istanza del cliente e conterrebbe una proprietà moltiplicatrice. L'oggetto del cliente viene popolato dai dati nel DAL.
La convalida per l'interfaccia utente andrebbe nel livello dell'interfaccia utente, le regole di convalida aziendale potrebbero andare nell'oggetto business e quindi il DAL è il livello di persistenza.
Ecco un esempio pseudo-codice molto semplice:
btnClick
Dim Cust as New Customer(ID)
multplr = Cust.DiscountMultiplier
End Click
Class Customer
Sub New(ID)
Data = DAL.GetCustomerData(ID)
Me.Name = Data("Name")
Me.Address = Data("Address")
Me.DiscountMultiplier = Data("DiscountMultiplier")
End Sub
Property ID
Property Name
Property Address
Property DiscountMultiplier
Return _discountMultiplier
End
End Class
Class DAL
Function GetCustomerData(ID)
SQL = "Paramaterized SQL"
Return Data
End Function
End Class
Saper refactoring è una buona cosa. Da adesso saprai come separare i livelli.
Tuttavia, penso che sarà meglio spendere il tuo tempo per aggiornare gli strumenti che stai utilizzando allo stesso tempo. Hai considerato di farlo con VB.Net?
Un modo per farlo preserverà la tua base di codice esistente è codificare il livello dati e BR in VB.Net. Quindi esporre BR attraverso l'interfaccia COM (questa è un'opzione di casella di controllo nel progetto). Puoi quindi utilizzare il nuovo BR dalla tua interfaccia corrente.
Al termine di BR e DAL, sarai a un passo da una piattaforma completamente nuova.