Рефакторинг на n-ярус - PullRequest
       17

Рефакторинг на n-ярус

1 голос
/ 23 октября 2008

Я самоучка для программиста 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 яруса.

Ответы [ 4 ]

3 голосов
/ 23 октября 2008

тривиальный пример, да, но со всеми основными элементами - они просто принадлежат к 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, потому что это так просто сделать) - если вам нужно правило мультипликатора цены в другом приложении вам нужно будет скопировать, вставить и отредактировать код в обработчике кнопок этого приложения. Теперь будет два места для поддержки одного и того же бизнес-правила и два места, где выполнялся один и тот же запрос клиента.

1 голос
/ 23 октября 2008

Знание того, как проводить рефакторинг, - это хорошо. Теперь вы будете знать, как разделять слои.
Тем не менее, я думаю, что ваше время будет лучше потратить на обновление инструментов, которые вы используете в то же время. Вы думаете сделать это с VB.Net?

Способ сделать это при сохранении существующей кодовой базы - это кодирование уровня данных и BR в VB.Net. Затем выставить BR через COM Interface (это опция флажка в проекте). Затем вы можете использовать новый BR из вашего текущего интерфейса.

Как только все BR и DAL будут сделаны, вы окажетесь в шаге от новой платформы.

1 голос
/ 23 октября 2008

Как правило, ваш код пользовательского интерфейса реагирует на события, вызванные пользователем, в данном случае - на нажатие кнопки.

После этого все зависит от того, как устроена ваша программа. Самым простым дизайном будет ссылка на экземпляр 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
1 голос
/ 23 октября 2008

Какова цель кнопки?

Моими первыми шагами будет:

  • извлечь часть, обращающуюся к базе данных. (предупреждение: воздушный код впереди)

функция getCustomer (CurrentCustomerID as Long)

strSQL = "select * from tblCustomers, где ID =" & CurrentCustomerID set rec1 = GlobalDataBase.openrecordset (strSQL) результат = 1

если rec1.recordcount> 0, то getCustomer = rec1 еще getCustomer = false ENDIF конечная функция

  • составляет функцию бизнес-логики:

функция getCustomerDiscount (customerID as Long)

customer = getCustomer (customerID)

res = 1 если клиент тогда если customer ("category") = 1), то res = .9 ENDIF ENDIF

getcustomerdiscount = res

конечная функция

  • затем измените кнопку:

Sub cmdMultiplier_Click () Pricemultiplier = getcustomerdiscount (currentcustomerid) конец суб

...