Coding Tips
| Coding Tips Powered by Webelink.com   | |
| 1. | BASIC: Compiler Includes Back to top. |
| Program Compiler Includes are sections of external program code which will be inserted during compile time into the body of any BASIC program. Using program Compiler Includes has the following advantages: We store our Includes in a separate file named APL.EQU since they do not need to be compiled and it is a good idea to seperate program includes from your BASIC program code. All of our programs include an item like the following, as the 1st Include, for standard variables: STD.VAR
001 * Standard Variable Equate (05-17-95)
002 *
003 CLS = @(-1) ;* Clear Screen
004 EOS = @(-3) ;* Clear to End of Screen
005 EOL = @(-4) ;* Clear to End of Line
006 VID.DASH = STR('-',79)
007 *
008 EQU AM TO CHAR(254) ;* Attribute Mark
009 EQU VM TO CHAR(253) ;* Value Mark
010 EQU SVM TO CHAR(252) ;* Sub-Value Mark
011 EQU LF TO CHAR(10) ;* Line Feed
012 EQU CR TO CHAR(13) ;* Carriage Return
013 EQU ESC TO CHAR(27) ;* Escape
014 EQU BELL TO CHAR(07) ;* Ring Bell
015 EQU TRUE TO 1 ;* Boolean True
016 EQU FALSE TO 0 ;* Boolean False
017 *
018 STS.ROW = @(0,22): EOL ;* Status Row
019 MSG.ROW = @(0,23): EOL ;* Message Row
020 *
021 WHO = OCONV('','U50BB') ;* ie. 05 APL.DEMO
022 PORT = FIELD(WHO,' ',1) ;* ie. 05
023 ***USER = FIELD(WHO,' ',3) ;* ie. APL.DEMO *%AP%* (Uncomment for Advanced Pick)
024 USER = FIELD(WHO,' ',2) ;* ie. APL.DEMO *%UV%* (Uncomment for Universe)
025 USER = OCONV(USER,'MCU') ;* UpperCase for uv
026 *
027 PROMPT ''
028 *
029 ***********************************************************************
030 * Modified by / on / Comments
031 *
032 * JJB 1.00 05-17-95 Create New Equate
033 *
034 ***********************************************************************
The following is a sample program using our Compiler Include: 001 ** Program : TEST 002 ** Date Written: 01-05-07 003 INCLUDE APL.EQU STD.VAR 004 * 005 CRT CLS ;* Clear Screen 006 CRT BELL ;* Send Beep 007 CRT EOL: 'Test Program Running' 008 CRT STS.ROW: 'Status Line' 009 STOP |
|
| 2. | BASIC: Compiler File Includes Back to top. |
| Compiler File Includes are an expansion of the Compiler Includes which include a File Include for every data file used in a program. We use a seperate File Include for each file referenced in our code. Using these Compiler File Includes has the following advantages: We store our Includes in a separate file named APL.EQU since they do not need to be compiled and it is a good idea to seperate program includes from your BASIC program code. A technique that we use to prevent duplicate element variable names and to aid in self documentation of source code, we always use a 2 to 4 character prefix in all variable names. For example, we assign the CU. prefix for all file equate variables for the CUSTOMER file. We assign the PR. prefix for all PRODUCT file equate variables. Each file must have a unique prefix assigned. As you read through source program lines, you can easily identify that a particular variable is a File Element Variable and what file it refers to. Note that File Equates must use a Dimensioned array. The following are several file equates and their usage: CUSTOMER 001 DIM CUSTOMER(199) 002 * 003 EQU CU.NAME TO CUSTOMER(1) 004 EQU CU.ADDR1 TO CUSTOMER(2) 005 EQU CU.CITY TO CUSTOMER(3) 006 EQU CU.STATE TO CUSTOMER(4) 007 EQU CU.ZIPCODE TO CUSTOMER(6) STATE 001 DIM STATE(50) 002 * 003 EQU ST.NAME TO STATE(1) ;* State Name 004 EQU ST.TAX.PCT.AMT TO STATE(2) ;* (MD2) State Sales Tax Percentage The sample source code follows: 001 INCLUDE APL.EQU CUSTOMER 002 INCLUDE APL.EQU STATE 003 * 004 OPEN.ERR = '' 005 OPEN 'CUSTOMER' TO FV.CUSTOMER ELSE 006 OPEN.ERR<-1> = 'CUSTOMER' 007 END 008 OPEN 'STATE' TO FV.STATE ELSE 009 OPEN.ERR<-1> = 'STATE' 010 END 011 IF OPEN.ERR <> '' THEN 012 CRT 'Open Errors: ': OPEN.ERR 013 STOP 014 END 015 * 016 MATREAD CUSTOMER FROM FV.CUSTOMER, '0100' THEN 017 MATREAD STATE FROM FV.STATE, CU.STATE ELSE ;* Read State File for Customer '0100' 018 MAT STATE = '' 019 END 020 END ELSE 021 MAT CUSTOMER = '' 022 MAT STATE = '' 023 END 024 * 025 CRT 'Customer Name : ': CU.NAME 026 CRT 'Customer Addr : ': CU.ADDR1 027 CRT 'Customer State: ': CU.STATE: ' ': ST.NAME ;* ie. IL Illinois |
|
| 3. | BASIC: A Solid READNEXT Structure Back to top. |
Too often we see the following bad code:001 LOOP READNEXT ID ELSE ID='' UNTIL ID='' DO 002 Do... Something 003 REPEATThe problem with this code is that a NULL ID is valid and may be in a file. This will cause the LOOP to exit before all records are processed and is probably not desirable. A preferred much better structure, which will read all file records, follows: 001 EOF = 0 002 LOOP READNEXT ID ELSE EOF = 1 UNTIL EOF DO 003 Do... Something 004 REPEAT |
|
| 4. | BASIC: How to Preserve an Active List? Back to top. |
| To preserve an active list you need to set it to a variable. An active list will be lost if you need to run an EXECUTE command while a list is active. This logic is also valid to keep several lists active. This technique works fine on UV and should work on other MV Databases as well. 001 SEL.LIST = '' ;* Needed to prevent "Var Unassigned" message 002 IF SYSTEM(11) THEN ;* List is Active 003 SELECT TO SEL.LIST ;* Save List to variable SEL.LIST 004 END 005 * 006 EOF = 0 007 LOOP 008 READNEXT ID FROM SEL.LIST ELSE EOF = 1 009 UNTIL EOF DO 010 Do... Something 011 REPEAT |
|
| 5. | BASIC: How to Edit Input for Control Characters? Back to top. |
| Very Often we are plagued with bad data in our files due to control characters. This can be caused by poor wiring, flakey hardware, bad keyboard, or user entered. A very fast and easy way to edit user input for control characters is to use an OCONV with the MCP conversion command. This command is very powerful and often forgotten by programmers. The MCP oconv will convert each non printable character to a period. The following code shows you how to use it: 001 INCLUDE APL.EQU STD.VAR 002 OK = 0 003 LOOP UNTIL OK = 1 DO 004 MSG = 'Enter Name:' 005 CRT MSG: ' ':; INPUT ASR 006 IF ASR # OCONV(ASR, 'MCP') THEN 007 CRT BELL: 008 ELSE 009 OK = 1 ;* Input is Valid, exit loop 010 END 011 REPEAT |
|
| 6. | BASIC: An easy technique to zero fill a numeric field. Back to top. |
| A simple way to zero fill a numeric field is use the "%" pad character instead of the "#" character. This is very useful for creating export files to systems which require a fixed length field. 001 AMT = 4574199 002 CRT AMT 'R%12' ;* zero fill the number in a field of 12 characters program output 000004574199 |
|
| 7. | BASIC: RELEASE command warnings Back to top. |
| The RELEASE command, without any options, releases all record locks for a BASIC program. The danger occurs when a program performs an EXECUTE to run another program and the new program performs a RELEASE command to release all record locks. On some MV Database implementations, a RELEASE command releases all record locks for your process including the driver program. This is not desirable. We recommend releasing individual records only, see the following code: 001 OPEN 'CUSTOMER' TO FV.CUSTOMER ELSE 002 CRT 'Cannot Open CUSTOMER' 003 STOP 004 END 005 * 006 READU CUSTOMER FROM FV.CUSTOMER, '0100' ELSE 007 RELEASE FV.CUSTOMER, '0100' ;* Release the active record lock, not a Global Release 008 END |
|
| 8. | BASIC: Deleting Multi-Values in a Loop Back to top. |
| To delete Multi-Values in a Loop, you must start at the last Multi-Value and work backwards. This will prevent loop problems if multiple items need deleting. Programmers new to the MV Database always stumble on this issue by running a forward loop. The following example shows how to purge old order links from the CUSTOMER File: 001 DIM CUSTOMER(199) 002 EQU CU.ORDER.NO TO CUSTOMER(130) ;* Multi-Value Order Number 003 EQU CU.ORDER.DATE TO CUSTOMER(131) ;* Multi-Value Order Date 004 EQU CU.ORDER.AMOUNT TO CUSTOMER(132) ;* Multi-Value Order Amount 005 * 006 EQU VM TO CHAR(253) ;* Value Mark 007 * 008 OPEN 'CUSTOMER' TO FV.CUSTOMER ELSE STOP 009 MATREADU CUSTOMER FROM FV.CUSTOMER, '0100' ELSE 010 RELEASE FV.CUSTOMER, '0100' ;* Release Record Lock 011 STOP 012 END 013 * 014 UPD.FLG = 0 015 PURGE.DATE = (DATE() - 90) ;* Purge Order Links Older Than 90 Days 016 TOT.MV = DCOUNT(CU.ORDER.NO,VM) ;* Total Multi-Values 017 FOR MV = TOT.MV TO 1 STEP - 1 ;* Loop Backwards 018 IF CU.ORDER.DATE < PURGE.DATE THEN ;* Order Link Older Than 90 Days 019 UPD.FLG = 1 ;* Set Update Flag 020 CU.ORDER.NO = DELETE(CU.ORDER.NO,1,MV) ;* Purge Order# 021 CU.ORDER.DATE = DELETE(CU.ORDER.DATE,1,MV) ;* Purge Order Date 022 CU.ORDER.AMOUNT = DELETE(CU.ORDER.AMOUNT,1,MV) ;* Purge Order Amount 023 END 024 NEXT MV 025 * 026 IF UPD.FLG THEN 027 MATWRITE CUSTOMER ON FV.CUSTOMER, '0100' ;* Only Write Item if Updated 028 END ELSE 029 RELEASE FV.CUSTOMER, '0100' ;* Release Record Lock 030 END |
|
| 9. | BASIC: Faster and Smooth Screen Displays Back to top. |
| Most of us connect to our MV Database through a Telnet connection which sends data over a TCP/IP network connection. TCP/IP automatically assembles the packets of data when a full block of data comes in or there is a slight pause meaning that the data coming in is probably complete. These packets get assembled randomly each time. This is very noticable over slow connections due to a low bandwidth or a connection with heavy user traffic. To improve performance and show users a smooth screen display, try to send the screen data as a single string of text. This will send fewer large packets instead of many smaller packets. This can be accomplished by creating a display variable first and then issuing a single PRINT command rather than a series of PRINT commands. Green screen displays will also benefit from this logic. For example, |
|
| 10. | BASIC: File Opens Back to top. |
There is an simple and effective way to do file opens in the MV Database.
I would recommend this technique as a good standard to follow.
OPEN.ERR = ''
OPEN 'CUSTOMER' TO FV.CUSTOMER.FILE ELSE
OPEN.ERR<-1> = 'CUSTOMER.FILE'
END
OPEN 'PRODUCT' TO FV.PRODUCT ELSE
OPEN.ERR<-1> = 'PRODUCT'
END
OPEN 'ORDER' TO FV.ORDER ELSE
OPEN.ERR<-1> = 'ORDER'
END
OPEN 'DICT','ORDER' TO FV.DCT.ORDER ELSE
OPEN.ERR<-1> = 'DICT ORDER'
END IF
IF OPEN.ERR # '' THEN
PRINT 'Open Errors: ': OPEN.ERR
INPUT ASR
END
All file opens are checked and all errors are displayed, rather than
stopping for each missing file and annoying the user.
Openning files to a File Variable name with a prefix of 'FV.' allows us
to use file equates with the same array name as the file name.
For file dictionary opens, use the prefix 'FV.DCT.'.
Note the usage of '<-1>' to insert data into a dynamic array OPEN.ERR.
This technique simplifies your BASIC code, by minimizing the number of
source program lines and adding consistency to your programs.
|
|
| 11. | Design: Designing for GUI Screens Back to top. |
| Design your current MV Database application code to allow for an easier transition to "GUI" Graphical User Interface at a future date. There are numerous technologies to perform a GUI upgrade. They all favor source code that uses internal or external subroutines which split green screen display logic from the business application logic. These are two separate functions. For GUI screen conversions, the screen display logic will be replaced while the business logic will stay. This technique will simplify the existing code and simplify future conversions to GUI screen forms. The worst code to work and test, is code which has scattered PRINT commands through out a program, especially within blocks of calculations. |
|
| 12. | Pick Dictionaries: Date Functions Back to top. |
Donated by Tom Phillips, website: www.tom-phillips.info Assume you are using a file named: "CALR" where the key is a “Pick” date. “DOY” – Day of the year. DOY 001 S 002 0 003 DAY OF YEAR 007 DJ 009 R 010 6 |
|
| 13. | Pick Dictionaries: Merge data from an application file to a Zip Code file Back to top. |
Donated by Tom Phillips, website: www.tom-phillips.info Assume that you have a Zip Code file where the key is a 5 or 9 digit zip code, attribute 1 is the City, attribute 2 is the State Code and maybe attribute 3 is the County. Now in your application you only save the State Code, City and County Code, if that data differs from the data in the Zip Code file. The problem then becomes: how to merge/concatenate this data when reporting? “CTY” will test attribute 5 for data, and if not there will use the City description in attribute 1 from the Zip Code file via the Zip Code in attribute 7. CTY 001 A 002 5 003 City 008 F;5;P;(S;"~";"");:;7;(T1,5);(P(5N));(TZIPF;X;1;1);P;(S;"~";"");:;:;7;(TZIPF;X;1;1);:;(G0~1) 009 L 010 20 “STE” will test attribute 6 for data, and if not there will use the State Code description in attribute 2 from the Zip Code file via the Zip Code in attribute 7. STE 001 A 002 6 003 State 008 F;6;P;(S;"~";"");:;7;(T1,5);(P(5N));(TZIPF;X;2;2);P;(S;"~";"");:;:;7;(TZIPF;X;2;2);:;(G0~1) 009 L 010 6 “CUN” will test attribute 35 for data, and if not there will use the County Code description in attribute 3 from the Zip Code file via the Zip Code in attribute 7. CUN 001 A 002 35 003 County 008 F;35;P;(S;"~";"");:;7;(T1,5);(P(5N));(TZIPF;X;3;3);P;(S;"~";"");:;:;7;(TZIPF;X;3;3);:;(G0~1) 009 L 010 6 “DISP.ZIP” displays a “formatted” Zip Code in attribute 7 if it is either 5 or 9 digits, otherwise the raw data is displayed (maybe it’s a Canadian code). DISP.ZIP 001 S 002 0 003 Zip Code 008 F;7;(P(9N));(ML#####-####);(P(5N-4N));P;(S;"*";"");:;7;(P(5N));:;(G0*1);(S;*;7) 009 L 010 10 “CSZ” displays a “nice” compilation. CSZ 001 S 002 0 003 City State Zip 008 A;N(CTY):", ":N(STE):" ":N(DISP.ZIP) 009 L 010 30 |
|
| 14. | Pick Dictionaries: File or Item Properties Back to top. |
Donated by Tom Phillips, website: www.tom-phillips.info File or Item Property Dictionaries These items can be stored in any file's dictionary level or the MD file to be used for all files. “AMC.CTR” will display the number of attributes in any item. AMC.CTR 001 S 002 0 003 Attribute Count 007 MR0, 008 U201E 009 R 010 9 “LINE.NBR” will display the detail data line number on a display. LINE.NBR 001 A 002 9998 003 Counter 007 MR0, 009 R 010 7 011 1 “SIZE” will display the item size (excluding the key length) SIZE 001 A 002 9999 003 Size 007 MR0, 009 R 010 10 “KEY.LENGTH” will display the length/size of the keys of any file. KEY.LENGTH 001 S 002 0 003 KeyL 008 L0 009 R 010 4 “TOTAL.SIZE” will display the total size of any key and item in any file (including +1 for the key/item separator) This is a “poor man’s” quick file size. Example: SUM filename TOTAL.SIZE TOTAL.SIZE 001 A 002 9999 003 Item Size 007 F;LPV;0;(L0);+;C1;+;(MR0,) 009 R 010 9 |
|
| 15. | Pick Dictionaries: Accounting Functions Back to top. |
Donated by Tom Phillips, website: www.tom-phillips.info Days old / Aging “AGE” will compute the age in days for the data element in attribute 2. This is assuming that “today” counts as zero days old. If “today” counts as one day, then use “DYS”. AGE DYS 001 S 001 S 002 0 002 0 003 Days Old 003 Days Old 008 F;D;2;- 008 F;D;C1;+;2;- 009 R 009 R 010 5 010 5 |
|
| 16. | Pick Dictionaries: Breaking on Words not Length Back to top. |
To break a report column on complete words rather than just the length, which may give un-desirable results, put a "T" with no quotes in element 9 of the dictionary. The "T" will break on text seperated by a space. The report column will display the maximum number of words that can be displayed on a line based on the length specified in element 10 of the dictionary. Additional lines will be used to display the remaining text. NAME 001 S 002 1 003 Name 009 T 010 25 |
|
| © Copyright 2003-2010 webelink.com. All Rights Reserved. | Click to Email for Info | Terms of Use | | |