Search code examples
vbaexcelcoding-stylecustom-object

Object oriented style - where to define properties? VBA


I'm quite green on object oriented programming and trying to get my style right.

Very often I have an object of which one the properties is a dictionary containing other objects. Call it class 'Team' that contains a class 'Player'.

Now let's say every time a Player is added to a Team I would like to have the average age of the team updated.

My favorite solution:

In Sub Main I should say just

 Team.add(Player)

Then in Team the method add is:

 Public Sub Add(Player As CPlayer):
      pPlayers.Add Player.Name, Player
      Me.UpDateAvgAge(Player.Age)       
 End Sub

Now I can imagine at least one alternative way to do that which is:

In Main:

Team.add(Player)
Team.UpDateAvgAge(Player.Age)

And the add method should off course not have the Me.UpDateAvgAge(Player.Age) line.

No need to say this is just simplest example. In real life there are a number of properties being 'updated' every time I 'add' something.

Is there a consensus among programmers on how to do this add/update? Any guidelines?

tks in advance!


Solution

  • I could imagine something like this. Class CTeam would precalculate sum of ages of team members right at the moment when new player is added to the collection. And then just use this number instead of having to loop through all the items and calculate the number. But you'll have to update the value in case member is removed from collection etc. You have to decide if this work is suitable or if you just calculate all the values at the moment when it is needed (means no caching).

    You could add and event to the CTeam class as well and so let the subscribers know that new team member was added to the collection. Like in this example UserForm1 is subscriber and it gets informed when publischer which is class CTeam creates new player. HTH

    ' CTeam Class:

    Public Event PlayerWasAdded(player As CPlayer)
    
    Private m_players As VBA.Collection
    Private m_sumTeamAge As Single
    
    Private Sub Class_Initialize()
        Set m_players = New VBA.Collection
    End Sub
    
    Public Sub Add(player As CPlayer)
        m_players.Add player, player.Name
        m_sumTeamAge = m_sumTeamAge + player.Age
        RaiseEvent PlayerWasAdded(player)
    End Sub
    
    Public Property Get AverageAge() As Single
        If m_players.Count > 0 Then
            AverageAge = m_sumTeamAge / m_players.Count
        Else
            AverageAge = 0
        End If
    End Property
    

    ' UserForm1 Class:

    Private WithEvents m_team As CTeam
    
    Private Sub UserForm_Initialize()
        Dim i As Integer
    
        Set m_team = New CTeam
    
        For i = 1 To 5
            m_team.Add CreateNewPlayer(i)
        Next
    End Sub
    
    Private Sub m_team_PlayerWasAdded(player As CPlayer)
        MsgBox "New player " & player.Name & " was added. Do something ...", vbInformation
    End Sub
    
    Private Sub ShowAverageAge_Click()
        MsgBox "Average age of team member is: " & m_team.AverageAge, vbInformation
    End Sub
    
    Private Sub AddNewPlayer_Click()
        m_team.Add CreateNewPlayer(...)
    End Sub
    
    Private Function CreateNewPlayer(platerIndex As Integer) As CPlayer
        Dim upperbound As Integer: upperbound = 35
        Dim lowerbound As Integer: lowerbound = 18
        Dim player As CPlayer
    
        Set player = New CPlayer
        player.Name = "Player_" & platerIndex
        player.Age = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
        Set CreateNewPlayer = player
    End Function