VBA Abstraction


Abstraction levels help determine when to split things up.

Abstraction is achieved by implementing functionality with increasingly detailed code. The entry point of a macro should be a small procedure with a high abstraction level that makes it easy to grasp at a glance what's going on:

Public Sub DoSomething()
    With New SomeForm
        Set .Model = CreateViewModel
        .Show vbModal            
        If .IsCancelled Then Exit Sub
        ProcessUserData .Model
    End With
End Sub

The DoSomething procedure has a high abstraction level: we can tell that it's displaying a form and creating some model, and passing that object to some ProcessUserData procedure that knows what to do with it - how the model is created is the job of another procedure:

Private Function CreateViewModel() As ISomeModel
    Dim result As ISomeModel
    Set result = SomeModel.Create(Now, Environ$("UserName"))
    result.AvailableItems = GetAvailableItems
    Set CreateViewModel = result
End Function

The CreateViewModel function is only responsible for creating some ISomeModel instance. Part of that responsibility is to acquire an array of available items - how these items are acquired is an implementation detail that's abstracted behind the GetAvailableItems procedure:

Private Function GetAvailableItems() As Variant
    GetAvailableItems = DataSheet.Names("AvailableItems").RefersToRange
End Function

Here the procedure is reading the available values from a named range on a DataSheet worksheet. It could just as well be reading them from a database, or the values could be hard-coded: it's an implementation detail that's none of a concern for any of the higher abstraction levels.