Рефакторинг до n-уровневого
-
03-07-2019 - |
Вопрос
Я программист-самоучка vb6, использующий DAO.Ниже приведен пример типичного фрагмента кода, который я мог бы написать:
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
Пожалуйста, представьте, что приведенное выше — это весь исходный код CRUD-приложения.Я знаю, что этот дизайн плохой, все перепутано.В идеале он должен иметь три различных уровня, пользовательский интерфейс, бизнес -логика и доступ к данным.Я получаю, почему это желательно, но я не знаю, как это делается, и я подозреваю, что именно поэтому я не понимаю, почему такое разделение хорошее.Я думаю, что я был бы намного дальше в будущем, если бы кто -то мог рефактировать вышеупомянутый смехотворно тривиальный пример на 3 уровня.
Решение
тривиальный пример, да, но со всеми основными элементами - они просто принадлежат к 3 различным классам (см. ниже). Основной причиной этого является «разделение интересов». принцип, то есть GUI касается только вещей GUI, уровень Biz Logic касается только бизнес-правил, а уровень доступа к данным касается только представлений данных. Это позволяет поддерживать каждый уровень независимо и повторно использовать в разных приложениях:
'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
[«реальное» приложение будет кэшировать текущего клиента, иметь константы или хранимые процедуры для запроса клиента и т. д .; игнорируется для краткости]
Сравните это с вашим исходным примером "все в кнопке-обработчике" (который ужасающе распространен в коде VB, потому что это так просто сделать) - если вам нужно правило мультипликатора цены в другом приложении, вам нужно будет скопировать, вставить и отредактировать код в обработчике кнопок этого приложения. Теперь будет два места для поддержки одного и того же бизнес-правила и два места, где выполнялся один и тот же запрос клиента.
Другие советы
Каково назначение кнопки?
Моими первыми шагами были бы:
- извлеките часть, обращающуюся к базе данных.(предупреждение:воздушный код впереди)
функция getCustomer (CurrentCustomerID as Long)
strsql = "select * from tblcustomers, где id =" & currentcustomerid set rec1 = globaldatabase.openrecordset (strsql) result = 1
Если rec1.recordcount> 0, то getCustomer = rec1 else getCustomer = false endif end function
- составим функцию бизнес-логики:
функция getCustomerDiscount (идентификатор клиента как длинный)
клиент = getCustomer (ID клиента)
res = 1, если клиент, то если клиент ("категория") = 1), то res = .9 endif endif
getcustomerdiscount = разрешение
конечная функция
- затем измените кнопку:
Sub cmdmultiplier_click () pricemultiplier = getCustomerDiscount (currentCustomerid) end sub
Как правило, ваш код пользовательского интерфейса реагирует на события, вызванные пользователем, в данном случае - на нажатие кнопки.
После этого все зависит от того, как устроена ваша программа. Самым базовым дизайном будет ссылка на экземпляр Customer, и он будет содержать свойство множителя. Ваш объект клиента заполняется данными из вашего DAL.
Проверка для пользовательского интерфейса будет осуществляться на уровне пользовательского интерфейса, правила бизнес-проверки могут входить в ваш бизнес-объект, и тогда ваш DAL будет вашим постоянным уровнем.
Вот очень простой пример псевдокода:
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
Знание того, как проводить рефакторинг, - это хорошо. Теперь вы будете знать, как разделять слои.
Тем не менее, я думаю, что ваше время будет лучше потратить на обновление инструментов, которые вы используете в то же время. Вы думаете сделать это с VB.Net?
Один из способов сохранить существующую кодовую базу - это кодировать уровень данных и BR в VB.Net. Затем выставить BR через COM Interface (это опция флажка в проекте). Затем вы можете использовать новый BR из вашего текущего интерфейса.
Как только все BR и DAL будут готовы, вы окажетесь в шаге от совершенно новой платформы.