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…