Scripting Maintainability

Tags:

Preview:

DESCRIPTION

My presentation for the Fronteers conference in September 2008 in Amsterdam.

Citation preview

Scripting

Maintainability

Christian Heilmann

Fronteers Conference 2008, Amsterdam, Holland

Hello there, I’m Chris.

I’m here to talk about maintainability of code.

Which really is not that easy.

I was also asked to deep-dive into the subject.

Oh well, let’s do this.

Humans and computers don’t work well together.

Computers love things structured and logical.

Humans, on the other hand like to tweak, fiddle and find

their own way.

Photo of a desire

path – a shortcut people

take to avoid having to go around a corner.

http://www.flickr.com/photos/skuds/602082016/

Humans also love to

bend the rules.

Photo of a parking lot with a barrier and

tire marks around the barrier on each side.

All of this makes it damn hard to create maintainable

products.

Especially in our market, as we are dealing with geeks.

Photo of a geek.

Finding easily maintainable code is very rare.

The reasons are several tales of woe:

The Village Bicycle Syndrome

The Pot Noodle Syndrome

The Lego Box

The Tale of the Missing Spanish Gentleman

The Truffle Shuffle

The village bicycle is where everyone can have a ride.

Sadly, this is what JavaScript has become, too.

Backend Engineer

Designer

SystemServerAdmin

JavaScript

Each of these will approach JavaScript in a different

manner and leave their own brand of confusion behind.

Unlike the village bicycle they are not likely to help

keeping it in a working condition.

Mainly because each of these comes in with a different idea

of what JavaScript is for.

We have to find a way to work around this – more on

that later.

However, a lot of hit & run editing is the cause for the

second syndrome.

The pot noodle syndrome is that your code turns into an

instant meal.

Cheap, hot, quick, immediately satisfying and

something you can prepare in any state of mind and

intoxication.

The problem of pot noodle code is that it is far too easy

to sell and get accustomed to.

Shortcuts don’t take much time and give you instant

success.

One of the signs of pot noodle code is that it fixes short term

issues with not much effort.

It is the kind of code that someone with delusions of knowledge adds quickly, shows to a manager and

proves thus that you “experts” overcomplicate

everything.

Examples:

Inline style blocks, innerHTML solutions to create complex

HTML, trusting user data, Ajax requests without timeout or

failure cases.

user = forms.main.name.value;if(user == ‘’){div = document.createElement(‘div’);div.style.border = ‘1px solid red’;// div.style.fontface = ‘Arial’div.innerHTML = ‘<font face=arial color=red>Enter a user Name!’;error = document.getElementById(‘error’);error.appendChild(div);

}

Which leads to the other tale: The Lego box.

As a kid, I had this massive box with all my Lego bricks.

Being the youngest, I inherited a vast and totally unordered arrangement of

bricks.

Which meant that whenever I built something, about 80% of

my time was spent rummaging noisily through

the box...

...scattering bricks all over the room and still not finding

what I was looking for.

...which of course drove my mom up the wall at 6 a.m.

...so she got me lots of little boxes and we spent a few

days organizing all the bricks into those.

The things I build afterwards were much prettier, more

complex and I was building them a lot faster.

I didn’t break any bricks rummaging or stepping on

them and the noise level was much lower.

The same can work for code.

By separating the different tasks into the right boxes, we

stop the pot noodle syndrome.

Everything visual is achieved with CSS!

HTML that makes sense without JavaScript should not

be created with JavaScript.

HTML that *only* makes sense *with* JavaScript should be created with

JavaScript.

Anything that is likely to change should not be

scattered all over your code but in a central location.

Let’s take a look at an example.

Screenshot of

the Yahoo Music API

video player.

http://ydntest.com/musicapi/playerfull.html

Everybody Duck!

There will be code

function videosreceived(data){ // create a new video player container var player = document.createElement('div'); player.id = 'videocontainer'; document.body.appendChild(player); // inject the video player with the id 'videoplayer' var so = new SWFObject('http://d.yimg.com/cosmos.bcst.'+ 'yahoo.com/up/fop/embedflv/swf/fop.swf','videoplayer','512', '322', '9', '#ffffff'); so.addVariable('eID','1301797'); so.addVariable('ympsc','4195351'); so.addVariable('lang','en'); so.addVariable('shareEnable','1'); so.addParam("allowFullScreen","true"); so.addVariable('enableFullScreen','1'); so.addVariable('autoStart','0'); so.addVariable('eh','bandsPlayer.handler'); so.addParam('allowScriptAccess','always'); so.write('videocontainer');

// get a reference to the video player - this needs to be global! vidplayer = document.getElementById('videoplayer');

var videos = data.Videos.Video; var list = document.createElement('ul'); for(var i=0,j=videos.length;i<j;i++){ var title = videos[i].title; var id = videos[i].id; var photo = videos[i].Image.url; // resize photo photo = photo.replace('=385','=75'); // turn duration into minutes and seconds var duration = videos[i].duration; var mins = parseInt(duration/60); var seconds = duration % 60; if(seconds < 10){ seconds = '0' + seconds; } duration = mins + ':' + seconds; var id = videos[i].id; var li = document.createElement('li'); // creata a link pointing to the playID method of the movie var a = document.createElement('a'); a.setAttribute('href','javascript:vidplayer.playID("v"+'+id+')'); var img = document.createElement('img'); img.setAttribute('src',photo);

img.setAttribute('alt','Video screenshot of: ' + title); a.appendChild(img); a.appendChild(document.createTextNode(title+' ('+duration+')')); li.appendChild(a); list.appendChild(li); } document.body.appendChild(list); }

Let’s clean this up!

yahoomusicplayer = function(){ var configuration = {}; var vidplayer = 0; function init(){}; function buildplayer(id){}; function received(data){}; function sanitize(data){}; function getMinutesAndSeconds(duration){}; function createItem(videodata){}; function play(id){}; return{ init:init, received:received, play:play, config:configuration }; }(); yahoomusicplayer.init();

Configuration objects rule!

If you make them accessible, you can also allow for programmatic access.

http://www.wait-till-i.com/2008/05/23/script-configuration/

*.className is your friend!

How can you hide a lot of different elements with a

certain class in a document?

// it's 2008, baby, yeah!if(document.getElementsByClassName){ var sections = document.getElementsByClassName('hide'); for(var i=0,j=sections.length;i<j;i++){ sections[i].style.display = 'none'; }// we're still in Redmond} else { var sections = document.getElementsByTagName('div'); var check = new RegExp("(^|\\s)hide(\\s|$)"); for(var i=0,j=sections.length;i<j;i++){ if(sections[i].className.match(check)){ sections[i].style.display = 'none'; } }}

alternatively...

_x$_2_(‘hide’).libraryMagicPixies.each(this.hide(‘snappy’));

How about?

var b = document.body;var c = b.className ? b.className + ' js' : 'js';b.className = c;

body.js div.hide{ position:absolute; left:-4000px;}

You use the right tool for the job, keep the headache of

designing to those who care about it and avoid looping to

boot!

You also give the CSS designer a handle to style a

non-JavaScript and JavaScript version.

The Tale of the missing Spanish Gentleman

Every product comes with a free Spanish novel.

About a man called Manual.

Spoof of an IKEA

manual explaining

JavaScript

Documentation is a lot harder than we think.

The reason is the diversity of people that will use your

script.

Biggest BS statement ever:

Good code explains itself.

“Yes that is understandable to you, as you are Dean Edwards, but I am not”

SCNR :)

The biggest issue with documentation?

How do you make sure it doesn’t get outdated?

We are very likely to update and fix code, but not the docs.

Therefore a great concept is to have at least part of the documentation generated

from comments in the code.

Big libraries do this to provide an in-depth

documentation of what is what.

... which is a cool start, and somewhat of a safety net.

... but it also poses a very high barrier of entry.

For the more visual and hands-on learners you also

need to provide step-by-step tutorials and shortcuts.

One structure for tutorials has become a very successful

blue-print:

What does it do?

Working Example

Full code

Chunks of code interspersed with explanations

You can generate this from comments in the source code

of a code example using a backend script:

http://is.gd/25A8http://icant.co.uk/sandbox/videoplayer

/*startmeta name: Yahoo Music API video player title: Detailed explanation of the demo script for the Yahoo Music API video player date: 12/09/2008 description: This is a step by step explanation of the cleaned up demo example for the Yahoo Music API video player tags: yahoo,music,api,videos version:1.0 authors:Christian Heilmann (http://wait-till-i.com) license:BSD license (http://wait-till-i.com/license.txt)endmeta*/

/*We're using the "revealing module pattern":http://www.wait-till-i.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/ to define the main script. In this case, the main module name will be #yahoomusicplayer#.*/yahoomusicplayer = function(){/*The configuration object defines the things that are likely to change, in this case the IDs of the player container and the video player itself. The label is the alternative text of the videothumbnails, it will be followed by the title of the video.*/

var configuration = { CSS:{ IDs:{ playerContainer:'videocontainer', player:'videoplayer' } }, labels:{ imagealt:'Video screenshot of: ' } };[...]

Copy and Paste examples are amazingly successful.

Make very sure that they work, and that they are high

quality examples.

A lot of people will not bother learning how things work...

...but fiddle around with the examples until they do what

they are asked to create.

Documentation is never a waste of time...

... unless people don’t find it.

Make sure that new developers get on the project

from the documentation to the code – not the other way

around.

This avoids the last issue of the list.

The Truffle Shuffle

The Truffle Shuffle

It is when something that should be small is far too big

for its own good.

a.k.a.

Code Bloat

Code bloat happens when code that is not explained or structured gets in the wrong

hands.

Very often this is the case with CSS.

Instead of editing the existing CSS selectors and values,

maintainers just add another line...

...increasing the specificity by adding another selector until you end up with things like:

body div#main ul#main li a.active span{color:#000;

}

A JavaScript classic is also just to add other functions and

call them immediately at the end of the script or with another window.onload.

I’ve talked in length about this a year ago:

http://icanhaz.com/codebloatinfo

However, here are some tricks to avoid code bloat.

Separate out – each method does one and only one task.

If you are likely to need to do the same task over and over, create a tool method (f.e. creating a link, adding new script node to the head)

Collate related task methods into modules.

Document the modules:

myapp.Dom does all the the Dom manipulation.

myapp.validate does all cleaning of user data.

Explain how to extend the modules!

The most important:

Have a build process!

Live code is for machines – development code is for

humans!

Minify, strip comments, collate into a single include

file and tag as

GENERATED, DO NOT EDIT!http://www.ejeliot.com/blog/72

What about code standards?

Here’s an idea: instead of forcing developers to change their ways, let’s think about

using technology.

The place where code needs to be in an agreed standard is

inside the code repository.

The easiest way to make this work is by automatically

converting it to this format when the code is submitted.

So instead of arguing pro and cons of writing code in a

certain format, let’s script our editors to do that for us!

The safest way is straight and narrow – no confusion, no

surprise.

More reading:http://delicious.com/codepo8/forfronteers08

Thanks!Chris Heilmann

http://scriptingenabled.org

http://wait-till-i.com

Recommended