1

我是一个使用 DAO 的自学 vb6 程序员。下面是我可以编写的一段典型代码的示例:

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

4 回答 4

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 代码中非常常见,因为这样做很容易) - 如果您需要在另一个应用程序中使用价格乘数规则,您会必须将代码复制、粘贴和编辑到该应用程序的按钮处理程序中。现在将有两个地方维护相同的业务规则,两个地方执行相同的客户查询。

于 2008-10-23T02:36:43.980 回答
1

按钮的用途是什么?

我的第一步是:

  • 提取访问数据库的部分。(警告:前面的空气代码)
function getCustomer(CurrentCustomerID as Long)

strSQL = "select * from tblCustomers where ID = " & CurrentCustomerID
set rec1 = GlobalDataBase.openrecordset(strSQL)
result = 1

if rec1.recordcount >0 then
    getCustomer = rec1
else
    getCustomer = false
endif
end function
  • 编写业务逻辑函数:
function getCustomerDiscount(customerID as Long)

customer = getCustomer(customerID)

res = 1
if customer then
    if customer("category")=1) then
        res = .9
    endif
endif

getcustomerdiscount = res

end function
  • 然后,更改按钮:
Sub cmdMultiplier_Click() 
    pricemultiplier = getcustomerdiscount(currentcustomerid)
end sub
于 2008-10-22T22:29:29.110 回答
1

通常,您的 UI 代码将响应用户引发的事件,在本例中为按钮单击。

之后它真的取决于你的程序是如何设计的,最基本的设计是引用一个客户实例,它会包含一个乘数属性。您的客户对象由 DAL 中的数据填充。

UI 验证将进入 UI 层,业务验证规则可以进入您的业务对象,然后您的 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
于 2008-10-23T00:48:58.580 回答
1

知道如何重构是一件好事。从现在开始,您将知道如何分离图层。
但是,我认为您的时间最好花在升级您正在使用的工具上。你有考虑用 VB.Net 做吗?

保留现有代码库的一种方法是在 VB.Net 中对数据层和 BR 进行编码。然后通过 COM 接口公开 BR(这是项目中的复选框选项)。然后,您可以从当前界面使用新的 BR。

完成所有 BR 和 DAL 后,您将离一个完整的新平台仅一步之遥。

于 2008-10-23T03:33:57.563 回答