This is a place to list rough ideas that might be patterns in the hopes that knowledgeable visitors will help out with the following tasks:
- Refactor descriptions into simpler form.
- Identify duplication of already existing, named patterns.
- Identify useful new patterns that should be recognized.
- Distinguish non-patterns that might be better listed in another category.
Proposed patternoid from SteveJorgensen - Proposed name: "Replace Arrow with Result Forwarding".
Say you have something like this Access VBA code.
Public Sub SetFooTo123()
Dim ctl As Access.Control
For Each ctl in Me.Controls
If ctl.ControlType = acTextbox Then
If ctl.Name Like "*Foo" Then
ctl.Value = 123
End If
End If
Next
End Sub
This is the ArrowAntiPattern. We could get rid of the arrow using ExtractMethod, but this leads to tightly-coupled, special-purpose procedures.
My idea is that, instead, we flatten the arrow by creating a series of procedure calls, each of which produces a byproduct that is passed to the next, as below. Refactoring is done from the outside in, like peeling an onion. There is, for now, a bit more code here than when we started, but it's mostly more general-purpose code and much less tightly coupled.
It is now possible to test each component atomically, rather than testing all at once, or testing C, then B -> C, then A -> B -> C. Also, it is now trivial to change the order of operations. Note that this is starting to resemble what one might do in a Functional programming language, but without the lazy evaluation. Note that VBA has on Continue statement for loops, so we can't flatten the mini-arrows that way. Of course, if we then implement some sort of Functors, we could get rid of the duplicated ForEach loops, and if we extract a class for filtering and manipulating Controls collections, we could probably get rid of all the objControls passing, but those are other refactorings.
Public Sub SetFooTo123()
Dim ctl As Access.Control
Dim objControls As Object
Set objControls = Me.Controls
Set objControls = ControlsOfType(objControls, acTextBox)
Set objControls = ControlsNamedLike(objControls, "*Foo")
SetValueOfControls objControls, 123
End Sub
Private Function ControlsOfType( _
InControls As Variant, _
ControlType As AcControlType _
) As VBA.Collection
Dim ctl As Access.Control
Dim colResult As New VBA.Collection
For Each ctl In InControls
If ctl.ControlType = ControlType Then
colResult.Add ctl
End If
Next
Set ControlsOfType = colResult
End Function
Private Function ControlsNamedLike( _
InControls As Variant, _
NamedLike As String _
) As VBA.Collection
Dim ctl As Access.Control
Dim colResult As New VBA.Collection
For Each ctl In InControls
If ctl.Name Like NamedLike Then
colResult.Add ctl
End If
Next
Set ControlsNamedLike = colResult
End Function
Private Sub SetValueOfControls( _
Controls As Variant, _
NewValue As Variant _
)
Dim ctl As Access.Control
For Each ctl In Controls
ctl.Value = NewValue
Next
End Sub