使用 MVP 的 VBA 设置对话框 - 我需要模型吗?

标签 vba mvp

我一直在阅读 MVP(模型- View -呈现器)及其变体(被动 View 、监督 View )的许多示例,以尝试使我的解决方案在 VBA 中更加健壮(并且可重用)(使用 Excel 作为在本例中为主机)。我发现的问题是在 VBA 中找到好的、简单的示例,但对于我需要的(希望是)简单​​的示例来说,这些示例并不是完全多余的。

我正在尝试创建一个“设置”对话框,将某些配置存储在工作表中(这是我的“存储库”)。

这是我的主要过程,由用户触发:

Private Sub ShowImportSelector()
    Dim importPresenter As DataImportPresenter
    Set importPresenter = New DataImportPresenter

    importPresenter.LoadConfig
    If importPresenter.Show = -1 Then Exit Sub
    importPresenter.SaveConfig

    ' begin processing...
    If (CStr([Settings.SelectedVersion].Value2) = "QQ") Then
       ' ...
    End If

End Sub

这是我的“演示者”(这里我使用源范围名称和配置目标):

Option Explicit

Private m_importForm As FImport

Private Sub Class_Initialize()
    Set m_importForm = New FImport
End Sub

Public Sub LoadConfig()
    m_importForm.SetAvailableVersions "tblVERSION"
    m_importForm.SetAvailableSalesOrgs "tblSALESORG"
    m_importForm.SetAvailableCategories "tblCATEGORY"
    m_importForm.ToolName = "Forecast"
End Sub

Public Sub SaveConfig()
    [Settings.SelectedVersion].Value2 = m_importForm.SelectedVersion
    [Settings.SelectedSalesOrg].Value2 = m_importForm.SelectedSalesOrg
    [Settings.SelectedCategory].Value2 = m_importForm.SelectedCategory
End Sub

Public Function Show() As Integer
    m_importForm.Show vbModal
    Show = m_importForm.Result
End Function

现在是“ View ”(VBA 表单):

Option Explicit

Private m_selectedVersion As String
Private m_selectedSalesOrg As String
Private m_selectedCategory As String
Private m_toolName As String
Private m_dialogueResult As Long

Public Property Get ToolName() As String
    ToolName = m_toolName
End Property

Public Property Let ToolName(ByVal value As String)
    m_toolName = value
    ToolNameLabel.Caption = value
End Property

Public Property Get Result() As Long
    Result = m_dialogueResult
End Property

Public Property Get SelectedVersion() As String
    SelectedVersion = m_selectedVersion
End Property

Public Property Get SelectedSalesOrg() As String
    SelectedSalesOrg = m_selectedSalesOrg
End Property

Public Property Get SelectedCategory() As String
    SelectedCategory = m_selectedCategory
End Property

Public Sub SetAvailableVersions(ByVal value As String)
    VersionSelector.RowSource = value
End Sub

Public Sub SetAvailableSalesOrgs(ByVal value As String)
    SalesOrgSelector.RowSource = value
End Sub

Public Sub SetAvailableCategories(ByVal value As String)
    CategorySelector.RowSource = value
End Sub

Private Sub SaveSelections()
    m_selectedVersion = VersionSelector.value
    m_selectedSalesOrg = SalesOrgSelector.value
    m_selectedCategory = CategorySelector.value
End Sub

Private Sub CloseButton_Click()
    m_dialogueResult = -1
    Me.Hide
End Sub

Private Sub ImportButton_Click()
    SaveSelections
    m_dialogueResult = 0
    Me.Hide
End Sub

此时,我对向上述内容添加模型的可能方向感到困惑 - 问题是:这个简单的示例是否需要这样做?

最佳答案

MVP 架构使代码更简洁,但更简洁的代码并不是 MVP 的主要目的;实现松散耦合更高的内聚性可测试性

如果不需要松散耦合的组件和可单元测试的逻辑,那么成熟的 MVP 确实是大材小用,并且将“模型”暴露为“ View ”上的属性绝对是足够好,因为它已经帮助您的“演示者”不需要关心表单控件。您将形式视为它所要求的对象,并且务实地说,这很可能就是您所需要的。不过,我会让 Show 方法返回显式的 Boolean,因为它是隐式使用的。

另一方面,如果您致力于解耦和可测试性,那么从 View 中提取模型只是第一步:那么您需要解耦从工作表中提取演示者,并可能引入一些将其抽象出来的 ISettingsAdapter 接口(interface),这样如果/当配置需要转到数据库或某些 .config 文件时,您的演示者代码不需要以任何方式改变...但这需要设计接口(interface)而无需考虑任何特定的具体实现,即无论数据是否在工作表上、在某个平面文件中,都无需更改即可工作,或在某些数据库表中。

MVP 需要范式转变:MVP 不再是过程式编程,而是 OOP。 OOP 是否对您的需求来说太过分了,取决于您愿意忍受多少耦合,以及面对 future 的变化,这种耦合使您的代码变得多么脆弱。通常,抽象就足够了:使用命名范围而不是硬编码范围地址是提高抽象级别的一种方法;将工作表隐藏在由工作表代理类实现的适配器接口(interface)后面(无论您做什么,绝不使工作表模块实现接口(interface):它将会崩溃)是另一个 - 取决于在哪里你的“过度杀戮”阈值是,但如果你确实实现了完全解耦并编写了单元测试,没有人会责怪你太过分:你只是在追随行业每个程序员都努力追求的最佳实践,提高您的技能,并使以后更容易地使用该代码并在 .NET 中重写它,无论是 VB 还是 C#。我怀疑有人会认为成熟的 MVP 在 .NET/WinForms 中是大材小用。

关于使用 MVP 的 VBA 设置对话框 - 我需要模型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52279450/

相关文章:

vba - 确定变量的完整类型

internet-explorer - 使用 VBA 自动化 IE - 单击 Javascript 链接(无 anchor 标记)

VBA 在特定细胞范围内提供清晰的值,并保护细胞免遭配方冲走

model-view-controller - Model View Controller 有哪些选择?

Android MVP-Architecture 如何使用SQLiteHelper在模型中进行数据库调用

vba - 使用表单属性在用户表单上设置值

Excel 2010+ VBA - 如何搜索范围的公式而不是值

scala - Clojure GUI 编程很难

android - Android开发中MVP模式下如何控制多线程?

android - MVP 架构模式中的实时数据