Good Programming Practices
Good programming practices are not just arbitrary rules. They are guidelines designed to help you get the most out of SBasic and Sesame. Regardless of your level of programming experience, following good programming practices will help you to write code that is more reliable and easier to maintain. You can write SBasic that does not follow these guidelines, but your long term experience with programming Sesame will be more productive if you do follow them.
Rule 1: Make It PrettyQ&A Sesame offers many more options for formatting and creating your code than Q&A. You have more tools and more ways to use them. You also don't have any space limits on how much programming you can have, as you had in Q&A, so you can afford to do it right.
Code written with a clean and consistent style is much more readable. This may not seem important at first, but, it makes all the difference when you are looking at something you wrote six months ago.
Put each statement on a separate line. It makes it much easier to
follow your program.
Not recommended:
Name = "Bob";Age = 25;Gender = "Male"
Recommended:
Name = "Bob"
Age = 25
Gender = "Male"
Use White Space. Spaces, blank lines and tabs don't interfere with your programming unless
they are inside double-quotes. White space spreads out your statements so that you can see
what is going on. Put a space between an operator and an operand. Put a space between
arguments. Use a blank line between sections of your program.
Not recommended:
Name="Bob"
Age=25
Gender="Male"
@MsgBox("This is a","message from","the programmer")
Recommended:
Name = "Bob"
Age = 25
Gender = "Male"
@MsgBox("This is a", "message from", "the programmer")
Indent your code. Indenting makes it clear which statements go
together. Indenting is also very helpful for finding where chunks of code inside control
blocks, such as If..Then..Else and Loops begin and end.
Not recommended:
While n < 100
{
vAmount = n * 5
vTotal = vAmount * vQty
}
Recommended:
While n < 100
{
vAmount = n * 5
vTotal = vAmount * vQty
}
Whatever style choices you make, stick with them. If you are writing code for your own use, consistency will make it much easier to figure out what you did when you want to change or update something. If you are a consultant writing code for others, the next person who has to read your code will be very appreciative.
Pick a naming convention for your variables and stick with it.
This includes how you capitalize. SBasic is not case-sensitive, but your eyes are.
It is easier to separate variable names from
layout element names in your code if you name them consistently. Make the variable names
descriptive enough that you can remember what they are for.
Not recommended:
var a as Int
VAR B AS string
Var vCt as INT
Recommended:
var vApple As Int
var vBoy As String
var vCat As Int
Pick a bracing style and stick with it. There are several legal bracing styles, plus BEGIN/END.
They are all acceptable, but choose one and always use it. The same goes for semicolons at
the ends of lines. SBasic can manage with or without the semicolons, but you should decide
which you will use.
Not recommended:
While vN < 100
{
vNAmount = vN * 5;
vNTotal = vNAmount * vNQty
}
While vX < 100 {
vXAmount = vX * 5;
vXTotal = vXAmount * vXQty;
}
While vY < 100
BEGIN
vYAmount = vY * 5
vYTotal = vYAmount * vYQty;
END
Recommended:
While vN < 100
{
vNAmount = vN * 5
vNTotal = vNAmount * vNQty
}
While vX < 100
{
vXAmount = vX * 5
vXTotal = vXAmount * vXQty
}
While vY < 100
{
vYAmount = vY * 5
vYTotal = vYAmount * vYQty
}
Decide how you are going to use white space and stick with it. If you are going to put spaces
between operators and operands, always do so. If you decide that you don't do that, never
do it.
Not recommended:
Name = "Bob"
Age= 25
Gender = "Male"
@MsgBox("This is a","message from", "the programmer")
Recommended:
Name = "Bob"
Age = 25
Gender = "Male"
@MsgBox("This is a", "message from", "the programmer")
Regardless of the many Application design reasons to use variables, there are also good programming practice reasons to use variables. While it may seem easier to simply work directly with Layout Element values, there is good reason not to do so. This is an code example from the programming manual:
var vBonus as Double
If Salary < 80000 Then
{
vBonus = Salary * .02
}
Else
{
vBonus = Salary * .035
}
BonusAmount = @ToMoney(vBonus)
You may wonder why the value is not simply assigned to BonusAmount as it is calculated, rather than using the vBonus variable, like this:
If Salary < 80000
BonusAmount = .02 * Salary
Else
BonusAmount = .035 * Salary
While the reasons to use a variable may not be obvious in such a simple piece of code, you should use variables rather than working directly with your Layout Element values.
Speed - It is much faster to operate on a variable than a Layout
Element value.
Data integrity - You are doing all the calculations in a variable and not affecting the actual Layout Element value until the last step. This way, if something goes awry, such as division by zero, you have not saved a half calculated value or corrupted your original value.
Code maintainability - No matter how many calculations you perform, BonusAmount is only assigned in one place. If something is wrong, you don't have figure out which of the assignments is the problem.
Predictability - Sesame has strong data typing. Your temporary value may not always meet type requirements. Assigning it to the Layout Element will force it to the correct type and may change the value you thought you had.
These considerations may seem minor when dealing with a simple case
like the one above, however, with even a small amount of complexity, this becomes very
important. The example below is only a little more complex than the previous examples, but
the advantages of waiting until the calculations are complete to assign the value to
BonusAmount should be more obvious.
var vBonus as Double
vBonus = Salary * .02
If Position = "Manager" Then vBonus = vBonus + (Salary * .025)
If YearsWorked > 10 Then
{
vBonus = vBonus + (vBonus * .05)
}
Else
{
vBonus = vBonus + 10
}
BonusAmount = @ToMoney(vBonus)
There are several kinds of variable scope available in SBasic. In general, local variables are safer than global variables because everything that can affect the variable's value is there in the same procedure. See the Variables section for a detailed explanation of variable scope.
Rule 4: One Way In, One Way OutHaving more than one way in and one way out of any particular procedure or control block is asking for trouble. Not only does it reduce the reliability of your code, but it also makes it far more difficult to figure out which part of your code is actually running. This can make maintaining and debugging your code unnecessarily difficult.
GoTo is not the recommended way to stop code from running. If you GoTo a different Layout Element,
none of the code after the GoTo will run. If you are using GoTo with code after it, you
are better off setting a "quit" variable or using a control statement to control whether
that code runs. A "quit" variable is especially useful if you have a case where more than
one condition may cause the GoTo.
Not recommended:
If Amount > 1000
{
GoTo LargeInvoice
}
// The following lines will never run if Amount > 1000
{
vLineTotal = Amount * Qty
}
vInvoiceTotal = InvoiceTotal + vLineTotal
InvoiceTotal = vInvoiceTotal
Recommended:
vQuit = 0
If Amount > 1000
{
vQuit = 1
}
// Note that in this example, you could have checked
// any number of conditions before this point to decide
// whether to quit.
If vQuit = 0
{
vLineTotal = Amount * Qty
vInvoiceTotal = InvoiceTotal + vLineTotal
InvoiceTotal = vInvoiceTotal
}
Else
{
GoTo LargeInvoice
}
Or:
If Amount > 1000
{
GoTo LargeInvoice
}
Else
{
vLineTotal = Amount * Qty
vInvoiceTotal = InvoiceTotal +
vLineTotal
InvoiceTotal = vInvoiceTotal
}
Never alter a loop control variable from inside the loop. The only exception to this is when you
simply increment it inside a While loop. Altering the loop control variable from inside
the loop virtually guarantees unpredictable behavior and extremely difficult debugging. If
you need to end a loop early because a condition has been met, use a While loop with a
quit variable.
Not recommended:
var sStr as String
var vLoop as Int
While vLoop < 100
{
vStr = LastName
If vStr = "Morgan" vLoop = 100
vLoop = vLoop + 1
}
Recommended:
var vQuit as Int
var sStr as String
var vLoop as Int
vQuit = 0
While (vLoop < 100) And (vQuit = 0)
{
vStr = LastName
If vStr = "Morgan" vQuit = 1
vLoop = vLoop + 1
}
Create user defined functions and subroutines for repetitive calculations. Not only does this save you a lot of typing, it also means that, if you want to change how something works, you only have to change it in one place.
Not recommended:LastName - OnFieldExit
var vLast as String
var vMiddle as String
var vFirst as String
var vFullName as String
var vSep as String
vLast = LastName
vMiddle = MiddleName
vFirst = FirstName
// Prevents an extra space if no Middle Name
If Len(vMiddleName) = 0
{
vSep = ""
}
Else
{
vSep = " "
}
vFullName = vLastName + ", " + vMiddleName + vSep + vFirstName
FullName = vFullName
FirstName - OnFieldExit
var vLast as String
var vMiddle as String
var vFirst as String
var vFullName as String
var vSep as String
vLast = LastName
vMiddle = MiddleName
vFirst = FirstName
// Prevents an extra space if no Middle Name
If Len(vMiddleName) = 0
{
vSep = ""
}
Else
{
vSep = ""
}
vFullName = vLastName + ", " + vMiddleName + vSep + vFirstName
FullName = vFullName
MiddleName - OnFieldExit
var vLast as String
var vMiddle as String
var vFirst as String
var vFullName as String
var vSep as String
vLast = LastName
vMiddle = MiddleName
vFirst = FirstName
// Prevents an extra space if no Middle Name
If Len(vMiddleName) = 0
{
vSep =
}
Else
{
vSep =
}
vFullName = vLastName + ", " + vMiddleName + vSep + vFirstName
FullName= vFullName
Recommended:
Global Code
Subroutine SetFullName()
var vMiddle as String
var vFirst as String
var vFullName as String
var vSep as String
vLast = LastName
vMiddle = MiddleName
vFirst = FirstName
// Prevents an extra space if no Middle Name
If Len(vMiddleName) = 0
{
vSep = ""
}
Else
{
vSep = " "
}
vFullName = vLastName + ", " + vMiddleName + vSep + vFirstName
FullName = vFullName
End subroutine
LastName - OnFieldExit
SetFullName()
FirstName - OnFieldExit
SetFullName()
MiddleName - OnFieldExit
SetFullName()
Rule 6: Be Specific
It is never a good idea to make a computer quess at what you mean. When performing operations of values of different types, use casting to make it clear to Sesame
what you want. The casting functions are those like @Str and @ToNumber, theat specifically convert a value to a particular type. If you make the computer guess , 10 + "Mary"
may produce a different result than "Mary" + 10.
Not recommended:
var vStr as String
vStr = "Mary" + 10
Recommended:
var vStr as String
vStr = "Mary" + @Str(10)
// vStr = "Mary10"
While these guidelines may seem unnecessary when you are writing a few simple lines of code, keep in mind that it rarely stops with a few lines. As you learn more about Sesame and get more comfortable with programming, you will want to improve your Application. Many of those improvements are likely to take the form of SBasic code, both in event programming and Mass Updates. As you write more code, and your code becomes more complex, you will be glad that you employed good programming practices right from the beginning.