I will be the first to admit that this time it's my fault. There's something wrong with the Internet and I'm afraid I did it. See, back when the Web was first getting to be a big thing, I and just about every other computer programmer made fun of people who claimed they could "program in HTML." We weren't the only ones on that bandwagon: Lots of businesses imposed a strict separation between "development" and "design" -- and still do.
The problem is, strictly separating designers from developers has resulted in a Web built by people frightfully unaware of the standards and technologies required to make it go. Most Web pages today extend well beyond the limited scope of HTML, and a good many of them bring together a "pure" programming language like Java or C++ (you know, real code with control structures and variables and stuff) with healthy chunks of JavaScript, PHP, HTML, CSS, and oh, don't forget, XML.
Designers who have been taught to not think of themselves as programmers take little responsibility for understanding how their designs translate into code -- which means more work for the people charged with implementing their designs. Worse, even Web developers who take the time to understand how something like Ajax works, rather than buying in to Adobe's Flex revolution, do not consider themselves Web engineers. The end result is a generation of Web designers and developers who are attempting to build increasingly sophisticated Web sites without reference to the best practices of software engineering: Things like requirements gathering, the DRY principle, and how to refactor your way out of a programming cul de sac.
This month, I'll talk about just a few of the software engineering best practices (generally learned the hard way over a period of decades) seemingly lost in the rush to build a brave new Internet.
Surely you've heard of requirements?
Requirements gathering is an essential aspect of software engineering that is consistently overlooked in Web development. Questions like "Should users be able to access this site from a cell phone browser?" or "Should URLs be intuitive enough to be used for site navigation?" are rarely answered in a structured way. Instead, decisions are made on the fly and users get to live with the results. For example, I was recently disappointed when my favorite online comic adopted a new naming convention that made it impossible for me to navigate through archived comics by date, as I previously had done for years.
Whereas the software developers of old spent years learning the theory of requirements gathering and the importance of doing it up front, today's Web developers too often seem to work in a vacuum, where the perspective and needs of the user are all but ignored. I don't object to uploading a plug-in for a Web site whose creators have carefully weighed the value of that plug-in and decided it's worthwhile. I do object when the question of audience, accessibility, and value to the end user clearly just never came up.
When you're working on a new site or feature, ask requirements questions up front. Who is your audience? What assumptions can you safely make about the browsers, operating systems, and hardware used to access your site? What assumptions do you want to make about the motor, vision, hearing, and speech ability of your users? Is it reasonable to assume that every user has access to an e-mail program? Maybe not, if you remember that many users access the Internet from public terminals or through a cell phone.
Bandwidth is another issue often taken for granted by Web savvy developers and designers, but it's still an issue for many users. Take the time to measure how long it takes for your server to generate a page in a variety of browsers and systems, including accessibility browsers and public library systems.
The Don't Repeat Yourself principle, also known as DRY, is considered a foundation of good engineering. Surprisingly, it's rarely followed in Web development. The point is not to duplicate material, components, or effort. It's practically inevitable that given two versions of a navigation bar you will eventually update one but not the other. Not only does that lead to confusion for the user, it also means more effort for you somewhere down the line. The answer, as grandpa might say, is Don't Repeat Yourself!
One most egregious example of Web developers overlooking DRY occurred during the browser wars, when pages were commonly optimized for a specific browser. Many people thought nothing of studding their Web pages with a wide variety of font and display tags, controlling the look and feel of their pages down to the finest detail. (It wasn't uncommon for every paragraph on a Web page to be carefully tagged with the desired font!). Of course, problems arose as these sites evolved. What happened when a company logo was redesigned and the page font had to be changed to fit it better? Hours were spent opening every single file on the site, searching for and replacing font tags, and hoping not to miss anything or make a mistake (such as changing "Times" to "Verdana" in text and not just in font tags).
When CSS (Cascading Style Sheets) came along it changed everything. These days layout information goes into a single central style sheet. Update an element in the CSS and the change takes effect wherever that style sheet is specified. Still, Web developers sometimes forget to implement the DRY principle when writing up style sheets, and the resulting duplication of effort is still unnecessarily time consuming.
Imagine, if you will, a style sheet that asserts the use of Helvetica for headings, with distinctions only in size. Well, it's easy enough to write that, isn't it?
Listing 1. Repetitive CSS
h1 { font-family: Helvetica, sans-serif; font-size: 250% }
h2 { font-family: Helvetica, sans-serif; font-size: 200% }
h3 { font-family: Helvetica, sans-serif; font-size: 150% }
h4 { font-family: Helvetica, sans-serif; font-size: 100% }
|
But what happens when you need to switch your pages over to a new font for some reason? The CSS in Listing 1 would have to be updated four times -- not such a big deal for a little code block like this one, but it could get hairy given a more complex style sheet. The programmer in me can't help thinking it would be better to write the font only once, as shown in Listing 2.
Listing 2. Less-repetitive CSS
h1, h2, h3, h4 { font-family: Helvetica, sans-serif; }
h1 { font-size: 250% }
h2 { font-size: 200% }
h3 { font-size: 150% }
h4 { font-size: 100% }
|
Now, you might be wondering why I'd make a big deal about this. The code in Listing 2 isn't that much shorter than in Listing 1, and it could be said that it's less readable to the non-programmer. If style sheets never grew past four lines, I'd probably agree. What tends to happen, though, is that style sheets grow. Eventually the little bitty CSS in Listing 2 could extend to hundreds of lines of code. Who's to say you won't need to change Helvetica to Times sometime down the line -- and who's to say you won't mess up and change most instances but not all of them. Worse, you might do a global search-and-replace only to discover, three pages of CSS later, that someone specified Helvetica for something other than headers, and didn't want it changed.
The issue here is that the Internet is a big place, and most Web development
happens at breakneck speed. Unlike software engineers, who had principles like
DRY drilled into their heads over a period of decades, Web developers tend to
work fast and prioritize time-saving efficiency right now. What saves
you time in the moment, though, may not save you time in the long run. If
you're doing multiple style sheets for a project where there's a lot of shared
data, save yourself endless pain and use @import rules to gather
all the repeated elements into a single style sheet. You'll thank yourself
later.
Software engineers have learned the hard way that some code is so awful that you just have to replace it. Replacing code can be prohibitively expensive, however, and there's a strong tendency to avoid or postpone it. It's hard to get enthusiastic about gutting an entire project, and even if you isolate the problem you'll end up with a huge set of test cases to work through and debug.
Refactoring is a neat compromise that allows you to change the way a given result is accomplished without actually changing the application's outward functionality. Rather than gut your software, you simply redesign it so it's easier to work with. Because each step of refactoring leaves the software's functionality the same, it's easy to test, and the system stays functional. Over time refactoring still results in code that is simpler, clearer, and easier to maintain, making it easier to get to the enhancements and bug fixes you wanted to do before. In my own experience, refactoring is often faster than overhauling software. In many cases it's also more reliable than trying to make a change by brute force.
Refactoring is most often applied to code like Java or C++, but it isn't hard to see how it could apply to CSS, page layout, and other aspects of Web design. See Resources to learn more about refactoring Web pages.
Test-driven development, or TDD, is not a decades-old software engineering technique. In fact, failure to test and debug production code is one of the bad legacies passed down through generations of computer programmers. Like their predecessors, many Web developers today tend to postpone testing until the last minute, only to discover critical flaws when it's way too late to change them. Users have come to accept buggy software, whether it comes packaged on a shelf or fresh off the Internet.
TDD is an agile development methodology that says you should test like you vote -- early and often! When you're designing a Web page, be sure you know what your target platforms are and whether your page works on them. Collect requirements, build a mock-up of your Web page, and find out whether it works on those platforms. If you've decided that your Web page has to be viewable in Safari, test it in Safari, from day one. (For a commercial project, the cost of a Mac mini is a tiny fraction of the cost of realizing only after you go live that there's a problem with Safari.)
A common problem with testing any user interface (including a Web interface) is that experienced users don't tend to make obvious mistakes. Real users do just that, however, and robustness in the face of those mistakes is very important. Test your site out on people who aren't as intimately familiar with its navigation scheme as you are. Failing that, abuse the site yourself. What happens if a user wanders away part-way through your checkout procedure? Some will do that. What happens if a user tries to enter the word no in a numerical field? What if a user enters a city name in your zip code box?
Like refactoring, TDD is most commonly applied to code, but the practice extends to Web page design, too. See Resources to learn more about test-driven development.
Software engineering is a lively field in which many of the best researchers will admit that they are still trying to learn their way around. Most of the best practices I've discussed in this column are the result of years of trial and error, but over time they've produced a standard for software engineering that is a little more advanced than a bunch of monkeys pounding on a compiler, hoping to produce the next UNIX®.
As a Web designer or developer, you should benefit from the hard-earned best practices of those who came before you. Don't let people who say that Web development isn't really software development stand in your way. The basic methodologies still apply more often than not.
If the best practices discussed here interest you, see the Resources section to learn more about them. Keep in mind that most software development books and articles assume some familiarity with a programming language or two; consider picking up enough familiarity to read the examples. Even if you don't want to learn a programming language, you will find it rewarding to pick up some of the tools and practices that have helped software developers make larger projects work better.
Action item: Take pride in your work, and work to improve it every chance you get. Web pages have become a major functional component of the daily lives of millions of people; you, the Web developer, are in a position to make that part of everyone's lives better -- so do it!
And with that, I bid you adieu
On March 13, 2001, I published the first column in The cranky user series on developerWorks. In the intervening six years I've written 75 cranky user columns -- 76 if you count this one. Despite my best efforts to promote user-centered design and change the world of Web development one Web site at a time, I received today an e-mail from an online brokerage addressed to "Dear Poor Sucker." Oops.
Similarly, it turns out the online travel site I use does not take a user-centered approach to selling plane tickets online. As a result I spent a few hours of my time and a few more hours of a co-worker's time resolving the mess they'd left me in. This leads me to suspect that my column may not have been read as widely or with the attention I would have liked.
So, here's a thought: Why don't you Web guys ping me when all the problems I've written about over the past six or so years have been fixed. When that day comes I'll go hunt down some new problems to write about. In the meantime, you may find me writing from time to time here on developerWorks, but my days of being formally cranky are done.
It's been a great run. I'd like to thank all of you who commented on the column, both positively and not.
Learn
-
The
cranky user series (March 2001 through July 2007): Read all of Peter Seebach's columns
in this series.
- "When Web pages don't
work" (Chris Paul, developerWorks, February 2005): Reveals some of the ways Web
designers can unwittingly alienate potential users.
- "Demystifying Extreme
Programming: Test-driven programming" (Roy W. Miller, developerWorks, April 2003): A primer on TDD.
-
Manifesto for Agile Software
Development: Agile software development (also known as extreme
programming) is one of many attempts to reformulate views of what software
development is like; it seems that it might be well-suited to the always-live,
always-changing environment of Web development.
-
Refactoring Home Page: Refactoring is a technique
for improving software. The same technique could be applied to many Web pages with
excellent results.
- "Javascript Refactoring For Safer Faster Better AJAX" (Pavel Simakov, Software Secret
Weapons, May 2007): Offers a concrete example of how to refactor a Web page.
-
CSS Specification 2.1: Learn more about
CSS.
-
Edward Tufte's home page: Edward Tufte's work
on displaying information to make it more accessible to readers is of inestimable value
to Web designers.
-
JND.org: The homepage of Don Norman,
whose The Design of Everyday Things is yet another example of a rich and
well-developed resource that most Web designers have never been encouraged to
study.
-
Improve Your
Java Code Quality: Andrew Glover's code quality forum is a developerWorks community
resource for improving the quality of your Web applications.
Discuss
-
developerWorks blogs: Get
involved in the developerWorks
community.
Comments (Undergoing maintenance)






