There’s More to Programming than Typing Commands

Up until now I’ve really shown you only little pieces of program?relatively simple handlers and scripts that don’t perform overly complex operations. Hopefully, you’ve been able to follow this and are also able to gather that the creation of complex programs is really very little more than stringing together some fairly simple scripts into what can turn into a pretty exciting piece of software.

In Part 2, we’ll go through this process in depth?the steps involved in planning, considering, testing, and executing different types of scripts to construct software that is capable of remarkably powerful operations on the computer.

Before we do that, though, I believe it’s essential to have a good, solid set of fundamentals in place. By this, I don’t mean knowing every possible Lingo keyword. Rather, I mean knowing how to write well-constructed Lingo scripts in the first place.

In the previous modules, I avoided using those principles, largely for clarity. From this point on, however, I shall employ them with absolute consistency, as I believe that once we’re well into Part 4, you’ll have a definite understanding of the merits of my approach.

How to Handle Yourself Properly

To begin, we’ll consider good handler construction. It’s not really sufficient to simply have an on something…end and call it a handler; good handler names and a relatively rigorous convention are extremely useful.

Director has several handler-type keywords that actually are used to construct handlers all the time; startMovie is, as you’ve already seen, one of them. Contrast this to the handler we made in Module 3, ButtonClicked, and I think you’ll notice an immediate difference.

Initial capitalization of handlers and handler calls, in scripts, is not absolutely necessary, but I believe it helps distinguish calls to custom script names from calls to Director’s built-in handler events. This is especially useful when you make use of external code objects constructed for the purpose of making your job easier. And since we will be making calls to such external objects, it won’t hurt to get into the practice now.

Tip: Director is not case sensitive, with one exception, but never as far as handler names are concerned. This means that buttonclicked, Buttonclicked, buttonClicked, BUTTONclicked, etc., are all considered by the Lingo interpreter to be the same thing. This is why it’s a good idea to adopt and stick to one convention for capitalization. It makes things just a little more clear than they would be to someone who’s used to languages that are case sensitive. Also, it’s a good idea, when you place that final end at the close of the handler, to add the handler name again. Doing so is, again, not strictly necessary, but when you are scrolling through several screens, it can be most frustrating not to know precisely where one handler may have ended and the next begun. (Sometimes it can be very hard to tell.)

So rather than this:
 

on startmovie
-- some code goes here
myHandler
end

on myHandler

--more code
end


in the interests of both consistency and a good general look to your scripts, this would be preferred:
 

on startMovie
-- some code goes here
MyHandler()
end startMovie

on MyHandler

--more code
end MyHandler


This version is considerably easier to read. You get a very clear demarcation between handlers and can tell in the first one where the second one is being called; the parentheses make it very clear.

You’ve surely noticed by now that I add parentheses when referring to a handler as a handler.

Note: This is important! It is not always obvious when a handler is being called, just by context or inference. There are handlers?and we’ll be writing some ourselves in the course of this book?that return values, meaning that they perform a set of operations and pass back a variable when they’re done. If you don’t make it obvious you’re calling a handler when you use such structures, it can look simply as if you are setting one variable equal to another?a misleading conclusion. Why this special attention? Because handlers are the primary means of program construction in Director (and, in fact, all modern languages have some derivation of them, be they called functions, subroutines, or what have you) and are not meant to be confused with keywords, variables, or any other kind of element you can gain access to or program via Lingo. For this reason, treat handlers as unique articles. Not only will this help you better understand the process of programming; it will make your programs easier for others to read.

Toward a Taxonomy of Variables

Another thing you have surely noticed from our earlier example is that there are two variables, x and y, and there’s no readily obvious way to know what it is they are supposed to contain. Numbers, presumably?but numbers representing what? GNP versus national debt? Miles versus gallons? Amount of chocolate ice cream versus days required to eat it? Or just coordinates on a polar axial system?

There’s no way to know, at least not from the variable names, and that is terrible, terrible Lingo design. Lingo does not require you to limit variable names to just six or eight characters, and there is no reason whatsoever to use terse variable names unless you are writing a very short program and won’t have a lot of data to keep track of. And even then, it’s bad design, so do not do it.

But there’s more to variable names than just the names themselves. Actually, I’m about to launch another vector here on a debate that has been going on for years regarding a variable naming convention known as Hungarian Notation.

Hungarian Notation holds that you can add single initials to the beginning of a variable’s name that help describe its contents (such as n for integer, s for string, etc.), its scope (l for local, g for global), its persistence (t for temporary, s for static), and so on.

Read the (Built-in) Manual

First, internal documentation is often the last thing thought of by most programmers. Many of them utter the phrase "Good code is its own documentation," which is as rotten an excuse for laziness as any I’ve ever come across. Furthermore, it has implicit the assumption that the programmer in question is capable of writing good code. Too often, that is not at all the case.

Note: Program code is a lot like cursive handwriting. Everyone thinks his or her own is perfectly readable. Obviously, this is an erroneous belief. It takes literally years of practice and a lot of concentration?every time you’re doing it?to have such completely lucid penmanship. I assure you it’s no different at all with programming. However clear it is to you, it won’t be to anyone else. Lingo allows you to use the double hyphen (--) to indicate the beginning of a comment. It’s general practice to add these at the beginning of a line, but they can also be appended to any line of Lingo without getting you into trouble, as long as you understand that everything to the right of the comment marker, right up until you hit a carriage return, will be considered a comment. It will be ignored completely by the Lingo interpreter; Director will behave as though those lines of text did not exist at all.

All programs need internal documentation, really, and the ratio should be about 1:4?that is, for every four lines of program, one line should contain some documentation regarding what the program is actually doing at that point.

This is important for many reasons. For starters, any novices attempting to read your code (perhaps to study it and learn from it) will be eternally grateful. Second, if you should happen to get run over by a cement truck, someone is going to have to take up where you left off, and the person filling your seat will definitely appreciate the boost in understanding your logic (otherwise she’ll probably end up thinking a cement truck was too good for you).

Of course, a year from now, when you yourself are trying to edit or improve your code, you’ll pat yourself on the back for having planned to help yourself along by adding reminders all over the place in your program of what it’s doing and how?a sort of trail of bread crumbs through your own thought processes at the time.

Finally, and perhaps most importantly, adding internal documentation makes you stop and think about the code you’ve written as part of explaining it to yourself. In doing so, you will very often find a much better, more efficient way to do what you had been doing, and will be able to rewrite some of your own Lingo to match a newer, faster, more efficient model because of that?in the process, perhaps identifying and trapping for possible error conditions that might have arisen otherwise. And that never hurts.

Naturally, actually adding documentation as you go is likely to be tedious and somewhat cumbersome, so I don’t think it’s necessary to stop and write the comments as you’re writing your active code. But you should reserve perhaps an hour each day of eight to just go over what you’ve done and document it. This will enhance your Lingo programming skills, increase the readability and stability of your Lingo code, and allow you to create more reliable, more expandable Director programs.

A Clean, Well-Lighted Script

At last we come to white space. Hemingway hated it; Melville tried to harpoon it. We’re going to make it our close companion.

White space refers to extra blank spaces inserted into your code lines. It’s there exclusively and only to make your code more readable to other human beings. The computer does not care about white space. As long as you create Lingo that Director can understand, you could jam it all together into one hideous mass of logical spaghetti (as we have seen).

Some languages?notably C++?don’t even require you to add line breaks. They just use semicolons, parentheses, and braces. In such languages, you can actually write an entire program on one single line, if you really feel like doing it, and there are even contests to see who can produce the most obfuscated program code.

Don’t even think of trying this with Lingo. For one thing, Lingo actually does require line breaks in a lot of (most) situations; for another, your goal is not to create bad code that confuses. Your goal is to create perfect code that is entirely lucid and comprehensible.

Again, we’re talking partly about adopting your own methods, and partly about doing things as I recommend them, at least until you get the hang of things enough to develop your own means. For the time being, please use what I recommend, and certainly expect all my code listings to use this convention themselves.

The simplest form of white space, the carriage return, is what I use most often. I include three between handler definitions, and two from the start of the definition to the first line of Lingo it contains. I also add two before the end of the definition.

Control structures always get an extra line of white space, to distinguish them visually even further than the standard indentation does.

Contiguous lines of code?that is, several variable initializations, for instance?don’t get any extra white space.

Your choice of font is important; don’t pick a font that tries to look like handwriting or cursive. Those get very hard to read after a while. You can set your script font to be anything you want by selecting File | Preferences | Script…. I generally prefer some version of Courier, since it’s monospaced (has a fixed width), which means that any white space I insert between a variable initializer and the comment I add describing it will align from one such line to the next.

The one major downside of Courier is that it can sometimes be hard to distinguish l (ell) from 1 or O (oh) from 0, and of course computers care about the difference, quite a lot. Another inconvenience is the serifs across the bottom of Courier characters, which can make them run together visually onscreen (though this helps make them more distinct when printing your scripts out). If you have Courier New, try that one?it represents an improvement over the original typeface.

Note: It’s actually rather ironic that many computer screen fonts don’t clearly make the distinction among one, zero, ell and oh, since all information stored on a computer is binary?composed entirely of ones and zeros. Given their high degree of importance, you’d think it’d be easier to tell them apart onscreen.