With any codebase there are set of conventions that should be followed For example, CONTANTS_SHOULD_BE_UPPER_CASE, functionsShouldBeCamelCase, _private_variables_should_be_underscored, spaces not tabs, etc. Making the decision early on as to what conventions to follow will give you a consistent codebase. The big benefit, though it's more than just aesthetic appeal. There are real, solid benefits to having consistent conventions in a project.
Reading, as a mental process is really hard for your eyes - the human eye can only focus on a very small portion of it's entire field of view to actually read the individual words in a line of text, however we are able to pick up a lot more information than just the small piece we're focusing on. By giving your entire codebase a constant structure, your giving you're brain a distinct advantage in understanding what's going on in the code in front of you. Similar to syntax highlighting (find me one programmer who isn't a fan) giving your overworked brain additional cues can lead to significant advantages in scanning over code to find bugs and make changes. Two of my favorite languages take this one step further. Ruby (and Rails specifically) pretty much defines one standard set of conventions to use through out your code - classes are UpperCase, methods_are_underscored, etc. Python makes indentation (one of the oldest visual cues programmer use to structure code) a feature of the language - ensuring a consistent usage across all python code.
The flip side is also true: code that has no consistent structure or conventions is much harder to grok at a higher level. One of the major differences between novices and masters, the ability to quickly scan and understand code, flies out the window if the code isn't structured consistently and readable. Being lazy about coding conventions does more than just look unprofessional, it makes it more difficult to understand what's going on and leads to more bugs in the codebase.
This doesn't mean you have to recode your entire codebase in hungarian notation and implement a 100 page style guide for every project - but make sure you pick conventions early on and stick with them. It's more than just an aesthetic advantage but will lead to better software in the long run.
One of the mistakes that I was (and probably still am - but being aware of the problem I think has helped) guilty of was the crime of trying to make one piece of code do too many things.
Like a vacuum cleaner with too many useless attachments that don't work correctly and keep getting lost, expanding on one function or piece of code by adding too many different conditional branches leads to a quick and ugly code death. At first glance, adding options might seem like vintage DRY - if you already have code that "almost" performs a certain function, why not add a couple of lines and a parameter or two to make it do a little bit more. In reality though, a hundred and one conditional branches are the quickest way to take an ugly-stick to your code. The next guy forced to look at the spaghetti that you've written will probably just end up quitting so that he doesn't have to maintain what you've written.
The better option, which is still DRY but also allows for separation of concerns is to extract the shared functionality separately and then invoke both your old function and a new function to get job done. To give a simplified example (extracted from some old PHP code I looked at recently), what's better:
function generate_table(&$data,$wrap_in_a_div = false) {
$table_info = ... // Generate your table
if($wrap_in_a_div} {
return "<div>" . $table_info . "</div>";
}
else {
return $table_info;
}
}
Or:
function generate_table(&$data) {
$table_info = ... // Generate your table
return $table_info;
}
function generate_table_in_div(&$data) {
return "<div>" . generate_table($data) . "</div>";
}
Ignoring the triviality of the example, for my money, the second one is liquid gold compared to the first one. There may be some perfectly valid need to have a table in a <div> tag sometimes and not sometimes, but the table generating code shouldn't worry about it because it's not it's job. If it turns out you need a whole bunch of junk occassionally wrapped in a <div>, you can down the road extract a generic wrap_in_div method and refactor generate_table_in_div to us that method.
When developing a web app, your app's capabilities are far more important than it's features. Aren't they the same thing? Not in my mind: a capability is something you can do with the product while a feature is something a product can do.
Capabilities are awesome. Features for features sake suck.
The first iPhone was a hit because even though it lacked in the feature department (No 3G, MMS, etc) it let people do things with their phone they couldn't or wouldn't have before. Same with the first iPod. In what has to be one of the funniest-in-retrospect single line reviews of the first iPod, alpha-geek CmdrTaco, the creator of Slashdot wrote:
No wireless. Less space than a nomad. Lame.
He couldn't have been more wrong. We as geeks tend to focus on the features because we think they are important to us, but the truth is that we are users too; what we can achieve with something is orders of magnitude more important than what the product itself can do.
The good news is that there seems to be a strong trend in software development to focus less on features first and rather on user stories.
On of the nice things about user story driven design is that you say "A user should be able to do YYY" and then figure out the simplest way to make that happen.
Feature driven design might say "we should have a web 2.0 interface" and so you spend two weeks creating the perfect developer framework for whatever web 2.0 means - and then the minute you try to add in an additional capability into the site you realize your framework doesn't support what you want to do. It's true at launch time you will get to check the checkbox "Web 2.0" on the back of the metaphorical box but all you really ended up with is code that will need to be supported but isn't at all essential to your users.
Microsoft word is the starkest example of this I've seen. The hell that the Microsoft programmers must go through supporting all the features that no one uses must be a very dark place indeed. I need my word processor to have a very limited set of capabilities:
After that anything else that gets added in is a feature I probably won't use. OpenOffice and Google Docs are slowly supplanting Word because they make the user experience better than Word (I'm counting not having to shell out $500 for useless features as part of that user experience) The first version I used of OpenOffice was awesome because it had, right there in the File menu a "Export as PDF". This was a feature - but it made the sharing of documents so much easier that it greatly added to the "sharing" capability - I could email a document and be sure it would look that same way on the person on the other end of tube's computer.
The poster boys for the "less features" community are 37Signals' applications - BaseCamp, HighRise and Backpack in each case they dramatically underfeatured any of the other project management / CRM / intranet suites out there but had all the capabilities that people needed. They also added the capability of "usable by moms and/or CEO's" because their products were so simple and built-on standard web user interface concepts. That's a capability that you don't ever get by adding features - it's something you only get by having solid UX coherency and a lack of confusing and overwhelming features.
If capabilities are so great, then why do we as programmers tend to spend our times focused on features?
Reason one: features are fun. I love coding in new whiz-bang features and I'd bet other developers are the same way. It means I get to walk over to another developer on the project and say "Did you see the sweet new realtime Ajax notification panel I put in?" and they say "Cool" and I feel like I earned my nerd points for the day. Unfortunately if that notification panel doesn't do anything besides add in some eye-candy it's not a win. It's going to be a weight on the codebase that will need to be carried along without adding in real value.
Reason two: far to often project descriptions are in terms of features rather than user stories. Features are easier to describe, more concrete and more estimatable than user stories. This is something that's easily solved though by making sure every feature relates back to a user story. If each feature you're adding in relates back to a user story (e.g. "Sally B. User should be able to login even if she forgot her password" = "Password Reset Feature") then the creepy features won't get in there.
For a great analysis of user stories and how use them to drive your development process I recommend "Head first software Development" from the wildly entertaining O'Reilly "Head First" serious (yes I just called a set of computer books wildly entertaining - once you've read one of the series you'll understand) Despite the title, it's by no means a basic book on programming but actually a great read on the higher level processes involved in making great software.
Remember, focus on capabilities driven by user stories, letting the features generate from the stories and everything will be ok. By the way, did I show you the cool new totally user-driven HTML5 websockets event mash-up stuff I'm working on?
I am not a designer now I will never be a designer. I don't have the talent or the patience for it. Unfortunately my very close proximity to a designer for the past 10+ years has led me to tend to place a higher value on how things look than I did previously (or would probably prefer).
This becomes an issue early in the development process when a web project is in it's beginning stage and tends to look like the illegitimate offspring of some jurassic-era reptiles. Sometimes we'll work from some nicely designed mockups, but for larger development projects, designing screens first and functionality later ends up being too constraining for the inevitable iterative spec changes that come down the line (see: Specs: The Consultant's MacGuffin ).
I would rather have some flexibility in developing the specific interface elements rather than be limited to an initial design mockup. Likewise, designers usually prefer or should prefer to have a good idea of all the elements that will needed to be in a site before really spending the time to generate a find-tuned design, so developing first and (graphically) designing later is a win-win.
... spending 8 hours a day working with something that looks like absolute garbage is incredibly demotivating.
Except that spending 8 hours a day working with something that looks like absolute garbage is incredibly demotivating. The default styles of most web browsers make simple markup look terrible. The good news is that the amount of effort it takes to make a HTML web application look half-way decent is pretty easy, more or less transferable from project to project, and doesn't add complexity that you'll regret later.
Simply applying a simple header and footer along with a couple of class names to your elements along with a basic CSS file will go a long way towards making your application output prettier and easier on the eyes. I'm going to take three examples of non-styled output and go through a couple of easy steps to make them look a lot nicer: a piece of content, a form and a table. If you're already pretty comfortable with CSS there's not a lot new here, other than the idea of getting some styles in earlier in the process than might be usual (click each image for the html version) 


1. No defaults - just like most people still surf with IE because it's pre-installed there's a lot of websites that don't override the default styles. These are usually the websites that look like a 4-year-old's refrigerator drawing so when I see nothing but Times New Roman it looks like they didn't even try - unless they are doing it on purpose.
2. Differentiation - different elements should look different, so give elements like table cells one look and table headers a very different look - don't just make it bold or one point bigger - give it a background and make it way bigger. When two elements look too similar it ends up looking like either a mistake or just bad design.
3. Grouping - related elements should be grouped together as it makes it easier to tell what's connected on a page. That means adding extra padding between your paragraphs and columns. Pull up a well designed site in your browser and notice how easy it is for your eyes to scan around the different components of the page. Now look at your page - same thing?
4. Whitespace - in general the more the better. Properly spacing elements is the easiest way to improve the look of a site and make it look more professional - remember - when in doubt, pad it out. This is very connected to grouping but worth mentioning separately. White space invites the eye into to read the content.
We're also going to apply 1 meta rule to consider the entire time: apply the rules above but stay consistent throughout the whole site - nothing looks worse than a mishmash of 60 different colors, fonts, sizes and spacing. So - apply the rules above, but do it in a consistent way - using just a couple different fonts, font sizes, colors, and background colors will make everything a lot easier on the eyes.
My designer gives me 1 baseline guideline: pick two fonts and three sizes and unless you know what you're doing stick to that or the site may start to look messy.
First things first - give yourself a decent doctype to make sure you are turning on "strict" mode so that you have some sort consistency across browsers:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Next pull in some sane defaults into your CSS file:
/* Reset all white-space to 0 for consistency across browsers */Now you can do some more involved resets, but I've found these 8 lines of CSS are a good start.
* { margin:0px; padding:0px; }
/* Default to some sans-serif font at a specific size */
body { font-family: Verdana, Arial, sans-serif; font-size:12px; }
/* Get some padding between paragraphs and some line spacing */
p { padding-bottom:5px; line-height:1.4em; }
/* Put some padding back onto our list elements */
ul, ol { margin-left: 10px; }
li { margin-left:10px; padding-left:10px; }
/* Bye bye ugly blue border */
a img { border:0px; }
/* No dots around clicked links */
a, a:active { outline: none; }
/* Class to any floated elements */
.clear { clear:both; }
Next lets wrap the each of our pages in some sort of template - unstick stuff from the top left of your browser. If you have an idea what target width your website is going to be (many websites these days are fixed width as it's easier to control how stuff looks, but there are plenty of exceptions) you might as well put something in there so that you can get an idea of how much content will fit on the screen at once pretty early in the process. If you are going to have a sidebar (or think you might) put one is as well so that you're working with a realistic sized canvas for your dynamic data. Some sort of dummy navigation that you can swap out as new things are added in will help as well. Depending on how you're developing you might have a layout template or a separate header and footer templates:
<div id='container'>
<div id='header'>
<div id='logo'><a href='/'><img src='images/logo.png'/></a></div>
<div id='tagline'>Lorem Ipsum, dolor sic Amet!</div>
</div> <!-- end #header -->
<div id='main_menu'>
<ul class=menu'>
<li><a href='#'>Item 1</a></li>
<li><a href='#'>Item 2</a></li>
<li><a href='#'>Item 3</a></li>
<li><a href='#'>Item 4</a></li>
</ul>
</div> <!-- end #main_menu -->
<div id='content_container'>
<div id='sidebar'>
<div class='sidebar_heading'>Some Heading!</div>
<div class='sidebar_body'>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
<div class='sidebar_heading'>Second Heading!</div>
<div class='sidebar_body'>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
</div> <!-- end #sidebar -->
<div id='content'>
<!-- Content Goes Here! -->
</div>
<div class='clear'></div>
</div> <!-- end #content_container -->
<div id='footer'>
<div id='copyright'>© 2009 Acme Co</div>
</div> <!-- end#footer -->
</div> <!--end #container -->
Now lets drop in a few lines of CSS to center and pad our page out and give it a little structure:
/* Set the width to 900 pixels, centered on the page with a little padding on top */
#container { width:900px; margin:0 auto; padding-top:10px; }
/* 90 pixels to work with at the top - positioned relative so that we can absolutely position our header elements easily */
#header { height:60px; position:relative; }
#logo { position:absolute; left:0px; top:0px; }
#tagline { position:absolute; right:0px; top:5px; color:#666666; font-size:14px; font-weight:bold; }
/* Quick right-aligned tab-looking text menu */
/* Make sure to be explicit with the padding and margin on our ul and li elements so we can change the defaults later on as necessary */
#main_menu { height:26px; border-bottom:3px solid #000000; margin-bottom:30px; }
#main_menu ul { display:block; float:right; list-style-type:none; padding:0px; margin:0px; }
#main_menu li { display:block; float:left; margin:0 5px; padding:0px; }
#main_menu a {
display:block;
float:left; /* Needed for IE */
padding:5px 20px;
color:white;
background-color: #000000;
text-decoration:none;
}
#main_menu a:hover { color: #000000; background-color:#666666; }
#content_container {
padding:10px 0px;
border-bottom: 1px solid #CCCCCC;
/* Do the IE hack to get a minimum content container height */
height:auto !important;
height:500px;
min-height:500px;
}
/* Floating left and then right means that we can play with the widths of the sidebar and content separately and not worry about explicitly setting the space between */
#sidebar { float:left; width:200px; }
.sidebar_heading { font-weight:bold; padding-bottom:2px; border-bottom:1px solid #CCCCCC; margin-bottom: 5px;}
.sidebar_content { padding-bottom:10px; }
#content { float:right; width:650px; }
#footer { height:20px; position:relative; }
#copyright { position:absolute; top:5px; right:0px; font-size:10px; color:#999999; }
Here's our three pages with the defaults CSS file and a little bit of structure added to them - already slightly better - they are starting to feel like a website and not something months away from being usable (click to go to the actual html files)


Ok, now let's go through each page one at a time and try to make them look a little nicer, starting with the piece of content.
Let's attack the CSS for the content:
First, make the header stand out with a color, some padding and a larger size.
Second, fix the information line closer to the header, make it smaller and lighten it up a little.
Third give our image some padding so the content isn't stuck to it.
/* Content Styles */
h1 { color: #333333; padding-bottom:15px; font-size:26px; }
.content .info { position:relative; top:-17px; font-size:11px; color:#999999; font-style:italic; }
.content img { float:left; padding:0px 14px 10px 0px; }
p { color:#444444; }
That was easy, no? Content already looks significantly better and will be nicer to work with as it continues to get developed:
<form action='...' method='post'>
<div class='horizontal_form'>
<div class='header'>Basic Information</div>
<div class='item'>
<div class='label'><label for='first_name'>First Name:</label></div>
<div class='data'>
<input name='frm[first_name]' type='text' id='first_name' class='text_field' size='30/>
</div>
<div class='description'>Enter your first name</div>
</div>
...More Items and headers...
</div>
</form>
Note - Some people have taken some serious issues with the use of divs, especially in the form elements (I even have a disease), so take a look at Prettier Accessible Forms for an alternative. I'm not a huge fan of that layout style, and I generally avoid fieldsets and legends like the plague because of the difficulty in styling them. I don't mind some extra divs around as it makes flexibly modifying forms via css simpler and cleaner and is easier to generate via code (I come from a cms background where we don't know what content is going where so a bunch of carefully crafted "#footer p img { position:absolute .. }" styles are worthless to me), but take a look the A List Apart post as a start and find what works for your project.
If you're targeting ie6 you'll need to add that extra classname to your input elements somewhere to tell you what input type your dealing with, otherwise you can use input[type=text]
Let's take quick stab at some css for a horiztontal (labels next to elements) form. Here's what we're going to do:
a few lines of CSS should do the trick:
/* Form Styles */
.horizontal_form .item { margin:10px 4px; }
.horizontal_form .item .label {
width:150px;
text-align:right;
float:left;
padding-right:10px;
vertical-align:baseline;
padding-top:3px;
color:#666666;
}
.horizontal_form .item .description {
clear:both;
padding-left: 160px;
font-size:11px;
color:#aaaaaa;
font-style:italic;
}
.horizontal_form .item .text_field {
border:1px solid #999999;
padding:2px 2px;
color:#666666;
}
.horizontal_form .item .text_field:focus {
background-color:#eeeeee;
}
.horizontal_form .header {
margin:15px 0px 10px 0px;
padding-left:0px;
font-size:16px;
border-bottom:1px solid #CCCCCC;
font-weight:bold;
color: #666666;
}
.horizontal_form .button { margin-left:200px; padding-top:10px; }
.horizontal_form .button input { padding:4px 10px; }
And we're done:
Finally let's take care of the table, here's what we're going to do:
1. Get rid of cellspacing and cellpadding
2. Highlight the headers and pad them out a little bit
3. Give the table cells a consistent padding on the left and right as well as top and bottom.
4. Add in some sort of separation - either a thin border between rows or a striping effect (or both) looks nice.
/* Table Styles */
table.account_table { border-collapse: collapse; }
table.account_table th {
padding: 10px 10px;
color:white;
font-size:14px;
background-color: #7caaff;
font-weight:bold;
}
table.account_table td {
padding: 6px 10px;
border-bottom:1px solid #999999;
}
table.account_table tr.odd td {
background-color:#eeeeee;
}
table.account_table td.currency { text-align:right; }
And we're done:
Now, you're not going to replace your designer in your organization (nor should you want to, programmers are much better paid) - but at least your work-in-progress will look a lot nicer. The point of this tutorial, and of creating a very basic, black and white site was to show you how little design knowledge and creativity is necessary to make something look halfway decent. Your not going to win any awards, but I bet you get a better reaction from the client with a couple minutes of simple CSS styling than you do from the entire week you spent getting getting that complex javascript validation to work correctly.
There's one thing that you need to be careful about making things look too finished too early - your client was often assume that the better something looks the closer it is to being done. So, for parts of the project that aren't anywhere near being done, make sure there is a stark contrast with the parts that are approaching completion - put a big X through them or give them a grayed out background. (See: Joel on Software's post The Iceberg Secret which talks the issues with having something look "done" when it's not).
Side note: Some people have mentioned the use of CSS frameworks, such as 960 Grid System. I'm don't like those from a developer's perspective as they leak a lot of information about your layout and design into the HTML of your site, where I don't think it belongs (this is especially true if a designer is going to come in and rework the design: you don't want to rewrite all your HTML to support a new design). They are also "heavy" in that you need a lot of css to set up the grid and what you can change by only modifying the CSS is more limited. I like the css Zen Garden philosophy a lot better - separate your content as completely as possible from the design and layout - but to each his own (aka "Flame On!")
So let's say you want to join all the cool kids and use gemcutter but you're Debian Lenny and it's still got a 1.3.4 version of rubygems (gemcutter apparently needs 1.3.5)? Well you could go install a local copy and screw up your dependencies, or you could just pull the version out of debian unstable as it doesn't seem to mess up anything else:
First, make sure you have the stable repopsitory pinned and create or edit:
/etc/apt/preferences
Package: *
Pin: release a=stable
Pin-Priority: 700
Then to add the unstable repository to your sources edit:
/etc/apt/sources.list
deb http://http.us.debian.org/debian/ unstable main contrib non-free
Finall update your packages and install the new version of ruby gems:
$ sudo apt-get update
$ sudo apt-get -t unstable install rubygems
And you should be good to go (we had to get starling installed on a production server and it requires gemcutter, so that's to motiviation)
If you want to be safe - I would recommend opening up your sources.list and remove unstable.