Now lets get down to the nitty-gritty of actually generating your code. All good developers have learned that applying a few simple rules to every code page they create saves them time and trouble in the future once the site or system is launched. Let's look at a few code development guidelines that can save you lots of time and headache once the code is complete.
Always test for your variables' existence between page calls before you use the variable. What does that mean? Consider the following example:
Assume payment.asp accepts three variables from shopping_cart.asp: nCartTotal, nCustomerId, and cSuggestedItem. Payment.asp is the page that actually completes the transaction by letting the customer purchase their items. When all three variables are passed, everything works as it should. But if one of your developers forgets to send cSuggestedItem from shopping_cart.asp, the page can bomb, displaying an ungraceful exit to your user.
The developer or at least a beta tester should catch such a scenario. But, in large systems, where specific processing pages can be called by numerous other locations, it is possible for a few bugs to slip through. We've found that by testing to ensure that a variable we expected to be passed to a page actually was passed, we're not only able to protect our pages from disgraceful exits, but we can provide feedback to the programmer during the development process. Psuedocode for such a test trap might look like this:
IF DoesNotExist( cSuggestedItem ) THEN Display (" This page requires the following information: cSuggestedItem" ) ( or other error processing routine) END PROCESSING END IF
Testing for variable existence can save you time in debugging as well, since you'll already have some error checking in place. In a web development environment, there are numerous chances for your page to be called incorrectly. For example, suppose someone bookmarked our sample payment.asp, which then wouldn't be passed the variables? Testing for variable existence helps ensure that your pages remain clean and bomb-free.
Not only should you test to make sure that passed variables actually exist before you use them, but you should also test to make sure they have a value. That is, never assume that the variable being passed contains a value. To make truly bullet-proof code, never assume anything in a web environment. You certainly don't want to just start adding values together, expecting a passed variable to have, say, a value of 5 or greater, only to find it has a value of Null. This not only wreaks havoc on your logic, but causes hard-to-find bugs. Again, there are too many chances for a web page to be called in ways you don't expect or plan for, so take the safe route and test for variable value. Yes, it takes a bit longer and seems tedious, but you'll be taking another step toward tight, clean, error-free code.
Good programming practice, and indeed many programming languages, dictate that you must declare your variables before you use them. Not only does declaration of your variables force you to follow the programming language rules, but it can also act as a single place for variable information to a developer just encountering your code. Declare your variables near the top of your page, and in the declaration section, include all the variables you're going to use on that page.
Some languages, such as Active Server Pages (ASP), provide a statement such as Option Explicit that forces you to declare variables. Even though ASP lets you declare variables on the fly, declaring variables in a central spot in your code just makes good sense. Why?
Variable declarations are easy to find.
You can determine the variables used in the page by checking one central location.
With settings such as Option Explicit (in ASP) turned on, the web application server will force you to declare your variables.
Declaring your variables forces you to think more clearly about your code design. You're not as apt to throw a variable into the mix just because its convenient.
One of the intangibles that is most difficult for a new developer to learn is to form good logic structure in programs. Learning how to properly test, branch, and execute based on those tests is a core component of programming development, and learning how to do it effectively and efficiently is the mark of a wise, seasoned developer. But logic control is just one piece of the logic structure puzzle. There's also the logical structure of how you put your code together. Do you have every bit of code related to a certain feature or function in a single page, or do you modularize it and break it out into separate files, as you should? The following guidelines will help with the learning curve.
It's generally faster to test for the positive in control statements. Take the following pseudo- code for example: IF TheTestExpression = TRUE will save you a few milliseconds in almost all languages over a statement such as IF NOT(TheTestExpression).
Programs will execute faster if you can avoid unnecessary IF-THEN statements and similar structures. Build your code logic so that you can reduce the number of tests since the server must evaluate every IF-THEN you create.
Whenever possible, combine numerous IF-THEN statements into a CASE statement. Instead of using something like the following:
IF x = 3 THEN do something with 3 END IF IF x = 5 THEN do something with 5 END IF IF x = 7 THEN do something with 7 END IF IF x <> 3 AND x <> 5 AND x <> 7 THEN do something else with x END IF use a CASE statement such as: SELECT CASE x CASE 3 do something with 3 CASE 5 do something with 5 CASE 7 do something with 7 CASE Else do something with x END SELECT
CASE statements are faster in execution because once the computer hits the case that is true, it jumps to the end of the statement without evaluating the rest of the tests in the CASE statement. Most programming languages have a structure similar to the CASE statement, but it might be called something else, such as SWITCH, SELECT, or even SELECT CASE.
Use temporary variables when you need them, but be judicious in their use. There's no need to use up system resources by using temporary variables just because you can. They not only consume memory, but they also make your code more difficult to follow. For example, suppose you have five counter loops in your code. As long as they're not nested loops, use the same counter variable for each. You don't need to use five counter variables when one will do.
Use parentheses and brackets whenever you think a statement might be difficult to follow or ambiguous. A statement such as x = y + t * v / pi might not only give you results that you didn't intend, but also force the reader to try to interpret what you mean. Parentheses make clear what you intended, as in: x = [y + (t * v)] / pi.
Use functions or procedures to replace repetitive code bits. If you have a particular piece of code that you repeat several times-perhaps a series of calculations performed on several user- input fields-don't repeat the same bit of code over and over in your page. Put that bit of code into a function or a procedure call to make your code cleaner and more efficient. If you have to make a change to the calculations, you then only have one place to make the change.
If you've created a section of code that another developer of your caliber would find difficult to understand, try rewriting it to make it clearer. Chances are, if you have to revisit this bit of code six months from the date you created it, you'll have a difficult time understanding it as well.
Don't try to add patches and fixes to bad code. Rewrite the bad code, instead. Patches and fixes only make bad code worse. If you must apply a patch to bad code for time-constraint reasons, make a note of the inefficient code section and put it in the schedule to be rewritten. Bad code will come back to bite you.
Whenever possible, test user input for validity before sending it to the server. There's more on this later in this chapter in the "Client-Side Validation" section.
Before you try to make your code as efficient and fast as possible, make sure that you have it clear, correct, and bullet-proof. You can waste lots of time trying to generate the fastest way to calculate and display your data, only to find out that your results are wrong. Always complete the initial goal first, and then tweak and improve the code.
Although flowcharts have basically gone by the wayside, there's still an advantage to creating a diagram of how your code should operate. A diagram provides a graphic representation of how your code is going to work. At the very least, create a site map so that you can see how your pages relate to one another, such as that shown in Figure 3.3.
Figure 3.3: A site map will help you keep your code's goal in perspective during development.
Large systems with dozens of features may seem overwhelming from a development point of view. Save yourself time, headaches, and frustration by developing your code in small pieces. You can then put those pieces together to form the whole program. For example, if you're creating a system to manage library books, don't try to create the entire book maintenance routine in one chunk. Break it out into adding new books, searching for books, removing books, and so forth.
We've already touched on some of the points needed to keep your script, or code, pages independent of one another, but it bears repeating. Keeping your script pages independent ensures that an individual page can stand alone if someone should link to it directly-whether or not you intended for the particular page to be linked to directly.
A specific page can crash or return an error message to the user if the developer hasn't put code in the page to trap for such an occurrence. Many times overlooked by the developer, this type of error can be prolific in even the best of sites. Fortunately, you can apply simple methods to your code pages that will prevent this ungraceful exit from rearing its ugly head on your site. Use one or a combination of the following at the top of all pages that you do not want the user to find directly:
The HTTP_Referer variable contains the page that the user was viewing before arriving at the current page. You can test to make sure that the previous page was the page you, the developer, were expecting. If it wasn't, send the user back to the previous page, or display a nicely formatted error message telling the user they shouldn't link directly to the page, or both.
Testing to make sure that the current page has received all the form variables you were expecting it to receive ensures that your page won't crash. However, this method doesn't guarantee that the user came from the page you were expecting. Using HTTP Post routines, a sophisticated user can link directly to the page, passing in the form variables you expected, which may bypass any error checking of the data you applied to the data input page. This type of behavior may not concern you and, indeed, may be by design. Just be aware that this bypassing possibility does exist.