Classic Computer Magazine Archive ATARI CLASSICS Volume 2, Issue 3 / June 1993 / PAGE 20

MOdUlAR PROGRAMMiNG iN ATARi BASIC

RON FETZER, AC CONTRibUTiNG AUThOR

    How many times have you said, "I wish I could write a big program like Print Shop"? Have you ever wondered how these long professional programs were written? Could you write a program like this? The answer is, YES! If you think programming is too hard or that you have no talent for it, your'e missing 90% of the fun of owning an Atari 8bit computer. If you learned programming by yourself, like I did, you know the limitations of "brute force" programming. I usually hit the wall around 200 lines before getting hopelessly lost.

Trade Secret Revealed!
    There's a method of programming- not widely known among BASIC programmers- called Modular Programming. If you can write fifteen lines of code, you can write modular programs that easily exceed the memory of your computer. The central idea of modular programming is to break a big task into small units, so you're only concerned with just a small part of the task at a time. This approach actually makes programming an enjoyable activity! The academic term for this method is "Structured Programming". The professionals use it all the time but keep mum about it to us amateurs. Atari BASIC is wellsuited to this method of programming because it's compact structure is so easy to learn.
    Modular programming basically consists of writing short modules which are then strung together to create a whole program. So, what benefits can you gain by adopting a modular approach? Let me give you my "short list":

1.Your program will be easy to write the first time
2.Your program will be easy to read by anyone.
3.Your program will be easy to modify.
4.You'll be able to locate bugs very quickly.
5.Your code will be self-documenting.
6.Large programs won't be a problem.
7.Your code will be "elegant".
8.Programming will become fun again!

Going Modular
    The first step is to simply write out your ideas for the program in longhand; make an outline just like you did for a composition in High School. Next you make a block diagram. That shows you how many modules you need and how they'll connect. Then you write a skeleton program. Its function is to ensure that the modules execute in the right order. Finally, you flesh out the skeleton program into a complete program.
    Writing the code for the program is the easiest part and should take the least amount of time. Planning the program should take most of your time. This probably looks like a lot of work, but it isn't. It can be sketched out very quickly: each step leads to the next. You've now created a blueprint that's guaranteed to work. After you've tried this method once, you'll never go back to Brute Force programming again.
    Using the modular approach, you start out with the most general module first and then proceed sequentially to the more specific ones. The first module is the control module: it's the head or brain of your program and controls all the other modules. However, these other modules don't influence the control module. In Atari BASIC you use the GOSUB - RETURN function for all modules.

The Envelope Printer
    Last Christmas my better half asked, "Dear can't you write a program that prints addresses directly on the Christmas card envelopes? Sticking on labels looks so commercial". Thus was born the idea of the Envelope program. Why stop with Christmas cards? Let's do business envelopes and large 7x9 envelopes as well! Below is my outline of the ideas that I want in my program.

ENVELOPE PROGRAM
I. MAIN HEADING
A)DIM SECTION
B)SCREEN COLORS
C)RETURN ADDRESS
D)FORWARDING ADDRESS
E)MENU
II. MENU
A)CHRISTMAS CARDS (5x7)
B)BUSINESS ENVELOPES (4x9.5)
C)LARGE ENVELOPES (7x9)
D)END
III. PRINT SECTION
A)PRINT RETURN ADDRESS
B)PRINT FORWARDING ADDRESS
    I want the user to have a choice of screen colors while the program is on the screen. The user should type his return address only once and then have a choice of envelope sizes. The menu should also have an END option so the user can exit.
    Now I have a general idea of what I want in my program. The next step is to write a block diagram. This block diagram will show you how many modules you need and the range of line numbers. Each line above will become a module.

Build Your Module With Blocks
    A "block" is a section of code that performs one task. A module can contain one or more blocks. A block as well as a module should follow the rule of "straight sequence": the entry point should be at the top and the exit at the bottom of the block or module. Don't jump out of the module or block with a GOTO or you'll end up with "spaghetti code".
    It's important not to skip this step. Sometimes you'll have modules calling sub-modules or sub-sub-modules. Each module is in the form of a GOSUB - RETURN. I in crement the line numbers for each module by 500 numbers to make life easy for myself. The block diagram below follows the outline I presented earlier.

  ENVELOPE BLOCK DIAGRAM
  10 - 499 CONTROL BLOCK
 500 - 999 DIM SECTION
1000 - 1499 SCREEN COLORS
1500 - 1999 ENTER RETURN ADDRESS
2000 - 2499 MENU
2500 - 2999 ENTER FORWARDING ADDRESS
3000 - 3499 * CHRISTMAS ENVELOPES
3500 - 3999 * BUSINESS ENVELOPES
4000 - 4499 * LARGE ENVELOPES
5000 - 5499 PRINT RETURN ADDRESS
5500 - 5499 END

    * These modules also use the sub-modules PRINT RETURN ADDRESS and FORWARDING ADDRESS.

    The control module calls all other modules. Each module returns eventually to the control module where it gets directed again to the menu module. A good program is easy to read, consistent and self-documenting. We now have an outline of our program with all its modules.

A Modular Skeleton
    Now it's a straightforward exercise to set up a skeleton program. The skeleton program will confirm the correct execution of your modules. Later, we'll flesh out the skeleton to the full program. Each module in the skeleton program should contain a PRINT statement to show the function of the module when the program is run. We'll remove these PRINT statements when we flesh out the program later on. Here's the skeleton program:


   ENVELOPE SKELETON PROGRAM


Scoping The Skeleton
    Notice how I separate each module with a REM and the module name. Then I fill in the rest of the module separator with asterisks until I have two 40-column screen lines. This makes it quite easy to identify each module in the program at a glance. The time delay loop in lines 30000 to 30020 is used only in the skeleton program to slow down the program so you can observe its execution.
    Every program should have a line 0,1 and 5. Line 0 should always be 'GOTO 10'. Thus when you type RUN the program will go to line 10 and execute. Line 1 should always be 'SAVE "D:FILENAME.EXT":CLR' (in my program it's'1 SAVE "D:ENVELOPE.ATR":CLR'). This is very useful when you're developing a program. Each time you want to save part or all of the program you type'GOTO 1'. The program will be saved with the same filename all the time. You won't have multiple versions of the program, just one version all the time. The CLR is needed to remove any previous DIM so the program will run okay.
    Line 5 is the title line of the program. It should always contain the following information:
The author of the program.
The name of the program.
The version number of the program.
The language used to write the program.
The date it was written.
    Look at line 5 of the listing; the above elements are there. You might also wish to include your address if you want users to contact you.

Meat On The Bones
    Now we'll flesh out our skeleton program. Remember our first module is the Control Module. When I clear the screen I always use ? CHR$(125) because every printer can list it; special characters can't always be listed. The Control Module is already finished as it appeared in the skeleton program:

10 REM CONTROL MODULE************
20 ? CHR$(125):GOSUB 500:REM DIM SECTION
30 GOSUB 1000:REM SCREEN COLORS
40 GOSUB 1500:REM RETURN ADDRESS
50 GOSUB 2000:REM MENU
60 GOTO 50

    The program flows from the DIM SECTION to the SCREEN COLOR module, then the RETURN ADDRESS module and finally the MENU module. Notice line 60: the program returns to this line after each menu selection is completed. Line 60 directs it again to line 50, so you always return to the menu. This is called a Case Structured program, and it's the most common type of programming structure used.
    Our next module is the DIM SECTION. The first thing you do is remove the PRINT statement from the skeleton program; we don't need it any more. There is nothing strange in this module. Just put in your DIMensioned variables as required. Your DIMensioned variables should always be in a module at the beginning of the program like this so you'll know where to find them. Don't forget the RETURN statement now has a new line number.
    The first line after the REM in each module is the "housekeeping line" for the module. Things like PEEKS, POKES, string lengths, initialization of variables, and special codes will be put in this line. I do this the same way for each module: such consistency is the hallmark of a good program. Notice in line 1010 the variable R$ is set to equal 13 empty spaces. Rather than use the POSITION command for my menu selection, I put R$ in front of the options. To center the options, all I have to do is change the length of R$. I want the user to have a choice of four different screen colors while using the program. Error trapping should be extensive and should always be done the same way in each module. The program exits to the end of the module when the user has made a selection. This module (and all modules) follow the law of straight sequence. You enter at the top and exit at the bottom. Make all your modules follow this rule, and your program will be easy to read and understand.

Filling In The Guts
    Next is the RETURN ADDRESS module. Remove the PRINT statement from the skeleton program. Again our first line after the REM is the housekeeping line. I only need a ? CHR$(125) in this module. Then I ask for INPUTS for name, street, town, state, Zip Code and country (optional). (I write many letters overseas so the country is important to me.) This is straightforward programming. The module ends with a RETURN in line 1590.
    Now for the MENU module. In the housekeeping line (2010) I have an'LPRINT CHR$(27);"8"'. This is the control code to TURN OFF PAPER SENSOR for an Epson printer. I want this sensor off because I'll constantly be feeding envelopes into my printer. If you don't know the code for your printer, proceed as follows. Remove the paper from your printer; the PAPER OUT sensor should cause an alarm to sound. Insert a narrow strip of paper into the paper feed until the alarm goes off. [The sensor in most printers usually consists of a weakly spring-loaded microswitch behind the platen that's activated by the pressure of the paper held against it. It's usually visible as a metal or plastic tab in the slot behind the roller where the paper enters the printer. Ed.] Then temporarily tape it to the top of your case so it won't get fed through the rollers. Now you can feed envelopes without interference from the sensor. Be sure to have an END option in the menu selection so the user can exit. Error trapping again is the same as in the other modules. The module exits with a RETURN in line 2100.
    In the FORWARDING ADDRESS module I initialize all variables to an empty string in the housekeeping line in 2510. This module will be accessed repeatedly. I want to ensure all the strings are empty. Otherwise, it's the same as the RETURN ADDRESS MODULE.
    The CHRISTMAS CARD, BUSINESS ENVELOPE and LARGE ENVELOPE modules are all very similar. In the housekeeping line I initialize the variables and set B$ equal to the required spaces. I call for sub-module FORWARDING ADDRESS (GOSUB 2500) and sub-module PRINT RETURN ADDRESS (GOSUB 5000). Then I print the name, street, town, state, Zip Code and country on the envelope. I exit with a RETURN that goes to line 2100 and then to the control module line 60, which returns you to the menu module.
    The last module is the END module. On the housekeeping line I use POKE 752,1 to turn off the cursor. Then I print "END OF PROGRAM" in the middle of the screen. I change the screen color back to default with a GRAPHICS 0 command and turn the cursor back on again.

Reviewing The BASICS
    You can now see how easy it was to complete each module and the whole program. Even if you're a beginner, you can read and understand this program. It's consistent, and it follows the law of straight sequence. You enter at the top and exit at the bottom of the modules. You now can easily modify this program by adding other modules for different envelope sizes if you wish. There was no frustration in writing these modules. It was fun and very satisfying. You don't have to be a super programmer to complete a program like this. If you use modular programming the fun of computing will come back again, and your programs will be a joy to read and run.

Make It Professional!
    The final step is to polish the program. Make sure titles are centered on the screen, variables initialized or set to 0, error trapping is in place. As the last step I renumber the program. I load it into TurboBASIC (which has a renumber command) and type RENUM 10,10,10. This renumbers my program from line 10 on with a 10 line interval and wraps everything up neatly.
    So far I've described all the things a good program should have, but there are some things you should avoid. Don't create a fancy graphic or logo screen as the first module. Remember, the user has to use your program repeatedly. A fancy opening screen says only one thing: "Look what a clever programer I am!". Conceit like this is hard to bear repeatedly. It's okay to have a fancy opening screen on your documentation file because it will be accessed only occasionally, which is tolerable.
    Writing good documentation is as important as writing a good program. Your program "docs" should be complete and as brief as possible. Reading a doc file is inherently boring, so make it short. Don't include all the clever programming tricks you used (the average user is "turned off" by this). Don't be verbose. It's okay to include printer control codes or other data the user might need to change in order to adapt the program to his particular environment, but other than that it should have no programming code in it. Also include your address in the docs so users can contact you.
    Don't compile a program unless necessary. There are only two good reasons to compile: faster speed and to hide your code. A program that depends for its speed on a peripheral device should never be compiled. For example, there would be no point in compiling my Envelope program because its speed is determined by the printer.
    Don't use obscure PEEKS and POKES if a regular structure is available. Overused PEEKS and POKES are only justified if your free memory is running out. Obscure and overused PEEKS and POKES say just one thing. "See how clever I am! You can't follow me." It's another form of programming conceit. I guess most of you have heard of Atari programming guru Dave Small, who began his programming career on the Atari 8-bit and then achieved fame as the wizard who emulated the Apple Macintosh on the Atari ST. As a final remark I'm aware of Dave's contempt for structured programming, but even he would admit that a clear organized program is better than messy spaghetti code!
    Ron is a member of the Ol'Hackers Atari User Group in Oceanside, New York. Your comments and reactions to this article are appreciated.
    [Editor's Note. for readers interested in further pursuit of BASIC programming, Ron has produced the TurboBASIC Programmer's Kit, a double-sided three-disk set distributed inexpensively by the OHAUG group. -BLP]

   ENVELOPE PROGRAM LISTING