Refator para n camadas
-
03-07-2019 - |
Pergunta
Eu sou um autodidata programador VB6 que usa DAO. Abaixo está um exemplo de uma peça típica do código que eu poderia despejar:
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
Por favor, fingir que o acima é todo o código-fonte de um aplicativo CRUD. Eu sei que este projeto é ruim, tudo é misturado juntos. Idealmente, deve ter três camadas distintas, interface do usuário, lógica de negócios e os dados de acesso. Eu meio-de get por que isso é desejável, mas eu não sei como ele é feito e eu suspeito É por isso que eu não entendo completamente por que tal separação é bom. Eu acho que seria muito mais abaixo na estrada, se alguém poderia refatorar acima ridiculamente exemplo trivial em 3 camadas.
Solução
Um exemplo trivial, sim, mas com todos os elementos básicos - eles só pertencem em 3 classes diferentes (veja abaixo). A principal razão para isto é a "separação de interesses" princípio, ou seja, a GUI é apenas preocupado com GUI coisas, a camada Biz Logic é apenas preocupado com as regras de negócio, ea camada de acesso a dados só está preocupado com representações de dados. Isto permite que cada camada a ser mantido de forma independente e reutilizado em aplicações:
'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
[uma aplicação 'real' seria armazenar em cache o cliente atual, têm constantes ou procedimentos armazenados para a consulta do cliente, etc .; ignorado por brevidade]
Contraste isso com o seu exemplo original tudo-em-o-botão-manipulador (que é assustadoramente comum em código VB, porque é tão fácil de fazer isso dessa maneira) - se necessário a regra do preço-multiplicador em outro aplicativo, você teria que copiar, colar e editar o código em botão manipulador desse aplicativo. Agora haveria dois lugares para manter a mesma regra de negócio, e dois lugares onde a mesma consulta ao cliente foi executado.
Outras dicas
Qual é o propósito do botão?
Os meus primeiros passos seria:
- extrair a parte acessando o banco de dados. (Aviso: Código de ar à frente)
função GetCustomer (CurrentCustomerID como Long)
strSQL = "SELECT * FROM tblCustomers onde ID =" & CurrentCustomerID definido rec1 = GlobalDataBase.openrecordset (strSQL) result = 1
Se rec1.recordcount> 0, em seguida, GetCustomer = rec1 outro GetCustomer = false fim se End Function
- compor a função lógica de negócios:
função getCustomerDiscount (customerID como Long)
cliente = GetCustomer (customerID)
res = 1 se o cliente, em seguida, Se o Cliente ( "categoria") = 1), em seguida, res = 0,9 fim se endif
getcustomerdiscount = res
Função final
- em seguida, mudar o botão:
Sub cmdMultiplier_Click () pricemultiplier = getcustomerdiscount (currentcustomerid) end sub
Normalmente, você terá seu código UI responder aos eventos gerados pelo usuário, neste caso, o clique de botão.
Depois que ele realmente depende de como o programa foi concebido, o projeto mais básico seria para fazer referência a uma instância do cliente e conteria uma propriedade multiplicador. Seu objeto cliente é preenchida a partir de dados em seu DAL.
Validação de UI iria na camada de interface do usuário, as regras de validação de negócios pode entrar em seu objeto de negócios e, em seguida, o seu DAL é a sua camada de persistência.
Aqui está um exemplo muito básico pseudo-código:
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
Saber como refatorar é uma coisa boa. A partir de agora você vai saber separar as camadas.
No entanto, acho que seu tempo será gastar melhor para atualizar as ferramentas que você está usando, ao mesmo tempo. Você tem considere fazê-lo com VB.Net?
Uma maneira de fazer isso irá preservar a sua base de código existente é codificar a camada de dados e BR em VB.Net. Em seguida, para expor a BR por meio COM Interface (esta é uma opção caixa de seleção no projeto). Você pode então usar a nova BR de sua interface atual.
Uma vez que todos BR e DAL feito, você será um passo para uma plataforma completamente nova.