Self-documenting code

Strong preference should be given to writing code that is self-documenting. A common approach is to write a lot of comments, but the problem with comments are twofold:

  1. It actually can harm the readability because it adds to the overall length of code to read and understand.
  2. It must be correct or it can end up wasting time. This is illustrated well with a silly gif:

If you feel that a procedure must be commented because it’s doing complex, the next question you need to ask yourself is:

Is the procedure doing too much?

To illustrate why it can be a problem, consider the following procedure:

'Use this only to send emails to clients
Private Sub SendEmail()
    Dim objOutlook As Object 'Outlook.Application
    Dim objEmail As Object 'Outlook.MailItem
    Dim fol As Object 'Scripting.Folder
    Dim fil As Object 'Scripting.File
    
    'Let's try to see if Outlook is open, otherwise make a new instance
    On Error Resume Next
    Set objOutlook = GetObject(, "Outlook.Application")
    If Err.Number Then
      Set objOutlook = Nothing
    End If
    On Error GoTo 0
    If objOutlook Is Nothing Then
      'We didn't get it, so we'll need to new it up
      Set objOutlook = CreateObject("Outlook.Application")
    End If
    
    Set objEmail = objOutlook.CreateItem(0) '0 means email
    
    'Now we have the email, let's get the clients' name
    objEmail.To = DLookup("Email", "tblEmployee", "EmployeeID = " & TempVars!EmployeeID)
    objEmail.Subject = "Updated documents"
    objEmail.Body = "We've made updates to the documents. Please login or see attached."
    'We need to get attachments, if any
    Set fol = TempVars!FolderName
    For Each fil In fol.Files
      objEmail.Attachments.Add fil.Path
    Next
    
    objEmail.Send
End Sub

If you read the entire procedure and understood what it does, mad props. However, this would read much easily:

Public Sub SendEmail( _
  EmployeeIDToBeEmailed As Long, _
  AttachmentFolderPath As String _
)
  Dim App As Object 'Outlook.Application
  Dim Email As Object 'Outlook.MailItem
  
#If LateBind Then
  Const olMailItem As Long = 0
#End If

  Set App = OutlookApp()
  Set Email = App.CreateItem(olMailItem)
  
  AddAttachments Email.Attachments, AttachmentFolderPath
  
  With Email
    .To = DLookup("Email", "tblEmployee", "EmployeeID = " & EmployeeIDToBeEmailed)
    .Subject = "Updated documents"
    .Body = "We've made updates to the documents. Please login or see attached."
    .Send
  End With
End Sub

Private Sub AddAttachments( _
  RefAttachments As Object, _ 
  AttachmentFolderPath As String _
) 
  Dim fol As Object 'Scripting.Folder
  Dim fil As Object 'Scripting.File
  
  Set fol = AttachmentFolderPath
  For Each fil In fol.Files
    RefAttachments.Add fil.path
  Next
End Sub

Though the 2nd version is 3 more lines, there are much less comments for following reasons:

  1. Instead of having to explain what the code does, the arguments the procedure requires makes it clear that it expects an employee to send an email to which is embedded in the parameter name EmployeeIDToBeEmailed . In first version, we had a TempVars!EmployeeID, which would lead to surprises if it doesn’t have the value we expect.
  2. Instead of having one large procedure that does 3 things:
    1. Get an instance of Outlook.Application
    2. Create an email
    3. Add attachments
  3. Instead of having a comment to each magical numbers, we define a constant that self-describes, in this case, the olMailItem, which is also already defined in Outlook object library but even if it was our own constant, it would still have a descriptive name and thus read much easier than having a comment affixed.

Legitimate reasons to comment

However, this does not mean comments do not have their place. The main reason why you should comment your code is to explain the why, not the how of the code. A good example would be something like this:

Private Sub SendFTP(UserName As String, Password As String)
  'Due to a bug in FTP library, we must first open a channel then authenticate
  MyFTP.Open()
  MyFTP.Authenticate(UserName, Password)
  MyFTP.Open()
  ...
End Sub

Another reason is to provide context where it is not possible. You saw an example of this earlier with this line:

Dim App As Object 'Outlook.Application

Because the code was late-bound, it provides information that we cannot embed in the code anyway.