
Habits that Help: Developing Good Programming Style Casey Cantrell, Clarion Consulting, Los Angeles, CA ABSTRACT The first goal of most new programmers is to write programs that run. Often, more time is spent checking and debugging programs than is spent writing them. As programmers mature, they typically find it easier to test, debug and document their programs. This occurs in large part because they have developed a consistent programming style and acquired habits that expedite error detection and documentation. Putting into practice a few simple procedures will yield significant benefits: greater accuracy, fewer hours invested and less aggravation. This paper will discuss practical programming ‘habits’ that will make the programmer’s work easier. INTRODUCTION One evening many years ago, while talking shop with some work mates, the conversation turned to the question of "What makes a good program?" Without thinking much about it, I stated imperiously that a good program was one that could complete a task with the fewest lines of code. My colleague, and senior partner, considered this for a while before offering his definition. “A good program," he said, " is one that can complete a task with the fewest lines of code that someone else can understand.” In the intervening years, I've come to realize how right he was and would delete only the words “someone else” from his definition. While it is certainly important to write code than others can work with, the programmer who does so also profits from the effort. Well-written programs are easier to maintain, modify and debug. Programs that are well organized, conforming to a consistent style facilitate documentation. Carefully planned programs provide for efficient use of the most important resource of all: the programmer’s time. Time invested in writing good programs will pay off handsomely for everyone in the long run. Although each programmer will develop his/her own style, there are habits common to all good programmers. First, they write with clarity and consistency, opting for simplicity whenever possible. Second, they test their programs and meticulously checks results. Third, the good programmer writes flexibility into his programs. Since his programs are "data-driven", they require little or no modification when the data change. Finally, the good programmer documents extensively. In short, good programmers write with an eye towards simplicity and flexibility. Their programs work, require little maintenance and are organized to expedite documentation. GOOD HABIT #1: WRITE CLEAR CODE Writing clear code involves not only writing programs that are easy to understand, but writing programs that are easy to read. Get in the habit of using adequate spacing, blank lines and indentation. SAS® is free format, meaning you may start your program on any column of any line, continue your program over several lines, and include as many blank columns and blank lines as you want. Like a good designer, use white space to your advantage. Do not try to squeeze your programs into as few lines as possible, nor put multiple statements on a single line. Remember that other programmers may read your programs on their computers, so format your code to fit comfortably on the screen. The programs below differ only in layout, but Program 1b is far easier to read.. DATA BOTHGEND; MERGE MEN (RENAME=(POP = MENPOP)) WOMEN; BY RACE AGE; PCT_MEN = (MENPOP/(MENPOP+ POP))* 100; Run; Program 1a DATA BOTHGEND; MERGE MEN (RENAME=(POP = MENPOP)) Easier WOMEN; to read BY RACE AGE; PCT_MEN = (MENPOP/(MENPOP+ POP))* 100; run; Program 1b 1 These two programs are also identical. Program 2b uses spacing and indention to improve legibility. Data bothgend; set male (in=menfile) female (in=womfile); if menfile then sex='M'; else if womfile then sex=’F'; run; Program 2a Data bothgend; Easier Set men (in=menfile) to read women (in=womfile); if menfile then sex = 'M'; else if womfile then sex = 'F'; run; Program 2b Get in the habit of beginning each program with a program header. The header should include your name, dates the program was written and modified, the program file name and location, and a description of what the program does. You may also include input and output files and any pertinent notes. An example follows. /*******************************************************************************/ /* MDsample.sas CC 2/21/10 */ /* c:/CMC3/Baseline/SAS Programs */ /* */ /* Reads: c:/CMC/Baseline/Data/PatientWave1 */ /* Writes: c:/CMC/Baseline/Analyis/PilotSample */ /* Create a sample of patients who completed the survey representing */ /* 7.5% of each MD’s patients. */ /* */ /* Modified 3/5/10 to increase sample to 10%. */ /* Note: Dr. Smith retired 12/31/09. Dr. Jones has taken over the practice */ /*******************************************************************************/ Get in the habit of using comments throughout your programs. Explain what you are doing and why. Describe problems, anomalies and complicated logic. If there is anything unusual about your program or data, make note of that. What may seem perfectly clear to you at 3am tonight may not be as clear six months from now. Comments are also a valuable way to organize and clarify your own thinking. /* Bookend style comment */ * This is also a comment ; SAS pays no attention to semicolons used within bookend style comments, so you may block out entire sections of code you do not want SAS to execute. This is especially helpful when testing or debugging a program. Use the label option on the data step to identify and describe files. If the file is a subset of another file, make note of that on the label. Later, this information may prove invaluable when you are searching for a particular file or trying to figure out how one file differs from several others just like it. Program 3 utilizes the label statement, as shown in Figure 1. data analysis1 (label=Subset of COMPLETED. Deletes records for MDs who did not complete baseline interview.); set newstat.allwave2; run; Program 3 2 Figure 1 Separate steps and conceptually distinct tasks for clarity. SAS will end and execute a step when it encounters the key words DATA or PROC, which designate the start of a new step. Nonetheless, get in the habit of including the "run;" statement to delineate steps in your programs. This will make it easier to follow your program logic and help you resist the temptation to mix DATA and PROC steps inappropriately. Program 3b illustrates the use of the “run;” statement, which is not used in Program 3a. DATA ages; dog_age=5; humanyrs=dog_age * 7; PROC PRINT data=ages; TITLE “Dog’s age in human years”; Program 3a DATA ages; dog_age=5; humanyrs=dog_age * 7; run; Include RUN; PROC PRINT data=ages; statement TITLE “Dog age in human years”; run; Program 3b Simplify complex expressions. Break tasks into steps. Use multiple statements if necessary to clarify your logic. Programs 4a and 4b do exactly the same thing: read a text variable (patient) and write out a new variable (name) in a different format, as illustrated in Figure 2. Which program is easier to read? Which would be easier to modify? Figure 2 data mailing; set patnames; name=substr(patient,index(patient,',')+2,length (patient)-index(patient,',')-1) || ' || substr(patient,1,index(patient,',')-1); run; Program 4a 3 data mailing; Easier set patnames; to read comma = index(patient,','); & follow longn = length (patient); lname = substr(patient,1,comma-1); fname = substr(patient,comma+2,longn - comma-1); pat_name =trim(fname) || ' ' || lname; run; Program 4b Avoid compound expressions when possible, and be particularly stingy in your use of NOTs and nested ANDs/ORs. Use DO LOOPS instead to clarify your logic and remember that compound expressions are less efficient, since SAS will evaluate each condition even when the first one is false. Evaluations stated in the affirmative are also easier to follow. Consider the following programs. Each in the pair performs the same task. Which is easier to follow? if sex=‘M’ AND race NE ‘B’OR race NE ‘W’’…; Program 5a if sex = ‘M’ then do; if race ne ‘B’ and race ne ‘W’ … end; DO loop Program 5b if elisa=1 &wb24 >1 & wb24 <4 & (wb120=1 or wb160=1) then westblot='1'; Program 6a if elisa = 1 then do; if 1 < wb24 < 4 then do; DO loop if wb120=1 or wb160=1 then westblot='1'; end; end; Program 6b GOOD HABIT #2: DEVELOP A CONSISTENT STYLE Get in the habit of organizing your programs using a consistent scheme. Define arrays, create labels and declare length attributes at the same place in your programs and group similar statements together. This makes it easier to see what you've done and easier to modify. Programs 7a and 7b again perform the same tasks. Data forlogit; set analyfile; LENGTH assignment length preteen $1. if 0 < age < 12 then preteen ='1'; else preteen = '0'; LABEL label preteen = 'Age < 12 years'; FORMAT assignment format preteen $teenf.; LENGTH assignment length senior $1.; if 65 < age < 99 then senior ='1'; else senior = '0'; LABEL label senior = 'Age > 65"; format senior $seniorf.; FORMAT assignment Program 7a 4 Data forlogit; set analyfile; LENGTH assignments length preteen senior $1.; if 0 < age < 12 then preteen ='1'; else preteen = '0'; if 65 < age < 99 then senior ='1'; else senior = '0'; LABEL assignments label preteen = 'Age < 12 years senior = 'Age > 65"; format preteen $teenform. Senior $seniorform.; FORMAT Program 7b assignments Keep SAS default actions in mind. Remember that new variables built from existing ones will inherit the attribute type of the original variable. Use explicit length statements when necessary and define them before using the variable in your code. Figure 3 illustrates the output generated from the Program 8a. Use of the LENGTH statement in Program 8b corrects the truncation as shown in figure 4.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages13 Page
-
File Size-