<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
    <title><![CDATA[Nefarious Designs]]></title>
    
    <link href="http://nefariousdesigns.co.uk/" />
    <updated>2012-05-28T10:30:23+01:00</updated>
    <id>http://nefariousdesigns.co.uk/</id>
    <author>
        <name><![CDATA[Tim Huegdon]]></name>
        
    </author>
    
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/nefariousdesigns" /><feedburner:info uri="nefariousdesigns" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><logo>http://nefariousdesigns.co.uk/favicon.ico</logo><entry>
        <title type="html"><![CDATA[Eliminating Web Development Waste]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/NgbC12YPZo4/eliminating-web-development-waste.html" />
        <updated>2012-05-28T09:02:00+01:00</updated>
        <id>http://nefariousdesigns.co.uk/eliminating-web-development-waste</id>
        <content type="html">&lt;p&gt;The concept of waste within web development might seem reasonably clear to most managers and developers, however in my experience it is something that most teams need help to identify. I’ve recently worked with a team who became exceptionally good at identifying waste and, as a result of this alongside a whole swathe of other techniques, were by far the most efficient agile team I&amp;#8217;ve ever worked with.&lt;/p&gt;

&lt;p&gt;Eliminating waste is the first—and most fundamental—principle of &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development"&gt;Lean Software Development&lt;/a&gt;; something that was introduced to me by an exceptionally talented Project Manager whom it was my pleasure to work with. Lean Software Development is a set of seven fundamental principles that really work hand in hand with agile development to improve software delivery. Those principles are: eliminate waste, amplify learning, decide as late as possible, deliver as fast as possible, empower the team, build integrity in, and see the whole. In this article I&amp;#8217;m going to look at how we can improve our ability to identify waste and iteratively remove it from our development chain.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Lean manufacturing&lt;/h2&gt;

&lt;p&gt;The principles of Lean Software Development are basically reinterpretations of the principles of Lean Manufacturing as designed and tested by &lt;a href="http://www.poppendieck.com/people.htm"&gt;Mary and Tom Poppendieck&lt;/a&gt;. Those original manufacturing principles—formulated by Sakichi Toyoda, the founder of Toyota Industries, and his son Kiichiro Toyoda, the founder of the Toyota Motor Corporation—were realised as an actual method of production by the Toyota engineer Taiichi Ohno. This later came to be known as both Just In Time Manufacturing and the Toyota Production System.&lt;/p&gt;

&lt;p&gt;Lean Manufacturing is a production practice that considers the expenditure of resources for any goal other than the creation of value for the end customer to be wasteful, and thus a target for elimination. Working from the perspective of the customer who consumes a product or service, “value” is defined as any action or process that a customer would be willing to pay for. At its most simple, Lean Manufacturing can be considered a move towards manufacturing to order rather than manufacturing to build stock since stock is essentially waste.&lt;/p&gt;

&lt;p&gt;In reading descriptions of American supermarkets, Ohno saw the supermarket as model for what he was trying to accomplish in the factory. A customer in a supermarket takes the desired amount of goods off the shelf and purchases them. The store restocks the shelf with enough new product to fill up the shelf space. Similarly, a Toyota work-center that needed parts would go to the inventory storage point for the particular part and withdraw the quantity it needed. The storage point would then be restocked by the work-center that produced the part, making only enough to replace the inventory that had been withdrawn.&lt;/p&gt;

&lt;h3&gt;The Toyota Production System&lt;/h3&gt;

&lt;p&gt;The key objective of the TPS was to design out overburden (muri) and inconsistency (mura), and to eliminate waste (muda). A manufacturing process that removes inconsistency is capable of delivering smoothly. However, that process also needs to be as flexible as possible so as not to introduce overburden which creates waste. Also there is clear value in the elimination of waste in any process.&lt;/p&gt;

&lt;h4&gt;TPS Reports&lt;/h4&gt;

&lt;p&gt;Anyone who&amp;#8217;s worked in the industry for a while, &lt;a href="http://youtu.be/0flsg4GMQxQ"&gt;or has seen the film Office Space&lt;/a&gt;, will be familiar with the term “TPS reports” being synonymous to pointless paperwork. TPS reports have nothing to do with the Toyota Production System, the TPS stands for “&lt;a href="http://en.wikipedia.org/wiki/TPS_report"&gt;Testing Procedure Specification&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;That being said, TPS reports as pointless paperwork is entirely relevant as waste that could be removed from your processes. We&amp;#8217;ll come back to that later.&lt;/p&gt;

&lt;h2&gt;Web vs. Software Development&lt;/h2&gt;

&lt;p&gt;Before we get too involved in investigating the waste element of this post, let&amp;#8217;s just examine the difference between general software development and web development:&lt;/p&gt;

&lt;p&gt;I consider myself to be a web developer and a web development manager. I am used to working with the internet as part of my development landscape and also as part of my toolkit. This means I am used to dealing with high numbers of users, a vast array of user-agents which interpret my code and therefore need to be tested against, a degree of uncertainty as to the capabilities of the user-agents and the users themselves, and a wide number of technologies. This has been described by &lt;a href="http://en.wikipedia.org/wiki/Douglas_Crockford"&gt;Douglas Crockford&lt;/a&gt;—the inventor of JSON, and often described as the godfather of JavaScript—as the “most hostile environment imaginable”.&lt;/p&gt;

&lt;p&gt;This is not to say that software development is any less hard or varied, just that there are a number of specific complications put on me as a web developer; and there are a number of very specific web-sourced problems that I&amp;#8217;m used to solving. It&amp;#8217;s simply different because it specifically involves the epic WAN that is the Internet.&lt;/p&gt;

&lt;p&gt;Lean Software Development translates very well when dealing specifically with web development since the same problems exist in both development life-cycles. What really varies is how we might implement a solution to those problems. Taking that into consideration, be aware that I&amp;#8217;m writing this article as a manager of web developers &lt;em&gt;not&lt;/em&gt; as a manager of software developers.&lt;/p&gt;

&lt;h2&gt;Waste in Web Development&lt;/h2&gt;

&lt;p&gt;The TPS identifies seven types of &lt;em&gt;manufacturing&lt;/em&gt; waste:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Overproduction&lt;/li&gt;
&lt;li&gt;Waiting&lt;/li&gt;
&lt;li&gt;Transportation&lt;/li&gt;
&lt;li&gt;Extra processes&lt;/li&gt;
&lt;li&gt;Overstock&lt;/li&gt;
&lt;li&gt;Motion&lt;/li&gt;
&lt;li&gt;Defects&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;In relation to &lt;em&gt;software development&lt;/em&gt;, however, it&amp;#8217;s clear that not all these types of waste translate. Lean Software Development identifies the following types of waste which translate perfectly between software and web development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Partially complete work&lt;/li&gt;
&lt;li&gt;Extra processes&lt;/li&gt;
&lt;li&gt;Extra features&lt;/li&gt;
&lt;li&gt;Task switching&lt;/li&gt;
&lt;li&gt;Waiting&lt;/li&gt;
&lt;li&gt;Motion&lt;/li&gt;
&lt;li&gt;Defects&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Since some of those are not immediately clear as waste, let&amp;#8217;s examine them in more detail…&lt;/p&gt;

&lt;h3&gt;Partially complete work&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s fair to say that &lt;em&gt;all&lt;/em&gt; web development is partially complete at some point in its lifecycle. The priority here is to minimise the &lt;em&gt;amount&lt;/em&gt; of partially complete work that is within a project at any given moment.&lt;/p&gt;

&lt;p&gt;Partially done web development can quickly become obsolete as it is replaced with a differing method or solution. The only way to be sure what problems exist in a piece of code are to have it fully integrated with the rest of the project. If you are working behind feature branches or feature toggles, or some other method for cloistering partially done work, you are suffering from your isolation as much as you are benefiting from it.&lt;/p&gt;

&lt;p&gt;In fact, the only place where you will capitalise on your investment in a feature is when it is in production. Partially done development ties up resources in investments that have yet to yield results. You need to provide integration test coverage, end-to-end test coverage, integration code, and a whole host of other methods of ensuring the minimum of bugs exist when you finally release it from its isolation. If your feature never actually &lt;em&gt;makes&lt;/em&gt; it to production, you have some significant investment to write off. Reducing the amount of partially complete work within your project is both a reduction of waste &lt;em&gt;and&lt;/em&gt; risk.&lt;/p&gt;

&lt;h3&gt;Extra processes&lt;/h3&gt;

&lt;p&gt;We all love our processes and documentation, right? I&amp;#8217;d be willing to bet that just about everyone who has worked in an agile organisation of some form has become disillusioned with the amount of meetings or breaks from focus they have to attend as agile “ceremonies”, and the added work dealing with documenting user stories, their requirements, and how they might be tested and accepted. In fact, two of the tennets of &lt;a href="http://agilemanifesto.org/"&gt;the agile manifesto&lt;/a&gt; are specifically related to process and documentation:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;We have come to value:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Individuals and interactions over processes and tools&lt;/li&gt;
&lt;li&gt;Working software over comprehensive documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;At every opportunity you should be assessing whether a particular process or document is entirely necessary for your development. Extra processes and documentation consume resource, slow down response times, and can mask problems elsewhere. What&amp;#8217;s more they break focus, which is something I&amp;#8217;ll come back to when I explain “motion” as a type of waste.&lt;/p&gt;

&lt;p&gt;Many development processes require paperwork of one form or another. Most of the companies I&amp;#8217;ve worked for recently have replaced actual hard-copy with wiki documentation these days, but those documents are still there. Documents for release processes, documents for sign-off, documents for traceability, not to mention documentation for security or compliance.&lt;/p&gt;

&lt;p&gt;The real test of these documents is whether someone is actually waiting for it as a deliverable, and whether it then adds value to &lt;em&gt;their&lt;/em&gt; process. If not, dump it. Otherwise, find ways to simplify that process. Reduce the amount of input required by using templates or pre-designed input forms. Condense the amount of information required. In fact, there should always be an ongoing process of refinement and efficiency evaluation for all documents and processes. Any required process should be as efficient and effective as possible. Rapid yet easy to validate.&lt;/p&gt;

&lt;p&gt;In terms of documenting code, do it as you go. Write clean, easily understandable, easy to maintain code and enforce style with static-code analysis and code reviews. Make sure code is commented effectively and you&amp;#8217;ll cut down on cost. It&amp;#8217;s important to remember that sometimes documentation is &lt;em&gt;required&lt;/em&gt; for code when knowledge needs to be shared over a wide base, but if you&amp;#8217;ve minimised what other documentation is required this will be the exception to the norm.&lt;/p&gt;

&lt;h3&gt;Extra features&lt;/h3&gt;

&lt;p&gt;Adding in extra features to a piece of development is over-engineering; don&amp;#8217;t do it. There will be many times that you foresee the need for an extra feature before you actually have the requirement. There are other times that a developer might see the opportunity to add something extra that may save time for others later on. Whilst at first glance this may seem relatively harmless and of benefit in the long run, it is almost always a source of waste.&lt;/p&gt;

&lt;p&gt;All code in the system should be tracked, reviewed, tested, and integrated every time it is touched. What&amp;#8217;s more it then needs to be maintained for the life of the project. With that in mind, it is important to remember that every bit of code adds complexity and a new possible point of failure. It also introduces something new for all the developers to understand and—worse—misunderstand and misuse.&lt;/p&gt;

&lt;p&gt;If there is no requirement for a piece of code &lt;em&gt;now&lt;/em&gt;, don&amp;#8217;t write it. Putting it in is waste. Resist your urge to over-engineer.&lt;/p&gt;

&lt;h3&gt;Task switching&lt;/h3&gt;

&lt;p&gt;The fastest way to complete two projects using the same people is to do it one at a time, sequentially. Trying to run two projects in parallel using the same resources introduces a large amount of waste. Likewise, sharing people between teams is also wasteful.&lt;/p&gt;

&lt;p&gt;Much like extra process, task switching breaks focus. Every time a developer, QA, IA, or designer have to switch tasks, there is a fair overhead to pay. These sorts of tasks require enough focus to warrant a significant amount of time to get into “the zone” or “flow”. Thus, switching between tasks incurs waste through time.&lt;/p&gt;

&lt;p&gt;Similarly, being a member of two teams introduces interruptions that might be entirely unrelated to the person&amp;#8217;s current task. This means even &lt;em&gt;more&lt;/em&gt; task switching, and probably at an even more granular level. For this reason alone it is unwise to assign people to multiple teams.&lt;/p&gt;

&lt;p&gt;To illustrate how much task switching can affect delivery time, list 6 peoples names. Firstly, time how long it takes to write each name one after the other. Next, time how long it takes to write a letter of each in turn until you&amp;#8217;ve written all 6 names completely. You&amp;#8217;ll find the latter takes significantly longer than the former. This is only the simplest form of task switching and yet the waste incurred is quite clear.&lt;/p&gt;

&lt;p&gt;Back in 2009, &lt;a href="http://www.paulgraham.com/bio.html"&gt;Paul Graham&lt;/a&gt; wrote a fantastic piece on focus entitled “&lt;a href="http://www.paulgraham.com/makersschedule.html"&gt;Maker&amp;#8217;s schedule, Manager&amp;#8217;s schedule&lt;/a&gt;”. In it he examined the difference between time schedules for developers and managers. It&amp;#8217;s important that all managers understand that their schedule is significantly different to the developers that report to them.&lt;/p&gt;

&lt;p&gt;A developer works in larger units of time than a manager, with much longer between breaks of focus; usually something in the region of a half-day unit. They dive into work as soon as they arrive at the office and will break focus at lunch. Likewise, when they return for lunch they&amp;#8217;ll dive back in and only come back to the surface when it&amp;#8217;s time to leave the office. Usually they&amp;#8217;ll arrange their tasks in chunks that align to this and therefore will complete tasks shortly before lunch or shortly before they&amp;#8217;re ready to leave for the evening.&lt;/p&gt;

&lt;p&gt;Managers work in shorter units; usually around 1 hour in length. This allows time for meetings and context switches in between. As a manager it&amp;#8217;s your &lt;em&gt;job&lt;/em&gt; to context switch effectively, although even the greatest manager in the world will struggle to do it for too many subjects. This is why it&amp;#8217;s important to make sure you don&amp;#8217;t bite off more than you can chew in terms of projects to run. If you have, it&amp;#8217;s time to start delegating.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a manager and you want effective makers, you need to arrange your days to suit them, not you. Allow 30 minutes in the morning for email checking and an added 15 minutes for the daily stand-up meeting. Don&amp;#8217;t bother them again until directly before or after the break for lunch or at the end of the day. Trust me; they&amp;#8217;ll cope with this much better than continuous interruptions throughout the day.&lt;/p&gt;

&lt;p&gt;Likewise, if you&amp;#8217;re a developer, be strict about what you do at these key times during the day. Make sure you don&amp;#8217;t kick off development before your stand-up or you&amp;#8217;ll fail to cope with the interruption. If people can&amp;#8217;t agree to arrive at the office at around the same time in the morning, then you&amp;#8217;ll be better off as a team scheduling the stand-up around lunchtime.&lt;/p&gt;

&lt;p&gt;All this might sound obvious but you&amp;#8217;ll be surprised how many teams let this sort of misalignment between team members screw up their daily flow. It&amp;#8217;s also worth noting that the larger the team, the harder it is to align this stuff. There&amp;#8217;s definitely a sweet spot to be found in team size and I personally believe it&amp;#8217;s around 6-8 members.&lt;/p&gt;

&lt;h3&gt;Waiting&lt;/h3&gt;

&lt;p&gt;Day to day development is thick with delays. It&amp;#8217;s a standard part of our working lives for projects to be delayed at the start, awaiting requirements or documentation; for the actual development to be blocked awaiting testing or deliverables from IA and UX; or to delay delivery through an inefficient release process.&lt;/p&gt;

&lt;p&gt;In web development, delays can be a serious form of waste. They prevent the completion of work and they prevent the capitalisation of investment in the development itself. The speed at which we can respond to a customer-driven requirement is directly related to the number of delays in our development life-cycle.&lt;/p&gt;

&lt;p&gt;As soon as we can accept that delays are a significant form of waste, we can identify where those delays occur and optimise them out of our processes. One of the seven principles of Lean Development is “decide as late as possible”. Taking that into account, it is better to re-prioritise tasks based on the delays you are likely to experience than suffer significant blockages in your delivery. This might mean putting tasks off until you have more information or free resource, or it might mean rearranging tasks so that developers are working on minimising those delays before delivering their original priority.&lt;/p&gt;

&lt;p&gt;The most common delays in web development are when work passes between individuals. There&amp;#8217;s nothing worse than finding out you&amp;#8217;re prevented from completing a task because the wireframe or design hasn&amp;#8217;t been completed or the requirements haven&amp;#8217;t been finalised due to poor prioritisation. It is important that, as a team, you don&amp;#8217;t agree to work on more than you can complete and similarly, it&amp;#8217;s also important that you don&amp;#8217;t agree to work on stories or tasks that have outstanding dependencies or requirements. Sometimes taking the time to groom your backlog as a team can mean the difference between wasting time on waiting or a user story or task flowing through your process painlessly.&lt;/p&gt;

&lt;p&gt;Further to that, you can often reduce the time waiting for a deliverable by eradicating the deliverable altogether. I&amp;#8217;ve had great success in the past by removing the need for wireframes and design visuals from the IAs and designers and getting them interacting with the developers on a regular basis. If the designers and developers maintain a clear style-guide with clear links to the front-end code—and at best a library of corresponding modules of code—they can easily relate new features to this through “pair programming” for an hour or two. Remove the requirement for a deliverable and you&amp;#8217;re only left waiting for the developer and designer to have some time together in their calendars. This should be significantly easier to achieve since both parties are no longer required to deliver anything but their expertise during the interaction.&lt;/p&gt;

&lt;p&gt;Finally, it&amp;#8217;s important to remember that implementation is everything. If you can&amp;#8217;t implement quickly following a key decision then you can&amp;#8217;t &lt;em&gt;delay&lt;/em&gt; that decision either. Empowering your team to deliver quickly and efficiently is your primary concern at all times, whether you are a manager or a team member.&lt;/p&gt;

&lt;h3&gt;Motion&lt;/h3&gt;

&lt;p&gt;Agile software development favours colocation for teams. Likewise, the agile manifesto states that we should value customer collaboration; involving them in all discussions and decisions throughout the development process. The point of both these principles is the reduction of “motion” within the team.&lt;/p&gt;

&lt;p&gt;It is important to make sure that developers, QAs, IAs, designers, product owners, project managers, and any other involved parties are immediately available to each other. Reducing the amount of time it takes for specific development-related questions to be answered is vital. Having everyone next to each other reduces that overhead.&lt;/p&gt;

&lt;p&gt;If you can&amp;#8217;t colocate people, the next best thing is to make sure they have easy communications as soon as they need them. Get everyone hanging out in a Jabber or IRC room, and make sure that&amp;#8217;s as much a social experience as it is a work experience or they won&amp;#8217;t come back. It should really imitate the local working environment so is likely to involve both work-related conversations and more water-cooler-type discussions and jokes. Expect that; nurture it; it&amp;#8217;ll bring the team closer together.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s also important to remember that it&amp;#8217;s good to put a name to a face. If some of your team are remote, make sure you get them over for social occasions once in a while. It&amp;#8217;s good to break bread with your colleagues, and it&amp;#8217;s easier to foster feelings of camaraderie when you&amp;#8217;ve all been out to the pub together.&lt;/p&gt;

&lt;p&gt;Similarly to social interactions, artefact interactions can also suffer from waste in motion. Reducing the amount of time it takes to pass a particular artefact of work from team member to team member can significantly improve the efficiency of the whole team. Good examples are the hand-off of design deliverables like style guides, wireframes, and visuals. Placing these in a known shared location using source control means all interested parties can have access to them immediately. Similarly, making sure tests are written and run in the same places regardless of whether they are written by developers or QAs means that there will be a clear vision of coverage for the whole team.&lt;/p&gt;

&lt;p&gt;Motion might seem like a fairly inconsequential form of waste with a minimum of impact, but really it combines with task switching to be quite a serious problem. A competent team will work with this at a minimum from the outset, and most teams can address this issue quickly to improve their performance.&lt;/p&gt;

&lt;h3&gt;Defects&lt;/h3&gt;

&lt;p&gt;Defects are an obvious form of waste, but really it&amp;#8217;s only the undetected defects that cause a project to suffer. That might sound obvious at first, but it&amp;#8217;s important to remember that the amount of waste generate by a defect is directly proportional to both the bug&amp;#8217;s severity and the amount of time it goes undetected. A critical show-stopping defect that is identified and addressed quickly generates significantly less waste than a small insipid bug that hangs around for months undetected.&lt;/p&gt;

&lt;p&gt;Reduce the impact of defects by finding them quickly through thorough testing practices and QA. Make sure the whole team are involved in that; quality is too important to be the responsibility of anyone &lt;em&gt;except the whole team&lt;/em&gt;. Practices such as test-driven development and continuous integration can massively improve the time it takes to detect issues. It is important to understand what you are trying to achieve by adopting these practices and implement what you can.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Understanding waste in your development process can help you improve the efficiency of your delivery. Being able to take the principles of lean development and integrate them into your agile teams are a clear way to improve your life as a manager. In my experience it&amp;#8217;s almost impossible to implement agile within an organisation without truly understanding the whys and hows. Further to this, it&amp;#8217;s everyone in the team that need to buy-in and understand, not just the managers or the organisation. This rings true for Lean Development as well.&lt;/p&gt;

&lt;p&gt;This has really been a study of the types of waste discussed in &lt;a href="http://www.amazon.co.uk/mn/search/?_encoding=UTF8&amp;amp;x=0&amp;amp;tag=gamersite-21&amp;amp;linkCode=ur2&amp;amp;y=0&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;field-keywords=lean%20poppendieck&amp;amp;url=search-alias=aps"&gt;the Poppendieck&amp;#8217;s various books on Lean Software Development&lt;/a&gt;. If you&amp;#8217;re interested, I recommend you buy at least one of the various volumes. They&amp;#8217;re absolutely worth it.&lt;/p&gt;

&lt;p&gt;This is the first of a couple of articles I&amp;#8217;ve started writing around agile and lean development practices and hopefully it&amp;#8217;s at least got you thinking about how you can improve &lt;em&gt;your&lt;/em&gt; life as a developer or manager. In the future I want to look at the complications around writing user stories, around implementing good testing practices, and how systems-thinking should be a primary goal of all teams.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/NgbC12YPZo4" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/eliminating-web-development-waste.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Flexible Responsive CSS Grids]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/l_R-J6yQqIU/flexible-responsive-css-grids.html" />
        <updated>2012-03-28T21:47:00+01:00</updated>
        <id>http://nefariousdesigns.co.uk/flexible-responsive-css-grids</id>
        <content type="html">&lt;p&gt;There are many ways to build CSS column grids; all of which have their pros and cons. In fact CSS3 has begun to implement a built-in model for columns which will be most useful in the future. However, until all the browsers our users surf the interwebs with are capable of this, we&amp;#8217;ll have to rely on the good old CSS2 tricks to do it.&lt;/p&gt;

&lt;p&gt;For a good while I used defined width floats for my grids. This means you have to calculate the width of each column and fix it (either with pixels or something more flexible like ems or percentages). That method is flawed due to rounding errors and general problems with flow when resizing. A better method is to use a mix of floats and negative margins for positioning. When I need to create a CSS column grid, I use this method.&lt;/p&gt;

&lt;p&gt;However, when I was recently asked to share my method—which was outlined to me by a good friend and CSS guru—I had to remind myself how to do it. These are the perils of becoming a manager and developing less. In the interests of remembering next time (and also sharing the knowledge), I&amp;#8217;ve decided to document the method in this article.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;A word on frameworks&lt;/h2&gt;

&lt;p&gt;Just a quick word really. There are frameworks out there that will do your grids for you. I know they exist but I do not use them. Often they result in bloated mark-up and esoteric element identifiers that create unmaintainable code. Your mileage, of course, may vary.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m capable of creating a grid with the minimum possible code required. Hence, for production purposes, that&amp;#8217;s what I do. In a prototyping situation, when I need something quickly and painlessly, I may choose to favour a framework; but it hasn&amp;#8217;t happened yet.&lt;/p&gt;

&lt;p&gt;If you choose to use a framework to set-up your grid, this article probably isn&amp;#8217;t for you.&lt;/p&gt;

&lt;h2&gt;Source order is important&lt;/h2&gt;

&lt;p&gt;It&amp;#8217;s good to make sure your main content is first in your source order. It&amp;#8217;s helpful for accessibility, and it&amp;#8217;s (a bit) helpful for SEO. This is something that isn&amp;#8217;t always easy to enforce when using traditional grid techniques. The technique I use is actually built around this concept.&lt;/p&gt;

&lt;h2&gt;Building the mark-up&lt;/h2&gt;

&lt;p&gt;The simplest possible mark-up we would want for a three column layout would be something like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    Main content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    Secondary content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    Navigation
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To make it a little easier to target, and to make it a bit more readable, we can add some element identifiers:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;main container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Main content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;related container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Secondary content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Navigation
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This gives us three containers for our columns. If we were to use the simplest possible method of floating each column left and fixing their widths, we&amp;#8217;d have ourselves a column grid. However, that grid would not respond reliably cross-browser and could pick up wrapping errors. It also requires exact knowledge of the required width of ALL columns. Depending on how we&amp;#8217;d like our grid to respond to change, this may be suboptimal.&lt;/p&gt;

&lt;h2&gt;Floats&lt;/h2&gt;

&lt;p&gt;A floated element is shifted to either the left or right of its containing box and surrounding content then flows around it. Floating multiple boxes stacks them up either left or right, which is useful behaviour when attempting to simulate columns. However, if there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.&lt;/p&gt;

&lt;p&gt;Floats are taken out of the &lt;a href="http://www.w3.org/TR/CSS2/visuren.html#normal-flow"&gt;normal flow of the document&lt;/a&gt;. This means the positioning model is changed somewhat and we can use that to our advantage.&lt;/p&gt;

&lt;h2&gt;The trick&lt;/h2&gt;

&lt;p&gt;Applying a negative margin to a floated element allows us to control how it makes use of empty space around it. We can make use of this if we add an extra wrapper to our main content:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Main content
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;related container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Secondary content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation container&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Navigation
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To make two satellite floats react correctly we need to make sure that our newly added container is also taken out of the normal flow of the document with a float. However, we don&amp;#8217;t want surrounding content to flow around it so we should fix its width to 100%.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;float&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Next we want to put some space around our main content using standard margins:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;margin-left&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;margin-right&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now let&amp;#8217;s fix the width of those satellite columns:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.related&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will result in our three containers floating alongside each other. However, because the first container is set to a width of 100%, the two satellites drop down beneath it.&lt;/p&gt;

&lt;p&gt;We want the satellites to take up that nice clear space we&amp;#8217;ve created with the normal margins on our main content within the first container. To do that, we shift them left across the first container using negative margins:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;margin-left&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.related&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;margin-left&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here we&amp;#8217;ve shifted the &lt;code&gt;navigation&lt;/code&gt; container 100% across the width of the &lt;em&gt;container of our floats&lt;/em&gt; (in this case, the body of our page). This puts it flush to the left, filling the space to the left of our first floated container.&lt;/p&gt;

&lt;p&gt;We then shift the &lt;code&gt;related&lt;/code&gt; container only 200px to the left, matching its width and therefore leaving it flush to the &lt;em&gt;right&lt;/em&gt; of the first floated container.&lt;/p&gt;

&lt;p&gt;This leaves us with a perfect three-column grid. What&amp;#8217;s more, since we&amp;#8217;re only fixed the width of our satellites and have left the main content in normal flow, it will respond to the width of its container, as will the position of the satellite floats.&lt;/p&gt;

&lt;h2&gt;Demo and source&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve taken the above and scrubbed it up a bit, to create a nice &lt;a href="http://timhuegdon.com/test-cases/flexible-css-grid/"&gt;flexible responsive CSS grid demo page&lt;/a&gt;. Further to that, I&amp;#8217;ve also stuck &lt;a href="http://github.com/nefarioustim/flexible-css-grid"&gt;the code up on GitHub in a &amp;#8220;flexible CSS grid&amp;#8221; repo&lt;/a&gt;. Feel free to do with it as you wish.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/l_R-J6yQqIU" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/flexible-responsive-css-grids.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Vagrant Virtualised Dev Environments]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/7DVQbbVRkVY/vagrant-virtualised-dev-environments.html" />
        <updated>2012-03-14T09:22:00+00:00</updated>
        <id>http://nefariousdesigns.co.uk/vagrant-virtualised-dev-environments</id>
        <content type="html">&lt;p&gt;In case you&amp;#8217;ve been living under a rock for the past couple of years, Vagrant is the latest development in easily controlled virtualised environments. In their own words:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The vision of the project is to create a tool to transparently manage all the complex parts of modern development within a virtual environment without affecting the everyday workflow of the developer too much.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Vagrant automates creation and provisioning of virtual machines within VirtualBox via the command line, whilst also allowing for easy distribution and reuse across multiple projects. In this article, I&amp;#8217;m going to look at how it can make life considerably easier when dealing with development environments.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Previously&lt;/h2&gt;

&lt;p&gt;Previously I&amp;#8217;ve written a couple of articles on virtualised development environments; &lt;a href="http://nefariousdesigns.co.uk/archive/2009/09/virtualised-development-environments-on-a-mac/"&gt;one on VMWare&lt;/a&gt; and &lt;a href="http://nefariousdesigns.co.uk/archive/2010/02/mac-virtualbox-linked-clone/"&gt;one on VirtualBox&lt;/a&gt;. Since then I&amp;#8217;ve upgraded my model to use Vagrant, which allows me to control my environment per project, and also fixes me up with painless access to Puppet provisioning.&lt;/p&gt;

&lt;p&gt;This has completely altered my workflow for development. To help you to understand why, I&amp;#8217;m going to walk through how Vagrant works and then look at setting up a Vagrant-powered development environment.&lt;/p&gt;

&lt;h2&gt;How it works&lt;/h2&gt;

&lt;h3&gt;The base box&lt;/h3&gt;

&lt;p&gt;The true power of Vagrant lies within its design. The basis of a Vagrant VM is its &amp;#8220;base box&amp;#8221; which is simply a VirtualBox VM that represents a base install of your system. This base install has the following basic requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VirtualBox Guest Additions for shared folders, port forwarding, etc.&lt;/li&gt;
&lt;li&gt;SSH with key-based auto. support for the vagrant user&lt;/li&gt;
&lt;li&gt;Ruby and RubyGems to install Chef and Puppet&lt;/li&gt;
&lt;li&gt;Chef and Puppet for provisioning support&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Thankfully the creation of base boxes has been done for you a thousand times over, and the subsequent base box files are available for download at various places across the interwebs. However, should you require something more specific, creating a base box is pretty undemanding and there are even programs like &lt;a href="https://github.com/jedi4ever/veewee/"&gt;VeeWee&lt;/a&gt; which will automate this process for you.&lt;/p&gt;

&lt;p&gt;For more information on building your own base box, take a look at &lt;a href="http://vagrantup.com/docs/base_boxes.html"&gt;the Vagrant base box documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;d rather download one that someone else has created, take a look here:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://vagrantbox.es"&gt;http://vagrantbox.es&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a really useful resource set-up by &lt;a href="http://morethanseven.net/"&gt;Gareth Rushgrove&lt;/a&gt;, the man behind &lt;a href="http://devopsweekly.com/"&gt;DevOps weekly&lt;/a&gt; and also a passionate advocate of Vagrant. If you can&amp;#8217;t find the box you need here, create it, host it somewhere, and let Gareth know so he can list it.&lt;/p&gt;

&lt;h3&gt;The VagrantFile&lt;/h3&gt;

&lt;p&gt;Once you&amp;#8217;ve got a suitable base box available within Vagrant, you&amp;#8217;re ready to start using it as the basis for your development environments. The plural is important here; Vagrant allows you to reuse the base box in generating VMs for multiple projects, each with their own set-up. To best understand that, I&amp;#8217;ve drawn a very simple diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://nefariousdesigns.co.uk/assets/img/vagrantfile.png" alt="One base box can be used by many VagrantFiles, and thus becomes multiple Vagrant boxes." class="central"&gt;&lt;/p&gt;

&lt;p&gt;Whilst you&amp;#8217;ll probably use the same base box for multiple projects&amp;#8211;my box of choice at the moment is a base install Ubuntu 11.10&amp;#8211;you probably want a very different set-up per project. For instance, you might have a PHP project that requires a box running Apache and mod_php whilst a Python project better suits nginx proxying to gunicorn. This is entirely possible in Vagrant.&lt;/p&gt;

&lt;p&gt;For each project you create, you&amp;#8217;ll have a base source directory. It&amp;#8217;s here that we&amp;#8217;ll create a VagrantFile to control the environment for that project. This means you&amp;#8217;ll end up with a VagrantFile per project:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/my_application/
    bin/
    etc/
    lib/
    var/
    VagrantFile
    …

/my_site/
    etc/
    public/
    templates/
    var/
    VagrantFile
    …
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To create a VagrantFile you simply run the following command in your project directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant init
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create a nicely annotated VagrantFile. I recommend reading through it to understand the various settings available for you to configure.&lt;/p&gt;

&lt;p&gt;The VagrantFile will allow you to change settings on the VM that vagrant will generate for you; for instance, you might want your VM to only have 512Mb of RAM, whereas another might need 2Gb of RAM. You can also specify what base box to use, what ports are forwarded to the VM, what IP address it is configured with, how the VM should handle networking (bridged, NAT, Host Only etc.), and many other system settings besides.&lt;/p&gt;

&lt;h3&gt;Provisioning&lt;/h3&gt;

&lt;p&gt;The VagrantFile also allows you to specify whether you want to provision your VM using Chef or Puppet. In OpsWorld™ [possibly the worst theme-park in the world] this means setting up the software on your VM. Personally, I prefer Puppet for this, simply because it uses an external DSL for configuration which I find easier to read than the internal Ruby DSL that Chef uses. (For an explanation of Domain Specific Languages, see &lt;a href="http://martinfowler.com/bliki/DomainSpecificLanguage.html"&gt;Martin Fowler&amp;#8217;s excellent blog post, book, and guide page&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Puppet automates the provisioning, patching, and configuration of operating system and application components across multiple servers. Vagrant uses Puppet to do exactly that; to set-up, patch, and configure the base box to suit your project. To do this, you need to specify that configuration in Puppet manifests&amp;#8211;which are basically scripts or programs for Puppet (hence the .pp filename).&lt;/p&gt;

&lt;p&gt;The core of the Puppet language is the resource declaration, which represents the desired state of one resource. Manifests can also use conditional statements, group resources into collections, generate text with functions, reference code in other manifests, and do many other things, but it all ultimately comes down to making sure the right resources are being managed the right way.&lt;/p&gt;

&lt;p&gt;For more on Puppet and its manifests, I recommend reading the &lt;a href="http://docs.puppetlabs.com/learning/"&gt;Learning Puppet documentation&lt;/a&gt;. You can probably even skip straight to &lt;a href="http://docs.puppetlabs.com/learning/manifests.html"&gt;the manifests section&lt;/a&gt;. Also, the resource types cheat sheet is invaluable.&lt;/p&gt;

&lt;p&gt;Another useful resource for Puppet is &lt;a href="http://puppetcookbook.com/"&gt;the Puppet Cookbook&lt;/a&gt;, which contains a collection of task oriented solutions in Puppet.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve recently started keeping a git repository of the various manifests I use for Vagrant. This way, I can copy them and share them between Vagrant projects depending on what software or set-up I require. You can find that repo on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/nefarioustim/puppet-manifests/"&gt;http://github.com/nefarioustim/puppet-manifests/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Be aware, I tend to use Ubuntu server hence package management is handled via &lt;code&gt;apt&lt;/code&gt;. This means these manifests will need a bit of editing should you want to use them on CentOS or some other linux distro.&lt;/p&gt;

&lt;h3&gt;The Vagrant VM&lt;/h3&gt;

&lt;p&gt;The Vagrant VM will be created according to your VagrantFile. This means there will be one per project. This granularity affords you a degree of independence with the VM, and allows you to treat it as a really powerful isolated root for your project. If you&amp;#8217;ve ever used &lt;code&gt;virtualenv&lt;/code&gt; when working with Python, imagine Vagrant to be &lt;code&gt;virtualenv&lt;/code&gt; squared. Since you&amp;#8217;re not sharing this environment with any other project, you can set it up, alter it, reconfigure it, and destroy it as much as you please; and since it&amp;#8217;s entirely controlled by the VagrantFile and the provisioning scripts, those processes are easy &lt;em&gt;and&lt;/em&gt; powerful.&lt;/p&gt;

&lt;p&gt;Once set-up, your vagrant VM contains a default user of &lt;code&gt;vagrant&lt;/code&gt;. That user has full sudo access and is generally the user you&amp;#8217;ll use for everything within your development environment. When you think about it, there&amp;#8217;s no real need for complex user set-up within this VM since you could be setting it up and tearing it down as much as you&amp;#8217;re doing development on it. If you &lt;em&gt;do&lt;/em&gt; need complex user set-ups, there&amp;#8217;s nothing stopping you doing that with Puppet or Chef during the provisioning stage.&lt;/p&gt;

&lt;p&gt;The Vagrant VM itself can be controlled at the command line through a number of commands:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first time you run this command, it will copy across the base box specified in your VagrantFile, boot it up with the specified networking set-up, and then provision it according to your Puppet manifests or Chef recipes. Once the box has been set up, and as long as it isn&amp;#8217;t destroy, this command will boot up the box and confirm the provisioning. You can deactivate provisioning on this command using the &lt;code&gt;--no-provision&lt;/code&gt; switch.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Logs into your project VM as the &lt;code&gt;vagrant&lt;/code&gt; user, using SSH keys. This circumvents the need for complicated SSH set-ups on your host machine and affords you all the power you need.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will remove all trace of your project VM from within VirtualBox. This means, the next time you run &lt;code&gt;vagrant up&lt;/code&gt;, Vagrant will need to recopy across the base box and reprovision it. Most of the time you&amp;#8217;ll only really want to do this if you&amp;#8217;ve b0rked your VM somehow, or you&amp;#8217;ve made a significant change to your VagrantFile; like specifying a different base box for example.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant suspend
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Takes a snapshot of your VM and suspends it, allowing you to &lt;code&gt;vagrant resume&lt;/code&gt; later. This saves you having to perform a length &lt;code&gt;vagrant destroy &amp;amp;&amp;amp; vagrant up&lt;/code&gt; cycle, but also stops the VM from taking up valuable memory and CPU cycles.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant resume
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Resumes a suspended VM from its snapshot state. The &lt;code&gt;vagrant up&lt;/code&gt; command will also resume if it detects a suspended VM.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant halt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Forces shutdown of a VM. This is basically a last resort shut down of your VM and the folks over at Vagrant recommend attempting a graceful shutdown via &lt;code&gt;vagrant ssh&lt;/code&gt; first.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant status
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Shows the current status of the VM related to the VagrantFile in the current directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant provision
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Runs the provisioning scripts without reloading the entire Vagrant environment. If you’re just tweaking or adding some cookbooks, this command can save you a lot of time.&lt;/p&gt;

&lt;p&gt;There are a few other Vagrant commands available to you but the above are pretty much the majority of what you&amp;#8217;ll use on a daily basis. For the complete list, see &lt;a href="http://vagrantup.com/docs/commands.html"&gt;the Vagrant commands documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;An example Vagrant environment&lt;/h2&gt;

&lt;p&gt;Now that I&amp;#8217;ve run through the workings hopefully you&amp;#8217;ve got a better understanding of the power of Vagrant and how it can improve your development workflow. To further highlight that, let&amp;#8217;s set-up a basic example Vagrant environment on a Mac, via the command line.&lt;/p&gt;

&lt;h3&gt;Installation the best way&lt;/h3&gt;

&lt;p&gt;With the release of v1.0 of Vagrant comes a new set of &lt;a href="http://downloads.vagrantup.com/"&gt;installation packages, available from the Vagrant downloads section&lt;/a&gt;. This is by far the best way to install Vagrant and will sort you out with all the prerequisites automatically. These are now the recommended and supported method of installation for Vagrant.&lt;/p&gt;

&lt;p&gt;When I began writing this article, these packages did not exist and, as such, I covered the slightly more complicated installation with all its prerequisites (for Mac). With these new packages, you should be able to follow along with the majority of this tutorial in Windows (albeit with slightly differing CLI commands).&lt;/p&gt;

&lt;h3&gt;Installation the old way&lt;/h3&gt;

&lt;h4&gt;Apple Developer Tools&lt;/h4&gt;

&lt;p&gt;You&amp;#8217;ll need to either install Xcode or the newly created Command Line Tools (significantly smaller than the full Xcode install and designed for stuff like this), which you can download from Apple (you&amp;#8217;ll need a free Apple ID to log in):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/downloads/"&gt;https://developer.apple.com/downloads/&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Homebrew&lt;/h4&gt;

&lt;p&gt;Firstly, I&amp;#8217;d recommend you install some package management for which I use &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt;. Whilst this is not required—you can always install from source—it &lt;em&gt;is&lt;/em&gt; lightyears ahead of MacPorts (the alternative package manager for Mac) and is &lt;a href="https://github.com/mxcl/homebrew/"&gt;actively supported on GitHub&lt;/a&gt;. If you don&amp;#8217;t have it already, do this:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;This is the &lt;a href="https://github.com/mxcl/homebrew/wiki/installation"&gt;recommended install for Homebrew&lt;/a&gt;. If you&amp;#8217;re unsure, &lt;a href="https://gist.github.com/323731"&gt;read the script first&lt;/a&gt;. It installs Homebrew to &lt;code&gt;/usr/local&lt;/code&gt; so that you don’t need sudo when you &lt;code&gt;brew install&lt;/code&gt;. It is a careful script, it can be run even if you have stuff installed to &lt;code&gt;/usr/local&lt;/code&gt; already. It tells you exactly what it will do before it does it too. And you have to confirm everything it will do before it starts.&lt;/p&gt;

&lt;p&gt;You can then use Homebrew to update your Ruby and RubyGems installs&lt;/p&gt;

&lt;h4&gt;Ruby and RubyGems&lt;/h4&gt;

&lt;p&gt;Vagrant is powered by Ruby and is installed as a RubyGem. This means you require both Ruby and RubyGems on your development VM host machine. Both are preinstalled on Mac OS, so we only need to update them:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;sudo gem update --system&lt;/kbd&gt;&lt;/pre&gt;


&lt;h4&gt;Install the gem&lt;/h4&gt;

&lt;p&gt;Once you&amp;#8217;ve made sure you&amp;#8217;ve installed all the requirements for Vagrant, the actual installation is really simple. Just install the Vagrant RubyGem:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;gem install vagrant&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Installing this gem will also install VirtualBox (if you haven&amp;#8217;t already).&lt;/p&gt;

&lt;p&gt;Bob&amp;#8217;s your uncle, Mary&amp;#8217;s your aunt, and Dave&amp;#8217;s your vicar&amp;#8217;s love-slave. You are now ready to start building Vagrant environments, but first you&amp;#8217;ll need at least one base box.&lt;/p&gt;

&lt;h3&gt;Base box&lt;/h3&gt;

&lt;p&gt;You now have the option of downloading a base box, or you can build your own in VirtualBox using your operating system of choice. Since this is supposed to be a development environment, I&amp;#8217;d recommend choosing an OS that is as close as possible to the one you&amp;#8217;re going to use in production. For me that tends to be Debian or Ubuntu (which is really just another flavour of Debian), so I&amp;#8217;m working with an Ubuntu base box.&lt;/p&gt;

&lt;h4&gt;Building your own base box&lt;/h4&gt;

&lt;p&gt;Creating a base box is straightforward as long as you&amp;#8217;re confident building and provisioning servers. If you&amp;#8217;re a bit unsure but you&amp;#8217;re not scared to give it a go, I heartily recommend trying to build your own because it&amp;#8217;s certainly a learning experience.&lt;/p&gt;

&lt;p&gt;To begin with, get yourself a disk image of your chosen OS. For me, that&amp;#8217;s Ubuntu 11.10 Server AMD64. Once you&amp;#8217;ve got your image, you&amp;#8217;re ready to start setting up a VM in VirtualBox.&lt;/p&gt;

&lt;p&gt;My template for new VMs is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;360Mb RAM&lt;/li&gt;
&lt;li&gt;10GB VDI disk, dynamically sized&lt;/li&gt;
&lt;li&gt;64 bit

&lt;ul&gt;
&lt;li&gt;In General &gt; Basic choose Linux &gt; Ubuntu (64 bit) as your OS&lt;/li&gt;
&lt;li&gt;Set System &gt; Motherboard &gt; Enable IO APIC to true&lt;/li&gt;
&lt;li&gt;Set System &gt; Processor &gt; Enable PAE/NX to true&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Disable audio&lt;/li&gt;
&lt;li&gt;Disable floppy drive&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Once that&amp;#8217;s set-up, make sure you&amp;#8217;ve &amp;#8220;inserted&amp;#8221; your OS disk image to the CD/DVD drive on the VM, and fire it up. I generally opt for a standard install for my base box, but if your OS of choice offers a low footprint install intended for virtualisation, you may want to opt to use that instead. If you do, make sure you know the differences; it may use a different kernel and therefore not support some of the motherboard and processor settings we discussed earlier.&lt;/p&gt;

&lt;p&gt;When the time comes, make sure you use a default user of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fullname: vagrant&lt;/li&gt;
&lt;li&gt;Username: vagrant&lt;/li&gt;
&lt;li&gt;Password: vagrant&lt;/li&gt;
&lt;/ul&gt;


&lt;h5&gt;Post install&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/db79878aa0e7eae56caa"&gt;I&amp;#8217;ve written a script to handle post install&lt;/a&gt; in a similar method to VeeWee. To use this you&amp;#8217;ll need to create a &lt;code&gt;.vbox_version&lt;/code&gt; file in your home dir:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;echo "4.1.8" &gt; ~/.vbox_version&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;You&amp;#8217;ll want to replace the &amp;#8220;4.1.8&amp;#8221; with the relevant version of your VirtualBox installation because this will be used to work out which Guest Additions to install. Next let&amp;#8217;s switch to root for ease:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;sudo -i&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;You&amp;#8217;ll also want to make sure cUrl is installed:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;apt-get install -y curl&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Once you&amp;#8217;ve done that, we can download and run the script (&lt;a href="http://git.io/cSGCgw"&gt;raw gist URL shortened for convenience here&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;curl -L http://git.io/cSGCgw | bash&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;If you read through the script you&amp;#8217;ll see it does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a log of the date and time we built the box in &lt;code&gt;/etc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Installs &lt;code&gt;aptitude&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Updates the package list&lt;/li&gt;
&lt;li&gt;Upgrades the installed packages&lt;/li&gt;
&lt;li&gt;Installs a bunch of packages that are useful for set-up&lt;/li&gt;
&lt;li&gt;Installs SSH&lt;/li&gt;
&lt;li&gt;Installs the NFS client&lt;/li&gt;
&lt;li&gt;Sets-up the correct permissions in &lt;code&gt;sudoers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Installs Ruby and RubyGems&lt;/li&gt;
&lt;li&gt;Installs the Chef and Puppet gems and updates the JSON gem&lt;/li&gt;
&lt;li&gt;Removes the the gemspec for an older version of JSON because it’s broken&lt;/li&gt;
&lt;li&gt;Installs the insecure Vagrant public keys supplied by Mitchell Hashimoto&lt;/li&gt;
&lt;li&gt;Makes sure SSH doesn&amp;#8217;t use DNS look-ups&lt;/li&gt;
&lt;li&gt;Installs the VirtualBox Guest Additions&lt;/li&gt;
&lt;li&gt;Zeros out the free space in the image to make it easier to compress&lt;/li&gt;
&lt;li&gt;Removes leftover DHCP and network rules&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Once the script completes you should be ready to rock. Better shut down that VM:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;sudo shutdown -P now&lt;/kbd&gt;&lt;/pre&gt;


&lt;h4&gt;Package up your self-built base box&lt;/h4&gt;

&lt;p&gt;Assuming the VM you created in VirtualBox is called &amp;#8220;ubuntu-11.10&amp;#8221;, we package it up using the following command:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;vagrant package --base ubuntu-11.10 --out ubuntu-11.10.box&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;The &lt;code&gt;--base&lt;/code&gt; parameter refers to the VM in VirtualBox and the &lt;code&gt;--out&lt;/code&gt; parameter is what we want our newly packaged &lt;code&gt;.box&lt;/code&gt; file to be called. Once you have a &lt;code&gt;.box&lt;/code&gt; file, you&amp;#8217;re ready to start using it with Vagrant&amp;#8211;and you&amp;#8217;re also ready to share it with other people should you so wish.&lt;/p&gt;

&lt;h4&gt;Using a pre-built base box&lt;/h4&gt;

&lt;p&gt;In true &lt;a href="http://en.wikipedia.org/wiki/Blue_Peter"&gt;Blue Peter&lt;/a&gt; fashion, here&amp;#8217;s one I made earlier:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://timhuegdon.com/vagrant-boxes/ubuntu-11.10.box"&gt;http://timhuegdon.com/vagrant-boxes/ubuntu-11.10.box&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For other options, as previously mentioned, have a look at &lt;a href="http://vagrantbox.es"&gt;Vagrantbox.es&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Making Vagrant aware of your base box&lt;/h3&gt;

&lt;p&gt;Assuming you&amp;#8217;re in the same directory as your &lt;code&gt;.box&lt;/code&gt; file, you can add it to Vagrant using the following command:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;vagrant box add ubuntu-11.10 ubuntu-11.10.box&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;The first parameter is the name Vagrant will use to refer to the box in Vagrantfiles, and the last is the path to your &lt;code&gt;.box&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;Configuring your VagrantFile&lt;/h3&gt;

&lt;p&gt;Now that you&amp;#8217;ve downloaded or created a base box, and have made Vagrant aware of it, our next step is to configure a VagrantFile for whatever project we&amp;#8217;re working on. It&amp;#8217;s here, amongst other things, that we&amp;#8217;ll specify which base box we want to use.&lt;/p&gt;

&lt;p&gt;Change directory to your project and run &lt;code&gt;vagrant init&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;cd ~/projects/myproject&lt;/kbd&gt;
&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;vagrant init&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Vagrant will have now created a VagrantFile at the root of that directory. Let&amp;#8217;s open that in the editor of your choice&amp;#8211;which for me is Sublime Text 2:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;subl VagrantFile&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;If you&amp;#8217;ve ever worked with Chef before, or indeed Ruby, you&amp;#8217;ll recognise that the VagrantFile is Ruby. You&amp;#8217;ll also notice that the folks at Vagrant have made newly created VagrantFiles wonderfully verbose, and if you read through the annotations, all the settings are explained.&lt;/p&gt;

&lt;p&gt;For our Vagrant VM we&amp;#8217;re going to want to use our base box, so update that line in the Vagrant file to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.vm.box = "ubuntu-11.10"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since we&amp;#8217;ve already installed this base box, we don&amp;#8217;t need the VagrantFile to be aware of a hosting URL, so leave that line commented.&lt;/p&gt;

&lt;p&gt;The next line defines whether you want to run your VM headless (i.e. without firing up the VirtualBox GUI). Generally the only time you&amp;#8217;ll want to uncomment this line is if you&amp;#8217;re debugging a problem with the VM. Most of the time you won&amp;#8217;t want to waste system resources on the VirtualBox GUI. With that in mind, leave it commented.&lt;/p&gt;

&lt;p&gt;Now we can choose networking options. For the purposes of this example I&amp;#8217;m assuming we&amp;#8217;re working on a local development machine and, as such, host-only networking will suit our purposes. If we were working on a separate dev box that may host multiple VMs, we&amp;#8217;d probably want to use bridged networking to expose them to the network. For now though, just uncomment the following line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.vm.network :hostonly, "33.33.33.10"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means the VM will be exposed to the host machine on the IP address 33.33.33.10, and will be able to access your network. However, machines other than your host machine &lt;em&gt;will not&lt;/em&gt; be able to see the VM.&lt;/p&gt;

&lt;p&gt;Since we&amp;#8217;ve uncommented this line, leave the bridged networking line commented.&lt;/p&gt;

&lt;p&gt;Now we have the opportunity to forward some ports from the host to the guest OS. This can be useful if you want to temporarily expose a host-only network VM to machines on your network, however, for the purposes of this tutorial, please leave this line commented too. Later on we&amp;#8217;re going to install a web server and connect to this VM as if it were any other server on our network, so port forwarding is not required here.&lt;/p&gt;

&lt;p&gt;Next we need to define some folders to share with the VM, and how to share them. It&amp;#8217;s a well recorded fact that when using VirtualBox on a unix-based system it struggles as the number of files within any shared folder increases. For this reason, if you&amp;#8217;re running Vagrant on a Mac, it&amp;#8217;s better to use NFS to mount your directories—Windows does not suffer the same issue so NFS is not required.&lt;/p&gt;

&lt;p&gt;To set up a directory to share on your Vagrant VM, simply declare it as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.vm.share_folder("v-root", "/vagrant", ".", :nfs =&amp;gt; true)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create a directory &lt;code&gt;/vagrant&lt;/code&gt; at the root of your VM. That folder will be shared with the directory on the host containing your Vagrantfile, implied by the &lt;code&gt;.&lt;/code&gt; directory reference. For a Windows host, just set &lt;code&gt;nfs: =&amp;gt; false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can choose how the Vagrant VM is provisioned. As I said earlier, I personally prefer to use Puppet, so uncomment the following lines and update the manifests path. I find &amp;#8220;puppet&amp;#8221; is more obvious than &amp;#8220;manifests&amp;#8221;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.vm.provision :puppet do |puppet|
  puppet.manifests_path = "puppet"
  puppet.manifest_file  = "base.pp"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will look for our base manifest, &amp;#8220;base.pp&amp;#8221;, in a directory called &amp;#8220;puppet&amp;#8221; at the same directory level as our VagrantFile. We&amp;#8217;ll set that up later.&lt;/p&gt;

&lt;p&gt;Finally, let&amp;#8217;s add a last line to our VagrantFile to tell it to set-up a VM with 512Mb of memory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.vm.customize ["modifyvm", :id, "--memory", "512"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll notice this particular command isn&amp;#8217;t annotated in the VagrantFile. For more information about customising the specific characteristics of the VM, take a look at the Vagrant docs.&lt;/p&gt;

&lt;p&gt;Once you&amp;#8217;ve completed these changes, your VagrantFile should look something like this (if you remove all the commented lines):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant::Config.run do |config|
    config.vm.box = "ubuntu-11.10"

    config.vm.network :hostonly, "33.33.33.10"

    config.vm.share_folder("v-root", "/vagrant", ".", :nfs =&amp;gt; true)

    config.vm.provision :puppet do |puppet|
        puppet.manifests_path = "puppet"
        puppet.manifest_file  = "base.pp"
    end

    config.vm.customize ["modifyvm", :id, "--memory", "512"]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our Vagrantfile will now create exactly the VM we require when we run the &lt;code&gt;vagrant up&lt;/code&gt; command. However, the VM itself only contains the software installed as part of the base box. Since this VM is serving our project, we probably want some more stuff on there like a web server or a particular version of a language. To set that up, we&amp;#8217;ll need to use a &lt;em&gt;provisioner&lt;/em&gt; which is where Puppet comes in. (If you want to use Chef, don&amp;#8217;t let me stop you. I just won&amp;#8217;t be covering Chef here.)&lt;/p&gt;

&lt;h3&gt;Provisioning with Puppet&lt;/h3&gt;

&lt;p&gt;Provisioning happens in Vagrant every time we run &lt;code&gt;vagrant up&lt;/code&gt; or &lt;code&gt;vagrant provision&lt;/code&gt;. This sets up the software on your VM according to a set of manifests (or &amp;#8220;recipes&amp;#8221; in Chef). Those manifests basically tell Puppet what it should script on the VM. This means you can update &lt;em&gt;anything&lt;/em&gt;, including copying across files, updating files already on the system, installing and uninstalling packages, changing permissions, stopping and starting services, and a whole host of other software changes.&lt;/p&gt;

&lt;p&gt;To do this, you&amp;#8217;ll need to learn Puppet&amp;#8217;s manifest language. This is a custom DSL that is quite easy to learn; although the Puppet documentation can be a little difficult to navigate. I&amp;#8217;d recommend looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://docs.puppetlabs.com/learning/"&gt;Learning Puppet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.puppetlabs.com/#reference-shelf"&gt;Puppet Docs Reference Shelf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.puppetlabs.com/#basic-features-and-use"&gt;Basic Features and Use&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.puppetlabs.com/puppet_core_types_cheatsheet.pdf"&gt;Core Types Cheat Sheet PDF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;To begin, let&amp;#8217;s set up a directory in our project folder to contain our manifests, and another folder within that to contain any files we may want to copy across to our guest OS with Puppet. From the directory on your host that contains your Vagrantfile do:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;mkdir -p ./puppet/files&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Now in the newly created &lt;code&gt;puppet&lt;/code&gt; folder, create a file entitled &lt;code&gt;base.pp&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;cd puppet &amp;&amp; touch base.pp&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Note that Puppet manifests have the &lt;code&gt;.pp&lt;/code&gt; extension. You should be able to find syntax rules for all good editors to deal with this extension and file type.&lt;/p&gt;

&lt;p&gt;Open up the newly created &lt;code&gt;base.pp&lt;/code&gt; file in your editor of choice. Puppet manifests have a number of constructs, chief of which is the concept of a &amp;#8220;resource&amp;#8221;. Resources can be packages, files, executed commands, users, groups and services. These resources can then be organised within classes. So let&amp;#8217;s start with a class for our dev box:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class devbox {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As an example, let&amp;#8217;s set-up nginx as a web server. To do that, the first thing we&amp;#8217;re going to need to do is install the package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package { "nginx":
    ensure =&amp;gt; latest
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That was quite simple, right? Puppet already knows to use &lt;code&gt;apt&lt;/code&gt; as the default package installer on Ubuntu, so this command checks the apt-cache to see if the latest version of the package is installed, and if it isn&amp;#8217;t installs it.&lt;/p&gt;

&lt;p&gt;Now we should make sure the nginx service is running:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;service { "nginx":
    ensure =&amp;gt; running,
    hasrestart =&amp;gt; true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Equally simple. Here we&amp;#8217;ve told Puppet to check the service nginx is running, and we&amp;#8217;ve also informed it that the service has a restart function which Puppet can make use of.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve stuck a bunch of &lt;a href="http://github.com/nefarioustim/puppet-manifests/"&gt;hacked together Puppet manifests into a repository on GitHub&lt;/a&gt;. Feel free to poke about in them; I&amp;#8217;ll be updating them as I do more stuff with Vagrant. For now, at least, take a look at the &lt;a href="https://github.com/nefarioustim/puppet-manifests/tree/master/files"&gt;files directory&lt;/a&gt; because we can repurpose some of my set-up for this example. Save the following from my repo to your &lt;code&gt;puppet/files&lt;/code&gt; directory which we created earlier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;files/nginx.conf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;files/vhost.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now we need to get these files from your host computer to the guest OS in the Vagrant VM. Once again, this is pretty simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;file { "/etc/nginx/nginx.conf":
    owner  =&amp;gt; root,
    group  =&amp;gt; root,
    mode   =&amp;gt; 644,
    source =&amp;gt; "puppet:////vagrant/puppet/files/nginx.conf"
}

file { "/etc/nginx/sites-available/vagrantsite":
    owner  =&amp;gt; root,
    group  =&amp;gt; root,
    mode   =&amp;gt; 644,
    source =&amp;gt; "puppet:////vagrant/puppet/files/vhost.conf"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the source exists within our &lt;code&gt;/vagrant&lt;/code&gt; directory, which we&amp;#8217;ve already set-up as a NFS shared directory. This means we&amp;#8217;re effectively copying the file from there to the &lt;code&gt;/etc/nginx/&lt;/code&gt; directory on the guest. Also, if the destination directory does not already exist, Puppet will create it. Notice how I&amp;#8217;m also setting the owner, group, and mode of the file during the copy.&lt;/p&gt;

&lt;p&gt;So far we&amp;#8217;re getting along fine, but wouldn&amp;#8217;t it be nice if we could let Puppet know we&amp;#8217;d like to handle these stages in some semblance of an order? We can do that in the resources using the &lt;code&gt;require&lt;/code&gt; parameter:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;file { "/etc/nginx/nginx.conf":
    owner  =&amp;gt; root,
    group  =&amp;gt; root,
    mode   =&amp;gt; 644,
    source =&amp;gt; "puppet:////vagrant/puppet/files/nginx.conf",
    require =&amp;gt; Package["nginx"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the reference to the resource we require is capitalised? This is a subtle difference between declaring and reference a resource.&lt;/p&gt;

&lt;p&gt;What would also be nice is if we could tell the nginx service that, by changing the configuration files, we&amp;#8217;d like it to restart. To do that we use the &lt;code&gt;notify&lt;/code&gt; param:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;file { "/etc/nginx/nginx.conf":
    owner  =&amp;gt; root,
    group  =&amp;gt; root,
    mode   =&amp;gt; 644,
    source =&amp;gt; "puppet:////vagrant/puppet/files/nginx.conf",
    require =&amp;gt; Package["nginx"],
    notify =&amp;gt; Service["nginx"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We just have a couple more things to do now. Firstly, let&amp;#8217;s create a symbolic link to &lt;code&gt;sites-available&lt;/code&gt; from within &lt;code&gt;sites-enabled&lt;/code&gt; so that our newly copied across vhost is picked up by the nginx configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;file { "/etc/nginx/sites-enabled/vagrantsite":
    ensure =&amp;gt; symlink,
    target =&amp;gt; "/etc/nginx/sites-available/vagrantsite",
    require =&amp;gt; Package["nginx"],
    notify =&amp;gt; Service["nginx"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice I haven&amp;#8217;t required the original file for this. That&amp;#8217;s because it&amp;#8217;s not a requirement for creating the symlink in the first place.&lt;/p&gt;

&lt;p&gt;Secondly, let&amp;#8217;s remove the default vhost because we don&amp;#8217;t need it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;file { "/etc/nginx/sites-enabled/default":
    ensure =&amp;gt; absent,
    require =&amp;gt; Package["nginx"],
    notify =&amp;gt; Service["nginx"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With all that in place, and adding a full set of &lt;code&gt;require&lt;/code&gt; and &lt;code&gt;notify&lt;/code&gt; parameters, our final class should look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class devbox {
    package { "nginx":
        ensure =&amp;gt; latest,
    }

    file { "/etc/nginx/nginx.conf":
        owner  =&amp;gt; root,
        group  =&amp;gt; root,
        mode   =&amp;gt; 644,
        source =&amp;gt; "puppet:////vagrant/puppet/files/nginx.conf",
        require =&amp;gt; Package["nginx"],
        notify =&amp;gt; Service["nginx"]
    }

    file { "/etc/nginx/sites-available/vagrantsite":
        owner  =&amp;gt; root,
        group  =&amp;gt; root,
        mode   =&amp;gt; 644,
        source =&amp;gt; "puppet:////vagrant/puppet/files/vhost.conf",
        require =&amp;gt; Package["nginx"],
        notify =&amp;gt; Service["nginx"]
    }

    file { "/etc/nginx/sites-enabled/vagrantsite":
        ensure =&amp;gt; symlink,
        target =&amp;gt; "/etc/nginx/sites-available/vagrantsite",
        require =&amp;gt; Package["nginx"],
        notify =&amp;gt; Service["nginx"]
    }

    file { "/etc/nginx/sites-enabled/default":
        ensure =&amp;gt; absent,
        require =&amp;gt; Package["nginx"],
        notify =&amp;gt; Service["nginx"]
    }

    service { "nginx":
        ensure =&amp;gt; running,
        hasrestart =&amp;gt; true,
        require =&amp;gt; Package["nginx"]
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next time we fire up our Vagrant VM, nginx will be installed, set-up, and running, and attempting to serve a website from the &lt;code&gt;/vagrant/static&lt;/code&gt; directory on your guest OS. This will be the &lt;code&gt;static&lt;/code&gt; directory within the same directory as your Vagrantfile on the host.&lt;/p&gt;

&lt;p&gt;On the host, let&amp;#8217;s create that directory and stick a very basic file in it:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;mkdir static &amp;&amp; cd $_&lt;/kbd&gt;
&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;echo 'Hello world from my Vagrant VM!'' &gt; index.html&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;Not the most well-formed example, but it&amp;#8217;ll do. Now let&amp;#8217;s fire up the Vagrant VM:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$&lt;/samp&gt; &lt;kbd&gt;vagrant up&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;This should copy across the base box we installed, set-up all the things we specified in the Vagrantfile, and begin provisioning from our manifest. You should see messaged that Puppet has successfully installed nginx and the relevant files, and that the service is running. Now point your browser to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;33.33.33.10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ta da! You have successfully set-up a vagrant development environment with specific software requirements for a specific project. Congratulations! Now go away and hack it.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;So this has been an epic 5000 word look at why Vagrant is now my development environment tool of choice. I hope you can see that it makes working with multiple projects—each with their own requirements for an environment—as simple as possible. With a good understanding of the features of Vagrant, and also of the provisioning tool of your choice, you really do have the power to fire up and destroy environments on a whim.&lt;/p&gt;

&lt;p&gt;Apologies for the sheer size of this article but I wanted to make sure I covered as much as possible to help newbies get up and running quickly. It doesn&amp;#8217;t take much effort, and it really empowers developers to be able to spin up new environments quickly for hacking around in.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/7DVQbbVRkVY" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/vagrant-virtualised-dev-environments.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Spring reboot]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/EaVWqz_4fss/spring-reboot.html" />
        <updated>2012-03-04T17:46:32+00:00</updated>
        <id>http://nefariousdesigns.co.uk/spring-reboot</id>
        <content type="html">&lt;p&gt;If you&amp;#8217;re looking at the site and not the feed you&amp;#8217;ve probably noticed some significant changes. After 5 long years of a heavily doctored Wordpress implementation with custom templates I&amp;#8217;ve finally gotten around to rebooting the site, bringing it more in line with my requirements.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s more of a realignment rather than a redesign. I&amp;#8217;ve trimmed back the cruft, and improved what I believe is important—and I&amp;#8217;ve also made some more drastic changes which can be reversed should I want to.&lt;/p&gt;

&lt;p&gt;So, without further ado, let me just take some time to explain my reasons…&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Technology&lt;/h2&gt;

&lt;p&gt;The site is now statically generated by &lt;a href="http://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; in Ruby instead of dynamically on request via &lt;a href="http://wordpress.org/"&gt;Wordpress&lt;/a&gt; in PHP. This has allowed me to rebuild my server and ditch a bunch of technologies I no longer work with. Key amongst those are MySQL and PHP, but I also no longer need Apache. It&amp;#8217;s also made the site faster and less in need of a caching solution.&lt;/p&gt;

&lt;p&gt;Statically generating the site has also meant I&amp;#8217;ve ditched some more dynamic functionality like the contact form and—more importantly—comments. Considering the ratio of signal to noise in the comments posted to my site, and the sheer weight of spam, I&amp;#8217;m reasonably confident I won&amp;#8217;t miss them. What&amp;#8217;s more, with the constant discussion on Twitter and the fact that I can easily bring comments back later with Disqus, I have the option for resurrection should I desire it.&lt;/p&gt;

&lt;p&gt;Jekyll has some pretty cool extensions and plug-ins, and if you take a look at some of my more code filled posts you&amp;#8217;ll notice the code samples are now styled up with the help of &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;, a python library that marks-up the code for styling in CSS. It&amp;#8217;s the same system used by &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve used an HTML5 doctype so I can add modern features as they become more widely supported cross-browser. I&amp;#8217;ve also used a fair amount of CSS3 so I hope you&amp;#8217;re browsing using an up to date browser rather than something as flawed as Internet Explorer.&lt;/p&gt;

&lt;p&gt;The styling now requires nothing but CSS and web fonts. I have significantly reduced the number of images required to make the site look pretty. This means the number of HTTP requests made by the page is significantly smaller and overall the site performs better in YSlow and PageSpeed. I have to say, this wasn&amp;#8217;t a primary concern but it&amp;#8217;s nice to get it without trying too hard.&lt;/p&gt;

&lt;p&gt;My new site is now much easier to deploy and update and I&amp;#8217;ve made use of all the good stuff I&amp;#8217;ve learnt about server administration over the past few years. You could say it&amp;#8217;s all much more DevOps-like in approach and makes use of stuff like Puppet, Rake, and SASS.&lt;/p&gt;

&lt;h2&gt;Design&lt;/h2&gt;

&lt;p&gt;I wanted to make sure I was designing for my content and not trying to fill space with extra information that nobody really wanted. Hence, the right hand menu has been replaced by much wider blog posts. Hopefully that&amp;#8217;ll do away with a few of the nasty horizontal scrollbars that crept into some of my code examples whilst also giving the main content of the site room to breathe.&lt;/p&gt;

&lt;p&gt;The typography of the site should now be significantly more predictable cross-browser. I&amp;#8217;ve used &lt;code&gt;@font-face&lt;/code&gt; before but it&amp;#8217;s nice to use it for one&amp;#8217;s own devices. Hopefully this new iteration is much easier to read than the last, and makes better use of the space available.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve improved everything for SEO; flattening the site architecture, making sure to include descriptions, moving navigation below the main content, and defining canonical URIs. I&amp;#8217;ve also got plans for the category pages but need some more time to plan out the work and felt it wasn&amp;#8217;t really a blocker for launch.&lt;/p&gt;

&lt;h2&gt;The future&lt;/h2&gt;

&lt;p&gt;So apart from the SEO stuff I&amp;#8217;d still like to work in, I&amp;#8217;ve still got some work to do on the responsiveness of the site. Currently it&amp;#8217;s not looking great for screens less than 480px in width and I need to rethink some positional stuff to make it work.&lt;/p&gt;

&lt;p&gt;For the moment I&amp;#8217;m reasonably happy with the site, and with some more work on it over the coming months I&amp;#8217;m sure I can turn it into something I&amp;#8217;m much more comfortable with. The real target was to make the core content more readable and I think I&amp;#8217;ve achieved that. I only hope you, as a reader, agree.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/EaVWqz_4fss" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/spring-reboot.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[User-controlled content density]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/YsoTXEPwoZ4/user-controlled-content-density.html" />
        <updated>2012-01-06T22:37:07+00:00</updated>
        <id>http://nefariousdesigns.co.uk/user-controlled-content-density</id>
        <content type="html">&lt;p&gt;Back in October of last year &lt;a href="http://googledocs.blogspot.com/2011/10/experience-new-look-of-docs-and-sites.html"&gt;Google Apps underwent a fairly extensive redesign&lt;/a&gt;. The overall intent of this realignment was to improve the user interface design, which has traditionally seemed to be a stumbling point for Google.&lt;/p&gt;




&lt;p&gt;Personally I think the new designs are excellent and really appreciate the fact that they address my need to access my Google Apps from a variety of devices. I also like the fact that they allow me my own preference for the visual density of content within the page.&lt;/p&gt;




&lt;p&gt;In fact this is such a killer feature that I reverse engineered it to better understand it. I’ll be looking to use this knowledge in some of my future work. Whilst I wouldn’t really refer to this deconstruction as such, plagiarism is the sincerest form of flattery. Unfortunately, due to extensive work commitments, I’ve only just gotten around to writing up my work…&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="responsive"&gt;Responsive&lt;/h2&gt;




&lt;p&gt;It’s my opinion that this technique relates quite closely to the responsive design ethos. The visual content density should respond to both the user’s available screen real-estate, their chosen font-size, and their own preference—which should always override any other external actors.&lt;/p&gt;




&lt;p&gt;The majority of responsive design discussions and tutorials seem to talk extensively around how a design responds only to the client width. True responsiveness, however, equates to so much more than this.&lt;/p&gt;




&lt;h2 id="visual_density"&gt;Visual density&lt;/h2&gt;




&lt;p&gt;In this article I am referring to &lt;em&gt;visual&lt;/em&gt; content density. This refers to the actual physical space around the content and is not to be confused with keyword density, which is concerned with the proliferation of words and phrases &lt;em&gt;within&lt;/em&gt; said content. Balanced visual content density is an important factor towards improved typography, improved legibility, and an improved interface overall. Most designers will wax lyrical on the benefits of plenty of whitespace and how giving content room to breathe can improve the usability of the interface.&lt;/p&gt;




&lt;p&gt;The visual density of content within your web-based documents can easily be controlled with an extensive set of CSS properties. However, there are only a few that give entirely predictable results across all browsers:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;code&gt;font-size&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;line-height&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;margin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;width&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;height&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Importantly, these properties control both content size and the amount of whitespace that surrounds it. Together these two factors can sway the balance between spacious legibility and the efficient use of limited screen real-estate.&lt;/p&gt;




&lt;h2 id="a_demonstration"&gt;A demonstration&lt;/h2&gt;




&lt;p&gt;Here’s a quick and dirty prototype that I’ve knocked up to demonstrate visual density variance at work. You can vary the density via the buttons at the top, or by resizing your browser window (which will override the former):&lt;/p&gt;




&lt;p&gt;&lt;a href="http://timhuegdon.com/test-cases/density/"&gt;http://timhuegdon.com/test-cases/density/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The source code for this example is available here:&lt;/p&gt;




&lt;p&gt;&lt;a href="http://github.com/nefarioustim/density-demo/"&gt;http://github.com/nefarioustim/density-demo/&lt;/a&gt;&lt;/p&gt;




&lt;h2 id="how_it_works"&gt;How it works&lt;/h2&gt;




&lt;p&gt;In my demo I am applying a class to the root element of the document that controls the level of content density selected by the user. I also repeat those styles within media queries for different client widths to allow denser content on smaller screens—try resizing the browser window to watch it respond.&lt;/p&gt;




&lt;p&gt;To make this more maintainable in the future I’d probably invoke those styles through some form of SASS or LESS mix-in to cut down on the obvious duplication of styles. However, be aware that the use of CSS preprocessors like SASS and LESS can complicate things when attempting to get browsers that do not support media queries to detect the styles using a JavaScript polyfill like Respond.js.&lt;/p&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;So there you have it; a simple technique that has a pretty significant impact to the readability of your content. Hey, and the demo is kinda fun to play with too.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/YsoTXEPwoZ4" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/user-controlled-content-density.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[On HTML element identifiers]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/EWMUlR2fxLQ/on-html-element-identifiers.html" />
        <updated>2011-09-27T10:11:43+01:00</updated>
        <id>http://nefariousdesigns.co.uk/on-html-element-identifiers</id>
        <content type="html">&lt;p&gt;Back in April 2007, I wrote a short &lt;a href="http://www.flickr.com/photos/nefarioustim/460040199/"&gt;article on HTML element identifiers for the .net magazine &amp;#8220;Expert Advice&amp;#8221; section&lt;/a&gt;. I have never republished it online—despite it being 400 words, nicely to the point and suitably succinct—and have long been meaning to reexamine the subject in more detail.&lt;/p&gt;




&lt;p&gt;By a total coincidence a discussion in a recent front-end code review and a discussion over the past couple of days on Twitter both relate to the use of HTML element identifiers. The former, a discussion on semantic value and remembering that HTML should not prognosticate styling; the latter, a discussion on the validity of using IDs to target CSS. With both of these considerations I’m going to study the fundamentals of writing good element identifiers within this article.&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="whats_an_element_identifier"&gt;What’s an element identifier?&lt;/h2&gt;




&lt;p&gt;HTML has two element identifiers; the &lt;code&gt;id&lt;/code&gt; attribute and the &lt;code&gt;class&lt;/code&gt; attribute. These attributes can be applied to most of the elements within a modern HTML document.&lt;/p&gt;




&lt;h2 id="what_do_they_do"&gt;What do they do?&lt;/h2&gt;




&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; attribute assigns a name to an element. This name must be unique within the document and each element can have only one.&lt;/p&gt;




&lt;p&gt;The &lt;code&gt;class&lt;/code&gt; attribute assigns a class or set of classes to an element. Any number of elements may be assigned the same class name or names and each element can have many.&lt;/p&gt;




&lt;p&gt;In relationship terms this means IDs and elements are a one-to-one relationship, and classes and elements are a many-to-many relationship. IDs are very much an absolute index system and classes are more of a tag-style classification aide.&lt;/p&gt;




&lt;p&gt;Make note of those words: &amp;#8220;name&amp;#8221; and &amp;#8220;classification”. I’ll come back to that in a bit.&lt;/p&gt;




&lt;h2 id="mislaid_mastery"&gt;Mislaid mastery&lt;/h2&gt;




&lt;p&gt;Put in those simple terms it’s all pretty straightforward, and I think that most front-end developers have a good general grasp of their usage. However, it’s the detail that introduces the issues, and if you take time to step back it’s easy to see why:&lt;/p&gt;




&lt;p&gt;Element identifiers are the perfect answer for cross-linking other front-end technologies to your HTML. They are the hooks on which to hang your styling and behaviours, and because of this they take on that personality in your mind. This is where so many developers go wrong.&lt;/p&gt;




&lt;p&gt;When front-end developers are first introduced to the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; attributes, it’s often so the identifiers can be targeted in CSS selectors as a means of styling the developers’ documents. They will also inevitably start using them to hook progressive enhancement into their documents via DOM scripting. These are the two most common uses of element identifiers:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;site-navigation&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    …
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nf"&gt;#site-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;border-bottom&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="k"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.navigation&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.navigation&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.navigation&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;outline&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="k"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;site-navigation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invokeOarsumNavWidget&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Use some modern browser native DOM + JS win&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;navCollection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByClassName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;navCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something to every element&lt;/span&gt;
    &lt;span class="c1"&gt;// with a class of &amp;quot;navigation&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Also, if you’ve ever wanted to make use of the &lt;a href="http://isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs"&gt;URI fragment identifier in a non-destructive way&lt;/a&gt;, you may have used the ID element identifier instead of the old-skool named anchor (&lt;code&gt;&lt;a name="something"&gt;&lt;/a&gt;&lt;/code&gt;) approach:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;In each of the above examples, the element identifiers were added specifically to be used by some other language; for styling it is CSS, for dynamic behaviour it is JavaScript, and for linking it is &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier"&gt;the URI RFC 3305&lt;/a&gt;. However, that association also occurs psychologically in our minds as developers and we often have trouble seeing past it.&lt;/p&gt;




&lt;h2 id="names_and_classifications"&gt;Names and classifications&lt;/h2&gt;




&lt;p&gt;Back to those &amp;#8220;name&amp;#8221; and &amp;#8220;classification” descriptions:&lt;/p&gt;




&lt;p&gt;It seems we have carelessly forgotten the fact that element identifiers are a feature of HTML and not the other languages that use them as targets. We should be using them as they were originally intended; to name and classify the content within our mark-up.&lt;/p&gt;




&lt;p&gt;We already use HTML elements to describe the content which they contain. This is the very heart of semantic HTML and should result in content like heading text being wrapped in &lt;code&gt;h1&lt;/code&gt;-&lt;code&gt;h6&lt;/code&gt; tags; lists in &lt;code&gt;ul&lt;/code&gt;, &lt;code&gt;ol&lt;/code&gt;, or &lt;code&gt;dl&lt;/code&gt; tags; and tabular data in &lt;code&gt;table&lt;/code&gt; elements. Since IDs and classes are attributes of these elements, we should use them to improve the semantic value of their hosts and provide further descriptiveness or context.&lt;/p&gt;




&lt;p&gt;If we return to our previous list example, the following mark-up is reasonably semantic:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/archive/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Archive&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;However, we can improve it further by giving it some context with an ID:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;site-navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/archive/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Archive&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Now it’s more obvious what this list of links actually is without seeing it styled up and rendered in the browser.&lt;/p&gt;




&lt;p&gt;We could provide even more information with a single class:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;site-navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;current-page&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/archive/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Archive&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;I’m sure most web developers have done something similar in the past, but it’s a very good example of applying context with a class the &lt;em&gt;right&lt;/em&gt; way. The HTML now gives us a very good description of the content it contains. In fact, you now only need glance at this markup to understand its function.&lt;/p&gt;




&lt;p&gt;Let’s take it a little further. Imagine we have several types of navigation in the page; we can better describe these elements by &lt;em&gt;classifying&lt;/em&gt; them as navigation:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;site-navigation&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;current-page&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/archive/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Archive&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;breadcrumb&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/index.html&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="ni"&gt;&amp;amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="ni"&gt;&amp;amp;gt;&lt;/span&gt; My Blog Post
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;page-footer&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;© 2011 Oarsum Corp, all rights reserved.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;terms.html&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Terms and conditions&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;privacy.html&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Privacy policy&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Simple, right? We’re using the element identifiers to improve the semantics of the markup and gaining improved readability as a side-effect. What’s more the added context can be targeted by whatever technology you so desire.&lt;/p&gt;




&lt;h2 id="anti_patterns"&gt;Anti-patterns&lt;/h2&gt;




&lt;p&gt;I’m pretty confident that most web developers will end up with markup similar to this without necessarily understanding my point. To that end, let’s take a look at some common anti-patterns (or misuses) that may go some way towards forwarding that understanding:.&lt;/p&gt;




&lt;h3 id="the_clearfix_class"&gt;The &amp;#8220;clearfix&amp;#8221; class&lt;/h3&gt;




&lt;p&gt;Way back in 2004 [ya rly!], &lt;a href="http://www.positioniseverything.net/easyclearing.html"&gt;Tony Aslett and Position is Everything published a clever method for containing floats&lt;/a&gt; that involved using the pseudo &lt;code&gt;:after&lt;/code&gt; selector to insert some content and use that as an anchor for &lt;code&gt;clear: both&lt;/code&gt;. It was a clever technique and was quickly adopted by the community, often incorrectly bound to a class entitled &amp;#8220;clearfix&amp;#8221;:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.clearfix&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;visibility&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* IE targeted property */&lt;/span&gt;
&lt;span class="nc"&gt;.ie&lt;/span&gt; &lt;span class="nc"&gt;.clearfix&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Quite apart from the somewhat erroneous name (it should really be &amp;#8220;contain-float&amp;#8221;) this is absolutely the wrong place to be addressing this sort of styling issue. A styling-specific meta-class such as this is no different to writing a class entitled &amp;#8220;red-text&amp;#8221; or &amp;#8220;big-blue-heading&amp;#8221;. In my opinion, the small amount of repetition it saves you in the CSS is not worth the non-semantic clutter in your HTML.&lt;/p&gt;




&lt;p&gt;There are several ways to contain floats in CSS and the method you should use absolutely depends on the context. What’s more, some of those methods are a &lt;em&gt;single CSS property declaration&lt;/em&gt;. For this reason, declaring a class of &amp;#8220;clearfix&amp;#8221; and implementing a single float clearing solution within it is actually potentially detrimental to the overall efficiency of your CSS.&lt;/p&gt;




&lt;p&gt;It’s worth noting also that providing a meta-class tool like this results in a disassociation between the problem and the &amp;#8220;fix&amp;#8221;. You’re likely to experience maintenance issues when you change any float behaviours and the containing mechanism is abstracted from the target’s styles. In addition to this you’re likely to find developers over using the solution to address problems they’ve introduced themselves.&lt;/p&gt;




&lt;h3 id="the_hide_offscreen_class"&gt;The &amp;#8220;hide-offscreen&amp;#8221; class&lt;/h3&gt;




&lt;p&gt;When developers are aware of accessibility issues, and are attempting to provide textual description for otherwise potentially inaccessible content, you will often find a class that looks something like this:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nc"&gt;.hide-offscreen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;text-indent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-999em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* or */&lt;/span&gt;

&lt;span class="nc"&gt;.hide-offscreen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;position&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-999em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This moves text off the screen, thus making it invisible for those not using a screenreader. This is preferable to &lt;code&gt;display: none&lt;/code&gt; (which you might use to hide content from &lt;strong&gt;all&lt;/strong&gt; users) because the content is only hidden within the browser viewport, but not removed from the complete rendering of the DOM.&lt;/p&gt;




&lt;p&gt;However, what we’ve done here is define our CSS &lt;em&gt;first&lt;/em&gt; and then apply that classification to our content. We’re supposed to be doing it the other way around. This class is unhelpful in describing the content that it wraps because it describes the behaviour the CSS should apply. This results in it providing little explanation of the developer’s intent, resulting in HTML like:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hide-offscreen&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Not a good class at all. This is an improvement:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;accessibility navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;I&amp;#8217;ve added the accessibility class here to signal intent: it&amp;#8217;s navigation for improving accessibility. I could have been more specific here, but overall I predict a high likelihood I&amp;#8217;ll want to signal a similar intent on other features within my document.&lt;/p&gt;




&lt;p&gt;However, the double class will cause problems if you need to target both classes at once (e.g. &lt;code&gt;.accessibility.navigation {}&lt;/code&gt;) in IE6. That browser will only target the final class in the selector. To fix this, you could combine the classes to create a new one:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;accessibility-navigation accessibility navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Or a less ugly solution would be to include an ID on the navigation:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;header-skip-links&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;accessibility navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Or to use a wrapping element and target with the descendant selector:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;accessibility&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#navigation&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Skip to navigation&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Here we’ve named the content and classified it well. It would be difficult to argue that we haven’t provided any targets for styling or behaviours now too. Unfortunately we’ve had to jump through hoops for IE6 and have broken our rule of changing the HTML for the CSS, but I just wanted to illustrate that there are more options available given a little thought.&lt;/p&gt;




&lt;h3 id="avoiding_repetition"&gt;Avoiding repetition&lt;/h3&gt;




&lt;p&gt;It’s entirely fair to argue that both the anti-patterns above avoid repetition within the CSS itself. However, this shouldn’t necessarily be the &lt;em&gt;only&lt;/em&gt; reason to adopt one of these types of solution. There are other options available to us to abstract away this kind of anti-&lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;DRY&lt;/a&gt; maintenance nightmare:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lesscss.org/#-mixins"&gt;LESS Mix-ins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins"&gt;SASS Mix-ins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Place the CSS higher up the cascade&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Indeed most CSS preprocessors will allow you similar functionality as it is clearly a &amp;#8220;missing feature&amp;#8221; of CSS as a whole. The alternative, of course, is to make your &amp;#8220;fix&amp;#8221; a part of the relevant cascade, so that all selectors beneath inherit that behaviour.&lt;/p&gt;




&lt;h2 id="a_nice_example"&gt;A nice example&lt;/h2&gt;




&lt;p&gt;A really nice example of classification is this &lt;a href="http://mikewest.org/2010/02/an-accessible-pagination-pattern"&gt;simple design pattern for pagination&lt;/a&gt;:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;paginglabel&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Pagination&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;paginglabel&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;%TYPE% Page&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;prev&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;prev&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;: %TYPE% Page&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;2&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;You&amp;#39;re currently reading %TYPE% page &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;3&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;next&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;next&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;: %TYPE% Page&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;4&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;audible&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;%TYPE% Page &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;5&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Here we see the &amp;#8220;audible&amp;#8221; class describing content that should only be exposed to non-visual devices, such as screen readers and content scrapers (like search engine spiders). This is a good classification of a &lt;em&gt;subset&lt;/em&gt; of the content.&lt;/p&gt;




&lt;p&gt;It’s also worth noting the good use of &lt;a href="http://www.w3.org/WAI/intro/aria"&gt;WAI-ARIA&lt;/a&gt; roles and the &lt;code&gt;rel&lt;/code&gt; attributes on the next and previous links. These are two other ways you can improve the semantics of your HTML and abstract away some of the classification to a more suitable annotation system.&lt;/p&gt;




&lt;h2 id="clean_code"&gt;Clean Code&lt;/h2&gt;




&lt;p&gt;Markup languages can often add to the obfuscation of code simply by their structure. If we use the element identifiers as they are intended we should end up reducing the overhead to &lt;a href="http://en.wikipedia.org/wiki/Grok"&gt;grok&lt;/a&gt; relatively clean code.&lt;/p&gt;




&lt;p&gt;Clean code is, amongst other things:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Readable&lt;/li&gt;
&lt;li&gt;Understandable&lt;/li&gt;
&lt;li&gt;Predictable&lt;/li&gt;
&lt;li&gt;Maintainable&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Use of element identifiers as semantic descriptors improves each one of these points. This is especially obvious when dealing with somebody else’s code, and in a team environment I personally feel it is imperative to include this in coding standards and best practices.&lt;/p&gt;




&lt;p&gt;Good use of names and classification is just as effective as good commenting. When the code is effectively self documenting through its element identifier annotation, the need for commenting is significantly reduced.&lt;/p&gt;




&lt;h2 id="on_css_best_practice_proposals"&gt;On CSS best practice proposals&lt;/h2&gt;




&lt;p&gt;Now that I’ve covered the &amp;#8220;hows&amp;#8221; and &amp;#8220;whys&amp;#8221;, I’d like to highlight why I think certain recommendations for CSS best practice directly contravene the correct use of element identifiers:&lt;/p&gt;




&lt;p&gt;There has been some discussion within the front-end community regarding the use of IDs when targeting CSS. The ID attribute has particularly strong specificity in CSS, due to its uniqueness. When used incorrectly, it can cause maintenance problems and specificity bugs. However, the idea that targeting the ID property with CSS should be considered harmful—as seen in CSSLint, for example—is extreme to say the least.&lt;/p&gt;




&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; reasonably simple to clobber other rules on an element by incorporating an ID in the selector, but this should really be an &lt;em&gt;expected&lt;/em&gt; outcome. The use of an ID in a selector should denote the intent that the rule targets only a single occurrence of something within the page. If that is not what the developer intended, then they’ve wildly misunderstood the need for that selector. Certainly it makes sense that targeting an ID should be considered harmful when the developer actually meant to target something less specific, but then that’s just using CSS properly, isn’t it?&lt;/p&gt;




&lt;p&gt;The argument that it is less valid to target IDs when working in a truly modular environment is even worse. A truly modular front-end environment will always require instance targeting alongside classification targeting. Sure, it’s likely to be the minority of situations, but there will always be cases in your system where it makes much more sense to target an ID than a class, and since they’re already in place on your HTML by this point [they are, right? We’ve already talked about this. If they’re not, go back and read it again.] you don’t have to worry about your CSS enforcing your HTML.&lt;/p&gt;




&lt;p&gt;The developers that make these sorts of recommendations must be aware that they, as leaders in their field, have a responsibility not to mis-sell their solutions. Problems born of misuse do not emphasise an inherent flaw with the technology but perhaps an inherent flaw with the expertise of the user. As an exercise in correlation, it’s worth noting that Chefs do not veto the use of sharp knives because someone once cut their fingertip off with one.&lt;/p&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;HTML, CSS, and JavaScript are separate technologies. They are quite tightly related in the world of client-side development, but they should always remain decoupled. The element identifier is an artefact of HTML and should therefore not attempt to predict the hooks required for other technologies; it should simply be a property of effective semantic markup.&lt;/p&gt;




&lt;p&gt;Further to this, avoiding the use of an element identifier, simply because it is so often misused by otherwise able front-end developers, is—at the risk of being blunt—ridiculous. Be proud of your HTML, spend as much time perfecting it as you would on any other language, and, most of all, don’t pollute it with the litter produced by a solution, in a related language, that lacks finesse.&lt;/p&gt;




&lt;h3 id="final_note"&gt;Final note&lt;/h3&gt;




&lt;p&gt;I realise, however, that—despite my banging on about it—there are some developers you just can’t reach. As Jared Spool so eloquently puts it in his blog post, &amp;#8221;&lt;a href="http://www.uie.com/brainsparks/2011/07/08/beans-and-noses/"&gt;Beans and noses&lt;/a&gt;&amp;#8221;:&lt;/p&gt;




&lt;blockquote&gt;
  &lt;p&gt;No matter how much you try, you can’t stop people from sticking beans up their nose.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/EWMUlR2fxLQ" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/on-html-element-identifiers.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Sniff my browser: The Modernizr inadequacy]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/-YEOP2fuvVw/sniff-my-browser-the-modernizr-inadequacy.html" />
        <updated>2011-05-17T13:03:47+01:00</updated>
        <id>http://nefariousdesigns.co.uk/sniff-my-browser-the-modernizr-inadequacy</id>
        <content type="html">&lt;p&gt;I’m currently involved in a project to write a fairly extensive set of best practices for front-end development. Alongside myself, this project includes input from a fair cross-section of my peers in the front-end development community. These best practices will be implemented alongside a coding standard as standards for development within the organisation I work for, and hopefully many other organisations when they are published.&lt;/p&gt;




&lt;p&gt;Of all the standards that a front-end team might want to implement, those that concern the identification and graceful degradation of cross-browser feature sets can be the hardest to define.&lt;/p&gt;




&lt;p&gt;With that in mind, I’ve been poking around the front-end community looking for possible solutions. By far the most common approach—and one that gains an astounding level of attention in the community—is to implement &lt;a href="http://www.modernizr.com/"&gt;Modernizr&lt;/a&gt;, a JavaScript feature sniffer created by &lt;a href="http://farukat.es/"&gt;Faruk Ateş&lt;/a&gt;, &lt;a href="http://paulirish.com/"&gt;Paul Irish&lt;/a&gt; and &lt;a href="http://alexsexton.com/"&gt;Alex Sexton&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Unfortunately, despite my respect for the developers involved, I just can’t advocate Modernizr as a solution. Let me explain why; but first, let’s revisit some concepts that are going to be quite relevant…&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="the_web_standards_trifle"&gt;The web standards trifle&lt;/h2&gt;




&lt;p&gt;The separation of structure, presentation, and dynamic behaviour is imperative to web standards. To that end, Andy “Malarkey” Clarke wrote a fantastic post detailing a method he liked to use to explain this fact to clients. He entitled it “&lt;a href="http://www.stuffandnonsense.co.uk/archives/web_standards_trifle.html"&gt;the web standards trifle&lt;/a&gt;”.&lt;/p&gt;




&lt;p&gt;In Andy’s metaphor, the separation of concerns can be imagined as follows:&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sponge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This layer is your content, marked-up with well structured and valid semantic HTML. This HTML provides more information about each piece of content and allows any device reading the code to output as appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fruity jelly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is your presentational layer. This separates all your presentational code into CSS, potentially allowing a user to override it with their own, or for you to serve something different based on context, e.g. a print or mobile stylesheet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the layer that accommodates any on-page behaviours. In the world of web standards we use this layer to progressively enhance our HTML and CSS layers with more interactive magic. I’ll come back to this later.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;The true virtue of this divide is that the presentational (jelly) and behavioural (custard) layers can potentially be removed or overridden without affecting each other, or the content and markup beneath. This is hugely important if we want our websites to maintain client agnosticism and improve accessibility.&lt;/p&gt;




&lt;h2 id="progressive_enhancement"&gt;Progressive enhancement&lt;/h2&gt;




&lt;p&gt;Following the publication of this article there have been several suggestions that I explain &lt;a href="http://nefariousdesigns.co.uk/archive/2010/10/object-oriented-javascript-follow-up-part-1-method/#graceful_degradation"&gt;the difference between &lt;em&gt;graceful degradation&lt;/em&gt; and &lt;em&gt;progressive enhancement&lt;/em&gt;&lt;/a&gt;. Suffice to say, this is something I have covered previously in another article.

&lt;h2 id="browser_vs_feature_sniffing"&gt;Browser vs. Feature Sniffing&lt;/h2&gt;

&lt;p&gt;Browser “sniffing” is the act of attempting to discern a user’s browser by some means. This “awareness” can then be used in conditional code to control output or interaction for a specific browser. This technique was used a great deal in days of yore, when browsers had very different rendering engines and didn’t all conform to web standards. However, it was only ever really required in JavaScript.&lt;/p&gt;

&lt;p&gt;The old school way:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// IE4&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// NN4&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// other&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;h3 id="not_a_good_solution"&gt;Not a good solution&lt;/h3&gt;

&lt;p&gt;There are problems with the method used above; for one thing, it is not the most direct method of identifying a browser. However, putting that aside for the moment, there are issues even with the &lt;em&gt;theory&lt;/em&gt; of browser sniffing:&lt;/p&gt;

&lt;p&gt;It’s quite obvious that browser sniffing does not scale. As new browsers are released, the sniffing code will need updating.&lt;/p&gt;

&lt;p&gt;To make matters worse, many manufacturers developed their browsers to identify themselves incorrectly to get around &lt;em&gt;legacy&lt;/em&gt; browser sniffing code. This ultimately meant that sometimes browsers were misidentified.&lt;/p&gt;

&lt;p&gt;Ultimately browser sniffing is not a good solution. If you adopt it, you will usually end up maintaining separate streams of development whenever you need to add or update features. There are ways to mitigate that pain, but what if there was a better solution?&lt;/p&gt;

&lt;h3 id="feature_sniffing"&gt;Feature sniffing&lt;/h3&gt;

&lt;p&gt;A more scalable approach is to use object detection in JavaScript to discover if a feature is available before you use it. An example of this might be:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;The obvious advantage here is that it is browser agnostic; there are no assumptions as to which browser is involved at all. Using this technique, we overcome the scalability and maintenance headaches incurred through browser sniffing, and we can develop for graceful degradation from the outset.&lt;/p&gt;

&lt;h2 id="css_is_a_dsl_that_lacks_features"&gt;CSS is a DSL that lacks features&lt;/h2&gt;

&lt;p&gt;Now, that’s all very well and good when we’re talking about JavaScript, but what happens when we need to affect the presentation layer?&lt;/p&gt;

&lt;p&gt;CSS is a very simple &lt;em&gt;domain specific language&lt;/em&gt; (DSL) that functions as a series of rules that override each other in a variety of ways (the cascade). There is no mechanism to detect a specific feature or a user-agent; only &lt;a href="http://www.w3.org/TR/CSS2/media.html"&gt;media types&lt;/a&gt; and potentially the odd CSS hack where a user-agent has imperfectly implemented an interpreter. There are also no conditionals; you just have to use the cascade to provide alternatives based on specificity or even just source order.&lt;/p&gt;

&lt;p&gt;With these limitations, it is &lt;strong&gt;impossible&lt;/strong&gt; to implement either browser &lt;em&gt;or&lt;/em&gt; feature sniffing in CSS. This means we need to find an alternative method to affect the cascade based on the user’s feature set.&lt;/p&gt;

&lt;h2 id="the_modernizr_method"&gt;The Modernizr method&lt;/h2&gt;

&lt;p&gt;Step in &lt;a href="http://www.modernizr.com/"&gt;Modernizr&lt;/a&gt;. In the words of &lt;a href="http://www.modernizr.com/docs/"&gt;the documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Modernizr aims to bring an end to the UA sniffing practice. Using feature detection is a much more reliable mechanic to establish what you can and cannot do in the current browser, and Modernizr makes it convenient for you in a variety of ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It tests for over 20 next-generation features, all in a matter of milliseconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It creates a JavaScript object (named Modernizr) that contains the results of these tests as boolean properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It adds classes to the &lt;code&gt;html&lt;/code&gt; element that explain precisely what features are and are not natively supported.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Following along so far? For the most part, that all seems fairly good. What’s more, Modernizr is definitely being pushed as the solution of choice amongst the front-end community:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://diveintohtml5.org/detect.html"&gt;Mark Pilgrim’s Dive into HTML5 “Detection” chapter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.alistapart.com/articles/taking-advantage-of-html5-and-css3-with-modernizr/"&gt;Faruk’s “Taking Advantage of HTML5 and CSS3 with Modernizr” on A List Apart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webdesignernotebook.com/css/how-to-use-modernizr/"&gt;Web Designer Notebook: How to use Modernizr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.sitepoint.com/build-an-awesome-image-gallery-with-jquery-modernizr-and-css3/"&gt;Image Gallery tutorial on Sitepoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So with all that in mind, let’s go back to why I will not be recommending Modernizr as a best practice:&lt;/p&gt;

&lt;h3 id="sniffing_css_features_with_javascript"&gt;Sniffing CSS features with JavaScript&lt;/h3&gt;

&lt;p&gt;The real issue is that Modernizr uses JavaScript to do the feature sniffing. This method is absolutely fine if we were only looking to test for the features in JavaScript. However, Modernizr is marketed on its ability to detect CSS3 and HTML5 features so that you can write gracefully degrading CSS:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Modernizr is a small and simple JavaScript library that helps you take advantage of emerging web technologies (CSS3, HTML 5) while still maintaining a fine level of control over older browsers that may not yet support these new technologies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Modernizr had sold itself as a JavaScript feature sniffing solution that also detected CSS features perhaps I could be more forgiving. In that context, it would be the developers’ responsibility to use Modernizr correctly. However, since the Modernizr site and documentation are selling it &lt;em&gt;specifically&lt;/em&gt; as a CSS feature sniffing solution, for primary use within CSS, the error is clearly with the Modernizr team themselves.&lt;/p&gt;

&lt;p&gt;It’s all down to the final step outlined in the documentation I quoted earlier:&lt;/p&gt;

&lt;blockquote&gt;
 It adds classes to the &lt;code&gt;html&lt;/code&gt; element that explain precisely what features are and are not natively supported.
&lt;/blockquote&gt;

&lt;p&gt;Modernizr uses JavaScript to add those classes to the &lt;code&gt;html&lt;/code&gt; element; one for each of the features detected in the current browser. If we examine the generated source we see the following:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;modernizr-com&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot; js flexbox canvas&lt;/span&gt;
&lt;span class="s"&gt;canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb&lt;/span&gt;
&lt;span class="s"&gt;hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize&lt;/span&gt;
&lt;span class="s"&gt;borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns&lt;/span&gt;
&lt;span class="s"&gt;cssgradients cssreflections csstransforms csstransforms3d csstransitions&lt;/span&gt;
&lt;span class="s"&gt;fontface video audio localstorage sessionstorage webworkers applicationcache&lt;/span&gt;
&lt;span class="s"&gt;svg inlinesvg smil svgclippaths&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;When I first saw that, I was horrified. Not only is it ridiculously cluttered, it also feels decidedly unsemantic and looks like a terminal case of &lt;a href="http://www.sitekin.com/blogdetail/avoid_CSS_Classitis"&gt;classitis&lt;/a&gt;. However, let’s try to be pragmatic here; it’s a means to an end, potentially a minor side-effect to a process that will win us some power in the bigger picture. In fact, it’s one step on from &lt;a href="http://paulirish.com/2009/avoiding-the-fouc-v3/"&gt;Paul Irish’s proposed work around to the FOUC (flash of unstyled content)&lt;/a&gt; which I’ve advocated as a reasonable fallback to marking progressively enhanced objects with an “enhanced” class.&lt;/p&gt;

&lt;h3 id="making_use_of_the_classes"&gt;Making use of the classes&lt;/h3&gt;

&lt;p&gt;The Modernizr method allows you to assign styles based on these new classes on the document’s root element like so (example lifted from the Modernizr docs):&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.glossy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt; &lt;span class="sx"&gt;url(gloss.png)&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;repeat-x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.cssgradients&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.glossy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;top&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;bottom&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.cssgradients&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.glossy&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;Here we can see that &lt;code&gt;button.glossy&lt;/code&gt; is first defined with a standard &lt;code&gt;png&lt;/code&gt; as its background. The Modernizr-added &lt;code&gt;.cssgradients&lt;/code&gt; class is then used to increase specificity and assign a WebKit gradient instead.&lt;/p&gt;

&lt;p&gt;What happens if we approach the problem &lt;em&gt;without&lt;/em&gt; the .cssgradients class:&lt;/p&gt;

&lt;p&gt;CSS allows us to define a property twice in the same rule. It also contains built-in error handling that will ignore a property it doesn’t understand; so browsers that do not understand &lt;code&gt;-webkit-gradient()&lt;/code&gt;, for example, will simply ignore a property that uses it. This allows us to progressively enhance our CSS like so:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.glossy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt; &lt;span class="sx"&gt;url(gloss.png)&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;repeat-x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;top&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;bottom&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.glossy&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;However, because we can no longer target the &lt;code&gt;.cssgradients&lt;/code&gt; class specifically, we cannot target the &lt;code&gt;button:hover&lt;/code&gt; styles only when CSS gradients are detected. Clearly this is an issue we’ll have to find some way around and is exactly what Modernizr is attempting to solve.&lt;/p&gt;

&lt;p&gt;This all seems as if Modernizr is giving us a great deal of power, however, it comes with a significant cost.&lt;/p&gt;

&lt;h2 id="dependency_on_javascript_is_bad"&gt;Dependency on JavaScript is bad&lt;/h2&gt;

&lt;p&gt;Fellow web developer and good friend &lt;a href="http://isolani.co.uk/"&gt;Mike Davies&lt;/a&gt; wrote a really great article containing a good summary of &lt;a href="http://isolani.co.uk/blog/javascript/DisablingJavaScriptAskingTheWrongQuestion#javascript-obstacles"&gt;obstacles potentially preventing JavaScript from executing&lt;/a&gt; back in October 2010. This followed a somewhat presumptuous post by &lt;a href="http://www.nczonline.net/"&gt;Nicholas Zakas&lt;/a&gt; on the YDN regarding the &lt;a href="http://developer.yahoo.com/blogs/ydn/posts/2010/10/how-many-users-have-javascript-disabled/"&gt;number of users with JavaScript disabled&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In short, there are a large number of obstacles that can affect the execution—or even rewrite the source of—JavaScript included in your pages. Hence, dependancy on JavaScript is bad because it introduces many significant points of failure.&lt;/p&gt;

&lt;p&gt;As an example of &lt;em&gt;why&lt;/em&gt; dependency on JavaScript can be catastrophic, I recommend you read another of Mike’s posts on &lt;a href="http://isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs"&gt;Gawker’s JavaScript dependent URIs and how it broke their sites quite considerably&lt;/a&gt;. It’s worth noting that the Gawker sites have since seen the error of their ways and are &lt;a href="http://kotaku.com/5800365/the-first-of-many-updates-to-kotakucom-design-is-live-right-now"&gt;attempting to fix the damage&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="styling_dependant_on_javascript"&gt;Styling dependant on JavaScript&lt;/h3&gt;

&lt;p&gt;By adding styles that are specific to classes that have been inserted with JavaScript, we are making those styles dependant on JavaScript. This means those styles will fail to apply if JavaScript itself has been disabled or, more commonly, the JavaScript file applying the classes has failed to load or execute successfully due to one of the reasons above. In essence, we may just as well add those styles with JavaScript directly because we’ve already broken the web standards separation of concerns.&lt;/p&gt;

&lt;p&gt;Do we really want to remove the majority of CSS items covered by Modernizr if the Modernizr JavaScript include fails for some reason?&lt;/p&gt;

&lt;p&gt;It would only be the feature-sniff-dependant CSS rules that would fail, since those classes would now be missing. Potentially this only means the loss of a few nice in-browser rendering optimisations. However, it also means there is a significant loss in the overall structure of specificity within your stylesheets, which could easily cascade unintended effects through to other elements. This could easily result in some content being styled to be unreadable, or worse, incorrectly hidden. This would be very bad indeed.&lt;/p&gt;

&lt;h2 id="alternative_solutions"&gt;Alternative solutions&lt;/h2&gt;

&lt;p&gt;Modernizr is clearly unfit for purpose. If it were simply a JavaScript feature sniffing library for use &lt;em&gt;only&lt;/em&gt; in JavaScript, it would be a suitable solution although only really useful for JavaScript progressive enhancement.&lt;/p&gt;

&lt;p&gt;With that in mind, what other options are available that allow us to target our CSS?&lt;/p&gt;

&lt;h3 id="server_side_browser_sniffing"&gt;Server-side browser sniffing&lt;/h3&gt;

&lt;p&gt;We could browser sniff on the server and add a class to the &lt;code&gt;html&lt;/code&gt; element as we generate the HTML that is delivered in the HTTP response. This could result in something like the following:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;firefox&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;This means we can target CSS with the &lt;code&gt;.firefox&lt;/code&gt; class in much the same way that we used the feature classes that Modernizr provided. There is no way for us to perform feature sniffing on the server; the best we could offer is a feature lookup based on the user-agent string that we’ve used to sniff the browser, but that would ultimately still be browser sniffing.&lt;/p&gt;

&lt;p&gt;In fact, the best browser sniffing solution would allow us a little more flexibility on browser versions:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;moz ff ff3-6&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;Note I’ve added several classes this time; one for the rendering engine, one for the browser, and one that contains the major and minor versions. This would allow us more specificity.&lt;/p&gt;

&lt;p style="padding: 10px; background: #fee; border: 1px solid #c00;"&gt;&lt;strong&gt;Update:&lt;/strong&gt; Matthew Pennell has written an interesting post on &lt;a href="http://www.thewatchmakerproject.com/blog/no-more-css-hacks-browser-sniffing-with-htaccess/"&gt;server-side browser sniffing with .htaccess and environment variables&lt;/a&gt;. Definitely worth a read.&lt;/p&gt;

&lt;h4 id="cache_issues"&gt;Cache issues&lt;/h4&gt;

&lt;p&gt;However, server-side browser sniffing means that you’ll run into issues if your pages are publicly cacheable. This server-side solution results in a different HTTP response (the HTML) for each differing browser.&lt;/p&gt;

&lt;p&gt;If you utilise any intermediary caching (&lt;a href="http://www.squid-cache.org"&gt;Squid&lt;/a&gt;, &lt;a href="http://www.varnish-cache.org"&gt;Varnish&lt;/a&gt;, or a custom origin CDN) for static pages, and you use server-side browser detection, you need to make sure those caches don’t inadvertently send the wrong content to the wrong browser. To do this you’ll need to &lt;code&gt;Vary: User-Agent&lt;/code&gt; header in the HTTP response. This instructs any intermediary caches to store multiple copies of the page (one for each &lt;code&gt;User-Agent&lt;/code&gt; string that it sees) and to inspect the incoming &lt;code&gt;User-Agent&lt;/code&gt; string when looking for cached responses to the current request.&lt;/p&gt;

&lt;h3 id="ie_targeting_with_conditional_comments"&gt;IE targeting with conditional comments&lt;/h3&gt;

&lt;p&gt;If we’re entirely honest with ourselves as web developers, we can probably admit that the majority of woes we experience in CSS are as a direct result of features that any given version of Internet Explorer has not implemented. In fact, I regularly interview developers who advocate maintaining a separate stylesheet for IE that is included through the use of IE’s conditional comments. Having attempted to use this method in the past, I can confidently say that it is a maintenance nightmare and quickly becomes pretty unmanageable.&lt;/p&gt;

&lt;p&gt;A better technique would be to adopt conditional comments to add IE specific classes in much the same way we have with Modernizr or server-side browser sniffing. This method was first proposed by none other than Paul Irish back in 2008 in his article &amp;#8221;&lt;a href="http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/"&gt;Conditional stylesheets vs. CSS hacks? Answer: neither&lt;/a&gt;&amp;#8221;. With that method, our &lt;code&gt;html&lt;/code&gt; element would look like this:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="c"&gt;&amp;lt;!--[if IE ]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if !IE]&amp;gt;--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;This looks a bit odd, and often (for the true markup perfectionist) takes a bit of getting used to. However, it does give us what we need without requiring JavaScript or multiple cache versions.&lt;/p&gt;

&lt;p&gt;We can even make it more specific if we so desire:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="c"&gt;&amp;lt;!--[if lt IE 7 ]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie ie6&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if IE 7 ]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie ie7&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if IE 8 ]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie ie8&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if IE 9 ]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie ie9&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if gt IE 9]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;html lang=&amp;quot;en&amp;quot; dir=&amp;quot;ltr&amp;quot; class=&amp;quot;ie&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--[if !IE]&amp;gt;&amp;lt;!--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--&amp;lt;![endif]--&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;Quite clearly this gets ever uglier, but the solution is entirely encompassed in the structural layer; we will always have the correct class, even if CSS or JavaScript are unavailable for some reason. We also have the same markup regardless of user-agent string, which means caching is not a problem.&lt;/p&gt;

&lt;p&gt;The only flaw with this solution is that we can only target versions of Internet Explorer. No other browser implements conditional comments.&lt;/p&gt;

&lt;h3 id="use_css_properly_and_make_use_of_the_cascade"&gt;Use CSS properly and make use of the cascade&lt;/h3&gt;

&lt;p&gt;As previously stated, CSS is designed to cascade. This means the built-in error handling will ignore properties the interpreter does not understand, and we can override rules based on specificity and source order. In most cases, these key features are more than adequate to develop gracefully degrading stylesheets.&lt;/p&gt;

&lt;p&gt;Most capable front end developers are already doing this and coping just fine. Add this to the previous IE targeting approach and you’ll find that you do not need to over-engineer a solution.&lt;/p&gt;

&lt;h2 id="in_summary"&gt;In summary&lt;/h2&gt;

&lt;p&gt;So, in summary then, I absolutely cannot recommend implementing Modernizr as a best practice for front end development. It attempts to solve a problem from the wrong direction, and introduces a new potential point of failure. What’s more it breaks the fundamental ethic of web standards; the separation of concerns.&lt;/p&gt;

&lt;p&gt;I continue to recommend well crafted, gracefully degrading CSS, backed up by conditional commented classes on the &lt;code&gt;html&lt;/code&gt; element for targeting IE.&lt;/p&gt;

&lt;p&gt;Modernizr may still be a worthy solution for JavaScript-only feature sniffing, if only it allowed the developer to disable the injection of classes on the &lt;code&gt;html&lt;/code&gt; element.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/-YEOP2fuvVw" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/sniff-my-browser-the-modernizr-inadequacy.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[SEO for Web Developers: Page Construction]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/xMqEfMF9Gp0/seo-for-web-developers-page-construction.html" />
        <updated>2011-04-06T10:29:27+01:00</updated>
        <id>http://nefariousdesigns.co.uk/seo-for-web-developers-page-construction</id>
        <content type="html">&lt;p&gt;Following on from “&lt;a href="http://nefariousdesigns.co.uk/archive/2011/03/seo-for-web-developers-keywords-and-links/"&gt;SEO for Web Developers: Keywords and Links&lt;/a&gt;”, this next article in my SEO series focuses on page construction. Whilst I’ve previously stated that in-links (i.e. external incoming links) are the fundamental workhorse of good SEO, it is also important to make sure you are constructing your pages in a way that easily exposes your content, and that clearly links it to your identified keywords.&lt;/p&gt;




&lt;p&gt;Further to that, it’s important to know what the search bots are looking for when they spider your pages. From URL structure through to semantic markup and page specific metadata, there are a multitude of features you can build-in from the start that will improve the search engines’ insight into your content.&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="a_note_on_ranking_factors"&gt;A note on ranking factors&lt;/h2&gt;




&lt;p&gt;Every two years, &lt;a href="http://www.seomoz.org/"&gt;SEOmoz&lt;/a&gt; conduct a survey across various SEO experts which they use to publish &lt;a href="http://www.seomoz.org/article/search-ranking-factors"&gt;statistical findings in relation to search engine rankings&lt;/a&gt;. This data is exceptionally useful in judging what elements to concentrate your efforts on during development.&lt;/p&gt;




&lt;p&gt;In 2009 link metrics were worth a whopping 43% of value when calculating rankings. However, in the latest figures, that value has dropped to only 22%, which brings it in line with similar values for domain-level link authority (i.e. your domain is a “trusted” domain for quality). This reduction in size hasn’t resulted in other factors growing in value, but rather new factors have been introduced. These additions are domain-level keyword usage (how the keywords are relevant across the site), domain-level brand metrics (highlighting the importance of “brands” as a whole), and page-level traffic/query metrics.&lt;/p&gt;




&lt;h2 id="understanding_the_bots"&gt;Understanding the bots&lt;/h2&gt;




&lt;p&gt;Understanding how the search engine bots evaluate your pages and content is key to learning how page construction affects SEO.&lt;/p&gt;




&lt;h3 id="page_vs_site"&gt;Page vs Site&lt;/h3&gt;




&lt;p&gt;I have previously written—in my article “&lt;a href="http://nefariousdesigns.co.uk/archive/2007/03/semantics-and-structure/"&gt;Semantics and Structure&lt;/a&gt;“—of the importance of remembering that the web is simply a network of single pages. This network has only a vague understanding of the &lt;em&gt;human&lt;/em&gt; concept of site; via the comprehension of URLs beneath a fixed domain—and even that doesn’t necessarily translate to a single site, despite being used for authority rankings. Large sections of search bot AI has been dedicated to discerning site structure from the links within your pages.&lt;/p&gt;




&lt;p&gt;Whilst we can see from the metrics above that domain-level factors are now more prevalent in the calculations for ranking, it is still important to imagine each page of your site as an independent unit, and structure your content and code accordingly. This means that the &lt;em&gt;page&lt;/em&gt; title should be situated in an &lt;code&gt;h1&lt;/code&gt; tag and &lt;em&gt;not&lt;/em&gt; the site title. That is unless you’re developing the home page, in which case the site title probably &lt;em&gt;does&lt;/em&gt; belong in an &lt;code&gt;h1&lt;/code&gt; element.&lt;/p&gt;




&lt;p&gt;Site-wide architecture should be situated within non-pertinent markup (i.e. markup that doesn’t apply any semantic emphasis on the content) and placed accordingly in the source order. I&amp;#8217;ve heard very peculiar things about content placed in paragraph tags being more pertinent than content that isn’t. In my experience this is a significant fallacy. For more information about “pertinent markup”, read the “&lt;a href="#on_page_optimisation"&gt;On-page optimisation&lt;/a&gt;” section later in this article.&lt;/p&gt;




&lt;h3 id="block_level_analysis"&gt;Block-level analysis&lt;/h3&gt;




&lt;p&gt;Search engines, for the most part, follow an algorithm of block-level analysis. This means they will break a page down into sections (e.g. masthead, navigation, footer, main content, secondary content etc.) as a signal towards ranking the content within.&lt;/p&gt;




&lt;p&gt;It is a good idea to make sure that the content you want to rank for is situated within your main content area. This may sound obvious but in a brave new world of modular development, and pages made up of “modules” of content, it is surprisingly easy to confuse the search engines and suffer for it in the rankings.&lt;/p&gt;




&lt;h3 id="source_order_is_important"&gt;Source order is important!&lt;/h3&gt;




&lt;p&gt;It’s also important that you are prioritising your main content in your source order. Search engines will only evaluate the link text of the first use of a URI in a page. If you’re repeating a link with more valuable and relevant link text in your content than you are in your navigation, you’ll need to make sure the navigation comes &lt;em&gt;after&lt;/em&gt; the main content. This is often the exact opposite of good UI design which will attempt to &lt;a href="http://www.websiteoptimization.com/speed/tweak/clickstream/"&gt;place navigation in the most obvious place; across the top, or down the left&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Take the following code as an example:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About me&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My site&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to my site. In here you can find
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;information about me and
my career&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; and &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;my personal
blog about web development and the
internet&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Here the navigation links will be the first things evaluated by the bots, but they’re probably not the most contextually relevant links to the content in question. In fact, the second set of links include good keywords and may add significant value. For this reason the better option would be this:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My site&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to my site. In here you can find
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;information about me and
my career&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; and &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;my personal
blog about web development and the
internet&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/about/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About me&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/contact/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Obviously you can change the &lt;em&gt;visual&lt;/em&gt; position of this content with CSS. Whilst the more sophisticated search bots will render CSS in an attempt to detect invisible content (i.e. that which is hidden either through &lt;code&gt;display&lt;/code&gt; or &lt;code&gt;visibility&lt;/code&gt; rules, or that which is moved offscreen), they are less bothered about the reordering of content visually.&lt;/p&gt;




&lt;h2 id="creating_content"&gt;Creating content&lt;/h2&gt;




&lt;p&gt;It may sound entirely obvious but it’s exceptionally important to write good textual content for search engines. You will always rank higher if you include a good balance of text and links—with a high relevancy to each other—on your pages.&lt;/p&gt;




&lt;h3 id="duplication_is_bad"&gt;Duplication is bad&lt;/h3&gt;




&lt;p&gt;Try to avoid duplication of content. By this I mean avoiding the same content on two different URIs. If your content &lt;em&gt;is&lt;/em&gt; duplicated then you will be diluting its value by placing it in two places, even if it’s actually the same page served from two different URIs. I’ll cover the method you should use to declare the One True Version™ of your pages later on.&lt;/p&gt;




&lt;p&gt;It’s also important to make sure your pages don’t duplicate content that is elsewhere on the internet. Good examples of this sort of repetition would be travel brochure text or product descriptions which are highly likely to be used on a multitude of affiliate sites; especially if that content is included in some sort of feed. Wherever possible try and create your own content; it will always serve you better and will ultimately separate you from the crowd.&lt;/p&gt;




&lt;h3 id="dynamic_vs_static_content"&gt;Dynamic vs. static content&lt;/h3&gt;




&lt;p&gt;Dynamic content is that which updates regularly and hardly ever stays the same from day to day. Good examples of this might be a list of blog posts on a blog index page (where the blog items update regularly), news item indexes, feeds from other sites (e.g. RSS, Twitter etc.), and regularly moderated lists of links.&lt;/p&gt;




&lt;p&gt;Static content is that which hardly ever changes. Good examples might be “about me” text on your blog, the description on a product detail page, and the article text on a blog article page.&lt;/p&gt;




&lt;p&gt;It is very important to find the right balance of both dynamic and static content on your pages. Some pages will suit more static content (e.g. the article page of a blog) whereas others will suit more dynamic content (e.g. the index of that blog). In either case, make sure you’re including some of &lt;em&gt;both&lt;/em&gt; types of content. On the article include links to the top articles on the blog, or feeds from Delicious or Twitter; on the index page include some static “about this blog/author” text.&lt;/p&gt;




&lt;h2 id="design_your_uris"&gt;Design your URIs&lt;/h2&gt;




&lt;p&gt;Since links are the most important part of your SEO strategy, it’s hardly surprising that the &lt;em&gt;design&lt;/em&gt; of the URI is a fundamental ranking factor. It’s important that you use just as much care with the URI as you do with the text of those links. Here are the important factors in good SEO-friendly URI design:&lt;/p&gt;




&lt;h3 id="keywords_in_your_domain"&gt;Keywords in your domain&lt;/h3&gt;




&lt;p&gt;If you can, try to get some keywords in your domain. Often the most successful domains will have one or more relevant keywords in their domain name, and the closer to the left the better. A good example of this might be something like travelsupermarket.com, which is currently number one in Google for “travel”.&lt;/p&gt;




&lt;p&gt;Rather interestingly, _exact_ keyword match domains seem to perform marginally better than domains with _some_ keywords. By this I mean domains that are entirely formed of keywords in the order for which they are searched (e.g. cheapmajorcaholidays.com). Hyphenated exact match domains (e.g. cheap-majorca-holidays.com) seem to perform slightly worse than those without hyphens, and domains that contain all query terms but are not an &lt;em&gt;exact&lt;/em&gt; match are marginally worse again.&lt;/p&gt;




&lt;h3 id="choose_the_right_tld"&gt;Choose the right TLD&lt;/h3&gt;




&lt;p&gt;Rather notably the .com TLD (top-level domain) appears to perform better than any other TLD. That’s not to say that you can’t easily out rank a .com domain, but they do seem to gain an advantage in a like-for-like ranking test with pretty much every other TLD I tried.&lt;/p&gt;




&lt;h3 id="subdomains"&gt;Subdomains&lt;/h3&gt;




&lt;p&gt;Subdomains do not count as part of the domain. Cross subdomain links, as previously stated, are deemed internal and URIs containing a keyword subdomain appear to rank similarly to URIs with the same keyword as the first path element. Example:&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;http://games.mygamessite.com/
&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;Ranks the same as:&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;http://mygamessite.com/games/
&lt;/code&gt;&lt;/pre&gt;




&lt;h3 id="keep_paths_shallow"&gt;Keep paths shallow&lt;/h3&gt;




&lt;p&gt;Try to keep your URI path to a minimum. Each level you go down the hierarchy, the less value you give to keywords within it. This is another good reason to maintain a &lt;a href="http://nefariousdesigns.co.uk/archive/2011/03/seo-for-web-developers-keywords-and-links/#improving_8220crawlability8221"&gt;flat site architecture&lt;/a&gt;. Also, remember that the keywords on the left of each path segment (i.e. each section delimited with /) are the ones with the highest value at that level.&lt;/p&gt;




&lt;p&gt;The maximum number of layers (or segments) you should use in a path is about 3. Any more than that and you’ve basically lost any SEO benefit from that section of the URI.&lt;/p&gt;




&lt;h3 id="be_strict_with_your_characters"&gt;Be strict with your characters&lt;/h3&gt;




&lt;p&gt;There are a limited subset of characters that are permissible in URI syntax. However, that subset still allows a great variation in the &lt;em&gt;style&lt;/em&gt; of your characters. In general it is best to keep your URIs strictly lowercase so as to cut down on the chance of creating or generating duplicates through case sensitivity. Also, try and internationalise the character set in your URIs; it’s always going to be easier to match a UTF-8 search term against a UTF-8 keyword in your URI.&lt;/p&gt;




&lt;h3 id="space_separators"&gt;Space separators&lt;/h3&gt;




&lt;p&gt;There are several characters that can be decoded as a space in URI syntax, but only two that will work successfully as part of your path: “%20”, and “-“. It is best to enforce the use of a hyphen as a word separator in your paths. Google understands this as a space, and it will ensure your URIs remain readable. Underscores (“_”) are not recognised as a word separator and are therefore of little use. &lt;a href="http://www.mattcutts.com/blog/dashes-vs-underscores/"&gt;Matt Cutts has previously discussed this in his &amp;#8220;dashes vs. underscores&amp;#8221; blog post&lt;/a&gt;.&lt;/p&gt;




&lt;h3 id="branches_and_leaves"&gt;Branches and leaves&lt;/h3&gt;




&lt;p&gt;Do not underestimate the value of human readability when designing your URIs. I have personally experienced, through extensive user research and user testing, that users afford a certain level of confidence to a readable URI. What’s more, some SEO consultants whom I have spoken with recommend applying slightly different rules to branch and leaf URIs.&lt;/p&gt;




&lt;p&gt;A branch URI is a node that could potentially lead to more branch URIs or leaf URIs. The recommendation is that these URIs should end with a /.&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;Branches:

http://sportsnews.com/football/
http://sportsnews.com/football/bundesliga/
&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;A leaf URI is one that is the final node in the path tree. The recommendation is that these URIs should &lt;em&gt;not&lt;/em&gt; end with a /, and should include some kind of filetype extension (usually &lt;code&gt;.html&lt;/code&gt;). I prefer leaving out the extension myself, since it feels a bit old school and almost enforces a file-type assumption on the resource in question, but I accept I may be clouded by a developer’s understanding of HTTP and REST.&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;Leaves:

http://sportsnews.com/football/international/teams/england.html
http://sportsnews.com/contact-us.html
http://sportsnews.com/terms-and-conditions
&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;These recommendations amount to a more traditional OS directory-style vision, which makes them more familiar to the general non-techie user. It’s worth remembering that the URI is displayed prominently in the SERPs and as such inform the users’ confidence in clicking the item.&lt;/p&gt;




&lt;h2 id="on_page_optimisation"&gt;On-page optimisation&lt;/h2&gt;




&lt;p&gt;Now you’ve hosted the pages on good SEO friendly URIs, and you’ve built a good network of links to those pages, it’s about time we looked at improving the way the search bots spider and evaluate your content:&lt;/p&gt;




&lt;h3 id="page_title"&gt;Page title&lt;/h3&gt;




&lt;p&gt;The page title should sum up the content in as few words as possible. On left-to-right reading pages the left most words are deemed more significant (I’ve no research on right-to-left languages, but one would assume the opposite). A good title will have a healthy sprinkling of keywords whilst remaining human readable:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SEO for Web Developers - Nefarious Designs&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note that, in my titles, I&amp;#8217;ve chosen to include the site title following the page title. Firstly, this means the site title will be included in the page title on the SERP, but it &lt;em&gt;also&lt;/em&gt; means that the site title is associated as a keyword or keywords.&lt;/p&gt;

&lt;h3 id="semantic_content_mark_up"&gt;Semantic content markup&lt;/h3&gt;




&lt;p&gt;The majority of semantic markup won’t give you a significant boost in rankings. Sorry folks, it’s true; despite the fact that we web devs love some good semantic markup, the search bots are less bothered. Let’s face it, the internet is still full of badly constructed web pages and the bots have to spider, analyse, and rank those too.&lt;/p&gt;




&lt;p&gt;However there are &lt;em&gt;some&lt;/em&gt; semantic elements (and some presentational elements) that will have a greater influence on denoting keywords in your content to the search engines. These are:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;h1&lt;/code&gt;-&lt;code&gt;h6&lt;/code&gt;: Well structured headings, that are relevant to your content (and not used as way-finders such as “navigation”) are highly important. The &lt;code&gt;h1&lt;/code&gt; on your page is arguably the second most important element short of your page &lt;code&gt;title&lt;/code&gt; and should contain relevant keywords accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;em&lt;/code&gt;, &lt;code&gt;strong&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;: Emphasising textual content with these tags will infer the content has some degree of added value. However, it’s important not to saturate your content with this as it will inevitably be flagged as keyword spam. Overall my tests were inconclusive in quantifying the effect of emphasised keywords, but there is clearly value in it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;a&lt;/code&gt;: I’ve previously waxed lyrical on the importance of links within your content, and the textual content of those links is just as important. Linking to similar pages with text that involves your keywords, or is simply related, can significantly boost your pages’ performance in the SERPs.&lt;/p&gt;

&lt;p&gt;As a side note, I’ve been told by so-called SEO “consultants” that all internal links should be fully qualified (i.e. be absolute links including the domain) to prevent scrapers from duplicating your content elsewhere on the internet. This is absolute nonsense. There’s really no reason that a scraper won’t be able to remove the domain from any links it identifies as internal to your site (i.e. on the same domain as the page it’s scraping).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3 id="meta_elements"&gt;Meta elements&lt;/h3&gt;




&lt;p&gt;There are plenty of articles misrepresenting the value of &lt;code&gt;meta&lt;/code&gt; elements in terms of SEO. For pretty much the last ten years, they have been mostly irrelevant for SEO. In fact, at the moment, this very site isn’t using them (more through laziness than intention—the site templates are old and I intend on migrating away from them sooner or later).&lt;/p&gt;




&lt;h4 id="keywords"&gt;Keywords&lt;/h4&gt;




&lt;p&gt;The keywords &lt;code&gt;meta&lt;/code&gt; element is all but abandoned by todays’ search engines. You will see little effect in rankings if you remove it altogether. I have noticed some smaller search engines using it, and it’s conceivable that other search engines may use links from these search engines as authority on your content. In short, you might see a small amount of benefit by proxy, but possibly not enough to warrant making the effort to keep the keywords list up to date and matching your content.&lt;/p&gt;




&lt;h4 id="description"&gt;Description&lt;/h4&gt;




&lt;p&gt;The description &lt;code&gt;meta&lt;/code&gt; element is used as the first port of call for the description of your page in the search engine. There is also a minor ranking effect from including keywords in this description but as ever, it’s important not to spam them here.&lt;/p&gt;




&lt;h3 id="link_element"&gt;Link element&lt;/h3&gt;




&lt;p&gt;The &lt;code&gt;link&lt;/code&gt; element is a sneaky little devil. Most web developers use it solely for linking stylesheets to their pages, but it has so many other uses that can help the search engines understand your site architecture better.&lt;/p&gt;




&lt;p&gt;&lt;a href="http://www.w3.org/TR/html401/struct/links.html#h-12.3"&gt;The &lt;code&gt;link&lt;/code&gt; element&lt;/a&gt; allows you to specify another URI that is linked to your page, and also what relationship that URI has with the current one. To specify the relationship, you declare it in the &lt;code&gt;rel&lt;/code&gt; attribute. The &lt;code&gt;rel&lt;/code&gt; attribute has many possible values, but only a few that are relevant to SEO:&lt;/p&gt;




&lt;h4 id="canonical"&gt;Canonical&lt;/h4&gt;




&lt;p&gt;At a minimum it’s important to understand the canonical &lt;code&gt;link&lt;/code&gt; element. This allows you to declare the One True Version™ of any page on your site. This is probably easier to explain through example. Consider the following two URIs:&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;http://sportsnews.com/football/

http://sportsnews.com/football/?ads=false
&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;Assuming these are actually the same page, the search engine will consider these to be unique URIs and could penalise you for duplication of your content. To avoid this, it’s important to declare one version as the canonical version. To do this you add the following to the page:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;canonical&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://sportsnews.com/football/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This method is also true of something more subtle like “topic” style pages. Imagine the following URIs:&lt;/p&gt;




&lt;pre&gt;&lt;code&gt;http://sportsnews.com/teams/tottenham-hotspur/peter-crouch

http://sportsnews.com/teams/england/peter-crouch
&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;By adding a canonical &lt;code&gt;link&lt;/code&gt; to the first item we can declare that, although the pages are exactly the same, the second is actually the same page on a slightly different URI.&lt;/p&gt;




&lt;h4 id="others"&gt;Others&lt;/h4&gt;




&lt;p&gt;There are a whole host of available options to use in the &lt;code&gt;rel&lt;/code&gt; attribute of the &lt;code&gt;link&lt;/code&gt; element that may improve the search engines’ understanding of your pages and site structure. I really can be bothered listing them all out here, but you can find &lt;a href="http://www.seoconsultants.com/meta-tags/link-relationship"&gt;an interesting explanation of SEO relevant &lt;code&gt;rel&lt;/code&gt; values here&lt;/a&gt;.&lt;/p&gt;




&lt;h2 id="search_bots_as_knowledge_based_systems"&gt;Search bots as knowledge-based systems&lt;/h2&gt;




&lt;p&gt;Modern search engine bots are incredibly complex programs. Considering the amount of information they gather on each pass of your pages, they should certainly be considered to be knowledge-based systems. As the web changes, so do the methods the bots adopt to navigate your pages in as close to a humanised way as possible.&lt;/p&gt;




&lt;p&gt;To this end, both Googlebot and Bingbot are capable of understanding fairly complex navigation systems. What’s more, they are very good at evaluating navigation links within your pages to ascertain different routes to your content. Through this understanding they are able to apply value calculations to specific URIs.&lt;/p&gt;




&lt;h3 id="breadcrumbs"&gt;Breadcrumbs&lt;/h3&gt;




&lt;p&gt;Google announced at the end of 2009 that they were attempting to display site hierarchies as an alternative to the URL in the SERPs where they could surmise it from on-page breadcrumbs. For more information on this, see “&lt;a href="http://googleblog.blogspot.com/2009/11/new-site-hierarchies-display-in-search.html"&gt;New site hierarchies display in search&lt;/a&gt;” on the Googleblog.&lt;/p&gt;




&lt;p&gt;To do this, Googlebot simply analyses any constructs that look like a breadcrumb within your pages. This can be either a list of links identified by “breadcrumb” as an ID or class, or a set of links separated by the “&gt;” character. In my tests both of these methods have been successfully picked up by Googlebot and displayed as site hierarchies on the Google SERP.&lt;/p&gt;




&lt;p&gt;There are other methods of marking up breadcrumbs using “rich snippets” which I will talk about later.&lt;/p&gt;




&lt;h3 id="learning_new_interaction_paradigms"&gt;Learning new interaction paradigms&lt;/h3&gt;




&lt;p&gt;Googlebot has been designed to understand modern in-page navigation paradigms, such as tab, carousel, and accordion widgets. It does this by searching for the presence of known markup configurations and included scripts.&lt;/p&gt;




&lt;p&gt;For this reason, it’s sometimes better to use commonly used scripts such as popular jQuery or jQuery UI widgets which are likely to have a large user base across the web. Sadly this often means that badly written front-end interaction scripts may perform better than more bespoke options.&lt;/p&gt;




&lt;p&gt;You can also improve Googlebot’s understanding of your pages by adopting common element identifiers on your JavaScript enhanced elements. This means using classnames such as “open”, “closed”, “active”, or “selected” etc.&lt;/p&gt;




&lt;p&gt;It is worth noting, however, that in my tests rankings seemed better when pages used prebuilt widgets (i.e. those already in its knowledge base) than with bespoke techniques using predictable classes or IDs.&lt;/p&gt;




&lt;h3 id="rich_snippets"&gt;Rich snippets&lt;/h3&gt;




&lt;p&gt;These days Google is capable of rendering a large number of “rich snippets”. These are generally pieces of code specifically designed for marking-up data of a particular type, e.g. &lt;a href="http://microformats.org"&gt;microformats&lt;/a&gt;, &lt;a href="http://dev.w3.org/html5/md/"&gt;microdata&lt;/a&gt;, and &lt;a href="http://rdfa.info/"&gt;RDFa&lt;/a&gt;. Often these snippets simply involve a range of predictable element identifiers or tags.&lt;/p&gt;




&lt;p&gt;When displaying search results, Google will try and handle these rich snippets in the best way it sees fit. For example, reviews will appear as a 5 star rating widget just below the title of the search item. Recipes, on the other hand, are awarded their very own search utility:&lt;/p&gt;




&lt;p&gt;&lt;a href="http://www.google.com/search?q=chicken+madras&amp;amp;tbs=rcp%3A1"&gt;Google Recipe search for “Chicken Madras”&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Currently, Google supports the following types of rich snippet:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Reviews&lt;/li&gt;
&lt;li&gt;People&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Businesses and organisations&lt;/li&gt;
&lt;li&gt;Recipes&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;For more information on implementing these snippets for your content, take a look at &lt;a href="http://www.google.com/support/webmasters/bin/answer.py?answer=99170"&gt;Google’s excellent rich snippet explanation page&lt;/a&gt;.&lt;/p&gt;




&lt;h2 id="javascript"&gt;JavaScript&lt;/h2&gt;




&lt;p&gt;Googlebot currently runs a headless browser as it navigates pages. A headless browser is basically a browser with no user interface and, in this context, it means Googlebot constructs the correct DOM, and attempts to render all CSS and some JavaScript. It also means that many DOM events are fired as it follows links through your site, potentially exposing functionality it wouldn’t normally find.&lt;/p&gt;




&lt;p&gt;The JavaScript related tests I have run to analyse the bots’ paths through my sites have largely been quite inconclusive; it appears that sometimes Googlebot simply evaluates embedded script in the page (i.e. code inside &lt;code&gt;&lt;script&gt;&lt;/code&gt; tags) for URLs and then spiders those, and other times it is finding URLs within external script files (i.e. that which is included using &lt;code&gt;&lt;script src=“”&gt;&lt;/script&gt;&lt;/code&gt;). It also appears to find URLs manipulated into links on click events. However, it is definitely finding links in embedded script tags more regularly than those in external script files.&lt;/p&gt;




&lt;p&gt;So far I haven’t managed to get Googlebot to spider content or links added during a DOMready or window.onload event. My tests are ongoing and I shall endeavour to document my findings on this blog once I have a clearer picture.&lt;/p&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;Apologies for the length of this article, it just kept growing! There was so much to cover that I really didn’t want to have to split it out into several sub-articles; especially considering the fact that it’s already part of a series.&lt;/p&gt;




&lt;p&gt;Hopefully you’ve now got a head-start when it comes to building your pages for SEO. Tie this to the link building and keyword targeting you’ve been doing following my first article and you’ll be ranking well in the SERPs.&lt;/p&gt;




&lt;p&gt;In the following article I’ll be looking at what you can do to help the search engine robots specifically by providing metadata for them, and how proper handling of HTTP can improve crawlability. I’ll also cover some basic tools that can aid your monitoring and improvement of SEO.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/xMqEfMF9Gp0" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/seo-for-web-developers-page-construction.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[SEO for Web Developers: Keywords and Links]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/Lt579kd1Ph0/seo-for-web-developers-keywords-and-links.html" />
        <updated>2011-03-22T22:47:12+00:00</updated>
        <id>http://nefariousdesigns.co.uk/seo-for-web-developers-keywords-and-links</id>
        <content type="html">&lt;p&gt;Since the dawn of the web, developers and content editors have sought insight and enlightenment into the arcane art of search engine optimisation (SEO). This relentless battle to rise above the competition and feature at the top of the search engine result page (SERP), for a chosen keyword or search term, has forced a constant clandestine evolution upon the search engines themselves whilst they adapt to out-trick the trickster.&lt;/p&gt;




&lt;p&gt;What’s more the proliferation of false knowledge, the equally charlatan-populated worlds of SEO consultancy and web development, and the sheer abundance of SEO false positives have meant that snippets of true SEO wisdom are drowning in a sea of irrelevant balderdash.&lt;/p&gt;




&lt;p&gt;It is no wonder then that your average web developer is not armed with the erudition required to fight the good fight; knowledge that will allow them to articulate the message of their content to the search engines and therefore be exposed to a wider audience.&lt;/p&gt;




&lt;p&gt;Fear ye not, weary web devs, for here is your codex of power. I hereby commit to blog my personal experiences and knowledge of Getting SEO To Actually Work™. Everything I discuss in this series of articles has been learned through experimentation, careful analysis, and search-bot honey-pot test sites. Oh, and mummyfrakkin’ science, bitches.&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="keywords"&gt;Keywords&lt;/h2&gt;




&lt;p&gt;One term you will hear more than others when researching or improving SEO is “keyword”.&lt;/p&gt;




&lt;p&gt;A keyword is a word or phrase that contains high relevance to your content’s subject matter. A keyword is best imagined as a term a user might enter into a search engine in the hope of finding content like yours. For example, on a travel website generalised keywords might include “travel”, “vacation”, and  “holiday”, whereas more specific keywords might be “5 star holidays” or “Greek holidays”.&lt;/p&gt;




&lt;p&gt;As the search engines crawl and index the content on your pages they keep track of those pages in keyword-based indices. Thus, rather than storing 25 billion web pages all in one database, the engines maintain a vast array of smaller databases, each centred on a particular keyword term or phrase. This denormalisation makes data retrieval much faster, reducing it to mere fractions of a second.&lt;/p&gt;




&lt;h3 id="use_of_keywords"&gt;Use of keywords&lt;/h3&gt;




&lt;p&gt;The search engines analyse the embedded keywords within your content to ascertain their relevance to the subject matter. This means a good way to optimise your content is to make sure the keywords are situated in key content structures, such as URLs, page titles, headings, and areas of emphasis (&lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt;; your non-presentational mark-up bears little relevance here). I’ll cover this in more detail when I talk about on-page optimisation later in this series.&lt;/p&gt;




&lt;p&gt;It is also of note that a generalised keyword—such as “car insurance”, for example—will have a broader use, and therefore considerably more competition in terms of rankings. Something more specific like “women’s small car insurance” will limit your competition but might not have such a large search density. There is a clear balance to be found in your market and it’s important to identify the keywords you wish to target for a given page as early as possible.&lt;/p&gt;




&lt;h3 id="a_word_on_keyword_density"&gt;A word on keyword density&lt;/h3&gt;




&lt;p&gt;The term “keyword density” describes the density (i.e. occurrence) of a keyword within your content. The term is a veritable minefield of misinformation and should set off alarm bells as soon as it is mentioned.&lt;/p&gt;




&lt;p&gt;The density of your keywords bears no relation to the quality, semantics, and relevancy of your content; and it is these characteristics that glean the highest return. Do not be tempted into thinking that a page saturated with keywords will perform better in search rankings than a page that seats fewer keywords in higher quality, higher relevancy content.&lt;/p&gt;




&lt;h3 id="keyword_targeting"&gt;Keyword targeting&lt;/h3&gt;




&lt;p&gt;As I said earlier, it’s important to identify the keywords you wish to target before you do anything else. To be effective, SEO requires that keywords are associated with and contained in your content at as many levels as possible.&lt;/p&gt;




&lt;p&gt;Most SEO consultancies will invest significant amounts of time researching keywords for a given market, and also the competition against those keywords. What’s more, that analysis is ongoing, as the value of your chosen keywords will fluctuate wildly due to changes in the market, target saturation (i.e. too many people using it), and other such external factors (including black-hat devaluation which I will cover later).&lt;/p&gt;




&lt;h2 id="links"&gt;Links&lt;/h2&gt;




&lt;p&gt;Let’s make sure we’re not under any false illusions before we get too far in; the two most important things about any page—in terms of SEO—are the links into it, and the keywords associated with those links. You could serve up the most hideous pile of non-web-standards, non-semantic, tables-for-layout, text-in-images content, and if the links into it are plentiful, and also contain the right keywords and/or link juice (more on that later), it will perform well in the rankings. Links are how the search engines will begin to calculate the relevancy of your page. Once they have a relevancy rating, it will then be affected by the analysis of the &lt;em&gt;content&lt;/em&gt; of that page.&lt;/p&gt;




&lt;p&gt;That’s not to say that there isn’t some artistry in the placement, design, and variance of those links, but since hyperlinking is the very essence of the world wide web, it is unsurprising that it is also the very essence of SEO. A high quality link will be featured on a page containing high relevance to the link’s subject matter, will be situated in an area of highly relevant content, and will have link text containing relevant keywords. It’s all about relevance.&lt;/p&gt;




&lt;h3 id="link_juice_aka_pagerank"&gt;Link Juice (aka PageRank)&lt;/h3&gt;




&lt;p&gt;Search engines apply a numeric score to a spidered page known as PageRank. This is often called “Link Juice” in SEO circles and is a calculated number based on the links—and the quality of those links—into, and out of, your page. This score is then used as a factor in calculating the ranking of your page against keyword relevancy.&lt;/p&gt;




&lt;p&gt;As the search-bots spider the links within a page they pass a proportion of the host page’s score to each link. The page at the other end of the link is therefore afforded a total based on the score flowing into it from links elsewhere &lt;em&gt;and&lt;/em&gt; how it passes that score onward. The best way of imagining this is as a complex network of pipes and sluice gates (links), with the score being the liquid within. High quality pages will have higher page rank due to incoming links with a higher score.&lt;/p&gt;




&lt;p&gt;Bear in mind, however, that “link juice” is calculated differently based on “internal” and “external” links. Most search engines appear to deem links within a domain (internal) of less importance than those from a different domain entirely (external). For the most part, my linking tests seems to infer that cross-sub-domain links are &lt;em&gt;also&lt;/em&gt; deemed internal. However that sort of testing is fairly difficult to quantify, so I’d recommend investigating for yourself if you’re intending doing something like that.&lt;/p&gt;




&lt;p&gt;As an aside, it’s worth noting that a high link score (juice, PageRank, call it what you will) &lt;em&gt;does not&lt;/em&gt; necessarily mean high SERP rank.&lt;/p&gt;




&lt;h3 id="the_8220nofollow8221_rel_attribute_value"&gt;The “&lt;code&gt;nofollow&lt;/code&gt;” &lt;code&gt;rel&lt;/code&gt; attribute value&lt;/h3&gt;




&lt;p&gt;Following the dawn of the “blogosphere” and other such UGC (user-generated content), such as forums and guestbooks, there was an explosion of link-spam. These are links that have been placed on as many different sites as possible—either manually, or through automated processes known as spam-bots—with little relevance to the intended page content or conversation. This link spam is a black-hat method of rustling link juice into a given target page.&lt;/p&gt;




&lt;p&gt;To combat this, the search engines implemented a scheme that allows a developer to mark a link as non-pertinent in the flow of link juice. To do this, you apply a &lt;code&gt;rel&lt;/code&gt; attribute of &lt;code&gt;nofollow&lt;/code&gt;:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://somewhere.com/&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nofollow&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4 id="nofollow_sculpting"&gt;&lt;code&gt;nofollow&lt;/code&gt; sculpting&lt;/h4&gt;




&lt;p&gt;The &lt;code&gt;rel="nofollow"&lt;/code&gt; attribute used to allow you to &lt;em&gt;sculpt&lt;/em&gt; the score that would pass between links on your site, by preventing score flowing through no-followed links. &lt;strong&gt;This is no longer the case&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Before Google changed their algorithm, &lt;code&gt;rel="nofollow"&lt;/code&gt; used to be handled like this:&lt;/p&gt;




&lt;pre&gt;Link 1 - Link score/4
Link 2 - Link score/4
Link 3 - Link score/4
Link 4 - Link score/4

Link 1 - Link score/3
Link 2 - No follow
Link 3 - Link score/3
Link 4 - Link score/3&lt;/pre&gt;




&lt;p&gt;Now it works like this:&lt;/p&gt;




&lt;pre&gt;Link 1 - Link score/4
Link 2 - No follow
Link 3 - Link score/4
Link 4 - Link score/4&lt;/pre&gt;




&lt;p&gt;This means that you get significantly less benefit from no-following a link than you used to. However, all the search engines (with Ask being an exception) state that they do take &lt;code&gt;rel="nofollow"&lt;/code&gt; into account when weighting rankings:&lt;/p&gt;




&lt;p&gt;Google, Yahoo!, and Bing say no-followed links are treated as plain text and therefore have no added emphasis when calculating keyword relevancy. Y! and Bing, however, &lt;em&gt;do&lt;/em&gt; state that they use no-followed links for discovery and may follow them without affecting your rankings.&lt;/p&gt;




&lt;p&gt;It’s all very complicated but suffice to say, it’s probably better to mark unimportant links on your pages as &lt;code&gt;rel="nofollow"&lt;/code&gt; and let the search engines sort out amongst themselves what they want to do with it.&lt;/p&gt;




&lt;h2 id="improving_8220crawlability8221"&gt;Improving “crawlability”&lt;/h2&gt;




&lt;p&gt;To improve the efficiency of spidering (i.e. how the search bots crawl your site) it is advisable to maintain a flat site architecture. In this context, site architecture is simply a means to describe the link depth of your pages. “Link depth” is the number of links it takes to navigate from the home page of your site to any given page within it. The shorter the maximum link depth, the better the “crawlability”.&lt;/p&gt;




&lt;p&gt;For the most part, search engines understand a “site” to be a confined &lt;a href="http://en.wikipedia.org/wiki/Graph_(data_structure)"&gt;graph&lt;/a&gt; of internal links as mapped by the search bot when it spiders your site. Each pass through the site will give the bot a better understanding of your site-map. There are several ways to inform this process, such as sitemap XML files and the robots.txt file. I’ll cover those later in this series.&lt;/p&gt;




&lt;h3 id="maximum_links_per_page"&gt;Maximum links per page&lt;/h3&gt;




&lt;p&gt;Most search engines recommend hosting less than 100 links on any page. This is primarily because, above a certain number, link score will deteriorate due to a search engine defined degenerative quality equation. This will result eventually in links that are not spidered at all. Secondly, a large number of links on any page is a signal of diminished content quality and will directly affect SERP rankings as a result.&lt;/p&gt;




&lt;p&gt;The arbitrary value of 100 is misleading though as a high quality landing page, such as your homepage, can easily maintain 250-300 good quality links without penalty. The pages at the next level can then host ~200 quality links and so on. With this architecture, a site with a link depth of 4 or 5 can easily maintain millions of pages within its structure with little or no penalty.&lt;/p&gt;




&lt;h2 id="link_building"&gt;Link building&lt;/h2&gt;




&lt;p&gt;Link building is the art of obtaining external links back to your content from high quality (i.e. high relevance to your content subject matter) pages elsewhere on the web. There is a fine line to walk between link building and creating link spam; it is the difference between the relevance of the surrounding content on the link hosting page.&lt;/p&gt;




&lt;p&gt;Many SEO companies employ link building specialists who will inundate the web with links, either posted manually or accrued through link sharing contracts, registration with pay-to-link directories, and other such socially manufactured solutions.&lt;/p&gt;




&lt;h3 id="third_party_linking"&gt;Third-party linking&lt;/h3&gt;




&lt;p&gt;To build effective links it also a good idea to offset the effort. In some cases, placing a link on a site with high traffic, but that isn’t particularly high quality—or isn’t even spidered effectively—can work in your favour. A good example of this is Facebook which hides a large majority of its content from search engine spiders. A link placed on Facebook has a high likelihood of being reposted elsewhere, where the link quality will be vastly improved.&lt;/p&gt;




&lt;p&gt;In today’s internet company you will find many Social Media “Experts” who’s sole responsibility is to use social networking to market the brand, the company, and, more importantly, links to the website. Whilst the quality of links on social networks is debatable, the benefit of reposts elsewhere cannot be ignored, regardless of quality.&lt;/p&gt;




&lt;h3 id="link_bait"&gt;Link bait&lt;/h3&gt;




&lt;p&gt;Another technique when link building is to create content that can be classed as “link bait”. This is content that has a high likelihood of being reposted elsewhere and is therefore subject to significant third-party linking.&lt;/p&gt;




&lt;p&gt;In my personal opinion the concept of link bait is very hypothetical; one man’s link bait is another man’s quality content. In web development particularly there are any number of cynical parties waiting in the wings to troll a link as link bait. This may, however, have something to do with the inherent cynicism in the development world in general.&lt;/p&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;Understanding the concept of keywords, and then applying that concept to link building and your internal link structure, are really the two base concepts of SEO. Once you have mastered them you should be well on the way to improving your performance in search engine rankings.&lt;/p&gt;




&lt;p&gt;The next article in this series will cover SEO in page construction, including information about on-page optimisation, designing your URLs, correct use of HTTP, and other such technical information.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/Lt579kd1Ph0" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/seo-for-web-developers-keywords-and-links.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Stalking friends on GitHub]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/ZXEDIsZKnZ8/stalking-friends-on-github.html" />
        <updated>2011-02-20T23:42:26+00:00</updated>
        <id>http://nefariousdesigns.co.uk/stalking-friends-on-github</id>
        <content type="html">&lt;p&gt;A while back, I used &lt;a href="http://pipes.yahoo.com/"&gt;Yahoo! Pipes&lt;/a&gt; to filter my private &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; RSS feed, so that it only shows information that may be interesting for me to track. The resultant feed allows me to see what my friends have started watching or have forked, or repos they have recently created, from the comfort of my feed reader.&lt;/p&gt;

&lt;p&gt;Following a small refactor—guided by some more Pipes-knowledgable friends of mine (cheers &lt;a href="http://blog.zottmann.org/"&gt;Carlo&lt;/a&gt; and &lt;a href="http://ginader.com"&gt;Dirk&lt;/a&gt;)—I privatised my token, and allowed customisation of the GitHub account used.&lt;/p&gt;

&lt;p&gt;So, without further ado, here&amp;#8217;s the pipe; feel free to use it to stalk your friends on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pipes.yahoo.com/pipes/pipe.info?_id=85709214354b9319d6e345be3c1a6c46"&gt;GitHub Friend Stalker&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/ZXEDIsZKnZ8" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/stalking-friends-on-github.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[On coding standards]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/caNTMSZUXm0/on-coding-standards.html" />
        <updated>2011-01-31T22:00:16+00:00</updated>
        <id>http://nefariousdesigns.co.uk/on-coding-standards</id>
        <content type="html">&lt;p&gt;In my time as a web developer, I have been involved in the definition, implementation, and maintenance of several different coding standards, across various web-based languages. In my experience, this process is not as straightforward as it first seems, and can lead to a great deal of headaches if not handled in a very specific manner.&lt;/p&gt;

&lt;p&gt;As the front-end development team where I currently work are going through a definition process, I have been reminded of a few things I’ve learnt over the course of my career. With that in mind, I thought I’d type up some of that knowledge in the hope that it might benefit other developers out there.&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2 id="some_things_to_remember"&gt;Some things to remember&lt;/h2&gt;


&lt;p&gt;It’s important to remember that a developer takes great pride in his or her work, and as a result has a significant emotional attachment to the code they output. When that code is submitted for a code review—where the implementation of any coding standards is going to be assessed by the developer’s peers (obviously alongside other things)—it is important not to tear the code apart without respecting that emotional attachment.&lt;/p&gt;

&lt;p&gt;Further to this, it is important that the reasoning behind the rules in the coding standard are rigorously explained and well documented, along with good and bad examples. If the developers understand &lt;em&gt;why&lt;/em&gt; they should be doing something, you’re more likely to get them doing it as second nature.&lt;/p&gt;

&lt;p&gt;Finally, always check to see if there is a more general coding standard you can utilise, such as &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;Python’s PEP-8 standard&lt;/a&gt; or the &lt;a href="http://pear.php.net/manual/en/standards.php"&gt;PHP PEAR standard&lt;/a&gt;. It makes far more sense to start with one of these and then build your own standards upon it.&lt;/p&gt;

&lt;h2 id="why_have_a_coding_standard"&gt;Why have a coding standard?&lt;/h2&gt;


&lt;p&gt;There is really only one reason to adopt a coding standard; to maintain a predictable base of easily maintainable, understandable, and legible code. Ultimately, you are aiming to develop code that can be picked up by any developer—either in an internal team, or some other, wider community—and easily read, understood, and either fixed or appended.&lt;/p&gt;

&lt;p&gt;Further to that, it is not the opportunity to enforce your own particular coding style on others; in fact, you should probably expect to change your own style as there will invariably be some decisions made that will alter your usual syntax or method. This should be embraced as a &lt;em&gt;good&lt;/em&gt; thing, as you may learn something.&lt;/p&gt;

&lt;h2 id="creating"&gt;Creating&lt;/h2&gt;


&lt;p&gt;When creating a new coding standard, it’s important not to dictate rules to the wider team or community. The best standards are defined in agreement, not by dictation. It’s important to make the definition of &lt;em&gt;team&lt;/em&gt; standards a &lt;em&gt;team&lt;/em&gt; task.&lt;/p&gt;

&lt;p&gt;When a standard—and the reasoning &lt;em&gt;behind&lt;/em&gt; that standard—are offered to the team, discussion will invariable ensue. That discussion needs to be controlled and constructive, without dragging on. Nobody wants to sit and listen to two or three developers arguing; sooner or later someone will need to step in and make a decision, despite potentially disagreeing (and therefore upsetting) multiple parties involved.&lt;/p&gt;

&lt;p&gt;A good way to avoid massive discussion on mailing lists, or in team meetings, is to make sure your recommendation and acceptance processes are not too complex. As soon as you instigate a complicated system of recommendation, confirmation, voting etc. you will instantly regret it. Developers are adverse to change, and you are potentially changing the very fundamentals of their day to day work. You just can’t expect the process to be quick and painless unless you &lt;em&gt;enforce&lt;/em&gt; quick and painless at every possible stage.&lt;/p&gt;

&lt;p&gt;The absolute best way to implement and maintain a coding standard is based on the outcome of code reviews. These are the perfect forum for discussion of style and method, and a good follow-up on that discussion is to update the coding standard.&lt;/p&gt;

&lt;p&gt;The last thing you should bear in mind when developing a coding standard is that it will usually work best if it’s fairly language agnostic. Similar rules should be applied universally across languages; if you break this rule, you’ll quickly find yourself in a heated discussion about some minutia of syntax that is entirely deconstructive. Having said that, there are always going to be particular features and conventions of a specific language that should be applied to aid legibility or maintenance.&lt;/p&gt;

&lt;h2 id="comments"&gt;Comments&lt;/h2&gt;


&lt;p&gt;I hate badly commented code. I also hate writing comments. Ergo, I hate my own code.&lt;/p&gt;

&lt;h3 id="comment_as_you_go"&gt;Comment as you go&lt;/h3&gt;


&lt;p&gt;Commenting code is usually way outside the modus operandi of most developers. If we feel a piece of code should be commented, we’ll go back and do it afterwards, which means we’ve automatically given ourselves a mind-numbingly dull job that will, without fail, fall by the wayside upon release. To comment effectively, it’s important to do it as you go, even if you find yourself changing the comments as you refactor your code.&lt;/p&gt;

&lt;h3 id="comment_sensibly"&gt;Comment sensibly&lt;/h3&gt;


&lt;p&gt;Comments should be added in distinct blocks, rather than commenting every single line. It’s important to remember what is important in a block of code and explain that. You’re documenting it for maintenance, so at least afford the next developer a modicum of intelligence. Of course, if you come back to it 6 months down the line, that next developer could very well be you!&lt;/p&gt;

&lt;p&gt;When I say “distinct blocks”, I mean functions, methods, objects, classes, event callbacks, blocks of CSS rules, and anything else that requires explanation e.g. particularly complicated or confusing sections of functionality that might not otherwise be entirely obvious. Also, be sure to include references to other sections / files that may be relevant.&lt;/p&gt;

&lt;h3 id="pick_your_audience"&gt;Pick your audience&lt;/h3&gt;


&lt;p&gt;As I’ve said previously, comments are there for the code maintainer, so if you can hide them from the end user, you may as well do so. Comments should be added in the template language rather than the HTML; likewise, any other code generation should keep the comments in the generator not the generated file (unless it is specifically pertinent to do so). If you comment JavaScript and CSS, make sure the comments are removed as part of your build process/combo handler, alongside minification.&lt;/p&gt;

&lt;h3 id="commenting_standards"&gt;Commenting standards&lt;/h3&gt;


&lt;p&gt;Commenting standards, such as JSDoc, are a good thing. You’re already trying to implement a coding standard, you might as well leverage [manager++] someone else’s.&lt;/p&gt;

&lt;h2 id="naming_conventions"&gt;Naming conventions&lt;/h2&gt;


&lt;p&gt;Language constructs may allow you the freedom of your given language, but please adopt a little restraint. It’s important to make them readable and decipherable by the next developer along.&lt;/p&gt;

&lt;h3 id="style"&gt;Style&lt;/h3&gt;


&lt;p&gt;Try and adopt a naming convention that suits the style of the language. Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTML and CSS — Use hyphenated lowercase IDs and classes:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;live-scores&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tab-module&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    …
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JavaScript — Use camelCase variable naming, with constructors in UpperCamelCase:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;myFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Wicked awesome codez here.&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;MyConstructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PHP, Python — Use lowercase with underscore separation, with UpperCamelCase for classes:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="x"&gt;$dev_name = &amp;quot;Timmah&amp;quot;;&lt;/span&gt;


&lt;span class="x"&gt;function get_foo() {&lt;/span&gt;
&lt;span class="x"&gt;    return &amp;quot;foo&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;


&lt;span class="x"&gt;class SimpleClass {&lt;/span&gt;
&lt;span class="x"&gt;    // property declaration&lt;/span&gt;
&lt;span class="x"&gt;    public $var = &amp;#39;a default value&amp;#39;;&lt;/span&gt;
&lt;span class="x"&gt;    // method declaration&lt;/span&gt;
&lt;span class="x"&gt;    public function displayVar() {&lt;/span&gt;
&lt;span class="x"&gt;        echo $this-&amp;gt;var;&lt;/span&gt;
&lt;span class="x"&gt;        }&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h3 id="grace"&gt;Grace&lt;/h3&gt;


&lt;p&gt;It is important to keep names concise yet explanatory. There’s no need to write a variable name that’s fifty characters long, if you could do it in ten. Likewise, it’s important you aren’t just writing a nonsensical string of characters that ends up looking like some kind of demented &lt;a href="http://en.wikipedia.org/wiki/Countdown_(game_show)#Conundrum"&gt;Countdown Conundrum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bad:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;boolean_flag_for_portrait_view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Also bad:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bl_flg_pview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Good:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;is_portrait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3 id="prefixing_suffixing_type"&gt;Prefixing / suffixing type&lt;/h3&gt;


&lt;p&gt;Type prefixes and suffixes are a bad idea; loosely typed languages allow the developer the ability to change things up, so you’d better expect it once in a while. Further to that, any intelligent developer can work out what type a variable is if they absolutely have to, so why waste the characters?&lt;/p&gt;

&lt;p&gt;Final note: If type prefixes and suffixes are a bad idea, &lt;a href="http://en.wikipedia.org/wiki/Hungarian_notation"&gt;Hungarian notation&lt;/a&gt; is a very &lt;em&gt;very&lt;/em&gt; bad idea. Don’t go there. SRSLY.&lt;/p&gt;

&lt;h2 id="style"&gt;Style&lt;/h2&gt;


&lt;p&gt;As I’ve stated previously, a coding standard is &lt;em&gt;not&lt;/em&gt; a way for you to enforce your own coding style on others. Try and keep any such rules to a minimum.&lt;/p&gt;

&lt;h3 id="tabs_vs_spaces"&gt;Tabs vs. spaces&lt;/h3&gt;


&lt;p&gt;One of the first conversations you’re going to have, when defining a coding standard, is whether you should be using tabs or soft-tabs (spaces) for indentation. In a modern development environment, this is irrelevant—even in languages where whitespace indentation is important, such as Python.&lt;/p&gt;

&lt;p&gt;A developer should be able to set-up their IDE to use either tabs or spaces when indenting, thus they shouldn’t have to worry about it. The only thing that &lt;em&gt;is&lt;/em&gt; important in this area is that it remains uniform in any given file. There is nothing worse than opening a file to find some things indented by 4 spaces, and others indented by 3 [deviants!].&lt;/p&gt;

&lt;h3 id="legibility"&gt;Legibility&lt;/h3&gt;


&lt;p&gt;It’s important to write code that is legible; the more so, the better. To aid comprehension of blocks of code, it is useful to separate them with new lines.&lt;/p&gt;

&lt;p&gt;It’s also important to try to keep lines of code to a reasonable length. Many developers and coding standards recommend a length of around 80 characters, with some even enforcing it. Python’s PEP-8 certainly falls under this heading. Personally, I’d prefer going over that length if the line remains legible; often breaking a line with carriage returns can have a negative effect on legibility.&lt;/p&gt;

&lt;p&gt;Similarly, Lines that are too long are often difficult to read. If this is the case, then you must attempt to find the most legible form. Legibility is &lt;em&gt;always&lt;/em&gt; the most important factor.&lt;/p&gt;

&lt;h3 id="whitespace"&gt;Whitespace&lt;/h3&gt;


&lt;p&gt;Liberal use of whitespace in your syntax can mean the difference between readable and unreadable code. Having said that, &lt;em&gt;over&lt;/em&gt; use of whitespace can be entirely detrimental. Like my previous notes on style, it is important to find a balance when wrapping parentheses, expressions, assignments, and other such code with whitespace:&lt;/p&gt;

&lt;p&gt;Readable:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Less readable:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myVar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h2 id="accepted_standards"&gt;Accepted standards&lt;/h2&gt;


&lt;p&gt;There are many accepted standards used across multiple languages. It is important to make sure you don’t break these with your coding standard, even if you don’t specifically declare them anywhere. Good examples might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use of i, j, k for simple iterators.&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use of _ to denote private members.&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myConstructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_private&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;something private&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use of UPPERCASE to denote constants.&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;v1.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="expressions"&gt;Expressions&lt;/h2&gt;


&lt;p&gt;Expressions are often where the complex logic within your code can be found. As such, to aid assimilation, you may like to break them down to their constituent parts.&lt;/p&gt;

&lt;p&gt;A complex expression:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Might become:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;isStringMatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isStringMatched&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If we clean it up further:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isStringMatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt;
                       &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isStringMatched&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt;
               &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note the fact that I have broken the logical operators onto their own lines. This is another technique that can sometimes aid the readability of an expression, should it adopt multiple ANDs and ORs.&lt;/p&gt;

&lt;p&gt;This last example may look more complex to begin with, but should a second developer read your original code, they will be left confused. The second example breaks the expression down into constituent boolean values to aid legibility.&lt;/p&gt;

&lt;p&gt;Now imagine we have a similar example, but adopted using ternary notation:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;win&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fail&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This would become:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isStringMatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myString&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isStringCorrectLength&lt;/span&gt;
                       &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;isStringMatched&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isArrayShort&lt;/span&gt;
               &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;hasCorrectString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isPassed&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;win&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fail&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ternary becomes much easier to read by a second party when used in this way; particularly when dealing with nested ternary statements. Of course, a good rule of thumb is to just avoid nesting ternary statements altogether.&lt;/p&gt;

&lt;h2 id="concerns_over_file_size"&gt;Concerns over file size&lt;/h2&gt;


&lt;p&gt;In some languages, the size of the source code files you are creating can be pertinent to the performance of the final software. The obvious example of this is JavaScript files being served to a client.&lt;/p&gt;

&lt;p&gt;In this instance, it is important not to sacrifice maintainability for optimisation. Should your files need optimising for final consumption, factor that optimisation away into your build or delivery mechanism. With JavaScript, this means minifying your code using an algorithm that can understand how to refactor it. Google’s Closure Compiler is a good example of one such tool; however, it still has limitations, and you may find it beneficial to write your own based around your coding standards.&lt;/p&gt;

&lt;h2 id="enforcing"&gt;Enforcing&lt;/h2&gt;


&lt;p&gt;There is really only one way to enforce a coding standard, and that is exactly the same way you should be &lt;em&gt;developing&lt;/em&gt; your coding standard; through code reviews.&lt;/p&gt;

&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;


&lt;p&gt;As my final word, I’d just like to point out that your mileage with this may vary wildly. This article is really only based on my own experience. However, whether you agree with everything here or not, I would hope you agree that easily maintainable code is the most important outcome of any good coding standard.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/caNTMSZUXm0" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/on-coding-standards.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Object-oriented JavaScript follow up part 2: Technical]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/n7xsJAn7NBY/object-oriented-javascript-follow-up-part-2-technical.html" />
        <updated>2010-10-28T15:12:52+01:00</updated>
        <id>http://nefariousdesigns.co.uk/object-oriented-javascript-follow-up-part-2-technical</id>
        <content type="html">&lt;p&gt;Following on from &lt;a href="http://nefariousdesigns.co.uk/archive/2010/10/object-oriented-javascript-follow-up-part-1-method/"&gt;part 1 of my follow-up to “Object-oriented JavaScript”&lt;/a&gt;, part 2 provides a technical update to some of the theories and examples.&lt;/p&gt;




&lt;p&gt;Without further a-do, let’s jump in with the technical stuff:&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="a_quick_note_on_variable_declaration"&gt;A quick note on variable declaration&lt;/h2&gt;




&lt;p&gt;The &lt;code&gt;var&lt;/code&gt; declaration allows you to chain definitions in a comma separated list; what’s more that list can reference variables declared earlier in &lt;em&gt;the same list&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;Take this code as an example:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;elWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;elHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;elArea&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;elHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This could alternatively be written like so:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;elWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;elHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;elArea&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;elHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Personally, I prefer the latter method simply because it keeps my &lt;code&gt;var&lt;/code&gt; declarations in one place (where possible) without endless repetition of the &lt;code&gt;var&lt;/code&gt; keyword. However, this is simply a minor note on coding style, rather than something that can improve the operation of your code.&lt;/p&gt;

&lt;h2 id="understanding_object_oriented_scope"&gt;Understanding object-oriented scope&lt;/h2&gt;




&lt;p&gt;As any experienced JavaScript coder knows, JavaScript is functionally scoped; this means any variables created within an object or function are only available within that object or function.&lt;/p&gt;




&lt;p&gt;Simple, right?&lt;/p&gt;




&lt;p&gt;Well no, there are actually a couple of complications to this behaviour that you should really understand:&lt;/p&gt;




&lt;h3 id="passing_by_reference"&gt;Passing by reference&lt;/h3&gt;




&lt;p&gt;When passing arguments in JavaScript, it’s not immediately clear how those arguments are being handled internally. In fact, it is entirely dependant on the data-type of those arguments.&lt;/p&gt;




&lt;p&gt;When passing arguments of type Number, String, or Boolean, JavaScript will pass them in &lt;em&gt;by value&lt;/em&gt;. This means that the value stored in the argument will actually be a copy of the original value:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;accidentalFall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Remove one&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;greenBottles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// greenBottles is 10&lt;/span&gt;

&lt;span class="nx"&gt;accidentalFall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Pass by value&lt;/span&gt;

&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// greenBottles still 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Passing in an object, however, passes the argument &lt;em&gt;by reference&lt;/em&gt;. This means that, within the function, the argument is not a copy, but a reference—or link, if you like—to the original object. This means any members of that object are available within our function, and any changes to the object passed as an argument will be reflected &lt;em&gt;outside of the scope&lt;/em&gt; of the function.&lt;/p&gt;




&lt;p&gt;Actually, the way JavaScript handles references is another blog article in itself. Watch this space.&lt;/p&gt;




&lt;p&gt;Here’s our example again:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;accidentalFall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Remove one&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;greenBottles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;

&lt;span class="nx"&gt;accidentalFall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Pass by reference&lt;/span&gt;

&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greenBottles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This is a subtle difference, but one, I think you’ll agree, that is important to understand.&lt;/p&gt;




&lt;h3 id="the_this_special_operator"&gt;The &lt;code&gt;this&lt;/code&gt; special operator&lt;/h3&gt;




&lt;p&gt;The &lt;code&gt;this&lt;/code&gt; operator can be used to obtain a reference to the current context object and allows properties and methods within that execution context to be referenced. The context object can be considered a “hidden” parameter that is passed to any function.&lt;/p&gt;




&lt;p&gt;There are four ways the context is made available to a function:&lt;/p&gt;




&lt;h4 id="implicitly_with_a_method"&gt;Implicitly with a method&lt;/h4&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Context here is myObject, and has been passed&lt;/span&gt;
    &lt;span class="c1"&gt;// implicitly.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4 id="implicitly_with_new"&gt;Implicitly with &lt;code&gt;new&lt;/code&gt;&lt;/h4&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myConstructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Here we have a new anonymous context&lt;/span&gt;
    &lt;span class="c1"&gt;// understandable as the instance…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// …so the context here will be myObj&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;myConstructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4 id="explicitly_with_functioncall"&gt;Explicitly with &lt;code&gt;Function.call&lt;/code&gt;&lt;/h4&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implicit context is myObject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Explicitly force context to anotherObject&lt;/span&gt;
&lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anotherObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4 id="explicitly_with_functionapply"&gt;Explicitly with &lt;code&gt;Function.apply&lt;/code&gt;&lt;/h4&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implicit context is myObject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Explicitly force context to anotherObject&lt;/span&gt;
&lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anotherObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;In general, JavaScript developers tend to rely on &lt;em&gt;implicit&lt;/em&gt; context passing rather than &lt;em&gt;explicit&lt;/em&gt;. However, there is one situation where this reliance falls down…&lt;/p&gt;




&lt;h3 id="a_common_problem"&gt;A common problem&lt;/h3&gt;




&lt;p&gt;When registering event handlers against DOM nodes in JavaScript, the &lt;code&gt;this&lt;/code&gt; context no longer references the method’s parent object, but rather the DOM node to which the event handler is registered.&lt;/p&gt;




&lt;p&gt;The easiest way around this is to make sure the reference to the context object originally stored in &lt;code&gt;this&lt;/code&gt; is maintained before defining the event handler:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;myButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Clicked&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Further to this, according to Douglas Crockford, there is an error in the ECMAScript spec. that causes &lt;code&gt;this&lt;/code&gt; to be set incorrectly for inner functions; something that he discusses in his article &lt;a href="http://www.crockford.com/javascript/private.html"&gt;Private Members in JavaScript&lt;/a&gt;:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Now, the &amp;#8221;&lt;code&gt;var that = this&lt;/code&gt;&amp;#8221; technique is certainly a bone of contention amongst members of the JavaScript community, but I’m firmly on the fence in the whole discussion. Certainly my second example could be solved with a complex network of &lt;code&gt;Function.call&lt;/code&gt; and &lt;code&gt;Function.apply&lt;/code&gt; instead of &lt;code&gt;that.member&lt;/code&gt;, but my first example would be somewhat more difficult.&lt;/p&gt;




&lt;p&gt;Personally, I feel if Doug Crockford—a developer with many years more experience and infinitely more JS knowledge than myself—says it’s ok, then I’m fine with it.&lt;/p&gt;




&lt;h2 id="garbage_collection"&gt;Garbage collection&lt;/h2&gt;




&lt;p&gt;As JavaScript is a scripting language, it implicitly allocates memory for objects, strings, variables, and so on as it runs. &lt;em&gt;Garbage collection&lt;/em&gt; is the process by which the JavaScript engine detects when those pieces of memory are no longer reachable—that is, they could not possibly ever be used again—and reclaims the memory.&lt;/p&gt;




&lt;p&gt;The ECMAScript specification (of which JavaScript is an implementation) doesn’t include a definition on how a JS engine should handle garbage collection, so although each JavaScript engine includes garbage collection—memory usage would quickly snowball if they didn’t—they all handle it somewhat differently.&lt;/p&gt;




&lt;p&gt;Some engines are better than others; Google’s V8 is exceptionally good, where as the IE JScript engine is notoriously bad (often resulting in memory leaks).&lt;/p&gt;




&lt;h2 id="closures"&gt;Nested functions and closures&lt;/h2&gt;




&lt;p&gt;JavaScript allows the nesting of functions, creating nested scope blocks that inherit scope from their parents all the way up to the global scope.&lt;/p&gt;




&lt;p&gt;Take this code for example (there are much better ways of doing this; this method is only in the interests of illustration):&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;appendList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;itemPrefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;getListItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemPrefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;getListItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHtml&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;In the above example &lt;code&gt;getListItem&lt;/code&gt; is a nested function within &lt;code&gt;appendList&lt;/code&gt;. This means it inherits everything within the scope of &lt;code&gt;appendList&lt;/code&gt;. As a result of this, the inner function is able to make use of the &lt;code&gt;itemPrefix&lt;/code&gt; parameter that is passed to its parent without it needing to be passed in as another parameter on &lt;code&gt;getListItem&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;When JS automatically garbage collects the &lt;code&gt;appendList&lt;/code&gt; function, it will find no &lt;em&gt;external&lt;/em&gt; references to the &lt;code&gt;getListItem&lt;/code&gt; function and will garbage collect that as well.&lt;/p&gt;




&lt;p&gt;This is a useful feature of JavaScript, and allows for fairly advanced l&lt;a href="http://stackoverflow.com/questions/16501/what-is-a-lambda-function"&gt;ambda functions&lt;/a&gt; (anonymous functions), as well as providing a useful tool for namespacing library functions.&lt;/p&gt;




&lt;p&gt;However, if, upon garbage collection, JavaScript finds an external reference to a nested function, it creates a closure of scope; thus maintaining access to all the variables required within the scope of that function.&lt;/p&gt;




&lt;p&gt;This is known as &lt;strong&gt;a closure&lt;/strong&gt;.&lt;/p&gt;




&lt;h3 id="common_usage"&gt;Common usage of closures&lt;/h3&gt;




&lt;p&gt;The most common occurrence of a closure in JavaScript is when declaring event callbacks. This is simply due to the fact that the callback function is referenced within the event listener once registered.&lt;/p&gt;




&lt;p&gt;However, it’s important to understand that many modern libraries, plugin architectures, and plugins themselves also make use of closures, and understanding &lt;em&gt;how&lt;/em&gt; they use them can mean the difference between controlled and uncontrolled memory usage.&lt;/p&gt;




&lt;h3 id="invisible_pitfalls_are_invisible"&gt;Invisible pitfalls are invisible&lt;/h3&gt;




&lt;p&gt;It’s obvious when you think about it, but all closures have a potentially high memory imprint as they are maintaining much more than just their constituent parts. What’s more, because of their inherent avoidance of garbage collection, they are maintained until they are manually destroyed either by the code, or by a page refresh.&lt;/p&gt;




&lt;h2 id="prototypal_inheritance"&gt;Prototypal inheritance&lt;/h2&gt;




&lt;p&gt;I did discuss prototypal inheritance in &lt;a href="http://nefariousdesigns.co.uk/archive/2006/05/object-oriented-javascript/"&gt;my original Object-Oriented Javascript article&lt;/a&gt;, however I just want to go into a little more detail here.&lt;/p&gt;




&lt;p&gt;In a prototypal system, objects are supposed to inherit from objects; unlike in a &lt;em&gt;classical inheritance&lt;/em&gt; system where classes inherit from classes and &lt;em&gt;instantiate&lt;/em&gt; objects. JavaScript has no class (pun intended).&lt;/p&gt;




&lt;p&gt;Prototypal inheritance is actually simpler than classical inheritance once you get your head around it. You don’t need to define classification, so your code is smaller and less redundant since objects inherit from other more general objects. It is a model of &lt;a href="http://en.wikipedia.org/wiki/Differential_inheritance"&gt;&lt;em&gt;differential inheritance&lt;/em&gt;&lt;/a&gt;; i.e. each level of inheritance only adds the differences with its parent.&lt;/p&gt;




&lt;p&gt;Unfortunately, JavaScript is a bit confused about its prototypal nature, and wants to fit in with the other scripting languages by pretending to like The Beatles and by making itself more attractive to classically trained programmers by introducing the &lt;code&gt;new&lt;/code&gt; operator.&lt;/p&gt;




&lt;p&gt;This means that:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;myConstructor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;produces an object that inherits from &lt;code&gt;myConstructor.prototype&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;This indirection means that JavaScript actually has a pretty ugly constructor pattern and most new JavaScript developers never really get to grips with the inheritance model at all.&lt;/p&gt;




&lt;p&gt;However, all that has changed with the all singing, all dancing advent of JavaScript 1.8.5 (The New Shit™), which introduces the &lt;code&gt;Object.create&lt;/code&gt; method:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;human&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;legs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;arms&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tall&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;fat&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;overInflatedSenseOfSelfImportance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Mmm tasty, but since JS 1.8.5 only seems to be implemented in Firefox 4 (still in beta), don’t get all excited just yet.&lt;/p&gt;




&lt;p&gt;If you want something similar in your own code, you can implement the following for a similar approach (and still kiss goodbye to ever having to use the &lt;code&gt;new&lt;/code&gt; operator again):&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inherits&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;function&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inherits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;super_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inherits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parentConstructor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;childConstructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;What’s more, this DIY version will allow you access to any superclass’ implementations of a particular method like so:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;childConstructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Here’s some of that scope correction we discussed&lt;/span&gt;
    &lt;span class="c1"&gt;// earlier…&lt;/span&gt;
    &lt;span class="nx"&gt;childConstructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;super_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Other code&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This code is a mix of the &lt;code&gt;goog.inherits&lt;/code&gt; function—included in the Closure library—and the &lt;code&gt;Object.create&lt;/code&gt; outline by Crockford in his &lt;a href="http://javascript.crockford.com/prototypal.html"&gt;article on prototypal inheritance&lt;/a&gt;.&lt;/p&gt;




&lt;h2 id="javascript_design_patterns"&gt;JavaScript design patterns&lt;/h2&gt;




&lt;p&gt;Taking all this into account, we can start developing some incredibly useful design patterns that make use of prototypal inheritance, closures, and JavaScripts nuances of scope.&lt;/p&gt;




&lt;p&gt;In fact, several have already been developed within the JavaScript community:&lt;/p&gt;




&lt;h3 id="javascript_namespacing"&gt;JavaScript namespacing&lt;/h3&gt;




&lt;p&gt;To avoid the perils of globally scoped variables and functions, it is advisable to create a single global object for the purposes of namespacing the rest of your code. This is relatively simple to achieve:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;NEF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEF&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This command tests for the existence of a &lt;code&gt;NEF&lt;/code&gt; object at the global scope, and if evaluated to true, returns that object. Otherwise, it creates a new object using the object literal syntax.&lt;/p&gt;




&lt;p&gt;You may now assign any further variables or modules to your namespace:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;NEF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myAttribute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;NEF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3 id="module_pattern"&gt;Module pattern&lt;/h3&gt;




&lt;p&gt;The JavaScript module pattern was first proposed by Doug Crockford as a means of enforcing public and private object members through the use of closures.&lt;/p&gt;




&lt;p&gt;My preferred variation on the pattern is such:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;NEF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Private members&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;privateAttribute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;privateMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Private method called.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Public members&lt;/span&gt;
        &lt;span class="nx"&gt;publicAttribute&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="nx"&gt;publicMethod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Private members are in scope here&lt;/span&gt;

            &lt;span class="nx"&gt;privateMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Public members are addressable through the &amp;#39;pub&amp;#39; object.&lt;/span&gt;

            &lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicAttribute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;This method simple uses a closure to maintain private variables in the scope of the returned &lt;code&gt;pub&lt;/code&gt; object. The trick of this technique is the use of the &lt;code&gt;()&lt;/code&gt;, right at the end of the code, after the parent function definition, which causes the function to run immediately and return the &lt;code&gt;pub&lt;/code&gt; object.&lt;/p&gt;




&lt;h3 id="jquery_plugins"&gt;jQuery plugins&lt;/h3&gt;




&lt;p&gt;The jQuery plugin architecture also makes use of closures to do something quite similar to the Module Pattern above. However, jQuery plugins are specifically namespaced to the jQuery object itself:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Private members&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;debugMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;debugMode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;myPlugIn&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="err"&gt;…&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;

        &lt;span class="nx"&gt;publicMethod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;…&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;Alternatively, should you wish to only include a single public method, you can avoid &lt;code&gt;jQuery.fn.extend&lt;/code&gt; by instead making use of &lt;code&gt;jQuery.fn&lt;/code&gt; for definition:&lt;/p&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Private members&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;debugMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;debugMode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myPlugIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;…&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;In this code we can see that jQuery is passed to an anonymous function, that is run immediately, as the parameter &lt;code&gt;$&lt;/code&gt;. The anonymous function provides a scope block for the plug-in code, thus preventing potential headaches from variable naming clashes across shared code. The plug-in functions themselves are then created as closures so that they have access to the private variables and functions within that outer anonymous function. These plug-in variables are then bound to the passed in jQuery instance &lt;code&gt;$&lt;/code&gt; using jQuery’s own built in extension functions.&lt;/p&gt;




&lt;p&gt;This is actually quite a clever use of closures, although it does have the potential for memory leaks and excessive memory usage if variables and references aren’t kept in check. With that in mind, it’s often a very good idea to profile your jQuery plugins to understand what might need tidying up.&lt;/p&gt;




&lt;h3 id="custom_events"&gt;Custom events&lt;/h3&gt;




&lt;p&gt;Most modern JavaScript libraries include a mechanism for defining your own custom events. A custom event is merely a bespoke event, defined in your code, that other event-handler functions may be bound to. This custom event may then be triggered by you at any given point of execution in the code.&lt;/p&gt;




&lt;p&gt;The custom event architecture is an implementation of the Observer Pattern, in which an object maintains a list of dependant “observers” which it notifies automatically of any state changes. In JavaScript, the object maintaining the list is our event, and the “observers” are the event handlers.&lt;/p&gt;




&lt;p&gt;Using custom events in your own code provides a useful binding for other developers’ code. The event itself is loosely coupled to the event handlers, thus, &lt;em&gt;additional&lt;/em&gt; event handlers can be added or removed by third-party code.&lt;/p&gt;




&lt;p&gt;For more information on custom events, I’d recommend having a look at the documentation for the library of your choice. Here are few links:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;a href="http://api.jquery.com/bind/"&gt;jQuery custom events: .bind()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/event/#customevent"&gt;YUI2 custom events: The CustomEvent object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.yahooapis.com/yui/3/event/#customevent"&gt;YUI3 custom events&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;So that’s the technical addendum to my 2006 post. Hopefully, that should serve to bring the article up to date, and correct a few of my previous errors. As always, comments and corrections are welcome via the comment form below.&lt;/p&gt;




&lt;p&gt;Originally I had intended posting this article in two parts, however, it has continued to grow even as I write it. For this reason, the third and final part of this follow-up series will look at what’s on the horizon for JavaScript development, including how GoogleBot deals with JavaScript, the importance of supporting a core experience (where JavaScript is unavailable), server-side JavaScript, and architecting JavaScript applications.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/n7xsJAn7NBY" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/object-oriented-javascript-follow-up-part-2-technical.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Object-Oriented JavaScript Follow-Up Part 1: Method]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/PrakzYSV_TQ/object-oriented-javascript-follow-up-part-1-method.html" />
        <updated>2010-10-08T10:43:08+01:00</updated>
        <id>http://nefariousdesigns.co.uk/object-oriented-javascript-follow-up-part-1-method</id>
        <content type="html">&lt;p&gt;Back in May, 2006, I wrote an article entitled &lt;a href="http://nefariousdesigns.co.uk/archive/2006/05/object-oriented-javascript/"&gt;Object Oriented JavaScript&lt;/a&gt;. It was an exercise in both writing a useful tutorial, and a brain-dump of various things I had learned about writing object-oriented code on the client side. It quickly became apparent—as the article was linked to from a multitude of my favourite web standards development sources—that the tutorial itself was helpful; the comments burgeoned, and the traffic rocketed.&lt;/p&gt;




&lt;p&gt;When I read that article now, however, it bothers me. The tutorial is still good although the information within is somewhat dated; and my personal experience, knowledge, and general approach to writing JavaScript has changed quite drastically. The fact that the article still receives a consistently high number of unique visitors on a daily basis, when I no longer agree with all the content within it, bothers me even more. With that in mind, I have decided to write an update that looks at OOJS as I would currently use it.&lt;/p&gt;




&lt;p&gt;The resulting post has become quite extensive, so I’ve decided to split it into two separate articles. This first one will cover some development theory, whilst the second will dive into JavaScript coding specifics.&lt;/p&gt;




&lt;!--more--&gt;




&lt;h2 id="a_note_on_the_name"&gt;A note on the name&lt;/h2&gt;




&lt;p&gt;A friend of mine recently quoted this little gem in his Twitter stream:&lt;/p&gt;




&lt;blockquote&gt;
  &lt;p&gt;Java is to JavaScript as Ham is to Hamster.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Enough said.&lt;/p&gt;




&lt;h2 id="is_it_object_oriented"&gt;Is it object-oriented?&lt;/h2&gt;




&lt;p&gt;In my original article I stated that JavaScript was &lt;em&gt;not&lt;/em&gt; an object-oriented language, but rather an object-&lt;em&gt;based&lt;/em&gt; language. This was entirely unfair on JavaScript, and I’d like to fix that:&lt;/p&gt;




&lt;p&gt;JavaScript &lt;em&gt;is&lt;/em&gt; an object-oriented language. However, it breaks away from more conventional object-oriented languages by implementing prototypal inheritance, instead of classical inheritance. This is a Very Good Thing™ (although that seems to be a matter of opinion). More on that later.&lt;/p&gt;




&lt;h2 id="first_principles_for_javascript_programming"&gt;First principles for JavaScript programming&lt;/h2&gt;




&lt;p&gt;Before I start, let me be clear that there are first principles of programming that are language agnostic. We’re going to look at a couple of those, but I’d also like to discuss a few of the more JavaScript specific principles first; those that relate to the cross-browser web standards environment. Finally, I’m aware that I’m really only scratching the surface of some of these topics. I don’t really want to muddy the water here by waxing lyrical on good development practices, so if you’re after more depth, I’d recommend researching them via the search engine of your choice:&lt;/p&gt;




&lt;h3 id="proper_separation_of_the_behavioural_layer"&gt;Proper separation of the behavioural layer&lt;/h3&gt;




&lt;p&gt;Above everything else, it’s important to keep your content and markup (HTML), presentation (CSS), and behavioural (JavaScript) layers separate. Why is that important? Well if one or more of those layers are missing or broken (with the obvious exception of the core HTML), the others should still function as intended. Ultimately this makes presentation and behaviour optional, and a user might turn them off—via their browser settings—should they so desire. Alternatively, the user may include custom presentation or behaviour to aid a particular use-case.&lt;/p&gt;




&lt;p&gt;In JavaScript, proper separation requires making use of the DOM to bind behaviour to HTML elements via element identifiers (i.e. the &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt; attribute) in your source code. The alternative would be to write JS directly into the HTML, via event attributes such as &lt;code&gt;onClick=””&lt;/code&gt; or via the &lt;code&gt;javascript:&lt;/code&gt; pseudo-protocol in the &lt;code&gt;href&lt;/code&gt; attribute. This is not a good practice and I heartily recommend against it.&lt;/p&gt;




&lt;h3 id="graceful_degradation"&gt;Graceful degradation&lt;/h3&gt;




&lt;p&gt;Graceful degradation is a well known software engineering concept which involves writing your code to take advantage of awesome feature X, unless awesome feature X is unavailable, in which case degrade to use slightly-less-awesome feature Y (assuming that too is available).&lt;/p&gt;




&lt;p&gt;In web development terms this might mean making use of an amazing JavaScript date picker widget on a text-based input box, and just degrading to server-side date validation if JS is not turned on in the browser. It could also mean making use of the latest CSS3 styling techniques but degrading to use CSS2 techniques in less capable browsers.&lt;/p&gt;




&lt;p&gt;In short; build everything in the most up to date browser, making use of all it’s wonderful modern features, and then go back and make sure the site is still usable when any of those features are not.&lt;/p&gt;




&lt;p&gt;The problem with approaching the issue from this direction, however, is that you are saying to your users: “You (or your browser) are incapable of handling the full experience we want to present, so here’s a cut-down version.” This pretty much flies in the face of user-centric design, and good user experience. With that in mind, we’d be better using…&lt;/p&gt;




&lt;h3 id="progressive_enhancement"&gt;Progressive enhancement&lt;/h3&gt;




&lt;p&gt;Progressive enhancement involves approaching the problem from the other direction. You should design for the user-agent with the least capabilities and add functionality for more capable browsers afterwards.&lt;/p&gt;




&lt;p&gt;In web terms this means developing and designing with nothing but the base features of HTML in mind, and then enhancing those features (or the features of the browser interpreting that HTML) by attaching CSS and JS to the HTML via element identifiers like IDs and classes.&lt;/p&gt;




&lt;p&gt;The final outcome of these two approaches might be very similar, but the subtle difference is that you are giving more attention to the less capable user-agent when you progressively enhance.&lt;/p&gt;




&lt;p&gt;The most common use-case for progressive enhancement is the support of a non-JS experience.&lt;/p&gt;




&lt;h3 id="dry_dont_repeat_yourself"&gt;DRY (Don’t Repeat Yourself)&lt;/h3&gt;




&lt;p&gt;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. This means abstracting code into shared functions and objects whenever you find you are repeating yourself, and attempting to maintain a single source of truth in every aspect of your system.&lt;/p&gt;




&lt;p&gt;DRY is a well known paradigm in software engineering, and as such, should be applied in every detail of your JavaScript code.&lt;/p&gt;




&lt;h3 id="refactor_early_refactor_often"&gt;Refactor early, refactor often&lt;/h3&gt;




&lt;p&gt;Further to the principle of DRY, it is important that if you spot a potential issue in your JavaScript code you fix it. The more small refactors you do, the less time-consuming big refactors you are likely to need to do later on.&lt;/p&gt;




&lt;p&gt;Once you’re refactoring often, you’ll be able to…&lt;/p&gt;




&lt;h3 id="make_it_work_make_it_right_make_it_fast"&gt;Make it work, make it right, make it fast&lt;/h3&gt;




&lt;p&gt;The first iteration of your code should only look to reach the level of functionality defined in the functional specification. Once this has been achieved, refactor to improve the &lt;em&gt;way&lt;/em&gt; it works—so the code is “right” in your opinion. This may very well mean a complete overhaul of architecture, but you will be able to concentrate much more specifically on that since you already have it working. The final stage in this development cycle is to optimise your code for performance and efficiency; premature optimisation is a fundamental mistake in development.&lt;/p&gt;




&lt;h3 id="useful_resources"&gt;Useful resources&lt;/h3&gt;




&lt;p&gt;When it comes to general development, there are a veritable plethora of resources out there, but my recommended starting point is the book &lt;a href="http://www.amazon.co.uk/gp/product/020161622X?ie=UTF8&amp;amp;tag=gamersite-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=020161622X"&gt;&lt;strong&gt;The Pragmatic Programmer&lt;/strong&gt;, by Andrew Hunt and David Thomas&lt;/a&gt;. This book outlines quite a few paradigms that should get you thinking about the way you develop.&lt;/p&gt;




&lt;h2 id="important_things_to_understand"&gt;Important things to understand&lt;/h2&gt;




&lt;h3 id="pure_javascript"&gt;Pure JavaScript&lt;/h3&gt;




&lt;p&gt;In this age of JavaScript libraries and frameworks, it’s important to make sure you understand core JavaScript functions, objects, and methods. Although your library of choice may clean up any cross-browser issues you may encounter, it is always important to understand exactly how you are interacting with JavaScript as a language.&lt;/p&gt;




&lt;h4 id="useful_resources2"&gt;Useful resources:&lt;/h4&gt;




&lt;p&gt;The &lt;a href="http://developer.mozilla.org/en/JavaScript"&gt;Mozilla Developer Centre section on JavaScript&lt;/a&gt; is an invaluable reference resource when writing pure JavaScript. Also, make sure you own a copy of &lt;a href="http://www.amazon.co.uk/gp/product/0596101996?ie=UTF8&amp;amp;tag=gamersite-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0596101996"&gt;&lt;strong&gt;JavaScript: The Definitive Guide&lt;/strong&gt; by David Flanagan&lt;/a&gt;.&lt;/p&gt;




&lt;h3 id="the_dom"&gt;The DOM&lt;/h3&gt;




&lt;p&gt;The Document Object Model is an entirely separate beast to JavaScript, but is implemented natively within it. There are also DOM libraries for other languages that implement the W3 DOM specification when dealing with XML and SGML files.&lt;/p&gt;




&lt;p&gt;Understanding the DOM in JavaScript is essential when designing and developing interactions with your HTML and CSS. Thankfully all JavaScript libraries abstract out the pitfalls of DOM scripting so that you don’t have to, but as before, it’s still important for you to understand &lt;em&gt;how&lt;/em&gt; so that you can maximise your efficiency in using said library.&lt;/p&gt;




&lt;h4 id="useful_resources3"&gt;Useful resources:&lt;/h4&gt;




&lt;p&gt;Once again the Mozilla Developer Centre provides an excellent &lt;a href="https://developer.mozilla.org/en/DOM"&gt;DOM reference section&lt;/a&gt;, although it is slightly skewed in favour of the Gecko browser engine. You can also find plenty of &lt;a href="http://www.w3.org/DOM/"&gt;information on the DOM at the W3C site&lt;/a&gt;.&lt;/p&gt;




&lt;h3 id="interaction_with_the_browser"&gt;Interaction with the browser&lt;/h3&gt;




&lt;p&gt;When writing client-side JavaScript, it is important to take into account how HTML, CSS, and JavaScript interact with the browser directly. At every available opportunity, you should attempt to make sure you are not contradicting the browser, and that you are not rewriting interactions that are already well handled by the browser and operating system.&lt;/p&gt;




&lt;p&gt;A good example of this is to make sure you do not break the “back” button. Often this can be achieved by simply using the &lt;code&gt;window.location.replace()&lt;/code&gt; method to control which pages appear in the browser history.&lt;/p&gt;




&lt;h2 id="libraries"&gt;Libraries&lt;/h2&gt;




&lt;p&gt;Using libraries in JavaScript has become standard practice. A JavaScript library exists to save time and effort, and to provide a single source of truth (as discussed earlier) for many common tasks within that language.&lt;/p&gt;




&lt;p&gt;A JavaScript library provides you a toolbox full of handy devices to make your life easier. It needs to be treated as such, and not as a language in its own right. It is very important to understand the core structures of JavaScript, and how the library of your choice interacts within those structures and your own code.&lt;/p&gt;




&lt;p&gt;Every library is different and has its own pros and cons. I’m not going to go into my opinion of those here; perhaps that’s something for another post. They do, however, all interact somewhat differently with JavaScript, and it’s important to understand how the library you choose does that specifically.&lt;/p&gt;




&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;




&lt;p&gt;Hopefully that should get you in the right frame of mind to develop high quality JavaScript code. In the second half of this article I will be looking at specific use of JavaScript in regard to object-orientation.&lt;/p&gt;




&lt;p&gt;&lt;a href="http://nefariousdesigns.co.uk/archive/2010/10/object-oriented-javascript-follow-up-part-2-technical/"&gt;Continue reading part 2 of my object-oriented JavaScript follow-up&amp;hellip;&lt;/a&gt;&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/PrakzYSV_TQ" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/object-oriented-javascript-follow-up-part-1-method.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[jQuery Accordion]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/bAYcjD3r9yM/jquery-accordion.html" />
        <updated>2010-08-22T11:06:57+01:00</updated>
        <id>http://nefariousdesigns.co.uk/jquery-accordion</id>
        <content type="html">&lt;div style="background: #fcc; padding: 10px 10px 0; border: 1px solid #c33; margin: 1.2em 0;"&gt;&lt;strong style="color: #c33;"&gt;Update November 2010:&lt;/strong&gt; Documentation for this jQuery Accordion can now be found here:

&lt;a href="http://projects.timhuegdon.com/jquery-accordion/"&gt;jQuery Accordion - Tim Huegdon&amp;#8217;s Projects&lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Following on from my post about my &lt;a href="http://nefariousdesigns.co.uk/archive/2010/08/jquery-carousel/"&gt;jQuery Carousel&lt;/a&gt;, here&amp;#8217;s another widget: an accordion.&lt;/p&gt;

&lt;p&gt;Until recently, I&amp;#8217;ve usually used my friend and ex-colleague &lt;a href="http://www.i-marco.nl/weblog/jquery-accordion-menu-redux2/"&gt;Marco&amp;#8217;s jQuery accordion plug-in&lt;/a&gt;. However, whilst prototyping some stuff for work, I noticed a rather uncomfortable animation jump which, after some investigation, seems to be &lt;a href="http://jqueryfordesigners.com/slidedown-animation-jump-revisited/"&gt;a well documented issue with jQuery&amp;#8217;s &lt;code&gt;slideDown()&lt;/code&gt; method&lt;/a&gt;. Since I was prototyping at the time, I quickly knocked up my own very basic accordion and, over time, it grew into something more.&lt;/p&gt;

&lt;p&gt;The current version of my accordion follows a recent refactor&amp;#8211;there are still several features I&amp;#8217;d like to add&amp;#8211;but for now I&amp;#8217;m happy to let it out into the wild.&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2&gt;Demo&lt;/h2&gt;


&lt;p&gt;As was the case with my carousel, I&amp;#8217;d definitely recommend taking a look at my &lt;a href="http://nefariousdesigns.co.uk/projects/widgets/accordion/"&gt;page of example accordion implementations&lt;/a&gt;. This should give you a reasonable idea of the capabilities of the script; and as I update the widget, I&amp;#8217;ll update this page.&lt;/p&gt;

&lt;h2&gt;Source Code&lt;/h2&gt;


&lt;p&gt;All the source code for the accordion&amp;#8211;and the example page above&amp;#8211;is available in the following GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/nefarioustim/jquery-accordion"&gt;jQuery Accordion &amp;#8211; GitHub repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;




&lt;h3&gt;HTML&lt;/h3&gt;


&lt;p&gt;Basic HTML for the accordion is as follows:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;accordion&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Handle 1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;panel&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="ni"&gt;&amp;amp;hellip;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Handle 2&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;panel&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="ni"&gt;&amp;amp;hellip;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Handle 3&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;panel&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="ni"&gt;&amp;amp;hellip;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For each panel in the accordion, you will require both a panel (the content of our accordion pane) AND a handle (an item that is clicked to open a panel). These can be anything you want as you can specify the jQuery selector used for each as part of your configuration. By default, the selector for handles is &amp;#8220;h3&amp;#8221;, and the selector for panels is &amp;#8220;.panel&amp;#8221;. Obviously that was fairly specific to my original implementation, so I&amp;#8217;ll look to fix that in the near future.&lt;/p&gt;

&lt;p&gt;Notice that, because we&amp;#8217;re specifying our own selectors, we&amp;#8217;re able to use flexible HTML for either the panel or the handle. However, it&amp;#8217;s also worth remembering that the accordion script injects a link around the contents of whatever you specify as the handle, so that the handle becomes focusable and keyboard navigable. If you are likely to end up with invalid markup (i.e. the inline link wrapped around a block level element), you may get unpredictable behaviour cross-browser.&lt;/p&gt;

&lt;h3&gt;CSS&lt;/h3&gt;


&lt;p&gt;The included CSS is really only a reset style-sheet for the list elements within the accordion. You will probably already be achieving this with your own reset stylesheet, but you can add the following link to the head of your document:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;css/accordion.core.css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;JavaScript&lt;/h3&gt;


&lt;p&gt;To activate the accordion in your pages, you will require both jQuery and the accordion script itself to be included at the bottom of your page, just before the closing &lt;code&gt;&lt;/code&gt; tag, but before any script that applies the accordion to a jQuery object.&lt;/p&gt;

&lt;p&gt;A default implementation would look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;    &lt;span class="ni"&gt;&amp;amp;hellip;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;js/jquery-1.4.2.min.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;js/jquery.accordion.2.0.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.accordion&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As with my carousel, you can configure the accordion more specifically by passing a configuration object to the &lt;code&gt;.accordion()&lt;/code&gt; method:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.accordion&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;accordion&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="s2"&gt;&amp;quot;h3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;panel&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="s2"&gt;&amp;quot;.panel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;easing&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="s2"&gt;&amp;quot;swing&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;accordion&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;toggle&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;activeClassPanel&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;open&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;activeClassLi&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;lockedClass&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s2"&gt;&amp;quot;locked&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note: The above options are all the defaults.&lt;/p&gt;

&lt;p&gt;Parameters for the configuration object are as follows:&lt;/p&gt;

&lt;table style="border-collapse: collapse; font-size: 100%;"&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Option&lt;/th&gt;
            &lt;th&gt;Value&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;handle&lt;/td&gt;
            &lt;td&gt;A selector that specifies the element that will contain the injected link to trigger the opening of each panel.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;panel&lt;/td&gt;
            &lt;td&gt;A selector that specifies the panel element to open and close.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;speed&lt;/td&gt;
            &lt;td&gt;The animation speed for opening and closing. Defaults to 200.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;easing&lt;/td&gt;
            &lt;td&gt;The animation easing for opening and closing. Defaults to &amp;#8220;swing&amp;#8221;.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;accordion&lt;/td&gt;
            &lt;td&gt;A boolean to specify whether other items should close when one is opened. If this is false, all items work independently.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;toggle&lt;/td&gt;
            &lt;td&gt;A boolean to specify whether a handle can toggle opening and closing of an element.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;activeClassPanel&lt;/td&gt;
            &lt;td&gt;HTML class for the active panel.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;activeClassLi&lt;/td&gt;
            &lt;td&gt;HTML class for the active parent &lt;code&gt;&lt;li&gt;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;lockedClass&lt;/td&gt;
            &lt;td&gt;HTML class used to lock any panels open.&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;I&amp;#8217;ve tried to cover all the above concepts in the examples page. However, feel free to comment requests for more information, or bug reports. Alternatively, you can fork and append the GitHub repo, or register bugs there.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/bAYcjD3r9yM" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/jquery-accordion.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[jQuery Carousel]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/Zgfs2JRmEsY/jquery-carousel.html" />
        <updated>2010-08-18T23:16:40+01:00</updated>
        <id>http://nefariousdesigns.co.uk/jquery-carousel</id>
        <content type="html">&lt;div style="background: #fcc; padding: 10px 10px 0; border: 1px solid #c33; margin: 1.2em 0;"&gt;&lt;strong style="color: #c33;"&gt;Update November 2010:&lt;/strong&gt; Documentation for this jQuery Carousel can now be found here:

&lt;a href="http://projects.timhuegdon.com/modern-carousel/"&gt;Modern Carousel - Tim Huegdon&amp;#8217;s Projects&lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Recently I&amp;#8217;ve had the need to build several jQuery widgets, because, no matter how many already exist in the wild, they never seem to have all the features I require. Reinventing the wheel? Well yes, but there&amp;#8217;s no harm if the current wheel doesn&amp;#8217;t fit the vehicle.&lt;/p&gt;

&lt;p&gt;Further to that, building widgets with various JavaScript libraries is actually pretty good fun, and is definitely a good way of familiarising yourself with that particular library. Having recently moved from using YUI to the more widely used jQuery, these widgets have aided my education.&lt;/p&gt;

&lt;p&gt;So without further ado, here&amp;#8217;s the first: the carousel.&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2&gt;Demo&lt;/h2&gt;


&lt;p&gt;Take a look at the &lt;a href="http://nefariousdesigns.co.uk/projects/widgets/carousel/"&gt;page of example carousels&lt;/a&gt; first, to see the various implementation options.&lt;/p&gt;

&lt;h2&gt;Source Code&lt;/h2&gt;


&lt;p&gt;You can find all the source code hosted on GitHub here, with tarballs and zips:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/nefarioustim/modern-carousel"&gt;Modern Carousel — GitHub repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;




&lt;h3&gt;HTML&lt;/h3&gt;


&lt;p&gt;The core HTML of the carousel should look something like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;carousel&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;clip&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;horizontal&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;carousel&lt;/code&gt;, &lt;code&gt;clip&lt;/code&gt;, and &lt;code&gt;horizontal&lt;/code&gt; classes are all used by both the core CSS and the JavaScript to build the carousel. As a result, they are required features.&lt;/p&gt;

&lt;p&gt;The carousel &lt;code&gt;div&lt;/code&gt; must be the direct parent of the clip &lt;code&gt;div&lt;/code&gt;, which in turn must be the direct parent of the &lt;code&gt;ul&lt;/code&gt; element. The current version of the carousel script does not support the use of an ol, but it&amp;#8217;s one of the features on my todo list.&lt;/p&gt;

&lt;p&gt;For a vertical carousel, you should substitute the &lt;code&gt;horizontal&lt;/code&gt; class with &lt;code&gt;vertical&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;CSS&lt;/h3&gt;


&lt;p&gt;The only required CSS for the carousel, is the &lt;samp&gt;carousel.core.css&lt;/samp&gt; file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;css/carousel.core.css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;My examples also include a CSS skin file that applies some styling to the carousel controls. Feel free to reuse this, or poke at it to come up with your own styles:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;css/carousel.skin.css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h3&gt;JavaScript&lt;/h3&gt;


&lt;p&gt;To add the JavaScript, you simply need to include the script—along with jQuery—somewhere on your page. It&amp;#8217;s best to include scripts at the bottom of your pages, before the closing body tag, as some browsers can delay loading of the rest of the page whilst the script loads.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;js/jquery-1.4.2.min.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;js/jquery.carousel.2.0.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once you&amp;#8217;ve done that, you can simply apply the &lt;code&gt;carousel()&lt;/code&gt; method to any jQuery object, like so, to get the default options:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.carousel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Alternatively, you can configure the carousel by passing it a configuration object like so:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.carousel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;loop&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;autoplay&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;hovercontrols&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;hoverpause&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Parameters for the configuration object are as follows:&lt;/p&gt;

&lt;table style="border-collapse: collapse; font-size: 100%;"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope="col"&gt;Option&lt;/th&gt;
&lt;th scope="col"&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;visiblePanes&lt;/td&gt;
&lt;td&gt;The number of panes that are visible in the clipping area.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;panesToMove&lt;/td&gt;
&lt;td&gt;The number of panes to move the carousel when next/previous are clicked.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pagination&lt;/td&gt;
&lt;td&gt;Boolean value to turn on or off pagination.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;speed&lt;/td&gt;
&lt;td&gt;Speed of the transition between panes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;loop&lt;/td&gt;
&lt;td&gt;Boolean value to specify if the carousel loops after the final pane has been reached.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoplay&lt;/td&gt;
&lt;td&gt;Boolean value to specify whether the carousel autoplays.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hovercontrols&lt;/td&gt;
&lt;td&gt;Boolean value to specify if the controls only display when hovering over the carousel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hoverpause&lt;/td&gt;
&lt;td&gt;Boolean value that activates pause when hovering the mouse over the carousel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delay&lt;/td&gt;
&lt;td&gt;The delay, in milliseconds, between transitions when the carousel is playing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transition&lt;/td&gt;
&lt;td&gt;A reference to a transition function defined at $.fn.carousel. E.g. &amp;#8220;yourTransitionHere&amp;#8221; would reference a function defined at $.fn.carousel.yourTransitionHere.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;For more on the transition hooks, it&amp;#8217;s probably best to take a look at the code. When I have more time, I&amp;#8217;ll look at updating the GitHub wiki with details myself.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/Zgfs2JRmEsY" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/jquery-carousel.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Controlling DHCP for VMWare Fusion VMs]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/zAGKbP1aLUI/controlling-dhcp-for-vmware-fusion-vms.html" />
        <updated>2010-03-08T22:42:45+00:00</updated>
        <id>http://nefariousdesigns.co.uk/controlling-dhcp-for-vmware-fusion-vms</id>
        <content type="html">&lt;p&gt;This week I built a brand new Mac for work. This meant I also needed to install VMWare Fusion and knock up a couple of virtual machines for development. Everything was working as expected until I tried using the same VMs at home, and discovered a complete lack of connectivity to—and within—the VMs, despite having active network and internet access on the host OS. After a little investigation, I discovered the issue:&lt;/p&gt;

&lt;p&gt;When I&amp;#8217;ve used VMWare Fusion in the past, my VMs have all been assigned IPv4 addresses in the range 172.16.0.0 through 172.31.255.255, via DHCP (the 20-bit block of RFC1918). This has always suited me fine, and has meant I&amp;#8217;ve been able to assign host file mapping entries for those IP addresses with relative confidence since the addresses have never changed, even after reboots.&lt;/p&gt;

&lt;p&gt;However, on the new Mac, I was surprised to find my VMWare VMs being assigned IPv4 addresses in the range 192.168.0.0 through 192.168.255.255 (the 16-bit block of RFC1918). As you can imagine, this could cause a certain degree of havoc if you&amp;#8217;re LAN is &lt;em&gt;also&lt;/em&gt; assigning DHCP IP addresses in that range. This is exactly what was happening in my case—and on both my work LAN and my home LAN—so VMWare was having to change the IPs each time I changed network.&lt;/p&gt;

&lt;p&gt;To fix this issue, all I needed to do was tell VMWare to use a specific range of IP addresses when assigning DHCP. Unfortunately, VMWare doesn&amp;#8217;t make this particularly easy (despite including a handy network configuration script). So here&amp;#8217;s what you have to do…&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2&gt;A quick word on VMWare Fusion networking&lt;/h2&gt;


&lt;p&gt;Before I jump in with the &amp;#8220;how to&amp;#8221;, let me just take a moment to explain how networking works in VMWare Fusion:&lt;/p&gt;

&lt;p&gt;VMWare sets up two network interfaces during installation, plus a bridge from Fusion to your host&amp;#8217;s active network interface. The two network interfaces that are configured are &amp;#8220;vmnet1&amp;#8221;&amp;#8211;the host-only network&amp;#8211;and &amp;#8220;vmnet8&amp;#8221;&amp;#8211;the NAT network interface. It is the latter of the two that we need to configure for control over VM DHCP.&lt;/p&gt;

&lt;h2&gt;Resetting the network configuration&lt;/h2&gt;


&lt;p&gt;Firstly, make sure you have shut down all your VMs (even the headless ones), and that the VMWare GUI isn&amp;#8217;t running. We&amp;#8217;ll also need to make sure, before we start our configuration, that we&amp;#8217;re in a predictable state for all the configuration files used by VMWare. Handily, VMWare Fusion supplies a network interface configuration script that will allow us to do exactly that.&lt;/p&gt;

&lt;p&gt;VMWare records a bunch of information&amp;#8211;in regard to DHCP and the vmnets&amp;#8211;in a file called &amp;#8220;locations&amp;#8221;. To begin with, we&amp;#8217;ll need to delete that file so that it is regenerated later:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cd /Library/Application\ Support/VMWare\ Fusion/&lt;/kbd&gt;
$ &lt;kbd&gt;rm -f locations&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Following that, we run the handy configuration Perl script, which will automatically answer it&amp;#8217;s own questions with the default answers:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ./vmware-config-net.pl&lt;/kbd&gt;

Configuring a NAT network for vmnet8.

&amp;#8216;ping&amp;#8217; -q -t 10 192.168.119.1 &gt; /dev/null status = 2
The subnet 192.168.119.0/255.255.255.0 appears to be unused.

The file /Library/Application Support/VMware Fusion/vmnet8/dhcpd.conf that this program was about to install already exists. Overwrite? [yes]

The file /var/db/vmware/vmnet-dhcpd-vmnet8.leases that this program was about to install already exists. Overwrite? [yes]

The file /var/db/vmware/vmnet-dhcpd-vmnet8.leases~ that this program was about to install already exists. Overwrite? [yes]

…&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;I haven&amp;#8217;t included all the output here, but it continues on for a while.&lt;/p&gt;

&lt;p&gt;Once you have a prompt again, it&amp;#8217;s time to restart the network services with these update values (even though they&amp;#8217;re not going to be final):&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ./boot.sh --restart&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;This will give you a &amp;#8220;Shutting down VMware Fusion:&amp;#8221; message, followed by a &amp;#8220;Starting VMware Fusion:&amp;#8221; message.&lt;/p&gt;

&lt;p&gt;Once you get your prompt back, make sure the network interfaces have been set up correctly by running the interface configurator:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;ifconfig&lt;/kbd&gt;

…

vmnet8: flags=8863 mtu 1500
        inet 192.168.119.1 netmask 0xffffff00 broadcast 192.168.119.255
        ether 00:50:56:c0:00:08
vmnet1: flags=8863 mtu 1500
        inet 172.16.225.1 netmask 0xffffff00 broadcast 172.16.225.255
        ether 00:50:56:c0:00:01

…&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;You should see something like the above, even if the addresses are slightly different. As long as the vmnet8 and vmnet1 interfaces are showing, we&amp;#8217;re up and running again.&lt;/p&gt;

&lt;h2&gt;Defining your IP range&lt;/h2&gt;


&lt;p&gt;Remember that &amp;#8220;locations&amp;#8221; file we junked earlier? That&amp;#8217;s where we need to define our IP ranges so that the network configuration script can work its magic. Following our little clean-up, that file should now be nice and simple, and ready for our changes. To do that, you&amp;#8217;ll need to edit with root permissions:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;mate locations&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;I&amp;#8217;m using TextMate, which will prompt me for my admin password when I save the file. If you&amp;#8217;re using an editor like vi or vim, you&amp;#8217;ll need to sudo:&lt;/p&gt;

&lt;pre&gt;$ &lt;kbd&gt;sudo vim locations&lt;/kbd&gt;&lt;/pre&gt;


&lt;p&gt;The settings you need to define in the locations file are as follows:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;VNET_8_HOSTONLY_HOSTADDR
VNET_8_HOSTONLY_NETMASK
VNET_1_HOSTONLY_HOSTADDR
VNET_1_HOSTONLY_NETMASK
VNET_1_HOSTONLY_SUBNET&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;I defined mine like so, with the third digit matching the vmnet to which it is assigned, just so I have a point of reference if I need it:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;…
answer VNET_8_HOSTONLY_HOSTADDR &lt;kbd&gt;172.16.8.1&lt;/kbd&gt;
answer VNET_8_HOSTONLY_NETMASK 255.255.255.0
…
answer VNET_1_HOSTONLY_HOSTADDR &lt;kbd&gt;172.16.1.1&lt;/kbd&gt;
answer VNET_1_HOSTONLY_NETMASK 255.255.255.0
answer VNET_1_HOSTONLY_SUBNET &lt;kbd&gt;172.16.1.0&lt;/kbd&gt;
…&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Once we&amp;#8217;ve saved our changes, we simply need to reset the network configuration using the same Perl script as earlier:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ./vmware-config-net.pl&lt;/kbd&gt;

Configuring a NAT network for vmnet8.

Configuring a host-only network for vmnet1.

The host-only network is currently configured to use the private subnet 172.16.1.0/255.255.255.0. Do you want to keep these settings? [yes]&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Finally, restart VMWare Fusion daemons and reconfigure the network interfaces:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ./boot.sh --restart&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Once that is complete, VMWare is configured to use your defined range of IP addresses for both its vmnets. You can check this by running the interface configurator again:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;ifconfig&lt;/kbd&gt;
…
vmnet8: flags=8863 mtu 1500
        inet 172.16.8.1 netmask 0xffffff00 broadcast 172.16.8.255
        ether 00:50:56:c0:00:08 
vmnet1: flags=8863 mtu 1500
        inet 172.16.1.1 netmask 0xffffff00 broadcast 172.16.1.255
        ether 00:50:56:c0:00:01&lt;/samp&gt;&lt;/pre&gt;




&lt;h2&gt;Summary&lt;/h2&gt;


&lt;p&gt;So now you can configure your vmnets in VMWare Fusion to use a predictable range of IP addresses. That, as they say, is that.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/zAGKbP1aLUI" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/controlling-dhcp-for-vmware-fusion-vms.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Website builds using Make]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/owM441ghBJM/website-builds-using-make.html" />
        <updated>2010-02-26T11:17:54+00:00</updated>
        <id>http://nefariousdesigns.co.uk/website-builds-using-make</id>
        <content type="html">&lt;p&gt;In the interests of improving quality in production, of eliminating repetitive tasks, and of general development time saving, it&amp;#8217;s often a good idea to automate some of the website build process. What do I mean by “website build process”? Put simply, the task of preparation and publication to production (your live, open-to-the-internet environment), from a development environment.&lt;/p&gt;

&lt;p&gt;In many cases, this may only be a push from your local machine to your web server, via SCP (or worse, FTP). However, if you&amp;#8217;re working with any level of intricacy—or if you&amp;#8217;re working in a team environment—you will, no doubt, have experienced (amongst other things) the logistical nightmare of multiple CSS and JavaScript files: First building page specific style sheets, so you maintain a single HTTP request for each, and secondly compressing those files so that any unwanted elements are removed for production (e.g. comments, needless whitespace etc.). If you&amp;#8217;re not sure why you&amp;#8217;d want to do these things, I&amp;#8217;d recommend having a look at Steve Souder&amp;#8217;s “&lt;a href="http://www.amazon.co.uk/gp/product/0596529309?ie=UTF8&amp;amp;tag=gamersite-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0596529309"&gt;High Performance Web Sites: Essential Knowledge for Front-End Engineers&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;In this post, I&amp;#8217;m going to look at how you can automate the CSS and JavaScript part of the build process using Make, a handy little program that is installed with the standard build tools on most *nix based systems.&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2&gt;What we want to achieve&lt;/h2&gt;


&lt;p&gt;In the future, we may wish the build to pull completed code from a source-control repository (i.e. Git or SVN) down to a staging environment, and the subsequent push from staging to production. We may also wish our build to handle the pushing of static assets—including images—to a &lt;abbr title="Content Delivery Network"&gt;CDN&lt;/abbr&gt;, like &lt;a href="http://aws.amazon.com/cloudfront/"&gt;Amazon Cloudfront&lt;/a&gt;, or its platform, &lt;a href="http://aws.amazon.com/s3/"&gt;Amazon S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the purposes of this article, we simply want to handle the generation of page-specific CSS and JavaScript static assets. This is by no means a complete build, but it&amp;#8217;s as good a place to start as any. So let&amp;#8217;s break down that process into steps, to better understand it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;

We want to amalgamate our various style sheets, or JavaScripts, into a single, page-specific sheet, so that we can reduce HTTP requests for the page. Imagine we&amp;#8217;ve developed our pages to include CSS like so:

&lt;pre&gt;/index.html
&lt;code&gt;&amp;lt;link rel="stylesheet" href="reset.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="core.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="top-articles.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="tna-module.css" type="text/css"&amp;gt;&lt;/code&gt;

/article.html
&lt;code&gt;&amp;lt;link rel="stylesheet" href="reset.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="core.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="article-content.css" type="text/css"&amp;gt;
&amp;lt;link rel="stylesheet" href="tna-module.css" type="text/css"&amp;gt;&lt;/code&gt;&lt;/pre&gt;

As you can see, both pages include several of the same style sheets. However, they also each have &lt;em&gt;different&lt;/em&gt; sheets, which means we can&amp;#8217;t really have One Big Style Sheet To Rule Them All™ (a &amp;#8220;method&amp;#8221; I&amp;#8217;ve had to suffer so often in the past on large corporate projects) without including every style ever used across the entire site. That would mean downloading styles that could be entirely redundant in the current page.

If we adopt a build process to combine style sheets for a page based on what is actually needed, we can generate page-specific sheets without having to maintain duplicated style rules (which would be the case if we maintained page-specific style sheets manually). This means we reduce our HTTP requests for CSS to a single link per page:

&lt;pre&gt;/index.html
&lt;code&gt;&amp;lt;link rel="stylesheet" href="page-index.css" type="text/css"&amp;gt;&lt;/code&gt;

/article.html
&lt;code&gt;&amp;lt;link rel="stylesheet" href="page-article.css" type="text/css"&amp;gt;&lt;/code&gt;&lt;/pre&gt;

This also rings true for JavaScript, which should be treated in exactly the same way.

&lt;/li&gt;
&lt;li&gt;

We&amp;#8217;d like to compress our page-specific style sheets and external JavaScript using &lt;a href="http://en.wikipedia.org/wiki/Minification_(programming)"&gt;minification&lt;/a&gt;.

In my case, I tend to use the &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI Compressor&lt;/a&gt; tool, since it handles both JavaScript and CSS. There&amp;#8217;s really no reason why you couldn&amp;#8217;t use separate tools for each; &lt;a href="http://code.google.com/closure/compiler/"&gt;Google Closure Compiler&lt;/a&gt;, for example.

&lt;/li&gt;
&lt;li&gt;

The new page-specific files will require versioning so that the filenames change each time they are updated. This means we can adopt a far (or, at least, moderately far) future Expires HTTP header to better make use of caching.

You can read more on this in the YDN performance best practices under &amp;#8221;&lt;a href="http://developer.yahoo.com/performance/rules.html#expires"&gt;Add an Expires or a Cache-Control Header&lt;/a&gt;&amp;#8221;.

There are several methods I could adopt for this:

&lt;ul&gt;
&lt;li&gt;
Add a version number on the end of the filename:
&lt;pre&gt;&lt;samp&gt;styles.1.0.css&lt;/samp&gt;&lt;/pre&gt;
This means a certain degree of management in terms of major and minor releases, and often results in amusing version numbers like 1.132.
&lt;/li&gt;
&lt;li&gt;
Add some form of timestamp to the filename:
&lt;pre&gt;&lt;samp&gt;styles.20100221170134.css&lt;/samp&gt;&lt;/pre&gt;
Generation of timestamps may not be consistent across servers, particularly if you&amp;#8217;re working in a load balanced environment (i.e. the files are duplicated across front-end servers). Also, the filenames, and any related strings, are much longer.&lt;/li&gt;
&lt;li&gt;Create a hash (&lt;a href="http://en.wikipedia.org/wiki/MD5"&gt;MD5&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/SHA"&gt;SHA&lt;/a&gt; etc. of the updated file and use that, or a trimmed version of it, as the filename:
&lt;pre&gt;&lt;samp&gt;6c7f5ed2.css&lt;/samp&gt;&lt;/pre&gt;
This is a method I&amp;#8217;ve only recently been introduced to, but one that clearly has its advantages.

Firstly, hashing the file means we will have exactly the same result on all servers, since the file itself will be the same. It also means we don&amp;#8217;t need to remember previous version numbers. Finally, there&amp;#8217;s really no reason why we can&amp;#8217;t trim the filename down to 8 characters, since the chances of generating duplicates would still be significantly low—and if we &lt;em&gt;do&lt;/em&gt; get a duplicate, we can regenerate easily anyway.&lt;/li&gt;
&lt;/ul&gt;

You&amp;#8217;ve probably figured out that I intend to use the latter hashing method in my build, since it is probably the most robust solution and the one that I prefer.

&lt;/li&gt;
&lt;li&gt;

The HTML that links to our external static files will need to be updated to reflect the new versions of our built files. This simply means finding and replacing the old values.

&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;We want to achieve these four steps with the minimum possible fuss, so we should be aiming for a &amp;#8220;single button build process&amp;#8221; where we can literally click a button, or run a single command to complete the build. Just because we&amp;#8217;re only writing a small part of the final process here, doesn&amp;#8217;t mean we should approach our solution any differently; after all, the final process will probably only run specific sub-builds in turn.&lt;/p&gt;

&lt;h2&gt;Choosing a build method&lt;/h2&gt;


&lt;p&gt;Scripting a build process on the server can be achieved in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;

&lt;strong&gt;Shell scripting&lt;/strong&gt;: available in all operating systems and a good way to automate common command line tasks.

&lt;/li&gt;
&lt;li&gt;

&lt;strong&gt;Server-side scripting languages&lt;/strong&gt;: Perl, Python, Ruby, or even PHP. Any script that can be run from the command-line and that has access to the file-system would be fine. Since we&amp;#8217;re running a web server, most of the above are probably already installed.

&lt;/li&gt;
&lt;li&gt;

&lt;strong&gt;Specific build languages&lt;/strong&gt;: &lt;a href="http://en.wikipedia.org/wiki/Make_(software)"&gt;Make&lt;/a&gt;, &lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt;, &lt;a href="http://ant.apache.org/"&gt;Ant&lt;/a&gt;, &lt;a href="http://nant.sourceforge.net/"&gt;NAnt&lt;/a&gt;, or MSBuild. There are plenty of these around, each with its own pros and cons. They are specifically designed for the build process and, as such, are a perfect fit for what we want to achieve.

&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;As previously stated, I&amp;#8217;m using Make, which is pre-installed on almost every *nix-based system (it wasn&amp;#8217;t pre-installed on my JeOS VMs, but was trivial to install from packages—and is part of the &amp;#8220;build-essential&amp;#8221; package you may have already installed).&lt;/p&gt;

&lt;h2&gt;Using Make&lt;/h2&gt;


&lt;p&gt;Make basically processes a configuration known as a &amp;#8220;Makefile&amp;#8221;. The Makefile contains a list of all target files to be created, and the commands to create them.&lt;/p&gt;

&lt;p&gt;A simple Makefile consists of &amp;#8220;rules&amp;#8221; with the following structure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;target … : prerequisites …
    command
    …
    …
    …&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;

&lt;strong&gt;target&lt;/strong&gt; is usually the name of a file that is generated by a program or a set of commands; in our case, this is going to be the amalgamated and minified page-specific static files. A target can also be the name of an action to carry out, such as &amp;#8220;clean&amp;#8221;.

&lt;/li&gt;
&lt;li&gt;

&lt;strong&gt;prerequisite&lt;/strong&gt; is a file (or another target) that is used as input to create the target. A target is often likely to depend on several of these.

&lt;/li&gt;
&lt;li&gt;

&lt;strong&gt;command&lt;/strong&gt; is an action that Make carries out. A rule may have more than one command, each on its own line.

&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;If you&amp;#8217;re interested in learning more specifics about Make, I&amp;#8217;d recommend taking a look at the &lt;a href="http://www.gnu.org/software/make/manual/"&gt;GNU Make manual&lt;/a&gt;. The manual is available in a bunch of different formats.&lt;/p&gt;

&lt;h2&gt;Building static assets&lt;/h2&gt;


&lt;p&gt;So now that we understand the (very) basics of Make, let&amp;#8217;s try writing a Makefile for our proposed build. I&amp;#8217;m going to gradually build up a Makefile in this tutorial, so that it&amp;#8217;s easy to cut and paste at any given point.&lt;/p&gt;

&lt;p&gt;To begin, create a Makefile in your static assets directory like so:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;vim /path/to/staticfiles/Makefile&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;It&amp;#8217;s best to use a capital M on the Makefile simply to make sure it appears at the top of any &lt;code&gt;ll -l&lt;/code&gt; commands. You may also see all caps used. Personally, I prefer the single capital M.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start by adding a comment header, defining a target for our CSS, and also the prerequisites required:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

/path/to/staticfiles/css/page.css: /path/to/staticfiles/css/src/reset.css /path/to/staticfiles/css/src/core.css /path/to/staticfiles/css/src/top-articles.css /path/to/staticfiles/css/src/tna-module.css&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Straight away you should see a problem; there&amp;#8217;s a lot of repetition of paths there. We can probably adjust that a little by assuming the Makefile is in the /path/to/staticfiles/ directory, and replacing that with ./. However, we could do a better job if we use a Makefile variable like so:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path = /path/to/staticfiles/css/

$(css-path)build/page.css: $(css-path)src/reset.css $(css-path)src/core.css $(css-path)src/top-articles.css $(css-path)src/tna-module.css&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Here you can see we&amp;#8217;ve defined the absolute path as a variable at the top of the Makefile, and are then reusing it in both our target and our prerequisites—using an absolute path seems safer to me, but you may disagree. If we plan ahead a bit more, we can add a few more variables like so:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

$(css-page-target): $(css-page-prereq)&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Here I&amp;#8217;ve added the prerequisites in a space-separated list, since I can use them in that format for the prerequisites, and again when I make use of the cat command later…&lt;/p&gt;

&lt;h3&gt;Concatenating the files&lt;/h3&gt;


&lt;p&gt;We now have a target for Make to examine, and a list or prerequisites that our Make rule will depend upon before it runs.&lt;/p&gt;

&lt;p&gt;The first set of commands should handle the first stage in our build; the concatenation of the files into a single file:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Ok, so I have a few syntactical things to explain here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;

When adding a command to a rule, make sure the command line starts with a tab character. This is required, and if you&amp;#8217;re using an editor that uses the mythical &amp;#8220;soft tab&amp;#8221; (i.e. spaces) you&amp;#8217;ll enter unto a world of woe.

&lt;/li&gt;
&lt;li&gt;

If a line starts with &amp;#8217;&lt;code&gt;@&lt;/code&gt;&amp;#8217;, the echoing of that line is suppressed (but not any output from that command). This just means I&amp;#8217;m hiding the actual commands in the process; if any errors occur, those will appear in stderr.

&lt;/li&gt;
&lt;li&gt;

Ending an echoed string with a \c character prevents echo printing the default trailing newline character. I&amp;#8217;m using this to allow me to display &amp;#8220;[ Done ]&amp;#8221; on the same line, assuming no problems have occurred.

&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Right, now that I&amp;#8217;ve explained a little of the syntax, let&amp;#8217;s take a look at what those commands actually do:&lt;/p&gt;

&lt;p&gt;First of all, we make sure the target file doesn&amp;#8217;t exist by forcing an &lt;code&gt;rm&lt;/code&gt;. Then I&amp;#8217;m echoing a message to show the CSS build has started. Next I &lt;code&gt;cat&lt;/code&gt; the requisites together into a temporary file. Once this is all complete, I echo a &amp;#8220;done&amp;#8221; message (which will appear on the same line as the start message, since I ended the first echo with a /c character).&lt;/p&gt;

&lt;h3&gt;Minification&lt;/h3&gt;


&lt;p&gt;Now we have file containing all the prerequisite CSS files together, we want to minify it with the YUI compressor:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\t\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Here I&amp;#8217;ve specified the path to the YUI Compressor .jar file as another variable and have run our temporary CSS file through it, outputting to the target file. I&amp;#8217;ve also wrapped that process in the same echo trick as before.&lt;/p&gt;

&lt;p&gt;Next, we just need to clean up that temporary file, and this rule is complete:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Now if we run Make, our merged and compressed CSS file will be built:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cd /path/to/staticfiles&lt;/kbd&gt;
$ &lt;kbd&gt;make&lt;/kbd&gt;
Merging CSS files…        [ Done ]
Compressing merged CSS…       [ Done ]
$ &lt;kbd&gt;ls -lah css/build&lt;/kbd&gt;
total 8
drwxr-xr-x  3 auser  agroup   102B 23 Feb 14:17 .
drwxr-xr-x  5 auser  agroup   170B 19 Feb 22:45 ..
-rw-r&amp;#8211;r&amp;#8211;  1 auser  agroup   2.9K 23 Feb 14:17 page.css&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Great!&lt;/p&gt;

&lt;p&gt;At this point, it&amp;#8217;s worth sense-checking the contents of your new file, to see that all your prerequisite files have been included, and that it has been correctly minified. Assuming everything is correct, let&amp;#8217;s duplicate that rule for JavaScript files:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;I&amp;#8217;m using two separate rules here; one for CSS, and one for JavaScript. If I run Make at this point, only the first rule (for the CSS) will be run. This is because Make only ever runs the first rule automatically. If I want both rules to be run, I should set up another rule that defines these rules as prerequisites.&lt;/p&gt;

&lt;h3&gt;Cleaning up old builds&lt;/h3&gt;


&lt;p&gt;It&amp;#8217;s a good idea to define a &amp;#8220;clean&amp;#8221; target that removes all the files that are built in the Makefile. This means the user can start-over easily if they so desire:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

all: $(css-page-target) $(js-page-target)

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js

clean:
    @rm -f $(css-page-target)
    @rm -f $(js-page-target)&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;To run a specific target, rather than the first in the list, you simply pass it as an argument to Make. Let&amp;#8217;s run our clean target like so:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;make clean&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Now if you run Make again, it should build both the CSS and the JavaScript page files:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cd /path/to/staticfiles&lt;/kbd&gt;
$ &lt;kbd&gt;make&lt;/kbd&gt;
Merging CSS files…        [ Done ]
Compressing merged CSS…       [ Done ]
Merging JS files…     [ Done ]
Compressing merged JS…        [ Done ]
$ &lt;/samp&gt;&lt;/pre&gt;




&lt;h3&gt;Hash pipe (cut)&lt;/h3&gt;


&lt;p&gt;The next step is to hash our new page-specific CSS and JS files, and copy them to a higher level (so we don&amp;#8217;t need to have the &amp;#8220;build&amp;#8221; directory on production). To do that we&amp;#8217;ll want to pass the contents of the file to something that will generate a SHA1 checksum. On some systems, you can use &lt;code&gt;shasum&lt;/code&gt;, but on my Mac that didn&amp;#8217;t exist, so I&amp;#8217;m using &lt;code&gt;openssl sha1&lt;/code&gt; instead, like so:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cat file | /usr/bin/openssl sha1&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;This will output a full SHA1 checksum to stdout. We actually want to use it as our filename, and the full checksum is likely to be too long. We can fix that by using the &lt;code&gt;cut&lt;/code&gt; command as follows:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cat file | /usr/bin/openssl sha1 | cut -c1-8&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Now if we want to use that as a filename, we can generate a variable in our Makefile. Let&amp;#8217;s do that for both the JavaScript and the CSS:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

all: $(css-page-target) $(js-page-target)

install: css-build = `cat $(css-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.css
install: js-build = `cat $(js-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.js
install: all

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js

clean:
    @rm -f $(css-page-target)
    @rm -f $(js-page-target)&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Here I&amp;#8217;ve added a new &amp;#8220;install&amp;#8221; target, which uses the &amp;#8220;all&amp;#8221; target as its only prerequisite. I&amp;#8217;ve also defined two variables above the target as target-specific variables. This scopes the variables to this rule alone.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve used the target &amp;#8220;install&amp;#8221; to conform with accepted Make standards. This means that, each time we want to refresh the CSS, we only need to type the following (which is another accepted standard):&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;make clean install&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;As you can see, you are able to pass multiple targets into the &lt;code&gt;make&lt;/code&gt; command as arguments.&lt;/p&gt;

&lt;h3&gt;Using the hash for good, not evil&lt;/h3&gt;


&lt;p&gt;This is all very well and good, but even though we have the new filename stored in a variable, we&amp;#8217;re not doing anything with it. Let&amp;#8217;s rectify that:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

all: $(css-page-target) $(js-page-target)

install: css-build = `cat $(css-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.css
install: js-build = `cat $(js-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.js
install: all
    @cp $(css-page-target) $(css-path)$(css-build)
    @cp $(js-page-target) $(js-path)$(js-build)

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js

clean:
    @rm -f $(css-page-target)
    @rm -f $(js-page-target)
    @rm -f $(css-path)*.css
    @rm -f $(js-path)*.js&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Here I&amp;#8217;ve copied the files to the higher &lt;code&gt;css-path/&lt;/code&gt; and &lt;code&gt;js-path/&lt;/code&gt; directories. This means I won&amp;#8217;t need to sync the &lt;code&gt;build/&lt;/code&gt; and &lt;code&gt;src/&lt;/code&gt; directories to production.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve also added two &lt;code&gt;rm&lt;/code&gt; commands to the &amp;#8220;clean&amp;#8221; target that remove all built CSS and JS files in the respective directories, regardless of name. &lt;strong&gt;Note:&lt;/strong&gt; make sure you&amp;#8217;re not doing this recursively, otherwise you&amp;#8217;ll trash all your valuable source files.&lt;/p&gt;

&lt;p&gt;Now if you look in the &lt;code&gt;css-path/&lt;/code&gt; directory, you should see something like:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;ls -lah&lt;/kbd&gt;
total 4.0K
drwxr-xr-x 5 auser agroup  170 2010-02-25 22:36 .
drwxr-xr-x 7 auser agroup  238 2010-02-25 22:14 ..
-rw-r&amp;#8211;r&amp;#8211; 1 auser agroup 2.9K 2010-02-25 22:36 6c7f5ed2.css
drwxr-xr-x 3 auser agroup  102 2010-02-25 22:36 build
drwxr-xr-x 4 auser agroup  136 2010-02-25 21:54 src
$&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Great, so now we have a (reasonably) unique filename for our concatenated and minified CSS; and if you look in your JavaScript directory, you should see something similar.&lt;/p&gt;

&lt;p&gt;The next step is to actually find and replace the inclusion of your file in your HTML.&lt;/p&gt;

&lt;h3&gt;Automagically updating the HTML&lt;/h3&gt;


&lt;p&gt;We basically need to run a find and replace on the HTML that includes your external CSS and JavaScript files, whether that is an SSI or a full HTML page. To do that, we should probably specify those files as variables, so that they can be easily maintained:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

css-inc-file =      /path/to/publicfiles/page.html
js-inc-file =       /path/to/publicfiles/page.html

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

all: $(css-page-target) $(js-page-target)

install: css-build = `cat $(css-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.css
install: js-build = `cat $(js-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.js
install: all
    @cp $(css-page-target) $(css-path)$(css-build)
    @cp $(js-page-target) $(js-path)$(js-build)

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js

clean:
    @rm -f $(css-page-target)
    @rm -f $(js-page-target)
    @rm -f $(css-path)*.css
    @rm -f $(js-path)*.js&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;I&amp;#8217;ve added two variables here in case, at some point in the future, we decide to break the inclusions out into separate files.&lt;/p&gt;

&lt;p&gt;Now we&amp;#8217;ve defined those files in the Makefile, we should really use them for something. I&amp;#8217;m going to use &lt;code&gt;sed&lt;/code&gt; to find and replace the references to the external static files:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;#========================================
# Static Asset Build Makefile
#
# Author: Tim Huegdon
#========================================

domain =            yoursite.com

css-inc-file =      /path/to/publicfiles/page.html
js-inc-file =       /path/to/publicfiles/page.html

css-path =      /path/to/staticfiles/css/
css-page-target =   $(css-path)build/page.css
css-page-prereq =   $(css-path)src/reset.css \
            $(css-path)src/core.css \
            $(css-path)src/top-articles.css \
            $(css-path)src/tna-module.css

js-path =       /path/to/staticfiles/js/
js-page-target =    $(js-path)build/page.js
js-page-prereq =    $(js-path)src/carousel.js \
            $(js-path)src/awesome.js \
            $(js-path)src/beacon.js

yui-jar =       ~/tools/yui/yuicompressor-2.4.2.jar

all: $(css-page-target) $(js-page-target)

install: css-build = `cat $(css-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.css
install: js-build = `cat $(js-page-target) | /usr/bin/openssl sha1 | cut -c1-8`.js
install: all
    @cp $(css-page-target) $(css-path)$(css-build)
    @cp $(js-page-target) $(js-path)$(js-build)
    @echo "Linking to updated CSS and JavaScript…\t\c"
    @sed -i '' "s/http:\/\/static\.$(subst .,\.,$(domain))\/css.[^\"]*/http:\/\/static\.$(subst .,\.,$(domain))\/css\/$(subst .,\.,$(css-build))/" $(css-inc-file)
    @sed -i '' "s/http:\/\/static\.$(subst .,\.,$(domain))\/js.[^\"]*/http:\/\/static\.$(subst .,\.,$(domain))\/js\/$(subst .,\.,$(js-build))/" $(js-inc-file)
    @echo "[ Done ]"
    @echo "Installation is complete."

$(css-page-target): $(css-page-prereq)
    @rm -f $(css-page-target)
    @echo "Merging CSS files…\t\t\t\c"
    @cat $(css-page-prereq) &gt; $(css-path)build/tmp.css
    @echo "[ Done ]"
    @echo "Compressing merged CSS…\t\c"
    @java -jar $(yui-jar) -o $(css-page-target) $(css-path)build/tmp.css
    @echo "[ Done ]"
    @rm -f $(css-path)build/tmp.css

$(js-page-target): $(js-page-prereq)
    @rm -f $(js-page-target)
    @echo "Merging JS files…\t\t\t\c"
    @cat $(js-page-prereq) &gt; $(js-path)build/tmp.js
    @echo "[ Done ]"
    @echo "Compressing merged JS…\t\c"
    @java -jar $(yui-jar) -o $(js-page-target) $(js-path)build/tmp.js
    @echo "[ Done ]"
    @rm -f $(js-path)build/tmp.js

clean:
    @rm -f $(css-page-target)
    @rm -f $(js-page-target)
    @rm -f $(css-path)*.css
    @rm -f $(js-path)*.js&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;The first thing I&amp;#8217;ve done here is to define another variable for the domain name of the site. This is because I&amp;#8217;m going to need to use it to identify the links to the filenames in the regular expression.&lt;/p&gt;

&lt;p&gt;Next I added the sed commands to our &amp;#8220;install&amp;#8221; target, using the -i option (edit files in-place). The regular expression is basically looking for a reference to &lt;var&gt;http://static.yourdomain.com/css/something&lt;/var&gt; and replacing it with the full URI to our newly generated file.&lt;/p&gt;

&lt;p&gt;Once this step is finished, the installation of our newly built static files is complete; and, as such, so is our Makefile. As previously stated, to run a new build—that also cleans up old builds—simply type the following:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;make clean install&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;




&lt;h2&gt;A better development environment&lt;/h2&gt;


&lt;p&gt;Instigating a build process in your environment allows you the flexibility to design your &lt;em&gt;development&lt;/em&gt; environment for ease of maintenance, rather than having to think about optimisation and structure for production. Your development environment &lt;em&gt;should&lt;/em&gt; be quite heavily different from staging or production; you want it to be optimised for development, maintenance, and bug-fixing, rather than optimised for speed, efficiency, and load.&lt;/p&gt;

&lt;p&gt;Ultimately, this means that the build allows you &lt;a href="http://mikewest.org/2010/02/CSS-rules-of-thumb"&gt;the freedom to write better CSS&lt;/a&gt; and JavaScript, in well separated files. These files are then easily maintained by developers—since they&amp;#8217;ll be easier to read and well commented—and also easier to maintain through source control—since the separation into a greater number of files means more control of more specific code.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/owM441ghBJM" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/website-builds-using-make.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Premature Publish]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/d-cKW5-SJ9Y/premature-publish.html" />
        <updated>2010-02-26T10:50:22+00:00</updated>
        <id>http://nefariousdesigns.co.uk/premature-publish</id>
        <content type="html">&lt;p&gt;Last night I accidentally published a new post, &amp;#8220;Website builds using Make&amp;#8221; before it was complete. Apologies if you read it and wondered why it never reached a proper conclusion; I&amp;#8217;m still finishing it off.&lt;/p&gt;

&lt;p&gt;I really really need to move off of WordPress.&lt;/p&gt;

&lt;p&gt;Needless to say, the completed version of that post should be published very soon!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/d-cKW5-SJ9Y" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/premature-publish.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[Mac VirtualBox Linked Clones]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/xZS5mVH2iZA/mac-virtualbox-linked-clone.html" />
        <updated>2010-02-12T14:50:45+00:00</updated>
        <id>http://nefariousdesigns.co.uk/mac-virtualbox-linked-clone</id>
        <content type="html">&lt;p&gt;I&amp;#8217;ve been a VMWare Fusion user for quite some time, and I&amp;#8217;ve been more than happy with the experience, but the most recent version has dumped an unsupported feature that is essential to my personal workflow: Headless Mode.&lt;/p&gt;

&lt;p&gt;One of the VMWare developers responded to requests for information on the missing headless feature in the &lt;a href="http://communities.vmware.com/message/1403788#1403788"&gt;&amp;#8220;Fusion 3 Headless?&amp;#8221; VMWare communities thread&lt;/a&gt;. Needless to say, the feature may or may not reappear in a &lt;em&gt;newer&lt;/em&gt; version of Fusion, but certainly doesn&amp;#8217;t in the &lt;em&gt;current&lt;/em&gt; version.&lt;/p&gt;

&lt;p&gt;With that in mind, I decided it was about time I took a look at &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;, the Open Source virtualisation product from Sun (now Oracle). I&amp;#8217;d already heard mostly good things about VirtualBox—except some complaints of slow Windows VMs—and it definitely includes a Headless Mode of its own. What&amp;#8217;s more, after a bit of investigation on t&amp;#8217;internet, I discovered that linked cloning also appeared to be supported, and &lt;a href="http://nefariousdesigns.co.uk/archive/2009/09/virtualised-development-environments-on-a-mac/"&gt;linked clones are essential to my workflow&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;




&lt;h2&gt;Create the master&lt;/h2&gt;


&lt;p&gt;Before we can create clones, we&amp;#8217;re going to need a master. In my examples I&amp;#8217;ll be creating and cloning an &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; VM, but there&amp;#8217;s really no reason why you couldn&amp;#8217;t do the same with &lt;a href="http://www.microsoft.com/windows/default.aspx"&gt;Windows&lt;/a&gt;—in fact, it would be of benefit for cross-browser testing in the various versions of IE, since you can have an instance of Windows for each.&lt;/p&gt;

&lt;p&gt;Before we begin creating the master VM, it&amp;#8217;s worth updating the VirtualBox preferences so that it puts your files in a predictable place. The default is ~/Library/VirtualBox/ but I have a specific ~/vms/ directory that I like to use. When doing this, be aware that new virtual disk files are created &lt;em&gt;before&lt;/em&gt; new VM directories in the &amp;#8220;Create New VM&amp;#8221; process. This means it&amp;#8217;s worthwhile having two directories; one for virtual disk files, and one for the virtual machine directories. This is a pain in the proverbials for portability, but don&amp;#8217;t worry too much about it since VirtualBox creates the snapshot difference disks (which will be used by our clones) in the virtual machine directory.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s begin:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create new VM (cmd+N) and name it whatever you want. It&amp;#8217;s probably best to make some reference to it being your master, but that&amp;#8217;s entirely up to you. I used &amp;#8220;atum&amp;#8221; (first of the Egyptian Gods), and specified my OS as Linux / Ubuntu, unsurprisingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When asked to specify, I went with the recommended RAM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The next step in the wizard is to specify a new or existing virtual disk. Since this is our master, select &amp;#8220;Create New Disk&amp;#8221;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A second wizard will pop up, specifically for defining the new virtual disk. Use the following options: dynamically expanding, 10Gb (although, VirtualBox recommends 8Gb for Ubuntu, which would also be fine), located in your new default virtual disks folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click finish to end the Create New Virtual Disk Wizard. VirtualBox may pause for a second whilst creating the new .vdi and updating the various XML files that reference it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After a second or two, you should be presented with the original wizard again. Click &amp;#8220;Finish&amp;#8221; to complete the creation process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure new VM is selected in the list of VMs in your VirtualBox window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to make sure we can connect to the our new VM locally. To do that, you&amp;#8217;ll need to add a host-only network adaptor in addition to the standard NAT one. Click the &amp;#8220;Network&amp;#8221; heading on the right side of the VirtualBox window, and the settings dialog should pop up. Make sure &amp;#8220;Adaptor 1&amp;#8221; is enabled and using &amp;#8220;NAT&amp;#8221;, then select &amp;#8220;Adaptor 2&amp;#8221; and click &amp;#8220;Enable&amp;#8221;. Change &amp;#8220;Attached to&amp;#8221; to &amp;#8220;Host-only Adaptor&amp;#8221; and just use the suggested name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next we need to tell our VM to boot and install Ubuntu the first time we run our VM. Click &amp;#8220;Storage&amp;#8221; either in the right hand side of the VirtualBox window, or in the tab bar of the settings dialog that should still be open from the previous step. Choose the CD/DVD device and point it at your Ubuntu ISO, ready for your install.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &amp;#8220;Ok&amp;#8221; to close the settings dialog.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start your new VM and it should boot into the Ubuntu Installation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the installation introduction screen, push F4 and select &amp;#8220;Install Minimal Virtual Machine&amp;#8221;, then start the install as normal. This will install Ubuntu as JeOS, which is specifically configured for virtual machine use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Ubuntu however you like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once your install is complete, make sure to remove the Ubuntu ISO from the CD/DVD device. This won&amp;#8217;t come back to bite you straight away since the first few reboots appeared to ignore it during my install. However, I did end up spending a good 10 minutes wondering why I could no longer SSH to a VM that had previously been working fine before reboot during my install.&lt;/p&gt;&lt;/li&gt;
&lt;li style="background-color: #fee; border: 1px solid #f33; padding: 0 10px;"&gt;&lt;p&gt;&lt;strong style="color: #f33;"&gt;Top tip:&lt;/strong&gt; Depending on the keyboard set-up you opted for during the installation of Ubuntu, you may want to change the AltGr key to be the left alt (option) on your Mac keyboard. You can do this with the following bash command in Ubuntu:&lt;p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo dpkg-reconfigure console-setup&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;If you &lt;em&gt;don&amp;#8217;t&lt;/em&gt; do this, you may have trouble trying to enter # characters later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, let&amp;#8217;s make sure apt is all up to date. Do that by running the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo apt-get update&lt;/kbd&gt;
$ &lt;kbd&gt;sudo apt-get upgrade&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;If you&amp;#8217;re using an older than current version of Ubuntu, you may want to do the following (note: the second command reboots the VM):&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo apt-get dist-upgrade&lt;/kbd&gt;
$ &lt;kbd&gt;sudo shutdown -r now&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next I installed vim as my editor of choice.&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo apt-get install vim&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since the basic Ubuntu terminal is a little sparse, you&amp;#8217;ll probably want to be able to SSH into the VM and use your terminal of choice. To do that, we need to activate the secondary interface for the adaptor we added earlier.&lt;/p&gt;
&lt;p&gt;First, edit the following file:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo vim /etc/network/interfaces&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Add the following lines at the bottom:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;# The secondary network interface
auto eth1
iface eth1 inet static
    address 192.168.56.2
    netmask 255.255.255.0&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;#8217;s important to use that IP address, since the vboxnet0 is configured on 192.168.56.1 by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Activate the eth1 interface:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ifup eth1&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now make sure ssh is installed:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo apt-get install ssh&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Following all that, you should now be able to SSH to your new VM from your host:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;ssh 192.168.56.2&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should now install all the software you want shared across your clones. In my case, that was the usual scripting languages, web servers, database servers etc. used for web development.&lt;/p&gt;
&lt;p&gt;Once you&amp;#8217;re happy with your build, move on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let&amp;#8217;s clear the persistent net rules on our master disk, just so they don&amp;#8217;t come back to bite us later. In my VMWare tutorial, I did this on the clones, but it makes far more sense to do it on the master before cloning:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo cp /dev/null /etc/udev/rules.d/70-persistent-net.rules&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now that we&amp;#8217;re done with SSH, we should bring down the secondary interface so that it&amp;#8217;s easier to configure on our clones later. Bring the interface down like so:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ifdown eth1&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Next, go back into the interface configuration file, and comment out the second interface you added:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo vim /etc/network/interfaces&lt;/kbd&gt;
# The secondary network interface
# auto eth1
# iface eth1 inet static
#     address 192.168.56.2
#     netmask 255.255.255.0&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Now, when you create your clones, you&amp;#8217;ll be able to uncomment and make sure the IP doesn&amp;#8217;t clash with other cloned VMs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, shutdown your VM so we can break it down to the parts we need:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo shutdown -P now&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;Prepare the master for cloning&lt;/h2&gt;


&lt;p&gt;Unlike VMWare, preparing a VirtualBox VM for cloning is actually a fairly straightforward procedure, and can be completed in three fairly simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, you&amp;#8217;ll need to &amp;#8220;release&amp;#8221; the virtual disk from the virtual machine using the Virtual Media Manager in VirtualBox.&lt;/p&gt;
&lt;p&gt;To do this, just open VirtualBox and choose the Virtual Media Manager from the File menu (alternatively, push cmd+D). Select your master virtual disk in the &amp;#8220;Hard Disks&amp;#8221; tab, and click the &amp;#8220;Release&amp;#8221; button in the toolbar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next it&amp;#8217;s worthwhile telling VirtualBox that your master virtual disk is immutable. Run the following command in a terminal on your host machine:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;vboxmanage modifyhd --type immutable atum.vdi&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Where atum.vdi is the name of your master virtual disk. Don&amp;#8217;t worry about using the full path, VirtualBox should already know where your virtual disks all are (thanks to the Virtual Media Manager).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, you may like to make the .vdi file read-only:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;chmod a-w /path/to/atum.vdi&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;/ol&gt;


&lt;p&gt;And we&amp;#8217;re done. The master virtual disk is now ready to be cloned.&lt;/p&gt;

&lt;h2&gt;Create a clone&lt;/h2&gt;


&lt;p&gt;So let&amp;#8217;s go ahead and make a clone of our master:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new VM (cmd+N) and name it whatever you like (I used &amp;#8220;ra&amp;#8221;, to follow that Egyptian deity theme). Obviously, make sure to use the same OS as your master when you define your new VM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once again use the recommended RAM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose &amp;#8220;Use existing hard disk&amp;#8221; and select your master, which should already appear in the drop-down since it&amp;#8217;s already in the Virtual Media Manager.&lt;/p&gt;
&lt;p&gt;Once you do this, VirtualBox will automatically create a snapshot difference disk in the &amp;#8220;Snapshots&amp;#8221; child directory of your virtual machine directory. So in my case, that was here:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;/path/to/vms/ra/Snapshots/&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Be aware that the difference disks are named with a UUID, and that they reset automatically when the cloned virtual machine is rebooted.&lt;/p&gt;
&lt;p&gt;To stop the virtual disk from auto-resetting every time you reboot, you&amp;#8217;ll need to run the following command once the snapshot has been created:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;vboxmanage modifyhd --autoreset=off /path/to/vms/ra/Snapshots/{long-uuid}.vdi&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &amp;#8220;Finish&amp;#8221; in the &amp;#8220;Create New VM&amp;#8221; dialog.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once again, we need to set up the second network interface, so go ahead and do the same as we did for the master: Click &amp;#8220;Network&amp;#8221; and make sure &amp;#8220;Adaptor 1&amp;#8221; is enabled and using &amp;#8220;NAT&amp;#8221;. Select &amp;#8220;Adaptor 2&amp;#8221; and click &amp;#8220;Enable&amp;#8221;. Change &amp;#8220;Attached to&amp;#8221; to &amp;#8220;Host-only Adaptor&amp;#8221; and use the suggested name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start your new VM and log in with the same user you used on the master. Note your clone is still using the hostname of your master. We&amp;#8217;ll update that in a second.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It&amp;#8217;s time to reactivate the secondary interface within Ubuntu:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo vim /etc/network/interfaces&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Uncomment the secondary interface and update the last number of the IP address so that it is unique on the vboxnet.&lt;/p&gt;
&lt;p&gt;Now activate the interface again:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo ifup eth1&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;You can now ssh to the clone on the address you specified in the secondary interface configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, let&amp;#8217;s update the hostname of our clone in two places, so that it&amp;#8217;s unique. First, the hostname file itself, and secondly in the /etc/hosts file so the loopback doesn&amp;#8217;t get confused:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo vim /etc/hostname&lt;/kbd&gt;
ra
$ &lt;kbd&gt;sudo vim /etc/hosts&lt;/kbd&gt;
127.0.0.1    ra&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;Finally restart the hostname service:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo /etc/init.d/hostname.sh start&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;And that&amp;#8217;s it; you now have a fully functioning linked clone. Feel free to make some more from your master.&lt;/p&gt;

&lt;h2&gt;Headless Mode&lt;/h2&gt;


&lt;p&gt;Now that we have an army of working linked clone virtual machines, it&amp;#8217;s probably worthwhile making use of Headless Mode so that they are all running in the background without you needing the VirtualBox GUI invading your desktop and draining resources.&lt;/p&gt;

&lt;p&gt;First, shutdown your VM by logging in and running this:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sudo shutdown -P now&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Now you can start it back up by running the following command on your host:&lt;/p&gt;

&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;(VBoxHeadless -v=off -s ra &amp;)&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;


&lt;p&gt;Be aware that this runs the VBoxHeadless script in the background, as it doesn&amp;#8217;t normally auto-exit. I&amp;#8217;m running it in a sub-shell because someone far more knowledgeable than myself suggested that this was safer. Cheers Norm.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;


&lt;p&gt;Firstly, I&amp;#8217;d like to thank a few people for their help with this: &lt;a href="http://intranation.com/"&gt;Bradley Wright&lt;/a&gt; for being the usual tech. sounding board, &lt;a href="http://muffinresearch.co.uk/"&gt;Stuart Colville&lt;/a&gt; for clearing up the mystery of VirtualBox network adaptors, and &lt;a href="http://marknormanfrancis.com/"&gt;Mark Norman Francis&lt;/a&gt; for being considerably better at server administration and bash than me.&lt;/p&gt;

&lt;p&gt;You should be able to get a good virtualised development environment up in VirtualBox now. Feel free to post any questions in the comments, and if I can&amp;#8217;t answer personally, I&amp;#8217;ll pester someone that might be able to.&lt;/p&gt;

&lt;p&gt;In the future I&amp;#8217;m going to look at automating this process, but the VBoxManage command is considerably different to VMWare&amp;#8217;s vmrun and it&amp;#8217;s going to take me a little while to figure out stuff like creating new VMs, and releasing virtual disks without removing the entire IDE controller from the master (yeah; I already tried).&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/xZS5mVH2iZA" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/mac-virtualbox-linked-clone.html</feedburner:origLink></entry>
    
    <entry>
        <title type="html"><![CDATA[The value of trying things out]]></title>
        <link href="http://feedproxy.google.com/~r/nefariousdesigns/~3/ZLvT1udeEak/the-value-of-trying-things-out.html" />
        <updated>2010-01-27T19:25:06+00:00</updated>
        <id>http://nefariousdesigns.co.uk/the-value-of-trying-things-out</id>
        <content type="html">&lt;p&gt;I was recently reminded of an interesting situation that arose a while back at Yahoo! London; a situation that was resolved using simple testing and demonstration:&lt;/p&gt;

&lt;p&gt;We had recently begun extensive performance optimisation of the &lt;a href="http://uk.eurosport.yahoo.com/"&gt;Yahoo! Eurosport&lt;/a&gt; site in an attempt to improve our &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; grades. At the time, the design of the Yahoo! Eurosport site used rounded corners on all of the modules. Due to the fact that we had developed the modules to be bulletproof, and because the backgrounds varied slightly for different modules, this ended up with a considerable overhead on CSS backgrounds.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Yahoo! Eurosport before:&lt;/p&gt;

&lt;p&gt;Our first idea was to approach &lt;abbr title="User Experience Design"&gt;UED&lt;/abbr&gt; to find out if we could just remove the rounded corners and instantly improve our performance. In &lt;em&gt;our&lt;/em&gt; eyes, this was an insignificant visual change with an extremely high pay-off in regard to the performance boost. However, in UED&amp;#8217;s eyes, this change was unacceptable and would diminish the impact of the design enough for them to categorically say no.&lt;/p&gt;

&lt;p&gt;So we accepted the decision and went back to our desks to continue our optimisation. But, by its very nature, YSlow just couldn&amp;#8217;t let it rest; the resulting reports continually highlighted those backgrounds as a significant issue.&lt;/p&gt;

&lt;p&gt;With that in mind, one of the front-end developers on our team decided to take matters into his own hands and create a second style sheet without the rounded corner images just for the purpose of testing. The resultant comparisons were, unsurprisingly, an extensive boost in performance; both in download times, and in rendering time.&lt;/p&gt;

&lt;p&gt;Several days later, we were chatting with the UEDs on the team and happened to apologise for leaving the non-rounded corner style sheet active on the testing environment. It was then that we discovered &lt;strong&gt;they hadn&amp;#8217;t noticed at all&lt;/strong&gt;—and, what&amp;#8217;s more, they were pleasantly surprised to find the impact on the design was minimal. What&amp;#8217;s more, we were able to demonstrate the difference in rendering time to them in their own browsers.&lt;/p&gt;

&lt;p&gt;Yahoo! Eurosport after:&lt;/p&gt;

&lt;p&gt;Following that little test, and subsequent demonstration to the UED team, it was unanimously agreed that the gain in performance was significantly greater than the loss of visual impact, and we were able to move the updated CSS live.&lt;/p&gt;

&lt;p&gt;The only downside to this process was the fact that we had to leave a lot of legacy HTML wrappers in place that would normally have hosted the extra background images. In a perfect world, we would have been able to strip all that HTML as well. Unfortunately, the templates were developed in such a hurried way that this task was basically impossible, and those redundant wrappers are in place to this day.&lt;/p&gt;

&lt;p&gt;I think that little anecdote illustrates the value in testing changes even if you thoroughly disagree with them at the outset. You&amp;#8217;ll either be proven entirely right, or you&amp;#8217;ll be pleasantly surprised.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nefariousdesigns/~4/ZLvT1udeEak" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://nefariousdesigns.co.uk/the-value-of-trying-things-out.html</feedburner:origLink></entry>
    
</feed>

