Known‐Quirks‐and‐Caveats - Petewg/harbour-core GitHub Wiki
Harbour is a mature xBase language with decades of real-world use in production systems.
While it is powerful and reliable, it has several characteristics that developers should be aware of,
especially when maintaining or modernizing legacy codebases.
Harbour relies heavily on implicit workareas.
Forgetting to explicitly SELECT the intended alias may result in operations
being performed on the wrong table, often without any runtime error.
Indexes require careful handling:
- Incorrect tag selection
- Wrong order
- Inconsistent RDD usage
Any of the above can cause SEEK operations to silently fail while the application continues running.
Variables default to global scope if LOCAL is omitted.
This can lead to unexpected side effects and hard-to-trace bugs caused by unintended variable sharing.
Harbour performs implicit type conversions.
Values such as numbers and dates may silently become strings, requiring frequent manual
conversions (VAL(), CTOD(), DTOC()).
File-based concurrency relies on record and file locks (RLOCK(), FLOCK()).
These mechanisms work reliably in controlled environments but can fail under network latency
or improper usage, often without clear diagnostics.
Many logical errors do not raise exceptions.
The program may continue executing normally while producing incorrect results,
increasing debugging complexity.
Harbour supports OOP features, but with limitations:
- Weak encapsulation
- No strict interfaces
- Public access to internal
DATAmembers
This can lead to fragile designs if not carefully managed.
Global SET commands affect the entire runtime environment:
SET DELETEDSET DATESET CENTURY
A misplaced or forgotten SET can cause unpredictable behavior across the application.
Long-lived codebases often contain large procedural constructs (e.g. extensive DO CASE blocks)
with minimal documentation, making maintenance difficult.
-
Always use explicit workareas and aliases
UseSELECT <alias>consistently to avoid writing to the wrong table. -
Declare all variables
UseLOCALorSTATICfor variables to prevent accidental global variable collisions. -
Manage indexes carefully
Keep index tags, order, and RDD consistent. Regularly rebuild indexes if needed. -
Handle types explicitly
Avoid implicit conversions. UseVAL(),CTOD(),DTOC()where appropriate to ensure correct types. -
Use file locking conscientiously
ApplyRLOCK()/FLOCK()with awareness of potential network latency and lock contention. -
Document code and logic
CommentDO CASEblocks, complex loops, and legacy routines. Future maintainers will thank you. -
Limit global SET changes
Reset SET commands to safe defaults when entering/exiting routines. Avoid permanent changes in shared modules. -
Embrace modular design
Split functionality into procedures, functions, and classes where possible, even with Harbour’s OOP limitations. -
Test and validate thoroughly
Because silent errors are common, always validate output and include automated checks if feasible. -
Use version control
Even for legacy Harbour projects, track changes and maintain backups — debugging old DBF/NTX systems
without version history is painful.
Harbour remains stable and performant when used with care. Following these practices reduces common pitfalls
and makes legacy codebases more maintainable.
* Copyright © 2016–present Pete D.