VFP Coding Conventions
Naming Conventions
Database Field Prefixes (CRITICAL!)
| Prefix |
SQL Type |
VFP Type |
Example |
id* |
INT IDENTITY/INT |
Integer |
idperson, idclient |
d* |
DATE |
Date |
dbirthdate, ddeadline |
t* |
DATETIME |
DateTime |
tlogon, tcreated |
n* |
NUMERIC |
Numeric |
npercent, nprice |
c* |
VARCHAR/CHAR |
Character |
cname, ccode |
l* |
BIT |
Logical |
lactive, lbillable |
Variable Prefixes
| Prefix |
Scope |
Example |
gl_* |
Global (PUBLIC) |
gl_nSQLHandle, gl_cUser |
gll_* |
Global saved to .mem file |
gll_cExportPath |
m.* |
Memory variables (Scatter) |
m.cname, m.ddate |
lc* |
Local Character |
lcSQL, lcWhere |
ln* |
Local Numeric |
lnTotal, lnCount |
ld* |
Local Date |
ldStart, ldEnd |
ll* |
Local Logical |
llSuccess, llFound |
la* |
Local Array |
laResults, laFiles |
lo* |
Local Object |
loForm, loException |
Function Prefixes
| Prefix |
Purpose |
Example |
sql_* |
SQL Server helpers |
sql_exec(), sql_update() |
log_* |
Logging functions |
log_error(), log_info() |
get_* |
Data retrieval |
get_client(), get_settings() |
set_* |
Data modification |
set_status(), set_config() |
Code Patterns
1. VFP Does NOT Have ELSEIF!
*-- CORRECT - Use DO CASE
DO CASE
CASE nResult > 0
RETURN .T.
CASE nResult = 0
RETURN .T.
OTHERWISE
RETURN .F.
ENDCASE
*-- WRONG - VFP has no ELSEIF!
IF nResult > 0
RETURN .T.
ELSEIF nResult = 0 && COMPILE ERROR!
RETURN .T.
ENDIF
2. SCATTER for Read, REPLACE for Write (NOT GATHER!)
*-- CORRECT - Scatter to read, REPLACE to write specific fields
SELECT clients
Scatter Memvar
m.cname = "New Name"
REPLACE cname WITH m.cname
TABLEUPDATE(.T.)
*-- WRONG - Gather sends ALL fields (risky!)
Scatter Memvar
m.cname = "New Name"
Gather Memvar && May overwrite fields you didn't intend to change!
3. File Operations - Use STRTOFILE
*-- CORRECT - STRTOFILE for append
=STRTOFILE(lcText + CHR(13)+CHR(10), lcFile, .T.)
*-- WRONG - Fopen/Fputs/Fclose is fragile
lnHandle = Fopen(lcFile)
=Fputs(lnHandle, lcText)
=Fclose(lnHandle)
4. NULL Handling
*-- CORRECT - Check type before comparison
IF VARTYPE(ddeadline) = 'D' AND ddeadline < DATE()
lcStatus = "Overdue"
ENDIF
*-- WRONG - Will crash if field is NULL
IF ddeadline < DATE() && Error if NULL!
lcStatus = "Overdue"
ENDIF
5. Date Comparisons for "Overdue"
*-- CORRECT - < for strictly overdue (excludes today)
IIF(ddeadline < DATE(), "OVERDUE", "OK")
*-- WRONG - <= includes today (not overdue yet!)
IIF(ddeadline <= DATE(), "OVERDUE", "OK")
6. Error Handling with TRY/CATCH
TRY
*-- Risky operation
USE sometable EXCLUSIVE
*-- Process data
CATCH TO loEx
*-- Handle error
log_error(loEx.Message + " in " + loEx.Procedure)
MESSAGEBOX("Error: " + loEx.Message, 16, "Error")
FINALLY
*-- Cleanup (always runs)
USE IN SELECT("sometable")
ENDTRY
7. Safe Object Property Access
*-- CORRECT - Check object exists first
IF VARTYPE(loObject) = 'O' AND !ISNULL(loObject)
lcValue = loObject.Property
ENDIF
*-- WRONG - Will crash if object is NULL or doesn't exist
lcValue = loObject.Property
Common Errors
| Error |
Cause |
Solution |
| "Unrecognized command verb" |
Used ELSEIF |
Replace with DO CASE |
| "Operator/operand mismatch" |
NULL comparison |
Use VARTYPE() first |
| "Variable not found" |
Missing m. prefix |
Use m.varname with Scatter |
| "Property is read-only" |
Modifying .Name |
Some properties can't change at runtime |
Best Practices
- Always use m. prefix with SCATTER MEMVAR variables
- Prefer local variables (lc*, ln*) over public (gl_*)
- Close cursors explicitly - don't rely on scope cleanup
- Use TABLEUPDATE() after modifying buffered cursors
- Handle NULL values explicitly in comparisons
- Use TRY/CATCH for operations that might fail
- Log errors to help with debugging
Quick Reference
*-- String functions
ALLTRIM(string) && Remove leading/trailing spaces
UPPER(string) && Convert to uppercase
SUBSTR(string,n,m) && Extract substring
AT(search, string) && Find position
*-- Date functions
DATE() && Current date
DATETIME() && Current datetime
DTOC(date) && Date to character
CTOD(string) && Character to date
DTOS(date) && Date to string (YYYYMMDD)
*-- Type checking
VARTYPE(var) && Returns type letter (C,N,D,L,O,U,X)
TYPE("var") && Returns type (evaluates expression)
ISNULL(var) && Check if NULL
EMPTY(var) && Check if empty
*-- Array functions
ALINES(array, string, .T., CHR(13)+CHR(10)) && Split string to array
ALEN(array, 1) && Number of rows
ASCAN(array, value) && Find value in array
Resources