Guidelines: Code Readability - Pt1

At work I (with heavy input from the rest of the team) am writing these guidelines for our development practices, so that everyone is working 'on the same page.' I will share this series here for others who may want to know how some folks do it.

In everything there must be balance, two sides to every coin. A debate goes on about code "structure". To indent? Or not indent? One argument persists that unnecessary spaces/tabs within code increase the bandwidth used by our systems, serving up 'empty' content. The other argument is that this cost is minimal, in comparison to the time savings with relation to maintaining 'readable' code.

[More]

Watch What You Write, Someone Is Reading

Today I received the following comment here, on an older post on Variables and Naming Conventions:

...I wish Adobe would publish and adopt some kind of official naming convention. Sometimes reading sample code written in some other convention can make things harder to follow...
It was almost funny that this comment had come in when it had. Recently I was doing a lot of research for a User Group presentation I just did on the new ColdFusion 8 Ajax Components (have to re-record it before public release). In the process, I spent a great deal of time going over documentation all over the internet, from LiveDocs to countless blogs, absorbing the wealth of information that is already out there. It was outstanding that there were so many resources out there for people to learn from. On the other hand, it was a little sad that so much of the sample code was written in ways that can really start new developers off with some bad habits.

I'm not perfect, by any means, but I try to pay careful attention to the code that I place on this blog for readers to use and learn from. One thing that I attempt to do is pay attention to basic Web Standards, like using XHTML (the current standard) instead of HTML, keeping styles in the stylesheet, and having unobtrusive JavaScript. I don't always do it, sometimes it doesn't make sense for a quick example, but I try, especially within code downloads. I also try to adhere to my own Coding Guidelines, so that code appears to be consistent and easy to read and understand.

Probably the one that bothers me the most, and that I see most prevalent in blogs, documentation, and books, is the lack of proper variable scoping. I know that, often, we're just publishing quick examples, but this can be an extremely detrimental practice. I have worked on some very large enterprise applications, with years of code written by half-a-dozen different developers, most of whom learned their ColdFusion (and development) skills through the docs or a book. Many had actually come up with some very creative and effective algorithms to fix some issue, or create some new whiz bang feature, but their code was so poorly scoped that, after time, it could take down the server. Why? How? Enterprise sites may contain several hundred (or thousand) templates, containing dozens of variables on each page, and can potentially be hit by hundreds (or thousands) of users simultaneously. Multiply the number of variables by the number of pages by the number of users, then imagine ColdFusion doing a ScopeCheck on each one, to figure out which scope each variable requested belongs in. Even if the variable is in the VARIABLES scope, it's still that many times ScopeCheck will be called while rendering a page.

Still not convinced? Go download varScoper, and run it on your project root folder, including your subfolders, and see what it comes up with. Yeah, I'm still in shock. Cleanup on that is easier on a small subproject scale, but it's definitely forced me to think better when I'm writing my code, paying attention as I go, to minimize the performance impact of my applications, no matter how small it may be. I learned my bad habits from the docs, various books, sample code slung around on the CF-Talk list. I've continued to realize that there are better ways of doing things (like OOP and frameworks), and adjust my style and methods, and I think it's important to consider these 'best practices' when contributing. A little more code, but the right thing to do in the end, for you, your app, and your systems.

So, if you own a site of documentation, revise it. If you're writing a book, edit it. If you publish a CF blog, live it. The up-and-coming are reading us all of the time to find out how to use this wonderful language. Let's try to show 'em how to do it the right way. You might not follow any guidelines at all, within your development, but this scoping thing is way too important to gloss over, and will only help everyone in the long run.

Call For Input: Document Revision Comments

A little over a year ago we instituted a new policy within our dev team: placing a comment header at the top of every new (or revised) template. This comment header states what the template is, what it is used for, who originally created the file (if known) and a 'revision' listing. Every time a template is revised a notation was added to this header, with initials and date stamp, as to the purpose of the revision. This didn't replace line level comments to explain blocks of code, only augmented the process so that a total document change overview was available in an easy to review location.

[More]

Variables and Naming Conventions

At work I (with heavy input from the rest of the team) am writing these guidelines for our development practices, so that everyone is working 'on the same page.' I will share this series here for others who may want to know how some folks do it.

Variables. They define the data within our applications. Hard to peg down within our system, with thousands of variables over thousands of files. For this reason, it is time to define proper variable declaration.

Variable naming conventions and scoping can be very different in different programming languages. Within ColdFusion variables are case insensitive, whereas in most others proper case is critical. With the wide mix of languages used here (XHTML, CSS, ActionScript, JavaScript, etc.) we will take the stance that all variables, across all platforms, should remain case specific unless explicitly necessary to change. A camel case approach should be used, with the first letter of the first word (or one word) of a variable remaining lower case, while any subsequent word is capitalized. i.e.: oneVariable, anotherVariable, stillAnotherVariable. (Functions should capitalize each word) You may also employ Hungarian Notation to further identify the type of a variable, if you wish, but it won't (at this time) be required.

Another important action with variables is declaring, and referencing them, from their proper scope. In ColdFusion, you could reference most variables without identifying the scope, but to do so would cause unnecessary load on our systems. When a template is processed by ColdFusion, if the scope is not identified then the server will search through each scope separately until the variable is found. Not only does this cause the system to overwork, but you also run the risk of the system discovering a variable of the same name within a higher scope of the search tree. By expressly referencing all variables by their scope you eliminate these possible issues within our system. Also (within ColdFusion) all scope names should be listed in all uppercase. i.e.: FORM.strUserName, SESSION.intUserID, URL.intStartRow.

Flash

Although they've been used in the past, _global and _root scopes should only be used cautiously. As we integrate more of our tools into each other, these scopes can easily cause problems. Local Variables should be used in functions when possible.

Adobe has a detailed document on best practices on using scope in ActionScript.

Use variable/instance names that describe the functionality of the the item being named. Append an underscore then the ActionScript abbreviation for the type or variable or instance when appropriate. This will make code hinting available in the Flash IDE. For example, next_btn, or submitForm_lv

Use anonymous functions when appropriate, so as not to clutter the code with named trivial functions. Example:

/*Not this way:*/
function nextButtonPress(){
timeline.nextFrame();
}
next_btn.onRelease = nextButtonPress;

/*Rather, this way:*/
next_btn.onRelease = function(){
timeline.nextFrame();
}

Database Architecture

Table Names

Table names should be camel case, but with the first letter capitalized as well. Table names should not be the pluralized form of what it stores. Example: ProductItemDetail

Linking or Lookup tables which serve as a relationship between a Many-to-Many should include the word Map in the name, preferrably at the end. Example: ProductItemCategoryMap

Column Data Types

  • boolean: Boolean values are stored in bit columns, and have historically been named bVerbWhatever, for example bIsCertified.
  • foreign keys: Foreign key column names should be fkTableName, for example fkProductItemDetail.
  • hex color: Hexadecimal colors are stored in char(6) fields.
  • All fields that store numeric data should be of datatype INT(4) except for very special circumstances.

SQL

SQL keywords should appear in ALL CAPS. Tables should be aliased. For example:

SELECT      PID.displayName,
                  PID.description
FROM         ProductItemDetail PID WITH (NOLOCK)
WHERE      PID.ID = #arguments.itemDetailID#

All Joins should be specified in the FROM clause. For Example:

SELECT PI.Make, PICM.Price
FROM ProductItem PI WITH(NOLOCK)
INNER JOIN ProductItemCategoryMap PICM WITH(NOLOCK) ON PI.fkItem= PICM.fkItem

There are, always, exceptions to the rules. Typically these exceptions are due to the rules of another language. For instance, within XHTML all tag names, attributes, and attribute values are always lower case. The exception to that rule is anything calling a script function (like the event actions) where case is defined by the JavaScript itself (which is case sensative).

Examples:

<!--- ColdFusion variables --->
<cfset VARIABLES.strNextPage = "myNextPage.cfm" />
<cfparam name="URL.intRowStart" default="1" />

<cffunction name="GetNextPage" access="public" output="false" returntype="string">
   <cfreturn VARIABLES.strNextPage />
</cffunction>

/*Flash variables*/

selectedElements = {};

propCount = function(obj){
   var count = 0;
   for (var i in obj){
      count++;
   }
   return count;
}

delete_btn.onRelease = function(){
   if (propCount(selectedElements) == 0){
      this._parent.error_mc._visible = true;
   } else {
      this._parent.error_mc._visible = false;
      deleteElements(selectedElements);
   }
}

Comments

At work I (with heavy input from the rest of the team) am writing these guidelines for our development practices, so that everyone is working 'on the same page.' I will share this series here for others who may want to know how some folks do it.

First and foremost is documentation. We have an extremely large system, currently made up of nearly 7,000 ColdFusion, XML, Javascript, Cascading Style Sheet, ActionScript, and Flash templates. The original authors of these templates were spread fairly thin, working a variety of tasks while attempting to produce a usable product base to build our company upon. Because of this a large majority of our system is completely un-documented. Now, as a matter of standard practice, every template touched by a developer is given, at minimum, a document header comment to create some form of initial documentation.

[More]

BlogCFC v. 5.8.001 was created by Raymond Camden. Layout inspired by bluerobot.com., with some JQuery thrown in for fun.