Agileweb - Sites Darknet

ABOUT

I'm a web application developer, coming from a Coldfusion then PHP background. In the past year I've been relearning OO practices and have delved into Javascript Applications and Ruby and Rails.

Currently working in Cambridge on PHP based web applications, using the excellent MVC framework Agavi

Introducing MooSelectors

Moving to MooTools

Recently, I've moved away from Prototype, I've always loved the dark web sites library but the slow development cycle has meant that others have taken the OO javascript model and run with it. MooTools is a prime example, using Dean Edwards Base library for bug free inheritance. The effects library is lightweight and it has a fantastic download system which lets pick and mix all the components of the library as you need - it'll even compress the js for you!

CSS Event Selectors

I am a great fan of using CSS for event selectors and have used them in the past to keep my javascript unobtrusive, clean and compact. When I noticed there wasn't a port for MooTools, it was the first thing I did. I based all my work on Justin Palmers event selectors and you can almost use the same rules.

There is one main caveat - if you want to add events please use double colons (::) Why? Well to future protect you! Hopefully soon MooTools will have pseudoclasses and you will be able to:

'tr td:first-child::click': function (element) {

element.setStyle('clicked');
}

Wheres all the code? Well MooTools comes with domReady, so no need for :loaded or timers, simplifying the whole class, down to a few lines!

Remember this a port, more details on event selectors can be found in Justins article

Get it here!

Get it while its hot!! download here: MooSelectors

Updated!

27th Feb: - Updated IE bug when looping empty elements array with $each
1st March: - Updated IE bug passes an Event instance to the rule (have used a pass through function to keep the rules inline with event-selectors so its function(element, event){} )

Pay The Costs Up Front

False economies set traps

Recently, I've seen the costs of false economies in development. What I saw were problems derived from out sourcing and the curse of legacy - organic growth.

Outsourcing

The nature of the market of, and the choice of development outfit, can lead to code being produced that, whilst doing the immediate job, could soon become hard to manage. The outsourced code I witnessed, was entangled in a mass of dependencies and lack of abstraction, for example both sql and html were inline and mixed with the business logic. The development costs had been passed onto another party, where its multiple clients have proven the economic truth that time is money and not quality code. The code lacked love and with nurture being paid for by the hour, is it surprising the code (and therefore the product) suffered?

Organic growth

Another area I've repeatedly seen a lack of forward thinking in, which causes exponential costs in the future, is organic growth. When time pressures cause "quick fixes" and as deadlines loom, corners are cut and its all too easy to end up with a downturn in code quality. A lack of forward thinking, and without going back and putting the corners back in, will all too easily lead to a weakening of the foundations of the product. The costs of this erosion can be deceptive, initially being small but growing exponentially overtime. The time to develop new features takes longer and longer, bugs become increasingly frequent and new developers take longer to train.

How to avoid the downsides?

There are any number of methods and practices to avoid paying these costs, they all mean that you pay the costs up front and then maintain the quality by paying rent, little and often. Paying the rent means remembering that if there was a devil on your shoulder, there's also and Angel, and acting on what the Angel says!

Frameworks

Frameworks, either off the shelf or custom built are an excellent example, they should enforce a standardised methodology to tackling problems. They are the foundations of a project, they should provide a toolkit of interfaces to various components e.g. databases, so that if mySQL no longer cuts the mustard, moving to postGres should be a matter of pointing the database manager to the postGres implementation of the database interface. Obviously, frameworks vary, some lock in users to certain implementations i.e. ActiveRecord is the only ORM in Rails, where as others allow users to choose i.e. Agavi allows mulitple Database or ORM implementations. Frameworks vary on quality, however, all should provide a toolkit to help speed development and should encourage good practice.

They may require a high cost up front - as you have to learn to code within their parameters and understand the costs / benefits they provide. However, they help ensure that all developers working on a project standardise their code and help focus solving the problem at hand and not infrastructural / design problems.

'Paying the Rent'

There are a number of ways to ensure that you remain proactive as a developer and not fall into the organic growth trap. The great thing about 'Paying the Rent', is that it can return benefits even on the worst code bases if it is implemented consistently.

Unit Testing

Unit tests will save your neck! They are excellent for ensuring code is relevant and focused. It promotes abstracting to the simple core problems. As the code base grows, maintaining tests helps ensure that and bugs can be found earlier and should prevent bugs being released.

Refactoring

There's always time to refactor and whats more the more its practised, the less cost in 'Paying the Rent'. If you cut corners in the previous release, you need to ensure that refactoring happens in the next release. Refactoring, works nicely with testing as together I find they help identify elegant solutions to problems, by breaking down the problems into simple components.

Documentation

Finally, documentation its crucial in saving time, when inevitably time is needed the most. Inline code documentation via doc tags help lower the cost of learning and provide key indicators to the logic flow. 'Paying the Rent' here ensures that when revisiting code in 2 months or even 2 years time the logic and reasonings behind the code are easy to discover.

Presenting Prototype.js

Whilst attending MediaTel's 25th anniversary party for former employees (like me) and current employees, I volunteered to do a presentation about the Prototype javascript library. MediaTel recently adopted prototype.js as their base library for javascript and as a developer for openRico and a recent heavy user of Prototype for building a javascript View and Controller framework, I thought I'd pass on the benefits of Prototype.
It's not perfect but neither is javascript
The presentation wasn't about use cases for Prototype, (there are many quality articles out there for specific use cases), I wanted to talk about what prototype brings to the table and why you should use a solid base library for your code rather than just writing small spagetti libraries which seem to store up problems for the future.

If you are thinking about adopting Prototype read on!
I'm not saying that prototype is the answer to all your javascript woes, but if you are wanting to know what it can do for you then check out the presentation: prototype.js your javascript

Capistrano a ruby gem

On Monday I attended my first LRUG and was impressed by the formal and informal aspects of the night. First there was there was some talks at Skills Matter (an excellent venue) and afterwards, a few jars down the local pub!
The main talks were: "10 things I hate about Rails" and "Bad things to do with Capistrano". It was the Capistrano talk that opened my eyes!
What is it?
Simply put, its an Application Deployment application! Well, actually that is what it was designed to do. In actuality it allows you to execute commands on remote servers, and can do just about anything you can write shell script for. You just run those snippets of shell script on remote servers, possibly interacting with them based on their output. You can also upload files, and Capistrano includes some basic templating to allow you to dynamically create and deploy things like maintenance screens, configuration files, shell scripts, and more.

Whats good about it?

Well its not just for rails applications as stated, its not just for Ruby applications, its great for any application. It provides a clean interface and methodology for writing your application deployment and server management scripts. From controlling Apache to File editing on remote servers Capistrano can do them all. Commands can be run on in parallel on multiple servers via SSH and whats more the server you are executing commands on doesn't even need Ruby.

DRY Recipes

Capistrano works with recipes and there are three main ingredients: variables, roles, and tasks. Variables are just that and you can set any that you require. Roles, allow you to define named subsets of your servers eg. defining a database server, web server 1 and web server 2. Tasks are like methods and by default, a task is associated with all servers, but you can specify any subset of servers to be used - eg. just database servers.

This allows you to write a library of tasks to be used across your web applications, and specific recipes for each web application, removing some of the stresses of server / application deployment and server administration.

Want to know more?

Remember: its not just for Rails or even for Ruby!
Toms slides are available here: Doing bad things with Capistrano
The official: Capistrano Handbook

A Restful Client and Cross Domain Problem

Currently, I'm working on a site that is fully dynamic, so much so, development on the client side is separate from the server side. Coming from a background of working both on the server side and client side, this has created some new problems for me.

How do you develop separately and stay sane?

Communication

If you abstract the development process, then communication and flexibility between the client side and the server side is essential. Agility in the development process helps you create good web applications. Also, as a side note, play to the benefits of each technology; masses of processing in the client is costly compared to the server.

Decoupled Design

This should be obvious, but if you decouple the development process, then decoupling dependency in the client libraries is key. Why? So I can write my libraries / widgets / gimzos separately and test them accordingly. Yes, testing is key! Scriptaculous Unit Test Library.
"The goal of unit testing is to isolate each part of the program and show that the individual parts are correct." Sounds like decoupling to me!

Stay Restful

Restful design helps with the decoupling, it helps you think about encapsulation of functionality. Also, its flexible by design, if I want a new client in the future - i.e. a mobile then as the server is just a Rest API, then its just a case of building up the client in small steps!

Ajax Cross Domain Problems

Developing in this manner certainly throws up some problems! I don't have access to the server, so how can I do my Ajax - its on a different sub domain? And thats not allowed! Well I have two solutions:

Abstraction and Predictability - Tests and Fixtures

I think small, large concepts cloud my mind. Interactions I can deal with but monolithic widgets and gizmos scare me! So being predictable and decoupling means I can write functional tests for all my components! I can override my default Ajax handler to point to static JSON files. So I can work in standalone mode thats fantastic and allows me to develop quickly, but what about server integration??

Cross Domain? Mod_Proxy

I could write my own proxy server to serve me content from the same domain. That would work - but I want my code to work as if its all served from the core server. This is easy with Apache a virtual host and Mod_proxy! Simply add a ProxyPass and ProxyPassReverse for transparent use of remote servers eg: in my local.example.com vhost I can transparently connect to my rest server like so:

ProxyPass /rest remote.example.com:8080/rest
ProxyPassReverse /rest remote.example.com:8080/rest

This has meant I can integrate and fix the client side bugs undocumented features before deploying my code to a staging server!

Scriptaculous Builder

Recently, I've been using Scriptaculous' Builder class as a nice abstracted method to create HTML. Its excellent for use when looping round JSON Data Objects or Arrays. I am also used to using Prototypes Insertion class as an easy interface for inserting elements into the DOM. However, the two don't play nicely Prototype's Insertion expects to have elements in the form of a String and doesn't handle DOM elements, which Scriptaculous' Builder provides.
So how to fix?
Well it is really simple, a quick extension to the Abstract Insertion class adding a check to see if the content is an object and if it is send it to a new method which wraps DOM objects with a DIV and gets the innerHTML.

Object.extend(Abstract.Insertion.prototype, {
initialize: function(element, content) {

this.element = $(element);
if (typeof content == 'object') {
content = this.contentFromObject(content);
}
this.content = content.stripScripts();

....

contentFromObject: function (content) {

try {
var div = document.createElement('div');
div.appendChild(content);
content = div.innerHTML;
} catch (e) {
content = '';
}
return content;
}
});

Unfortunately, we have to redefine all the insertion classes again, as they have already inherited from the original Abstract.Insertion. I prefer to do it this way as my prototype extensions don't pollute the prototype library. For the full file see the downloads section.
Once this is done it really works a treat!
Also, in IE with Scriptaculous' Builder I was having problems using appendChild on tables (and I would have to do an innerHTML Hack for IE), however, using the updated Insertion class this is no longer an issue and I have a consistantly clean way of adding HTML to the DOM.

Downloads:

Insertion Extension js
Unit Test (requires scriptaculous)
Patch submitted To Prototype - track it here: 6508