Archive for April, 2008

Writing Modular Code - Make it Legible!

In the first post of my modular code series, we talked about overrides and how they are an important, and often overlooked, feature to consider in any code project. Today we will discuss an equally even more important concept: Ensure that others can quickly and easily read and understand your code.

What? Seriously?

Yes. Writing clean code is much like any other type of writing exercise, but with slightly different rules. Periods go at the end of a sentence, while semicolons go at the end of a line of code. You get the idea.

We don’t have to browse far in order to find that a lot of projects place a lot of importance on good syntax: Mambo, Drupal, PEAR, phpBB (a lot of projects, including Zen Cart, are based on this one), C++ (the big daddy), plus countless others.

The commonality between all writing formats is that you need to maintain discipline and consistency in your vocabulary. The establishment of consistent writing behavior allows your audience to focus on comprehending your message, and not waste time and brain power on first deciphering the words of that message. Again, the same rules apply to all readers, whether they be blog readers (hi there!) or fellow developers.

Even if you’re one of those coders who does his work from a dark basement, code by its very nature is supposed to be a shared. Unless you code only for yourself, your code will be viewed by other people at some point. Your work takes on an instant professional look when it’s well-formatted. Professional look means professional jobs, means professional-level fees, means 2009 Mustang GT (I’m working on that last one).

The only way you gain that ease of reading in your code is to practice and stay militant about sticking to your accepted conventions. The exact conventions you adopt are not as important as acting to own them in your coding.

The idea is much like the chores that Mr. Miyagi gave to Daniel LaRusso in Karate Kid (”wax on, wax off,” remember?). Miyagi made Daniel do the chores because they helped him develop specific muscle memories, which he applied directly to his technique training. Stick to your guns, and even when you adjust conventions, your code will still read nicely.

Want some good starting points? Listen up, Daniel-san.

Indent using spaces, not tabs.
I see tab indentation a lot in both young projects, and older, established ones, and there are several problems that come with them. Tabs display differently at different screen resolutions, on different displays, on different systems, in different programs. It may look alright on your screen, and horrendous on another.

In general, a tab pushes a ton of whitespace in front of the start of your code; in the worst cases there’s more whitespace on the line than actual code! Your uber 1900×1200 screen running Eclipse with tab stylizing enabled has no problem with 10 levels nested for loops and switches, but take pity on the 1024×768 guy, especially since he’s still holding the lion’s share of screen res on the web.

I use two spaces per level in my code. This is plenty using a fixed width font for display, though some projects do prefer four.

Keep nested logic in line with code at the same level.
All that talk about spaces over tabs means nothing if you don’t actually do it. Any code editor worth its salt will have auto-indent, which pushes the cursor to match the indentation of the previous line when a newline is created. Start there, and make sure you keep track of your nesting levels (e.g. for loop, inside an if statement, inside a switch).

Place a header comment block at the very top of every code file.
I’m talking about those blocks of code you find at the top of most files in an established project. Mambo has a very good layout description. These are important for one reason: they let people know that you made this.

You should put them in every file because never know which file a person will open first. A newbie will start high, naturally, somewhere like the index. But if they’re debugging, chances are they’ll go right to the class or function that’s throwing the error.

Plus, you never where your code may end up. If someone borrows your code, most are nice enough to give you the credit. But even if they grab the whole file, someone else may eventually wander into it. And you always hope the person who does see your stuff appreciates work, and is willing/able to pay for something custom. I want that person to know how to reach me.

Bottom line: there’s nothing wrong doing everything you can to get credit, however small, for your efforts.

Avoid inline comments ( // or # ) in favor of comment blocks ( /* */ ).
It just looks better, reads easier, and is way easier to use when you have more than one line of comments at a time. I find it useful in isolated cases to make short inline comments, however most of the time I use full-on blocks, with the opening /* on one line, the closing */ on another, and the comments in between.

Starting out go for comment blocks. It sets a good precedent and will avoid the bad habit of using single line syntax for multi-line commenting. You also must use this syntax if you intend to use a documentor with your project, such as phpDocumentor.

Use camel case or underscores, but not both.
This one deals with how you assign multi-word variables and elements. With camel case you capitalize the first letter of a new word, usually with the first word lowercase (e.g. “$myVariable”). This is the standard adopted by JavaScript. Otherwise you can break apart words with an underscore character (e.g. “$my_variable”). The choice is completely personal, neither is better than the other. Camel case saves an extra character between each word, making your total variable shorter, while underscores are typically easier to read.

Again the case can be made for both in different situations; some developers use underscores in the database tables / fields, and camel case in variables. However establishing standards is hard enough without using different ones in different circumstances. Pick one and go.

Stay standard with spacing and newlines around parentheses ( ), brackets [ ], and braces { }.
This is the biggie, which is why I saved it for last. What you decide to do with the wrapper symbols will have the most impact on your code’s overall legibility. Parentheses go around evaluation statements (e.g. “( (1 + 2) * (9 / 3) )”), function calls (e.g. “myFunction($argument)”), and control structures (e.g. “if ((condition1) || (condition2)) “). Brackets get used most often in arrays (e.g. “$myArray[$key1][$key2] = $value;”). Braces are the walls of your logic nesting, wrapping classes, functions, and nearly every control structure.

Personally, I use spaces around parentheses and braces, because they often contain complex logic. Brackets often hold nothing more than a key, so they’re not as necessary. The opening brace of a class/function/whatever stays on the same line as the starting code (e.g. “myFunction() {”), while the closing one will get its own line and match indentation with up with the opening brace (see tabs and nested logic above).

The goal here is to use whitespace to adequately pad your code for easy reading, while not making it overly elongated. I avoid placing the opening brace on its own line because the code just gets crazy long, making for lots of scrolling. phpBB elected this style, but as their own standards state, “This one is a bit of a holy war.” The basics of this rule can be expanded to include all spacing around everything, such as equal signs, commas, and mathematical symbols.

That should be more than enough to get you started. For more ideas, refer to the project links I provided at the start, and just poke around other people’s code.

Zen Cart Toronto Conference

This weekend is the first ever Zen Cart Developer’s Conference, and I am very happy to say I will be attending. Saturday is a meet ‘n greet between the founders and some of the community developers. Sunday is a public forum for any Zen Cart enthusiast to come out and meet the team, the developers, and each other. If you plan on attending, I look forward to meeting you!

I actually have the special privilege of presenting to the founders a new concept that could make its way into the Zen core code. I’ll post more info if it looks like it will happen. If not, I’ll weep silently for a few days and continue with my modular code post series.

We’ll see. Wish me luck.

Writing Modular Code - Overrides

If you code long enough, you’ll eventually hear that you should write your code in a modular fashion. Problem is, the ivory tower sage who told you to do that can’t communicate beyond the proverb. So starting today, over a few posts, I’ll lay out in hardcore concrete terms what the heck it actually means to write modular code.

People usually start trying to explain modular code from the perspective of object oriented design, or “OOP.” We’ll come back to that one later, and start with an even simpler concept: overrides. As the term implies, overrides in code occur when a system allows the introduction of third party code into the logic flow. Essentially, at a given point, the code stops to check if there’s a unique set of instructions to run, and fall back on its defaults if none are found. Done right, the potential for introducing an override can occur at every point the flow of logic in your program “turns” (e.g. load this library, turn and load that DB data, turn and set up page headers, etc).

Overrides come in two basic flavors: file existence checks and runtime configurations.  Here’s a simple example of each.

  • File existence check
    Your web project stores all the css definitions in a folder called “stylesheets.” Within that folder you have another one called “overrides.” When your stylesheets are loaded, your code first checks to see if a file with the same name exists in the overrides folder. If a match is found, the file located in /stylesheets/overrides will be loaded instead of the one found in /stylesheets.
  • Runtime configurations
    Let’s say that your /stylesheets folder contains all the css for your entire site, but you only need 1 or 2 on a given page. You don’t want to blindly load all of them on every page, because that would kill your load times, and the styles might conflict with each other. Instead, your code has a single default CSS in mind, but first it checks for a variable called load_custom_css. That variable is defined in a configuration file unique to every page on your site. If that variable points to alternative css files, those are loaded instead of the default.

In the real world, both methods are typically used together. We can combine our two examples above without too much effort: after the custom CSS files are selected from load_custom_css, the code can do a quick check in /stylesheets/overrides to see if that file has a replacement.

The open source world provides a plethora of ultra high quality examples, because they have to account for upgrades, and end users make modifications. In Wordpress, just drop some properly formatted code into the wp-content/plugins folder, and the system will recognize and execute it properly. The Zen Cart e-commerce system allows developers to get even further into the nitty-gritty with its InitSystem and Observer class, which control how backend libraries and overall page processing occurs.  Those are relatively new features on top of a robust templating system; a template designer is required to include only the files needed to achieve the desired layout. If a necessary file is not included in a custom template, the system pulls the file from the default template location.

Overrides are important for any software project because they allow outside developers to hook into your system without having to hack up your core. The importance to an open source project is obvious (see above), however don’t discount their utility if you maintain an internal company system, even if you’re the only developer (which is really not a good idea, FYI).

  • You will not be the only developer forever
    You will get promoted, or find a better paying job, or someone will get hired to help you. Change is the only constant, especially in this line of work. You’d be wise to prepare your system for that eventuality, and make the new guy’s transition easier.
  • Even if you were, you still can’t do it all
    Most companies doing their own internal development will hire outside developers at some point. They complete portions of a larger project, speeding it up, or build functionality for which a company has no internal specialty. You can’t do it all, so make your own life (and the life of that outside dev) easier by allowing him to link into the software easily.

With overrides, any and all foreign code is corralled into expected locations, allowing both you and the 3rd party or parties to manage your own areas effectively. Do it right and you’re on your way to modular code (note: doing it right comes up later in the series).