Professional Documents
Culture Documents
Conventions
for Caché
Atlas Development Corporation, 6351 Owensmouth Avenue., Suite 101, Woodland Hills, California 91364 USA
Tel+1 818 340 7080 Fax+1 818 340 7079 E-mail info@atlasdev.com http://www.atlasdev.com
CONTENTS
Projects 3
Tables 4
Maps 6
Global Structures 7
Forms 10
Menus 12
Reports 13
Views 14
Queries 15
Routines 16
2
Advanced Development Standards
Document: Standards.doc
Release: version n/a
Revision Date: 021501
2001 Atlas Development Corporation. All rights reserved.
3
PROJECTS
Project
A project is the set of all programming objects (tables, forms, menus,
reports, views, queries, routines, and globals) used in an application.
System Areas
A project is divided up into system areas. Each system area is a logical
grouping of programming objects based on their usage within a project.
(e.g. “Accounting”, “Forecasting”, “Shipping”, etc.) Each programming
object belongs to one system area. The choice of which system area a
particular programming object belongs has no affect on the function of the
application. System areas are used only to assist in project control and
ease of programming.
4
Advanced Development Standards
TABLES
Table Name
Tables are named “[System Area Alias]_[Table Moniker]” (e.g.
ACT_AccountsReceivable). Components are separated by an underscore.
The table moniker should always be the grammatical singular, not the
plural (e.g. “Person” rather than “Persons”).
This format ensures that tables are sorted by system area alias in Caché
lookups. It also tells the programmer what system area a table belongs to
by reading the table name.
Table Alias
Each table is given a one to five character code (e.g. “AR” for
ACT_AccountsReceivable). Table aliases should be unique within a
system area. The table alias is also used in other naming conventions.
Standard Caché does not recognize this attribute.
Table Description
After the table description, the following information should be added and
right justified:
([Table Alias], [Table Number]). For example
“Accounts Receivable (AR, 253)”.
A/Frame maps this to read each table’s table alias. The table number in
the description is useful when performing functions where the table name
is displayed but the developer would like to know the table number as
well.
5
While adding a field to an older codeset the field column number has to be
maintained. If a certain field is not required in a particular codeset, a
dummy field (placeholder) needs to be created.
It should have the following properties -
Name - <table alias>_FLD+<column number>
Description – Reserved For Later Version
Data Type – Text
Computed Field – Yes. Computation is S {Field}=””
Row ID Name
The rowID field is named “[Table Alias]_RowID” (e.g. AR_RowID).
Components are separated by an underscore.
Child Subscript
The child counter is named “[Table Alias]_ChildSub” (e.g.
AR_ChildSub).
6
Advanced Development Standards
7
MAPS
8
Advanced Development Standards
GLOBAL STRUCTURES
Global Name
A non-child table’s global is named “[System Area Alias][Table Alias]”
(e.g. ^ACTCUST). (The components are not separated.)
For child tables, the global name is the same as the parent table. The
global name indicates to which system area and table the child table
belongs. Also, the table name indicates what global stores the table’s data.
Surrogate Keys
Surrogate keys, rather than primary keys, should be used for most tables.
There are numerous advantages to this:
þ If the definition of a table’s primary key changes after a table
is built, many changes must be made to the table’s underlying
global. With surrogate keys, these definitions never change.
þ If the data of a primary key changes, all referencing tables
must have their designative references modified to reflect the
change. Surrogate key values never change.
þ Primary keys need to be defined early in the data modeling
process. This step is delayed or eliminated when surrogates
key are used.
þ With primary keys, uniqueness must be enforced. If a primary
key is built off multiple fields, this must be enforced with
code. With surrogate keys, uniqueness of row ID’s is
automatically assured.
þ With surrogate keys, the global subscript structure is consistent
across all tables. If primary keys are used, global structures
cannot be standardized.
þ With surrogate keys, designative references are simpler and
usually smaller than when primary keys are used.
The disadvantages of using surrogate keys over primary keys are:
þ Tables with surrogate keys generally require an additional
index based on the logical primary key.
þ When primary keys are used, designative references hold
meaningful data so the need to reference extended tables is
reduced.
9
Since the number of advantages greatly outweighs the disadvantages, the
use of surrogate keys is advised. One exception is the case of static
dictionary tables, which have a simple unchanging code indicating the
dictionary record. In these cases, the code can be used as the row ID and
therefore, tables that reference the dictionaries will store the code itself.
In many cases, this will reduce the need to reference the dictionary table.
Since the code is a single field, the standard global structure is not
affected.
Subscript Structure
For non-child tables, the subscript is the row ID field (e.g.
^ARCUST([CUST_RowID]).
For child tables, the subscript is the same as the parent table’s subscript
structure followed by “[Table Alias]_RowID” (e.g.
^ARCUST([CUST_RowID],“AR”,[AR_RowID])).
This standard effectively segregates children under a parent.
Counter Node
The counter node is used to assign surrogate key values
For non-child tables, the counter node is at the global’s “0” subscript (e.g.
^ACTCUST(0)). This must be incremented using $$next code on the
default M expression of the table’s row ID field. Because the “0” node is
reserved for the counter, the first value of the special access code should
be set to one (1) in the access path specification of the master map’s row
ID.
For child tables, the counter is at the “0” level of the child table portion of
the global (e.g. ^ACTCUST([CUST_RowID],“AR”,0)). This must be
incremented using $$next code on the default M expression of the table’s
child subscript field. Because the “0” node is reserved for the counter, the
first value of the special access code should be set to one (1) in the access
path specification of the master map’s row ID.
10
Advanced Development Standards
be set to “One Per Node”. The node for each field is a short descriptive
code (e.g. “DESC” for description).
Index Subscripts
The index subscripts are the following:
0
“Field Name 1”
“Field Name 2”
...
Field Value 1
Field Value 2
...
Row ID Component 1
Row ID Component 2
Index Data
Usually, no data is stored in the nodes of an index map. However, field
values may be stored (denormalized) in the index to enhance lookup
performance.
11
^ACTCUST(0,”CUST_City”,6,1)=“”
^ACTCUST(0,”AR_Amount”,34512,1,2)=“”
^ACTCUST(0,”AR_Amount”,68862,2,1)=“”
^ACTCUST(0,”AR_Amount”,83535,1,1)=“”
^ACTCUST(0)=2
^ACTCUST(1)=“Customer 1”_$C(127)_6
^ACTCUST(1,”AR”,0)=2
^ACTCUST(1,”AR”,1)=“1234”_$C(127)_83535
^ACTCUST(1,”AR”,2)=“1236”_$C(127)_34512
^ACTCUST(1,”DESC”,0)=2
^ACTCUST(1,”DESC”,1)=“Description 1”
^ACTCUST(1,”DESC”,2)=“Description 2”
^ACTCUST(2)=“Customer 2”_$C(127)_3
^ACTCUST(2,”AR”,0)=1
^ACTCUST(2,”AR”,1)=“6432”_$C(127)_68862
12
Advanced Development Standards
FORMS
Form Name
Forms are named “[System Area Alias] [Form Moniker], followed by the
form number, right justified and in parentheses (e.g. ACT Account
Review (345)). Components are separated by a space.
This format ensures that forms are sorted by system area alias in Caché
lookups. The form number is used for program calls to form A/Routines.
Window Name
Windows are named “[Form Number][single alphabetical letter] [Window
Description]” (e.g. 345A Account Review). The single alphabetical letter
is used to identify the specific window.
The window name appears on the status line during runtime, so that the
form (window) can be immediately be identified by the form number.
This assists in debugging and remote communication with users.
13
POFORM Post form
PRWINA Pre window for window “A”.
PRWINB for window “B”
POWINA Post window for window “A”
COFO# Computed value for form field #
CONUFO# Computed null for form field #
AVFO# Additional validation for form field
#
EIFO# External to internal for form field #
IEFO# Internal to external for form field #
DEFFO# Default value for form field #
RQIFFO# Required if for form field #
PRFO# Pre field trigger for form field #
POFO# Post field trigger for form field #
PRTB# Pre field trigger for table field #
POTB# Post field trigger for table field #
OPEN# Programmed lookup open #1
FETCH# Programmed lookup fetch #1
CLOSE# Programmed lookup close #1
14
Advanced Development Standards
MENUS
Menu Name
Vertical menus are named “[System Area Alias} [Menu Moniker]” (e.g.
ACT Billing Functions). Components are separated by a space.
Horizontal menus are named “[System Area Alias] H [Menu Moniker]
(e.g. ACT H Acct Review). Components are separated by spaces.
15
REPORTS
Report Name
Reports are named “[System Area Alias] [Report Moniker]” (e.g. ACT
BillingSummary). The components are separated by a space.
16
Advanced Development Standards
VIEWS
View Name
Views are named “[System Area Alias]_[View Moniker]” (e.g.
ACT_BillingView). Components are separated by an underscore.
17
QUERIES
Query Name
Queries are named “[System Area Alias]_[Query Moniker]” (e.g.
ACT_OverdueCheck). Components are separated by an underscore.
18
Advanced Development Standards
ROUTINES
Routine Name
A routine which is not an A/Routine is named “X[SystemAreaAlias]#”
where # is a sequential number (e.g. XAR1). This implies that every
routine belongs to a system area.
Variable Names
When using the “SELECT * INTO” syntax to populate an array, the array
is named “[Table Alias]” (e.g. AR).
When a variable stores the value of a table’s row ID, the variable is named
“[TableAlias]ROW” (e.g. ARROW).
Cursors
1. The cursor name should start with the table alias of the table queried,
followed by a simple modifier to differentiate between other cursors
querying against the same table in the same routine.
2. Please note that the cursor name should not be more than six
characters long. The Cache SQL compiler will use the first six
characters of the cursor name to create local variables in the INT code.
If multiple cursors share the same first six characters in their names,
there will be redundant variable names in the INT code. This should
be avoided.
3. Following the “FETCH” command, use the line “I SQLCODE=0 D”
instead of “Q:SQLCODE”. This forces subsequent code in your loop
to be contained in its own dot level scope, which will avoid scope
conflict with similarly named variables like “SQLCODE”.
4. In general, you should add the line “N SQLCODE” immediately after
“I SQLCODE=0 D”, which should be in its own dot level scope to
avoid confusion with references to SQLCODE defined previously in
your code.
Please see the cursor code example on the next page.
19
Cursor Code Example:
CO25(LOROW)
#;
N SQLCODE,RETVAL,SIGNED
S RETVAL=""
#;
&SQL(DECLARE LOOCS CURSOR FOR
SELECT LOOC_ABNSigned
INTO :SIGNED
FROM ORD_LOOCode
WHERE LOOC_LO_ParRef = :LOROW)
#;
&SQL(OPEN LOOCS)
F D Q:(SQLCODE)
. &SQL(FETCH LOOCS)
. I SQLCODE=0 D
.. N SQLCODE
.. ; *** YOUR CODE GOES HERE ***
&SQL(CLOSE LOOCS)
Q RETVAL
#;======
#;
20