Refactor a n-tier
-
03-07-2019 - |
Pregunta
Soy un programador vb6 autodidacta que utiliza DAO. A continuación se muestra un ejemplo de un fragmento de código típico que podría producir:
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
Supongamos que lo anterior es el código fuente completo de una aplicación CRUD. Sé que este diseño es malo, todo está mezclado. Idealmente debería tener tres capas distintas, interfaz de usuario, lógica de negocios y acceso a datos. En cierto modo entiendo por qué esto es deseable, pero no sé cómo se hace y sospecho es por eso que no entiendo completamente por qué tal separación es buena. Creo que estaría mucho más lejos en el camino si alguien pudiera refactorizar el anterior ridículamente Ejemplo trivial en 3 niveles.
Solución
un ejemplo trivial, sí, pero con todos los elementos básicos, solo pertenecen a 3 clases diferentes (ver más abajo). La razón principal de esto es la "separación de preocupaciones" principio, es decir, la GUI solo se ocupa de los aspectos de la GUI, la capa de Biz Logic solo se ocupa de las reglas de negocios, y la capa de acceso a datos solo se ocupa de las representaciones de datos. Esto permite que cada capa se mantenga de forma independiente y se reutilice en todas las aplicaciones:
'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
[una aplicación 'real' almacenaría en caché al cliente actual, tendría constantes o procedimientos almacenados para la consulta del cliente, etc .; ignorado por brevedad]
Contrasta esto con tu ejemplo original de todo en el botón-controlador (que es terriblemente común en el código VB porque es muy fácil hacerlo de esa manera) - si necesitas la regla del multiplicador de precios en otra aplicación, tendría que copiar, pegar y editar el código en el controlador de botones de esa aplicación. Ahora habría dos lugares para mantener la misma regla de negocios y dos lugares donde se ejecutó la misma consulta del cliente.
Otros consejos
¿Cuál es el propósito del botón?
Mis primeros pasos serían:
- extraer la parte que accede a la base de datos. (advertencia: código de aire por delante)
función getCustomer (CurrentCustomerID como largo)
strSQL = " selecciona * de tblCustomers donde ID = " &erio; CurrentCustomerID set rec1 = GlobalDataBase.openrecordset (strSQL) resultado = 1
si rec1.recordcount > 0 entonces getCustomer = rec1 más getCustomer = false terminara si función final
- componer la función de lógica de negocios:
función getCustomerDiscount (customerID como largo)
customer = getCustomer (customerID)
res = 1 si el cliente entonces Si el cliente (" categoría ") = 1) entonces res = .9 terminara si endif
getcustomerdiscount = res
función final
- luego, cambia el botón:
Sub cmdMultiplier_Click () pricemultiplier = getcustomerdiscount (currentcustomerid) end sub
Por lo general, su código UI responderá a los eventos provocados por el usuario, en este caso, haga clic en el botón.
Después de eso, realmente depende de cómo se diseñe su programa, el diseño más básico sería hacer referencia a una instancia del Cliente y contendría una propiedad multiplicadora. Su objeto de cliente se rellena a partir de los datos en su DAL.
La validación de la interfaz de usuario iría en la capa de la interfaz de usuario, las reglas de validación de negocios podrían ir a su objeto comercial, y luego su DAL es su capa de persistencia.
Aquí hay un ejemplo de pseudocódigo muy básico:
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 cómo refactorizar es una buena cosa. A partir de ahora sabrás cómo separar capas.
Sin embargo, creo que será mejor gastar su tiempo para actualizar las herramientas que está utilizando al mismo tiempo. ¿Tienes pensado hacerlo con VB.Net?
Una forma de hacerlo preservando su base de código existente es codificar la capa de datos y BR en VB.Net. Luego, para exponer la BR a través de la interfaz COM (esta es una opción de casilla de verificación en el proyecto). Luego puede usar el nuevo BR desde su interfaz actual.
Una vez que todos los BR y DAL estén listos, estarás a un paso de una nueva plataforma completa.