14 · Architecture, programming style and configurable SQL
This chapter summarises the technical rules used to evolve Factuzam. It is
intended for development, advanced support and implementers. The complete
repository reference is maintained in LIBRO_DE_ESTILO_DELPHI.md,
LIBRO_DE_ESTILO_BBDD.md, PLAN_SOLID.md and MANUAL_SQL_PERFILES.md.
1. Programming style
Factuzam is written in Object Pascal/Delphi VCL and prioritises readable, predictable code that is compatible with its installed base.
Main rules:
- Code, domain names, comments and commits are in Spanish; Delphi and third-party component prefixes are retained.
- One statement per line.
if,whileandforplace the condition and action on separate lines. ExitandContinueare avoided in new code so the method's complete flow remains visible.- Within each class section, fields are declared before methods, as required by Delphi.
- Comments are brief and explain decisions, limits or business rules; they do not repeat an obvious line.
- Methods use Spanish verbs and must represent one cohesive step. Before a large class is extended, a collaborator, strategy or domain function is extracted.
- Maintenance forms inherit from
TfrmMtoGenand modal forms fromTfrmBase; independent utilities retain their own project. - UniDAC, DevExpress, JEDI and FastReport remain architectural decisions; they are not replaced with new dependencies without justification.
Database changes are delivered as idempotent scripts under
DESARROLLOS EN CURSO/. The factuzam_original.sql dump is not modified.
2. SOLID applied progressively
Factuzam is migrating in instalments from a legacy core towards a SOLID architecture. This is not presented as a completed rewrite: every extraction first locks down behaviour with tests and reduces coupling without mixing in functional changes.
| Principle | Application in Factuzam |
|---|---|
| SRP — single responsibility | The form coordinates the interface, the data module persists data, and libraries execute business rules. Large responsibilities are extracted into TGestor* collaborators or specific services. |
| OCP — open/closed | Purchase, sale, printing and document variations are modelled through configuration and strategies, avoiding copies of complete forms for every case. |
| LSP — substitution | Base classes publish coherent contracts and hooks; a base is not extended when its descendants would need to cancel the behaviour with empty methods. |
| ISP — small interfaces | Each consumer receives only the capability it needs. Project interfaces are small, have a GUID, and are grouped only when they share the same implementation. |
| DIP — dependency inversion | The domain depends on inLib*Intf contracts; UniDAC implementations are created externally and injected from the composition root. |
The sequence for an instalment is: a test that fixes the behaviour, extraction of one responsibility, Win32/Win64 compilation, the DUnitX suite, and verification of automatic architectural ratchets.
3. Layers and dependency direction
fzam.dpr / Core (composición)
|
v
Forms / Modals (presentación y coordinación)
|
v
UniData* (persistencia) ---> inLib* (dominio y colaboradores)
|
v
inLib*Intf (contratos)
| Layer | Responsibility |
|---|---|
| Core / composition | Creates connections, repositories, services and forms; connects implementations to contracts. |
| Forms / Modals | Displays data, requests confirmation, coordinates tabs and translates business results into visual actions. |
| UniData / DataModules | Queries and persists through UniDAC, controls datasets and transaction boundaries. |
| inLib | Calculations, validations, transformations, orchestrators and reusable collaborators. |
| **inLib*Intf** | Stable interfaces and types without dependencies on VCL, forms or persistence implementations. |
A domain library does not create a repository, know about a form or obtain a global connection. Its constructor or parameter receives the contract it needs. Connections, identity and credentials have an explicit owner and life cycle.
Writes affecting several tables are atomic: they respect an existing
transaction or perform Commit/Rollback at the same level. Threads do not
share datasets or connections with the interface.
4. Configurable and queryable SQL
The SQL catalogue by profile allows certain read queries to be corrected
without recompiling or replacing fzam.exe. The domain requests a business
operation from a repository; the persistence implementation chooses between:
- The base SQL, included and tested with the executable.
- Active custom SQL in
fza_usuarios_perfiles.
The domain does not receive SQL text and does not expose a generic
Ejecutar(SQL) method. Each operation retains a stable key in this form:
KEY_USUPER = SQL_REPOSITORIOS
SUBKEY_USUPER = SQL__Repositorio__Operacion
Activation by screen
The oGetSQLFromDB profile property enables the catalogue for each consuming
form. When the screen opens:
- Factuzam loads the definitions from the shared catalogue.
- It publishes any missing base operations without overwriting an existing customisation.
- It resolves each read against the active profile or base SQL.
Disabling the switch on one form does not change other consumers of the same operation.
The inventory of units that read the switch, publish profiles or provide
catalogue definitions, together with the historical traversal of data
modules, is in
MANUAL_SQL_PERFILES.md.
Validation and safe fallback
Before executing a customisation, Factuzam verifies that it:
- is not empty;
- is a valid read (
SELECTorCALLwith a dataset); - retains exactly the declared parameters;
- returns all required fields and aliases;
- does not contain several statements;
- does not include
DROP,ALTERorTRUNCATE.
If validation fails, the custom query is discarded, the cause is logged and the base SQL runs. If it passes validation but fails to open or returns an incorrect structure, Factuzam retries once with the base SQL. If the base also fails, the error is displayed normally.
Writes do not use this automatic retry: any future write customisation must be
protected by a transaction and perform Rollback before changing
implementation.
Review, audit and rollback
The catalogue administrator can publish, review and export base and profile definitions. The review displays status, policy, version, hashes, validation and the latest fallback cause. Each row also stores its modification time and user.
To return immediately to the behaviour included in the executable, you can:
- Disable an operation by changing its status from
StoN. - Delete only its custom row.
- Set
oGetSQLFromDB=Falsefor the whole screen.
There is no need to deploy another executable. Before editing a query, make a copy of its SQL and metadata; never change parameters or aliases required by the contract.
5. Tests and non-regression rules
- DUnitX covers domain functions, collaborators and fake repositories without requiring a real database.
- Integration tests cover procedures, SQL and transactions.
- Ratchet scripts prevent the reintroduction of layer dependencies, new SQL in the domain, global variables, or growth of classes and methods beyond the current limits.
- A refactor does not mix functional changes, bulk renames or formatting normalisation.
- Before closing a cross-cutting change, the affected Win32 and Win64 platforms are validated.
The aim is for every improvement to leave an automatic barrier that later code cannot cross again.
◀ Mobile applications · Contents · Next ▶ PrestaShop integration