10 Rules to Code By

January 22, 2007

in Career

Over the last few years the We-Create development team has built up quite a few unwritten rules that have helped us create some excellent code. You will probably recognize a few, but I doubt anyone knows them all. Therefore it’s time to write them down, understand their reasoning and live by all of them all of the time.

  1. All users are evil.
  2. Design for users, not programmers.
  3. JavaScript must only be used for interface enhancements.
  4. Clean separation of logic, presentation and interface every time.
  5. Semantics matter.
  6. Standards matter.
  7. Document or die.
  8. Security through obscurity is no security at all.
  9. KISS: Start simple. Enhance later.
  10. Use the team. We’re on your side.

1. Assume all users are evil.

This isn’t literally true since the vast majority of our users are not, in fact, evil. However, for security’s sake we must assume that they all are. Even computer savvy people with privileged access to a system can be corrupted or have their computers hijacked by evil people. Therefore, all of our software must defend itself from compromise in every possible way.

Moreover, some users are evil without even knowing it. They will make mistakes and do things that we are not expecting. They might stumble upon a case we haven’t tested for, or do things in a different sequence than our design assumes. Therefore, every piece of data that can be modified by the user should be checked and rechecked before trusting it in any way. This includes not only escaping SQL special characters, but ensuring that the type of data is correct and comparing it with the data we have already accepted to ensure that the information makes sense in context.

Remember that POST values can be manipulated just as easily as GET values, so treat them both as equally unsafe data. Also, don’t trust the cookie data without checking first, even if you think it is encrypted or otherwise protected from manipulation (see rule #8).

Lastly, there is no such thing as a system that is 100% secure, but we can strive for 99.9% if we try hard enough. Place security as the first and primary design objective and consider it from the start in everything you do. Going back and securing code after it’s “done” doesn’t work, and it’s not done until it’s secure.

2. Design for users, not programmers.

One of the best ways to prevent users from making mistakes that cause security problems is to properly design the user interface so that it is intuitive and guides the user down the right path. This is much easier said than done. However, consider the case of GET versus POST values mentioned above. Making a conscious decision to place any parameter that would allow a user to bookmark a page’s state in the GET values helps them to use their browser as they expect. Additionally, using POST values for anything that needs URL encoding can help demystify the address that they can see and sometimes dissuade them from manipulating it directly.

The most important thing to remember is that there are many ways to implement a feature, and some are more correct than others. Therefore when a decision is being made we must remember that non-programmers will use the end result and they tend like things sites and tools that are clean, easy and intuitive. If a feature can be implemented in two or more ways, select the one that is most intuitive for the user. It’s likely also the most intuitive to implement and maintain as well. The user will thank you and the extra effort always pays off in the long run.

3. JavaScript must only be used for interface enhancements.

Our rule is that if it doesn’t work with JavaScript disabled, then it doesn’t work at all. This applies to all forms of JavaScript, including AJAX. Even a so-called “Web 2.0″ site should at least be usable on non-javascript browsers, even if it doesn’t look pretty or behave the same way. All content should be accessible via the traditional request-response web model from the early 1990′s.

Some of the biggest offenders are menu systems (like BostonPizza.com) that are built to be flashy by novice JavaScript programmers. A better approach is to make a system work entirely without JavaScript, then check to see if JavaScript is available. If it is, then, after the document is loaded (onload), use the DOM to manipulate the document and restructure what the user sees.

We dare you to try surfing the web with JavaScript turned off for a day. You’ll be surprised how many walls you run into in the first few minutes. This is not acceptable.

4. Clean separation of logic, presentation and interface every time.

Mixing markup (XHTML), CSS and JavaScript in a single document is almost as evil as our users are. There is never a need[1] to add inline styling (such as with the style=”" attribute), that can’t be better handled with proper ID and CLASS definitions and an external CSS file. The same rule applies for JavaScript. If your code design prevents you from putting all JavaScript functions in an external file, then you need to re-consider your design.

Not only does separating the markup/structure from the logic/presentation help when debugging, but it also helps with modules when a designer has to change the layout for different sites. Being able to grab hold of a nice CSS class/id handle instead of editing the PHP directly simply makes life easier for everyone.

Lastly, properly structured code is much easier to debug, so while the setup might cost you time in the design and alpha stages, it will save you (as much or more) time when dealing with the list of bugs that inevitably comes back from the beta-testers.

[1] See the comments for a load-time argument for mixing in at least height and width tags.

5. Standards matter.

Not every browser renders a standards-compliant document correctly or completely, but some do. Develop the system entirely for one browser that IS standards compliant (say FireFox 2.x), get everything working and validating then go back and add specific hacks for poorly built browsers like Internet Explorer.

Also, don’t strive for pixel perfect matches between all of the major browsers and versions. No user other than someone on the beta-testing team is ever going to do a side-by-side comparison. Simply ensure that the system works as intended, is bug free and looks reasonably close to that of the standards-compliant browsers. In the long run as people adopt newer browsers that are more standards compliant your system will be future-proof and continue to work properly.

Lastly, remember this quote from Yahoo’s article on Graded Browser Support:

“Support[ing multiple browsers] does not mean that everybody gets the same thing. Expecting two users using different browser software to have an identical experience fails to embrace or acknowledge the heterogeneous essence of the Web. In fact, requiring the same experience for all users creates a barrier to participation. Availability and accessibility of content should be our key priority.”

Amen.

6. Semantics matter.

Semantically marking up a document allows a machine to obtain the same meaning from the document as a person would. The machines specifically we care about are screen-readers for the blind. You could argue that this represents an extremely tiny fraction of our overall visitors to any site. That is until you consider that the search engine spiders are blind too. Spiders see ONLY code and rarely download the CSS and JavaScript to do anything more than verify that you’re not trying to hide something deliberately (ie. Black-Hat SEO). So not using semantics means you’ll fewer visitors and also makes an obscene body gesture to those who are less fortunate.

That’s all well and good, but how do we produce semantic markup? Simply use tags and CSS classes that describe the meaning of the content rather than the visual appearance of the content or page. Here are a few examples:

* Don’t use <div class=”bigBlackText”> when you could use <h1>
* Don’t use <h1> when you really mean <b>
* Don’t use <b> when you really mean <strong>
* Don’t use <i> for emphasis, or <em> for italics
* Don’t use tables or divs to define a menu, since it’s really a list
* Don’t create containers like <div id=”LeftColumn”> when you mean <div id=”sidebar”>

Do you know about the <dl>, <dt> and <dd> tags? What about <abbr> and <acronym>? Yes? Ok then, do you know about <ins> and <del>? Be honest.

You get the idea? There are many things in our scripts that don’t yet have semantic markup tags in XHTML. For those use div and span containers with IDs and CLASSes that mean something. At least then a machine has a chance to understand what you are saying.

More info: http://www.digital-web.com/articles/writing_semantic_markup/

7. Document or die.

UPDATE Feb 2010: I’m less of a zealot about this particular rule these days. Overall we’ve adapted this rule to become more of a “Design, plan and document or die”. In essence, if we don’t have a firm, concrete plan with requirements, specifications etc in place, then we don’t proceed. Maintaining comments is part of that but not all of it. – Cam

Good, clean, high quality inline code comments make everyone’s job a lot easier. With a team that has dozens of projects on the go at any given time, your uncommented code could become someone else’s code nightmare seemingly overnight as teams are rearranged to meet the demands of new projects.

A good habit to get into is to begin a new file and then write out your entire plan of attack using only comments before writing any code. Once the strategy is laid out using comments go back and fill in the code between them. For example, simply adding a comment block to the head of a 200-line function doesn’t always help someone who is trying to fix the function if there is ever a problem. They need to know what general methodologies you used, what your plan was and why you did something a certain way before they can begin to see if you did it correctly. Of course, you can safely assume that once another programmer knows your plan, and the reasoning for it, they can read the code itself to figure out how it was done.

The best test you can use to check if your comments are good enough is to read only the comments and see if you understand the goal and plan behind making that goal a reality. If you need to read any code to understand that much then you need more comments. For those of you who insist on numbers, the ratio of code to comments should be someplace between 1:4 and 1:8 (by lines).

Here is a simple example of what I’m talking about:

EDIT: The header for this function has chanced from the original. See Jeff’s comment below for the original version.

/**
 * Validate the authenticity of a one time ticket
 *
 * This function takes a 32 character MD5 string and determines if it is a
 * valid, unused, recently assigned nonce. Used primarily in the login
 * function before comparing hashes sent by the user.
 *
 * @param resource $conn The connection to the database
 * @param string $ott The one time ticket hash
 * @return boolean true if valid, flase otherwise
 * @author Cam Turner <***********>
 * @see http://en.wikipedia.org/wiki/Cryptographic_nonce
 */
function validate_one_time_ticket($conn,$ott) {
	global $AUTHENT_CONFIG, $conn;

	// Validate the data is as we expect
	if (!check_type($ott,"MD5")) { return false; }

	// Verify that this OTT was assigned by us previously
	$query = db_query($conn,"SELECT * FROM one_time_tickets WHERE one_time_ticket='$ott'");
	if ((!$query) || (db_numrows($query) != 1)) { return false; }
	extract(db_fetch_array($query,0));

	// Remove the OTT from the DB so that it can't be used again
	$query = db_query($conn,"DELETE FROM one_time_tickets WHERE one_time_ticket='$ott'");
	if (!$query) { return false; }

	// Verify that the ticket has not expired
	$ttl = $AUTHENT_CONFIG['ttl']; // integer seconds
	$expiry = strtotime($time_issued) + $ttl;
	$now = time();
	if ($expiry <= $now) { return false; }

	// If we're still here then the ticket is fine.
	return true;
}

8. Security through obscurity is no security at all.

If something isn’t secure from the people who built it then it’s not secure at all. Any conceivable attack by a non-trusted individual should be expected to take at least as long as a brute-force, try-every-possible-combination-in-sequence attack. The short lesson is don’t design a system to protect information yourself, that’s what the experts are for.

Let’s use the example of a naive web developer trying to protect the contents of a string in transit from a user’s browser to the server[1]. The concern, that someone might be eavesdropping on an intermediary computer, is a legitimate one.

Using obscurity, the naive developer might reverse the string of text so that it reads backwards or might be tempted to simply encode[2] the information using base64. They might even get creative and reverse the base64 encoded version of the reversed string. Certainly this information is going to be un-intelligible to any human who doesn’t know the “secret” method, but trivial to undo for anyone who does.

The simple fact that knowing the strictly the method allows someone to obtain the sensitive data means there is no real security here, only false hope. At minimum the method should make use of some secret information (that is not part of the message) but is previously known by both parties, a pass phrase in a symmetric cryptographic cipher for example.

[1] Obviously, the correct security method for this application is SSL.

[2] Encoding and encrypting are NOT synonyms.

9. KISS: Start Simple. Enhance Later.

A lesson we’ve adopted from the Web 2.0 crowd of beta-labeling fanatics. Start small, build only the minimum set of features you need and then extend the project later using client, peer and user feedback.

Obviously waiting for visitor feedback doesn’t apply to client-driven projects since they usually have a grand vision and talking them into a phased-launch approach is nearly impossible. However we can still apply this basic rule and build the complete core set of functionality before going back and adding “gee-whiz-bang” features like ajax to the UI.

The benefit is that we are able to see a working “big picture” application earlier, impress the client with the relative speed then go back in and add polish to the interface as needed. We can identify flow problems earlier, ideally before they become barriers to success and we can avoid over-engineering solutions to problems that really only exist in our imaginations.

10. Use the team. We’re on your side.

The last rule is one that is less about programming and more about corporate culture. The basic idea is that there are no stupid questions. We’ve assembled a very diverse team and each of us has different skills and specialties. No one person can ever be expected to know everything about internet software development, the body of knowledge is simply too big. Therefore we’ve spread the responsibility out over a dozen or more people (so far) and we need to work as a team.

If asked a question that you can authoritatively answer, do. If you have an informed guess then try (but let the asker know it’s a guess). When all else fails think about who else on the team might know better and re-direct the question.

The second part is that asking for a second pair of eyes to look over some frustrating piece of code will often make your own eyes work better. Either by talking through the logic (out loud) or by having a flaw in your logic pointed out the frustration often vanishes. Never feel stupid or ashamed for having not seen the problem yourself, it happens to all of us more often than we’d like to admit. Ask, fix and get on with the fun stuff.

{ 30 comments… read them below or add one }

1 Kevin January 22, 2007 at 8:03 pm

Awesome! A very useful eyeopening article to say the least. As a developer always interested in trying to ward off the evil hacker types, this sort of stuff is vital to understanding what will and will not be effective in this battle. And make no bones about it it, it is a battle.

The term security by obscurity is unfortunately a fairly common practice as far as I have seen, myself being one who has practiced this type of insecure coding in the past, but this being because I simply did not know any better and figured these type of methods listed above would somehow increase the security of the site.

If it were not for being taught differently, I would likely still be implementing these sort of techniques. Fortunately that is not the case. I am curious how many web based applications are actually out there protected by these insecure security methods.

It sort of gives me the shivers to think about it.

Just my 2 cents worth

Cheers
Kevin Therriault

2 Vic January 22, 2007 at 10:14 pm

“A good habit to get into is to begin a new file and then write out your entire plan of attack using only comments before writing any code.”

This is something I have just started doing in the last week or so and it really helps.
Another thing that I like to do as well is add flags, such as =flag that I will then add as a legend at the top of the file. It makes navigating your code so much easer! I usually only do this for my CSS files, but occasionally for a complex PHP script I’ll use the flag / legend approach.

3 Cam Turner January 24, 2007 at 9:26 am

Anyone have comments on these? I expected a flare up about at least #7. :)

EDIT: I posted this before I checked the comments awaiting moderation. My Bad.

4 Rebecca January 24, 2007 at 9:42 am

Actually, I thought #7 was the best part :) At one of the previous places I worked, we had a specific coding policy of always pseudo-coding in comments before actually writing any code. In retrospect, I really with I had done it with KM. Looking towards the future, I can definitely say that I will make a habit of it from now on. Not only does it make things much easier, but it also provides a means of understanding how to test the application because you have clearly laid out actions and expected results.

5 Matt January 24, 2007 at 9:48 am

4 “There is never a valid need to add inline styling (such as with the style=” attribute)”

I agree with most everything here, but the line above. There are times in which inline styling is better and indeed sometimes necessary. Such as height and width styles. Due to the way a page is rendered, i’ve noticed that if you have something that is dependent on the size of one element, and you’ve defined the size in the css, sometimes the size isn’t defined until very late in the rendering process of a page. However, if its don’t in an inline style tag, the size is rendered almost immediately along with the rest of the HTML code, which is done first.

6 Jeffrey Sambells January 24, 2007 at 9:57 am

Use doc blocks! That will allow automatic document generation as well as integration with code hinting in IDE’s such as Zend Studio. It’s also a much clearer definition. Zend Studio has docblock built it (just type /**). For more info, see [phpDocumentor](http://www.phpdoc.org/)

/* FUNCTION: validate_one_time_ticket($ott)
This function takes a 32 character MD5 string and determines if it is a
valid, unused, recently assigned nonce. Used primarily in the login
function before comparing hashes sent by the user. Returns t/f.

Def. of a nonce: http://en.wikipedia.org/wiki/Cryptographic_nonce
*/

sould be:

/**
 * Validate the authenticity of a one time ticket
 *
 * This function takes a 32 character MD5 string and determines if it is a
 * valid, unused, recently assigned nonce. Used primarily in the login
 * function before comparing hashes sent by the user.
 *
 * @param resource $conn The connection to the database
 * @param string $ott The one time ticket hash
 * @return boolean true if valid, flase otherwise
 * @author Cam Turner <cam@wecreatecom>
 * @see http://en.wikipedia.org/wiki/Cryptographic_nonce
 */
7 Cam Turner January 24, 2007 at 10:04 am

Jeff you are correct. It should use DOC BLOCK. I’m going to edit the article now.

8 Jeffrey January 24, 2007 at 10:11 am

Matt, regarding: “There are times in which inline styling is better and indeed sometimes necessary”

I highly disagree. Inline styling is never necessary. Can you give a specific example where you would think this necessary? In what circumstances would you need to ‘correct’ size before the page is ‘finished’ rendering?

Any load events you apply will occur after the CSS has already been applied so all positioning information would be available. The only time I could see this being a problem is if you’ve also incorporated inline events and they rely on the size of an element. This however is also a big no-no and all event should be enabled and added using progressive enhancements through onload events.

9 Armando Murga January 24, 2007 at 10:13 am

Hi,

I remember talking about rule #7 with you Cam and I think it is not just another idea in the air, I think rule #7 is one of those rules that have the potential of making a developer’s life so much easier, specially when we working on different projects at the same time, that it should be a priority in everyone’s list.

Even though commenting code is sometimes boring, I do see the necessity and the extra time spent doing so is insignificant compared to the time it saves everyone else when reading the code.

10 Cam Turner January 24, 2007 at 10:13 am

Matt,

I completely disagree. Height and width inline styles are one of the biggest reasons we have this rule. Why does it matter to you when they are applied? What is your reasoning behind this? If ALL of the heights and widths are defined in the CSS how can one be dependent on another in such a fashion that it matters BEFORE the CSS file is loaded. Also, in my experience needing the height and width attributes as you describe is symptomatic of trying to do table-based layouts in CSS.

11 Jim Plush January 24, 2007 at 10:15 am

Most are excellent points. The only thing I don’t agree with is the Javascript issue. Like netscape 4 sometimes you just have to drop people. Look at any study done and you’ll see that users who have javascript turned off usually do not make purchases, nor click on adverts. Usually it’s not worth the extra development costs to support both. It all depends on the site and target audience. If you’re talking about a simple menu system, then yes you should probably support both. However if you’re talking about a major application like google maps, or gmail then I don’t believe in supporting both.

12 Cam Turner January 24, 2007 at 10:24 am

Hi Jim,

Welcome to the blog. I agree that we should drop some ancient browsers, but we should also be using unobtrusive JavaScript whenever possible. Talking about Google Maps, you’re right they can’t support both so there are exceptions. In terms of GMail, they DO support both (see the basic interface) and things like voting on an article (digg for example) could easily support BOTH the request-response and the asynchronous methods without any extra effort if they used techniques like hijax .

The extra effort is only a problem if it’s done after the fact, so it might be a problem in “start simple, enhance later” but if done correctly from the start, unobtrusive javascript is trivial and takes minimal extra effort and allows visually-impaired people (and search engines) to access the content.

13 Armando Murga January 24, 2007 at 10:24 am

Hi again,

Rule #4 is very important as well because a well-structured document is easier to debug, enhance, and understand. Breaking documents into different layers (interface, business logic, etc) is a good idea and, definitely, one of my top 5 new year’s resolutions lol.

14 Cam Turner January 24, 2007 at 10:26 am

One more thing Jim,

Why should we ignore people who don’t click on ads or buy products online? Seeing the ads has brand-awareness benefits even if they don’t click and many people RESEARCH online then DRIVE to a store to buy. They may very well still be valid, valuable customers.

15 Matt January 24, 2007 at 10:29 am

Jeffrey, its really very simple. To see what I am talking about. Put an image on a page, define its size in a css page or comment block(doenst matter). Then in your body onload event, do a simple alert(document.getElementById(‘imgid’).style.height);. Your alert box will be blank. Then do the same thing, only define the img height in an inline style attribute. Your alert will now return your img size.

now try the same thing with a div tag. your results will be identical.

In fact, if you need to reference an elements size attributes at all, and you define it in a css block or page, then you wont actually get anything returned, it will see it as not existing.

And if you are going for dynamic content and web apps that look and behave like a windows form, knowing the size and position of an element can be very important.

16 Rebecca January 24, 2007 at 10:31 am

I have to agree with Cam… you shouldn’t ignore people who don’t click on ads. I often turn off Javascript when I’m just surfing for information, and I also a frequent online shopper.

17 Vic January 24, 2007 at 10:54 am

Jim,

Your forgetting about another important “user” that ignores javascript. Searchbots.

If your site / app doesn’t degrade gracefully, then your search engine rankings are going to be horrible.

While searchbots are constantly being upgraded and their support for javascript will continue to improve, it is currently either non existent or hit and miss.

18 Amy January 24, 2007 at 11:18 am

I’m a big fan of #7. My biggest dilemma is how much time I should spend adding comments to someone else’s uncommented code.

Good article. :)

19 Cam Turner January 24, 2007 at 12:48 pm

Amy,

The simple answer to how much time to spend commenting other peoples code is this that each time you discover what the goal of a section of code is, you might as well write it down some place, why not in the code itself? If you’re unsure preface it with “I think this code does…” or to disclaim responsibility with “AMY says: I didn’t write this, but I think it does this…”

:)

20 Matt January 24, 2007 at 2:10 pm

Hmm, I may have not expressed myself well enough, I was hoping for a reply back.

You say never use inline style. I say; when it comes to programming of any kind, never say never. If something exists, then it has a purpose and a reason.

I’m not saying you are wrong, indeed I agree that you should keep your css separate for the most part. But there are several reasons when inline styles could and should be used. Per my example above after a page is rendered, when you reference an attribute defined in a separate page or block, the attribute is effectively invisible. Now, there are ways around this, yes, but the cost is much higher than the efficient method of just defining it in the element.

At some point you need to consider not only the appearance of the code, but the impact on the user. Making code more readable and easy to follow can have the side effect of making the end users experience more downtime.

A couple of examples:

In my above example, any time you go to reference size or positioning, the browser now must figure it out. Again, it’s not necessary to do it inline, but when you don’t, you cause the browser to slow down and do a lot of number crunching. Now, for a one shot deal, you might say ‘who cares, it will be instantaneous to the user’?, but if you need multiple repetitions, it’s a noticeable performance drag. And besides, even if it’s a one shot deal, there is no excuse for inefficient coding. Efficient codes, unfortunately isn’t always “pretty”, its still readable, just may not be in your preferred format.

The guys over at Yahoo recently published an article regarding separating your files out. The load time involved in a site where the css and js files are separated out greatly differs from the load time where there is a minimal number of file usage. This is because browsers only make 2 connections at a time, so it can only download 2 files at a time. The html is the first thing requested and received very quickly. The more files you have, including css and js, the longer it takes. You may say, ‘Yes, but caching takes care of that problem’?. They addressed that issue as well; they did a study regarding how many hits a certain page received and who didn’t have the page cached. The results indicated that over 50% of their unique hits were either first time visitors or visitors who no longer had the page in the cache. This means that over 50% of their visitors experience a complete page load, which the time taken to perform that is affected by the total number of files.

All I am saying is don’t sacrifice performance and user experience to make your code pretty. User experience is drastically affected by how the code is written. By saying never use inline style, when there are perfectly valid reasons to use them, indicates a lack of regard for the users perceived performance on their machine, especially if the user is on an older slower machine.

And, no, needing the height and width attributes is not symptomatic of table based layouts in css — it’s symptomatic of dynamic, user-customizable, interactive web based application design that still meets accessibility and standards compliance.

I apologize for the long reply.

21 Peter McCurdy January 24, 2007 at 8:09 pm

I have to say, I disagree about #7. The fundamental problem is that a comment (a) only describes what you think the code does and (b) only at the time you wrote the comment. In any sort of long-term maintenance situation, almost all comments turn into lies. The function header comments are sort of nice, if they’re high-level enough. But I’ve pretty much decided that if you need a comment to describe your actual code, your code isn’t legible enough.

Compare your function to:

/**
 * Validate the authenticity of a 32-character MD5 one time ticket.
 *
 * Used primarily in the login function before comparing hashes sent by the user.
 *
 * @param resource $conn The connection to the database
 * @param string $ott The one time ticket hash
 * @return boolean true if valid, false otherwise
 * @author Cam Turner
 * @see http://en.wikipedia.org/wiki/Cryptographic_nonce
 */
function validate_one_time_ticket($conn,$ott) {
    if (!check_type($ott,'MD5')) { return false; }

    $ott_data = get_ott_data($ott);

    if ($ott_data == array()) { return false; }
    if (!consume_ott($ott)) { return false; }
    if (is_ticket_expired($ott_data) { return false; }    

    return true;
}

function get_ott_data($ott) {
    global $conn;
    $query = db_query($conn,"SELECT * FROM one_time_tickets WHERE one_time_ticket='$ott'");
    if ((!$query) || (db_numrows($query) != 1)) { return array(); }
    return db_fetch_array($query,0);
}

function consume_ott($ott) {
    global $conn;
    $query = db_query($conn,"DELETE FROM one_time_tickets WHERE one_time_ticket='$ott'");
    return !!$query;
}

function is_ticket_expired($ott_arr) {
    global $AUTHENT_CONFIG;
    $ttl = $AUTHENT_CONFIG['ttl']; // integer seconds
    $expiry = strtotime($ott_arr['time_issued']) + $ttl;
    $now = time();
    return ($expiry < = $now);
}
22 Cam Turner January 24, 2007 at 8:13 pm

Hi Matt,

We’re usually paying attention to this blog in the morning and evenings.. between we’re busy writing software so please don’t take offense.

I’d love to see this article from Yahoo. Can you post a link? Until you can back up the numbers I’m going to reserve judgment entirely, as you are arguing quite well.

Your points above are valid and they even jive with rule #2 which in a nut shell says: if something has to be either hard on the user or hard on the developer then it should always be hard on the developer since we have an easier time understanding why, and the phone rings less :)

23 Peter McCurdy January 24, 2007 at 8:14 pm

Regarding my comment above, notice the following:

  1. Your business logic is now perfectly obvious, so much so that I removed its description from the function header description due to utter redundancy.
  2. Your business logic function doesn’t use any global variables.
  3. Your global variables are declared next to the code that uses them (PS: is $conn global or not?)
  4. You now have some helper routines for dealing with OTTs in the future, to pre-emptively get rid of code duplication.
  5. You don’t need any comments inside functions; the comments became the function names. You might want to put in descriptions of the parameters and return values, but it’s not ultra-critical.
  6. It’s obvious which parts of the code use the OTT itself, and which use its database values. This was particularly non-obvious in your original code (I didn’t notice the extract() at first, and had to go rewrite some of this).

The get_ott_data function is a bit ugly in how it’s used, but I didn’t feel like writing a OneTimeTicket class or anything crazy.

Reasonable people could disagree on this, I suppose. But 80% of programming is maintenance, and my experience maintaining large programs is that comments lie, large functions are buggy, and small functions let you skim code faster and see what’s going on. Plus if you save comments for the truly exceptional, weird situations, then they really stand out and you don’t gloss over them.

24 Cam Turner January 24, 2007 at 8:31 pm

Hi Pete,

I had no idea you were reading this too! (Pete was a roommate of mine at UW).

I know we’ve argued this exact point in the past and I agree in theory with many of your arguments.. things like having exceptional comments stand out, using smaller helper functions instead of bigger ones and having the small ones self-document. I agree and that is an alternative practice that can be equally good, and it would be excellent in a system modeled on MVC especially. In top-down script design I still favour my proposed #7.

On your “comments lie and 80% is maintenance”, that is true for applications like those you work on. In our case 90% of the scripts we write are written, tested, tweaked, delivered and forgotten. The clients are almost always happy with things as they end up on delivery. The problem arises two years down the road when they want a small change and someone new goes in to make the modification. Provided they ALSO keep the comments current, it does help greatly to use my method (as we’ve Proven at We-Create). Your method might help equally well however.

25 Cam Turner January 24, 2007 at 8:36 pm

One last point I’d like to make to everyone:

This article is a SHORT PRIMER. I could easily have written a full 2000 word feature on any of these topics individually, and may do so in the future (the comments here are inspiring). Keep in mind that it’s impossible to cover all aspects of an issue in 3 paragraphs (or less) and I agree with Matt when he says “In programming never say never.”

In this case I define “never” as “Don’t break one of these rules without another developer on your own team backing up the decision”… which fits nicely with rule #10 :^)

26 Nelz January 24, 2007 at 9:08 pm

While reading this article, and then the comments I went through a couple of phases. (Especially in reference to “#7: Document or Die”.

The first phase was of regret. I used to document up a storm via comments in the old programming language I used for work. (Don’t ask, it wasn’t pleasant…) When I switch jobs, and languages concurrently, I fell out of the habit. Yeah, I can partially blame the team environment which didn’t stress/emphasize the commenting, but I am a member of that team and could have helped to modify that stance. Lately I have been trying to influence the lack of comments through some coding metrics (JavaNCSS) and publishing the results.

The second phase was one of contrarianism, spurred on by Peter’s comments. I am a HUUUGE fan of automated testing. One of the coolest ideas I ever came across was that though comments may become stale, tests (especially in a Continuous Integration environment) will serve as living comments.

Ideally, I would love to see both good comments, and tests serving as living documentation. On my team, I am striving for that ideal state, but in the meantime our tests will have to do…

27 Matt January 24, 2007 at 10:45 pm

The link to the Yahoo guys page is here. I found it very informative.

http://yuiblog.com/blog/2007/01/04/performance-research-part-2/

I shows the break down of what elements are sent to the user and when. Now it is a study on empty cache vs full cache, but the results are quite surprising.

28 Cam Turner January 25, 2007 at 6:53 am

The folks over at reddit are talking about this article too and since I don’t feel like signing up for yet another account, I’ll respond to the most flaring comment here.

“This advice is as dated as demanding that everyone allow for a rich experience with Lynx, or design for a 640×480 screen. Arguments about how the scripting doesn’t improve the site, blah blah, are factless distractions — it’s a case by case decision, and universally saying that script-requiring sites are bad is inane.”

I think that if the commenter had read the other rules instead of flying off on a flame they might discovered that I also say don’t expect that every visitor get the same experience, just a functional one. I don’t expect people to avoid JavaScript because Lynx doesn’t do it, I simply expect that — if engineered correctly from the start — an alternative method for accessing the content can be given to these visitors.

“Oh it’s just 10% of people who don’t have JS, so screw ‘em!” is a very amateur thing to say. Sure millions of sites on the net use exactly that method, but the ones at the top (GMail etc) provide alternative interfaces for their fringe users. They aren’t as pretty or rich. They aren’t as easy to use and definitely don’t feel like desktop software… but they DO work, and they get the job done.

29 Cam Turner January 25, 2007 at 7:22 am

Matt,

Thank you for the link. I’ve read over the stuff and I think I’ll amend my statement to remove “there is never a valid need” to just “there is never a need” since there are valid reasons (as you’ve shown) when mixing the two might be considered acceptable. However, I still maintain that there is no “need” here, the application will run just fine with a clean separation, even if it is slightly slower.

30 Jeffrey Sambells January 25, 2007 at 11:54 am

Matt, regarding the alert(document.getElementById(‘imgid’).style.height); example. yes that is true, but the logic is slightly flawed. The style property on DOM elements only applies to inline style definitions. The style applied through a external style sheet will never appear in the example you lay out, regardless of when the CSS is applied to the document. Even after the page has finished loading, a click event would revel the same.

Your problem in this case is that you need to get the computed style. Try this:

getStyle(document.getElementById('imgid'),height);

It will work on load using the following function:

/* retrieve the computed style of an element */
function getStyle(element,property) {
    var camelProperty = property.replace(/\-(\w)/g, function (strMatch, p1){ return p1.toUpperCase(); });

    var value = element.style[camelProperty];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(property) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[camelProperty];
      }
    }
    return value == 'auto' ? '' : value;
}

The additional problem with using the CSS values to determine sizing is that it doesn’t necessarily return a numeric number. It could just a easily be a percentage, or a non pixel number (12em). Yo may want to use properties such as offsetHeight though it not part of the DOM spec.

That aside, you are correct, I shouldn’t use the term ‘Never’ as per your other arguments with the yahoo research.

Leave a Comment

Previous post:

Next post: