Access JumpStart 2.0 | Blog

A Rapid Development Framework for Microsoft Access

I gave copilot this prompt:

Rewrite this VBA function using Uncle Bob's SOLID principles:
Function time_()
'******************

Dim v_a As Integer
Dim v_b As Integer
Dim v_c As Integer
'- - - - - - - - -
v_a = Hour(Now)
v_b = Minute(Now)

'******************

If Hour(Now) > 12 Then
v_c = v_a - 12
time_ = v_c & ":" & v_b
Else
time_ = v_a & ":" & v_b
End If
End Function

And got this response:

// Begin Copilot response

Sure! Here’s a refactored version of your VBA function, applying Uncle Bob’s SOLID principles:

' Interface Segregation Principle: Define an interface for time formatting
Interface ITimeFormatter
    Function FormatTime(ByVal hour As Integer, ByVal minute As Integer) As String
End Interface

' Single Responsibility Principle: Separate the logic for time retrieval and formatting
Class TimeRetriever
    Public Function GetCurrentHour() As Integer
        GetCurrentHour = Hour(Now)
    End Function

    Public Function GetCurrentMinute() As Integer
        GetCurrentMinute = Minute(Now)
    End Function
End Class

Class StandardTimeFormatter Implements ITimeFormatter
    Public Function FormatTime(ByVal hour As Integer, ByVal minute As Integer) As String Implements ITimeFormatter.FormatTime
        If hour > 12 Then
            hour = hour - 12
        End If
        FormatTime = hour & ":" & minute
    End Function
End Class

' Dependency Inversion Principle: Depend on abstractions (interfaces) rather than concrete classes
Class TimeService
    Private timeRetriever As TimeRetriever
    Private timeFormatter As ITimeFormatter

    Public Sub New(ByVal retriever As TimeRetriever, ByVal formatter As ITimeFormatter)
        Set timeRetriever = retriever
        Set timeFormatter = formatter
    End Sub

    Public Function GetFormattedTime() As String
        Dim hour As Integer
        Dim minute As Integer
        hour = timeRetriever.GetCurrentHour()
        minute = timeRetriever.GetCurrentMinute()
        GetFormattedTime = timeFormatter.FormatTime(hour, minute)
    End Function
End Class

' Usage
Sub TestTimeService()
    Dim retriever As New TimeRetriever
    Dim formatter As New StandardTimeFormatter
    Dim service As New TimeService(retriever, formatter)
    MsgBox service.GetFormattedTime()
End Sub

This refactored code adheres to the SOLID principles by:

  • Single Responsibility Principle (SRP): Separating the responsibilities of retrieving the current time and formatting it.
  • Open/Closed Principle (OCP): Allowing the TimeService class to be extended with different time formatters without modifying its code.
  • Liskov Substitution Principle (LSP): Ensuring that any class implementing ITimeFormatter can be used interchangeably.
  • Interface Segregation Principle (ISP): Defining a specific interface for time formatting.
  • Dependency Inversion Principle (DIP): Depending on abstractions (ITimeFormatter) rather than concrete implementations.

// End Copilot response

Interesting. This would not compile at all in VBA because each Class enclosure here would require it to be placed in it’s own class module, but other than that, and if we put each class in it’s own module and name it appropriately…

Granted, it is a lot more code, but it does set forward an approach that would allow for flexible integration using interfaces.

You can try this to by going to https://m365.cloud.microsoft/chat/ and then copying and pasting the prompt I used above to see what it gives you. You can even try giving it additional prompts to get it to actually produce valid VBA code. One way to do this is to paste what it gives you into a VBA module and then tell it what error messages you get…