Good and Bad Coding

Let's say you need a function and you go fishing on the Internet. Bingo! You've found it. But what's wrong? The code is awful. You can't use it. It is poorly written. Some of us can not afford spending days in search of good code once they've already found something that works. The business just does not stand still. So what? What makes a program really good and nicely readable is a comment. Some of us work in a really quick pace and do not have time or intention to write it. I do not vote against comments, I just want to justify why the good code always says more than the best comment.

Let's take a look at some examples what is good and what is not very.

1. Use built-in constants.

Good:

res = (MsgBox "You've got mail. Open it?",vbYesNo or vbQuestion, App.Title)
If res = vbYes then
End if

Bad:

res = MsgBox ("You've got mail. Open it?", 36)
if res = 6 then
end if

2. Using IIF function often saves space and in simple cases adds clarity:

Good:

Res = Iif(A>B, A, B)

Not so good:

If A>B then
Res = A
Else
Res = B
End if

3. Use Select clause

When you are doing multiple selections it's the only choice.
It's not obvious when you have to select between 2 or 3 things. But, still I recommend using it.
Why? You might add a new condition at any time without messing up the whole program.

Good:

select case A
case 1:
case 2:
case else:
end select

Bad:

If A=1 then
'..
elseif A=2 then
'..
else
'..
end if

4. Always use Option Explicit

It really helps by checking the code syntax for you.


5. Avoid using non-restrictive or dynamic data types
It also helps when it comes to a later modifications.

Bad:

for k%=1 to 10
' ... some code
next

Good:

Dim k as Long
For k = 1 to 10
'... some code
next k

6. Use condition checking with caution

Good, if you use correct parentheses:

Dim Res as boolean
Res = (A=B)
'in some cases if you omit the parentheses you'll have problems

Good:

If A=B then
Res = true
Else
Res = false
End if

7. Error Handling

'rem Make it the habit in the very beginning of every function/sub include the following clause:

On Error Goto ErrHand
'? some code goes here

'and in the end of the function/sub make the label working
ErrHand:
If Err then
MsgBox Err.Description, vbExclamation, App.Title
Err.clear
End if
End Sub

The bad habit here would be skipping error handling at all or using On Error Resume Next, which is even worse. You will inevitably end up with long hours of searching for the hidden errors. The absolute worst thing here that might happen is when the error appears in one function and is transmitted to another function.


8. Window resizing

You'll never know what the user wants. The only thing he wants for sure is to be able to resize a window to a bigger size of a full screen. Make it happen. Use Form_Resize event.
But your form may contain controls that cannot be smaller than a certain size. Fix it.
In your code declare constants MINHEIGHT and MINWIDTH and use them.

Private Sub Form_Resize
On Error GoTo ErrHand
With Me
If .Height < MINHEIGHT Then .Height = MINHEIGHT
If .Width < MINWIDTH Then .Width = MINWIDTH
'?

9. Use With clause

Good:

With frmMyForm
.cboxNoAccess.Value = True
.cmdOk.Enabled = True
End With
' if you use With and then call form controls by their names preceded
' by dots, you'll get a full advantage of the IDE's typeahead feature.
' This will reduce your code generation time and help you to avoid
' misspellings.

Not so good:

cboxnoaccess.value = True
cmdok.enabled = True

10. Use "CaMeL" notation

This will help you to avoid many syntax errors before you hit F5 for the first time. Typeahead feature is the thing that will always guide you.

Good:

frmMyForm.lvListView.ListItems.Clear

Worse:

myform.listview1.Listitems.Clear

11. Use full names of classes in object declarations

Good:

Dim objMyObject as MyComponent.MyObject

Bad:

Dim myobject as MyObject

This will 1) ensure you always call the correct object, 2) allow you more easily switch to Late Binding in case you do not need Early Binding for that particular application.


12. Use Enum type for function parameters

Good:

Private Enum enumCity
Tampa
StPetersburg
London
Paris
End Enum


Private Sub CallCity(enCity as enumCity)
'..
End Sub

Bad:

Private Sub CallCity(enCity as integer)
'..
End sub

13. Forget the Integer data type

You work in the 32-bit environment anyway.

Good:

Private Function FunMult(byval nA as Long, byval nB as Long) as Long
FunMult = nA + nB
End Function
Bad:

Private Function FunMult(byval a as Integer, byval b as Integer) as Integer
'..
You'll inevitably end up with searching why in some cases the result value is smaller than one of the parameters J

14. Avoid using For clause when you do not know how many cycles your loop will go.

Good:

rs.MoveFirst
do while not rs.EOF
'?
rs.MoveNext
loop
Bad:

rs.MoveFirst
For k = 1 to 9999
If rs.EOF then exit for
'?
next

15. Always declare:

all your application-scope variables in a standalone BAS-module,
all module-scope variables in the very beginning of the module,
all function-scope variables in the very beginning of the function.
This will help you to find double-declarations, will help you to see all your currently active variables at the same time and in the same place.

16. Never declare class properties as simple variables like

Public MyProperty as string

Instead, use the Get-Let style:

Public property Let MyProperty(vNewValue as string)
'?
End property

Public property Get MyProperty as string
'?
End property

First, it allows you create unidirectional properties (read only, write only) and helps you to avoid breaking the interface compatibility if you want to change the object behaviour depending on the property value in the future.

17. Avoid using the same DLL file for Binary Compatibility in the Project Options. Create the copy of the DLL, rename it to something like *.CMP so it can not be occasionally overwritten be the next version.

To be continued?