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:
- It actually can harm the readability because it adds to the overall length of code to read and understand.
- 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:
- 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.
- Instead of having one large procedure that does 3 things:
- Get an instance of Outlook.Application
- Create an email
- Add attachments
- 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.