Refactoring - CL1 Flashcards

1
Q

Refactoring Concept (what/when/why)

A

Like many terms in software development, “refactoring” is often used very loosely by
practitioners. I use the term more precisely, and find it useful to use it in that more
Settings
precise form. (These definitions are the same as those I gave in the first edition of this
Support
book.) The term “refactoring” can be used either as a noun or a verb. The noun’s
definition is:
Sign Out
Refactoring (noun): a change made to the internal structure of software to make it
easier to understand and cheaper to modify without changing its observable behavior.
This definition corresponds to the named refactorings I’ve mentioned in the earlier
examples, such as Extract Function (106) and Replace Conditional with Polymorphism
(272).
The verb’s definition is:
Refactoring (verb): to restructure software by applying a series of refactorings
without changing its observable behavior.
So I might spend a couple of hours refactoring, during which I would apply a few dozen
individual refactorings.
Over the years, many people in the industry have taken to use “refactoring” to mean any
kind of code cleanup—but the definitions above point to a particular approach to
cleaning up code. Refactoring is all about applying small behavior­preserving steps and
making a big change by stringing together a sequence of these behavior­preservingsteps. Each individual refactoring is either pretty small itself or a combination of small
steps. As a result, when I’m refactoring, my code doesn’t spend much time in a broken
state, allowing me to stop at any moment even if I haven’t finished.
If someone says their code was broken for a couple of days while they are
refactoring, you can be pretty sure they were not refactoring.
I use “restructuring” as a general term to mean any kind of reorganizing or cleaning up
of a code base, and see refactoring as a particular kind of restructuring. Refactoring
may seem inefficient to people who first come across it and watch me making lots of
tiny steps, when a single bigger step would do. But the tiny steps allow me to go faster
because they compose so well—and, crucially, because I don’t spend any time
debugging.
In my definitions, I use the phrase “observable behavior.” This is a deliberately loose
term, indicating that the code should, overall, do just the same things it did before I
started. It doesn’t mean it will work exactly the same—for example, Extract Function
(106) will alter the call stack, so performance characteristics might change—but nothing
should change that the user should care about. In particular, interfaces to modules
often change due to such refactorings as Change Function Declaration (124) and Move
Function (198). Any bugs that I notice during refactoring should still be present after
refactoring (though I can fix latent bugs that nobody has observed yet).
Refactoring is very similar to performance optimization, as both involve carrying out
code manipulations that don’t change the overall functionality of the program. The
difference is the purpose: Refactoring is always done to make the code “easier to
understand and cheaper to modify.” This might speed things up or slow things down.
With performance optimization, I only care about speeding up the program, and am
prepared to end up with code that is harder to work with if I really need that improved
performance.

WHY SHOULD WE REFACTOR?
I don’t want to claim refactoring is the cure for all software ills. It is no “silver bullet.”
Yet it is a valuable tool—a pair of silver pliers that helps you keep a good grip on your
code. Refactoring is a tool that can—and should—be used for several purposes.

Refactoring Improves the Design of Software
Without refactoring, the internal design—the architecture—of software tends to decay.
As people change code to achieve short­term goals, often without a full comprehension
of the architecture, the code loses its structure. It becomes harder for me to see the
design by reading the code. Loss of the structure of code has a cumulative effect. The
harder it is to see the design in the code, the harder it is for me to preserve it, and the
more rapidly it decays. Regular refactoring helps keep the code in shape.
Poorly designed code usually takes more code to do the same things, often because the
code quite literally does the same thing in several places. Thus an important aspect of
improving design is to eliminate duplicated code. It’s not that reducing the amount of
code will make the system run any faster—the effect on the footprint of the programs
rarely is significant. Reducing the amount of code does, however, make a big difference
in modification of the code. The more code there is, the harder it is to modify correctly.
There’s more code for me to understand. I change this bit of code here, but the system
doesn’t do what I expect because I didn’t change that bit over there that does much the
same thing in a slightly different context. By eliminating duplication, I ensure that the
code says everything once and only once, which is the essence of good design.

Refactoring Makes Software Easier to Understand
Programming is in many ways a conversation with a computer. I write code that tells
the computer what to do, and it responds by doing exactly what I tell it. In time, I close
the gap between what I want it to do and what I tell it to do. Programming is all aboutsaying exactly what I want. But there are likely to be other users of my source code. In a
few months, a human will try to read my code to make some changes. That user, who
we often forget, is actually the most important. Who cares if the computer takes a few
more cycles to compile something? Yet it does matter if it takes a programmer a week to
make a change that would have taken only an hour with proper understanding of my
code.
The trouble is that when I’m trying to get the program to work, I’m not thinking about
that future developer. It takes a change of rhythm to make the code easier to
understand. Refactoring helps me make my code more readable. Before refactoring, I
have code that works but is not ideally structured. A little time spent on refactoring can
make the code better communicate its purpose—say more clearly what I want.
I’m not necessarily being altruistic about this. Often, this future developer is myself.
This makes refactoring even more important. I’m a very lazy programmer. One of my
forms of laziness is that I never remember things about the code I write. Indeed, I
deliberately try not remember anything I can look up, because I’m afraid my brain will
get full. I make a point of trying to put everything I should remember into the code so I
don’t have to remember it. That way I’m less worried about Maudite [maudite] killing
off my brain cells.

Refactoring Helps Me Find Bugs
Help in understanding the code also means help in spotting bugs. I admit I’m not
terribly good at finding bugs. Some people can read a lump of code and see bugs; I
cannot. However, I find that if I refactor code, I work deeply on understanding what the
code does, and I put that new understanding right back into the code. By clarifying the
structure of the program, I clarify certain assumptions I’ve made—to a point where
even I can’t avoid spotting the bugs.
It reminds me of a statement Kent Beck often makes about himself: “I’m not a great
programmer; I’m just a good programmer with great habits.” Refactoring helps me be
much more effective at writing robust code.

Refactoring Helps Me Program Faster
In the end, all the earlier points come down to this: Refactoring helps me develop code
more quickly.
This sounds counterintuitive. When I talk about refactoring, people can easily see that
it improves quality. Better internal design, readability, reducing bugs—all theseimprove quality. But doesn’t the time I spend on refactoring reduce the speed of
development?
When I talk to software developers who have been working on a system for a while, I
often hear that they were able to make progress rapidly at first, but now it takes much
longer to add new features. Every new feature requires more and more time to
understand how to fit it into the existing code base, and once it’s added, bugs often crop
up that take even longer to fix. The code base starts looking like a series of patches
covering patches, and it takes an exercise in archaeology to figure out how things work.
This burden slows down adding new features—to the point that developers wish they
could start again from a blank slate.

WHEN SHOULD WE REFACTOR?
Refactoring is something I do every hour I program. I have noticed a number of ways it
fits into my workflow.

The Rule of Three
Here’s a guideline Don Roberts gave me: The first time you do something,
you just do it. The second time you do something similar, you wince at the
duplication, but you do the duplicate thing anyway. The third time you do
something similar, you refactor.
Or for those who like baseball: Three strikes, then you refactor.

Preparatory Refactoring—Making It Easier to Add a Feature
The best time to refactor is just before I need to add a new feature to the code base. As I
do this, I look at the existing code and, often, see that if it were structured a little
differently, my work would be much easier. Perhaps there’s function that does almost
all that I need, but has some literal values that conflict with my needs. Without
refactoring I might copy the function and change those values. But that leads to
duplicated code—if I need to change it in the future, I’ll have to change both spots (and,
worse, find them). And copy­paste won’t help me if I need to make a similar variation
for a new feature in the future. So with my refactoring hat on, I use Parameterize
Function (310). Once I’ve done that, all I have to do is call the function with the
parameters I need.
“It’s like I want to go 100 miles east but instead of just traipsing through the woods,
I’m going to drive 20 miles north to the highway and then I’m going to go 100 miles
east at three times the speed I could have if I just went straight there. When people are
pushing you to just go straight there, sometimes you need to say, ‘Wait, I need to
check the map and find the quickest route.’ The preparatory refactoring does that for
me.”
— Jessica Kerr,
https://martinfowler.com/articles/preparatory­refactoring­
example.html
The same happens when fixing a bug. Once I’ve found the cause of the problem, I see
that it would be much easier to fix should I unify the three bits of copied code causing
the error into one. Or perhaps separating some update logic from queries will make it
easier to avoid the tangling that’s causing the error. By refactoring to improve the
situation, I also increase the chances that the bug will stay fixed, and reduce the
chances that others will appear in the same crevices of the code

Comprehension Refactoring: Making Code Easier to Understand
Before I can change some code, I need to understand what it does. This code may have
been written by me or by someone else. Whenever I have to think to understand what
the code is doing, I ask myself if I can refactor the code to make that understanding
more immediately apparent. I may be looking at some conditional logic that’s
structured awkwardly. I may have wanted to use some existing functions but spent
several minutes figuring out what they did because they were named badly.
At that point I have some understanding in my head, but my head isn’t a very good
record of such details. As Ward Cunningham puts it, by refactoring I move the
understanding from my head into the code itself. I then test that understanding by
running the software to see if it still works. If I move my understanding into the code, it
will be preserved longer and be visible to my colleagues.
That doesn’t just help me in the future—it often helps me right now. Early on, I do
comprehension refactoring on little details. I rename a couple variables now that I
understand what they are, or I chop a long function into smaller parts. Then, as the
code gets clearer, I find I can see things about the design that I could not see before.
Had I not changed the code, I probably never would have seen these things, because I’m
just not clever enough to visualize all these changes in my head. Ralph Johnson
describes these early refactorings as wiping the dirt off a window so you can see
beyond. When I’m studying code, refactoring leads me to higher levels of
understanding that I would otherwise miss. Those who dismiss comprehension
refactoring as useless fiddling with the code don’t realize that by foregoing it they never
see the opportunities hidden behind the confusion.

Litter-Pickup Refactoring
A variation of comprehension refactoring is when I understand what the code is doing,
but realize that it’s doing it badly. The logic is unnecessarily convoluted, or I see
functions that are nearly identical and can be replaced by a single parameterized
function. There’s a bit of a tradeoff here. I don’t want to spend a lot of time distracted
from the task I’m currently doing, but I also don’t want to leave the trash lying around
and getting in the way of future changes. If it’s easy to change, I’ll do it right away. If it’s
a bit more effort to fix, I might make a note of it and fix it when I’m done with my
immediate task.
Sometimes, of course, it’s going to take a few hours to fix, and I have more urgent
things to do. Even then, however, it’s usually worthwhile to make it a little bit better. As
the old camping adage says, always leave the camp site cleaner than when you found it.If I make it a little better each time I pass through the code, over time it will get fixed.
The nice thing about refactoring is that I don’t break the code with each small step—so,
sometimes, it takes months to complete the job but the code is never broken even when
I’m part way through it.

Planned and Opportunistic Refactoring
The examples above—preparatory, comprehension, litter­pickup refactoring—are all
opportunistic. I don’t set aside time at the beginning to spend on refactoring—instead, I
do refactoring as part of adding a feature or fixing a bug. It’s part of my natural flow of
programming. Whether I’m adding a feature or fixing a bug, refactoring helps me do
the immediate task and also sets me up to make future work easier. This is an
important point that’s frequently missed. Refactoring isn’t an activity that’s separated
from programming—any more than you set aside time to write if statements. I don’t
put time on my plans to do refactoring; most refactoring happens while I’m doing other
things.
You have to refactor when you run into ugly code—but excellent code needs
plenty of refactoring too.
It’s also a common error to see refactoring as something people do to fix past mistakes
or clean up ugly code. Certainly you have to refactor when you run into ugly code, but
excellent code needs plenty of refactoring too. Whenever I write code, I’m making
tradeoffs—how much do I need to parameterize, where to draw the lines between
functions? The tradeoffs I made correctly for yesterday’s feature set may no longer be
the right ones for the new features I’m adding today. The advantage is that clean code is
easier to refactor when I need to change those tradeoffs to reflect the new reality.
“for each desired change, make the change easy (warning: this may be hard), then
make the easy change”
— Kent Beck,
https://twitter.com/kentbeck/status/250733358307500032
For a long time, people thought of writing software as a process of accretion: To add
new features, we should be mostly adding new code. But good developers know that,
often, the fastest way to add a new feature is to change the code to make it easy to add.
Software should thus be never thought of as “done.” As new capabilities are needed, the
software changes to reflect that. Those changes can often be greater in the existing codethan in the new code.
All this doesn’t mean that planned refactoring is always wrong. If a team has neglected
refactoring, it often needs dedicated time to get their code base into a better state for
new features, and a week spent refactoring now can repay itself over the next couple of
months. Sometimes, even with regular refactoring I’ll see a problem area grow to the
point when it needs some concerted effort to fix. But such planned refactoring episodes
should be rare. Most refactoring effort should be the unremarkable, opportunistic kind.
One bit of advice I’ve heard is to separate refactoring work and new feature additions
into different version­control commits. The big advantage of this is that they can be
reviewed and approved independently. I’m not convinced of this, however. Too often,
the refactorings are closely interwoven with adding new features, and it’s not worth the
time to separate them out. This can also remove the context for the refactoring, making
the refactoring commits hard to justify. Each team should experiment to find what
works for them; just remember that separating refactoring commits is not a self­evident
principle—it’s only worthwhile if it makes life easier.

Long-Term Refactoring
Most refactoring can be completed within a few minutes—hours at most. But there are
some larger refactoring efforts that can take a team weeks to complete. Perhaps they
need to replace an existing library with a new one. Or pull some section of code out into
a component that they can share with another team. Or fix some nasty mess of
dependencies that they had allowed to build up.
Even in such cases, I’m reluctant to have a team do dedicated refactoring. Often, a
useful strategy is to agree to gradually work on the problem over the course of the next
few weeks. Whenever anyone goes near any code that’s in the refactoring zone, they
move it a little way in the direction they want to improve. This takes advantage of the
fact that refactoring doesn’t break the code—each small change leaves everything in a
still­working state. To change from one library to another, start by introducing a new
abstraction that can act as an interface to either library. Once the calling code uses this
abstraction, it’s much easier to switch one library for another. (This tactic is called
Branch By Abstraction [mf­bba].)

Refactoring in a Code Review
Some organizations do regular code reviews; those that don’t would do better if they
did. Code reviews help spread knowledge through a development team. Reviews help
more experienced developers pass knowledge to those less experienced. They help morepeople understand more aspects of a large software system. They are also very
important in writing clear code. My code may look clear to me but not to my team.
That’s inevitable—it’s hard for people to put themselves in the shoes of someone
unfamiliar with whatever they are working on. Reviews also give the opportunity for
more people to suggest useful ideas. I can only think of so many good ideas in a week.
Having other people contribute makes my life easier, so I always look for reviews.
I’ve found that refactoring helps me review someone else’s code. Before I started using
refactoring, I could read the code, understand it to some degree, and make suggestions.
Now, when I come up with ideas, I consider whether they can be easily implemented
then and there with refactoring. If so, I refactor. When I do it a few times, I can see
more clearly what the code looks like with the suggestions in place. I don’t have to
imagine what it would be like—I can see it. As a result, I can come up with a second
level of ideas that I would never have realized had I not refactored.
Refactoring also helps get more concrete results from the code review. Not only are
there suggestions; many suggestions are implemented there and then. You end up with
much more of a sense of accomplishment from the exercise.
How I’d embed refactoring into a code review depends on the nature of the review. The
common pull request model, where a reviewer looks at code without the original
author, doesn’t work too well. It’s better to have the original author of the code present
because the author can provide context on the code and fully appreciate the reviewers’
intentions for their changes. I’ve had my best experiences with this by sitting one­on­
one with the original author, going through the code and refactoring as we go. The
logical conclusion of this style is pair programming: continuous code review embedded
within the process of programming.

What Do I Tell My Manager?
One of the most common questions I’ve been asked is, “How to tell a manager about
refactoring?” I’ve certainly seen places were refactoring has become a dirty word—with
managers (and customers) believing that refactoring is either correcting errors made
earlier, or work that doesn’t yield valuable features. This is exacerbated by teams
scheduling weeks of pure refactoring—especially if what they are really doing is not
refactoring but less careful restructuring that causes breakages in the code base.
To a manager who is genuinely savvy about technology and understands the design
stamina hypothesis, refactoring isn’t hard to justify. Such managers should be
encouraging refactoring on a regular basis and be looking for signs that indicate a team
isn’t doing enough. While it does happen that teams do too much refactoring, it’s muchrarer than teams not doing enough.
Of course, many managers and customer don’t have the technical awareness to know
how code base health impacts productivity. In these cases I give my more controversial
advice: Don’t tell!
Subversive? I don’t think so. Software developers are professionals. Our job is to build
effective software as rapidly as we can. My experience is that refactoring is a big aid to
building software quickly. If I need to add a new function and the design does not suit
the change, I find it’s quicker to refactor first and then add the function. If I need to fix
a bug, I need to understand how the software works—and I find refactoring is the
fastest way to do this. A schedule­driven manager wants me to do things the fastest way
I can; how I do it is my responsibility. I’m being paid for my expertise in programming
new capabilities fast, and the fastest way is by refactoring—therefore I refactor.

When Should I Not Refactor?
It may sound like I always recommend refactoring—but there are cases when it’s not
worthwhile.
If I run across code that is a mess, but I don’t need to modify it, then I don’t need to
refactor it. Some ugly code that I can treat as an API may remain ugly. It’s only when I
need to understand how it works that refactoring gives me any benefit.
Another case is when it’s easier to rewrite it than to refactor it. This is a tricky decision.
Often, I can’t tell how easy it is to refactor some code unless I spend some time trying
and thus get a sense of how difficult it is. The decision to refactor or rewrite requires
good judgment and experience, and I can’t really boil it down into a piece of simple
advice.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Refactoring table layouts

A

Well-formedness and validity check basic syntactic constraints. The next
step is to make sure the semantics are appropriate. Each element should
be used for its intended purpose: ul for unordered lists, ol for numbered
lists, table for tabular data, blockquote for quotations, h1–h6 for
headings, and so forth. Using the proper semantics for each element
renders pages more intelligible to screen readers, and makes sure they
can be displayed properly on different platforms. As you’ll see, proper
semantics have a number of other beneficial characteristics as well.
Many good semantic elements, such as ul, blockquote, and table,
have been abused to achieve particular layout effects. The goal of this
abuse is to produce a very particular appearance for a page. However,
that appearance rarely extends across browsers, almost never across
platforms, and often not anywhere beyond the designer’s own computer.
Proper HTML can account for this, but you have to stop thinking about
what the page looks like and start thinking about what it means.
Of course, we do want our pages to have pleasing appearances. We
want them to stand out from the competition. It is possible to achieve this
by placing all the presentation information in a separate CSS stylesheet.
The CSS describes what the page looks like. However, browsers are free
to use a different or modified stylesheet if they choose. Indeed, you are
free to send different stylesheets to different browsers, tailored to each
one’s unique capabilities.
In modern browsers, CSS enables much greater control over the
appearance of a page. It’s not merely that the fanciest sites can be
duplicated in CSS. They can only be designed in CSS. Creating a
modern page requires moving away from tabular layout and font tags to
XHTML cleanly separated from CSS.

Replace Table Layouts
Remove all table layouts and replace them with div elements that
linearize the content. Then use a CSS stylesheet to position the divs in
the form you want.
Motivation
CSS layouts are more powerful and more accessible than table layouts.
They work better across a broader variety of devices, such as PDAs and
audio browsers. They are more understandable to machines and thus
enable better processing of content, including somewhat enhanced
search engine optimization. Finally, they make it easier to edit and update
pages both because the pages are simpler and because the style and
content are separated so that designers don’t step on authors’ toes and
vice versa.
CSS-based pages are smaller and simpler than table-based pages. This
makes them easier to edit and easier to author. It also makes them faster
to download. All those and tags add up. A kilobyte here, a
kilobyte there, and pretty soon you’re talking about real bandwidth. Highvolume sites such as Slashdot can save gigabytes per day and
thousands of dollars in bandwidth costs per year by moving to CSS.
Although the CSS files themselves take some bandwidth, they can be
cached and reused. They do not need to be downloaded with every
page.
Potential Trade-offs
CSS layouts do tend to fix sizes more than table layouts do. For example,
with tables it is possible to define a three-column layout in which each
column is as big as it needs to be, with any extra space distributed
among the columns. You can specify widths for the columns, but you
don’t have to. With CSS, you usually need to specify widths for at least
one of the columns.
Older browsers may not work as well with the CSS versions of a page as
they do with the table layouts. However, they will still see the complete
content of the page, and given the minuscule market share of browsers
that don’t support CSS, that’s good enough.
Although the overall site may download faster and perform better with
external CSS stylesheets, that is likely not true for the first such page
visited. The first time a browser loads the external CSS stylesheet two
HTTP connections will be needed. Over a fast connection, this is
negligible, but it can cause temporary problems for dial-up clients and
slow servers. I still tend to think that the speedups on second and
subsequent pages more than outweigh this, though.
Laying out pages with CSS absolutely has a steeper learning curve than
laying out pages with tables. This is very much a technique for full-time
professionals. Amateurs should either use professionally designed
templates or stick to simple, linear pages with browser default layouts.
Even for professionals, CSS layouts are much harder to implement and
debug, especially across browsers, than table-based layouts. You have
to invest more time and effort upfront. The saving grace is that not too
many layouts are needed. Probably less than a dozen basic layouts
account for 99% of all web pages, and almost all of these are simple
variations of one to three columns with optional headers and footers in
varying widths and heights. Consequently, you can copy preexisting CSS
layouts and make slight modifications, rather than reinventing each layout
from scratch every time.
Mechanics
No one layout works for every site and no one recipe fits all needs.
However, certain common layouts appear frequently enough to be worthy
of special notice. Mastering the techniques involved in these layouts will
enable you to customize them for many other cases. In particular, three
layouts are among the most common on the Web today:
Two columns, with a fixed-width sidebar on the left and a liquid
content column on the right
Two columns, with a fixed-width sidebar on the right and a liquid
content column on the left
Three columns, with fixed-width sidebars on the right and left and
content in the middle
Layouts with fixed-width content columns are also common. However,
fixed-width content is almost always a bad idea. Users have different
screen sizes, browser widths, font choices, and more. Some users
maximize their browser windows and some don’t. (Windows users are
much more likely to maximize their browser windows than Mac users are,
even on identically sized monitors.) One size does not fit all.
These layouts may or may not have headers and footers. Usually, the
header and footer belong to the main content column. However, they can
also precede or follow all three columns, in which case they usually
extend across the full width of the browser window. A header that
precedes all three columns is a little more common than a footer that
follows all three. The problem with a footer that is below all three is that it
may show up far underneath the main column if the main content is short.
Usually the column heights are determined naturally by the amount of
content they contain. Occasionally, the columns may be set at a fixed
height to guarantee equal widths. However, this is problematic for
content-heavy sites because the content of the individual columns is by
no means guaranteed to match up. It works a little better for short pages
consisting of no more than one screen of text.

The Content
Arranging the HTML itself is the easiest part. Divide each separate
section into its own div element. Give the div element a unique id
attribute by which it can be addressed. These divs can be nested if
necessary. Ideally, the main content div should appear before any
sidebars, headers, or footers. This way, screen readers that access the
page linearly will start with the most important content on the page. So
will search engine robots that often assign a higher priority to content that
appears earlier in the page.

Replace Frames with CSS Positions
Convert framesets to single pages.
Motivation
Frames were a bad idea that hasn’t improved in the ten years since they
were invented. They are a usability disaster. They make it extremely hard
to bookmark or return to a particular page. They make it hard to save a
page or print it. They break the connection between the URL displayed in
the title bar and the content on the page. They take control away from the
user, because frame sizes are set by the page author. Users cannot
resize individual frames to fit their needs. Scroll bars take up valuable
screen real estate.
Frames confuse search engines and reduce your Google rank.
Furthermore, when users do find a relevant framed page with a search
engine, they’re likely to come into the framed page directly, rather than
the frameset, thus completely bypassing your carefully designed frame
layout.
Browsers have partially compensated for some of these flaws with tools
such as the This Frame context menu in Firefox. However, this is still a
limited solution. Furthermore, when users take advantage of such
functionality, they may well break a site that depends on having all
frames in a set visible at once. Critical navigation or other content can be
missed when a reader sees only part of a frameset.
Potential Trade-offs
The techniques outlined here will not work quite as well in older browsers
that are rarely used anymore. However, the content will still be accessible
to them. It just won’t be as pretty. In modern browsers, by contrast, it
should be both more attractive and more usable.
The individual nonframe pages may require more bandwidth than the
frame equivalents. That’s because the frame content will need to be
served to the client on each page.
Mechanics
Frames were a hack in the very early days of the Web before browsers
supported CSS or servers supported sophisticated include schemes.
Today a combination of both of these is preferred to achieve a much nicer
frame effect with greater usability.
There are actually two reasons that sites use frames:
To include static content on all pages, without separately editing
each page
To present a multicolumn appearance
Although these are legitimate goals, in 2008 neither of them requires the
use of frames. You already saw in the preceding section that it’s not hard
to create multicolumn layouts with CSS.
It is very common for web sites to have navigation bars or other content
that remains the same or almost the same from page to page. For
example, in Java API documentation there are two frames on the lefthand side that contain a list of all packages and all classes in the current
package. The main content frame is on the right

Move Content to the Front
When reading the raw HTML from start to finish, the main content of the
page should be the very first thing encountered. Sidebars, headers,
footers, navigation, and such should follow
Motivation
Search engines often treat content earlier in the page as more important
than content later in the page. You usually want the unique content on
the page, not the navigation, advertisements, logos, and other froufrou.
Putting content first is extremely important for accessibility. Screen
readers see the page as a linear sequence that starts at the beginning
and continues to the end. Pages laid out as two-dimensional columns are
big problems for blind readers. For these readers, especially, it’s really
important to put the crucial content upfront rather than making them wade
through several dozen irrelevant links first.
Potential Trade-offs
Insisting on having the content first does make designing CSS
stylesheets with positioning more difficult. You’ll likely need to modify any
such stylesheets to account for the new content order.
Mechanics
To the extent that static content such as headers, footers, navigation,
ads, and sidebars are repeated from page to page, there’s usually some
constant string you can search for, such as id=”sidebar”. If your
pages are structured very consistently, you may even be able to
automate moving the secondary content after the main content. More
often, though, you’ll need to find these issues manually unless all the
pages are generated out of a CMS or database of some kind. If that’s the
case, you just need to update the template.
The biggest problem is likely to be reorganizing the CSS stylesheet to
support the new content order. CSS is not as independent of content
order as one would like it to be. However, the techniques given in the first
section in this chapter for converting from a table-based layout apply here
as well. There is one common problem I did not address in that section:
putting the header after the main content. This is tricky, though it can be
done. If you don’t want to update the stylesheets just yet, you should at
least install skip links, as discussed in the next chapter.
However, if you do want to go whole-hog, the trick is to absolutely
position the header at the top of the page and then give the content and
sidebars enough of a top margin to slide out of its way. This is not a
perfect solution. It does tend to let the main content bleed over the
header at very large font sizes, but it’s adequate for most sites.

Mark Up Lists as Lists
Make sure any lists are marked up as ul elements, or, occasionally, as
dl or ol elements
Motivation
Identifying lists as lists improves accessibility. In particular, it enables the
use of screen reader tools for skipping over and navigating through lists.
Potential Trade-offs
Most browsers assign very specific appearances to lists and list items,
typically indented and bulleted, and you may not want this appearance.
You can fix this easily with CSS in modern browsers. However, some
older browsers do not support all the necessary properties and will
display these pages in less-than-ideal fashion.
Mechanics
There’s no simple way to find all the unidentified lists in a site. You’ll just
have to read the pages and look for lists. They can be marked up in
dozens of different ways: as paragraphs, divs, tables, inline text
separated by commas or other symbols, and more.
Once you’ve found a list, marking up the individual items is easy. Just use
a ul, ol, or dl instead of the current wrapper element. Use the ordered
list ol if the items are numbered. Use dl if the list takes the form namedescription, name-description, name-description. Use ul for all other
lists.
Although lists are extremely common in content, list elements are not.
The reason is that browsers usually indent and bullet or number each
separate item, as well as placing line breaks in between items; and this is
not always desired. However, this is easy to fix with CSS.

Replace blockquote/ul Indentation with CSS
Change any blockquotes or ul elements used purely to indent their
contents into divs, and assign CSS rules to the div that use the
margin-left and margin-right properties to indent.
Motivation
blockquote should be reserved for quotations. ul should be reserved
for lists.
CSS offers much greater control over exactly how far any given chunk of
text is indented. You also have the option to set a right margin separately
from the left margin, to indent the first line differently than the rest, to
specify a hanging indent, or anything else you can imagine. CSS is
simply a more powerful and precise means of indenting text than
blockquote and ul ever were.
Potential Trade-offs
Minimal. Even if a browser cannot load the CSS stylesheet, the
consequent lack of indentation has a very small effect on the overall
appearance of the page.
Mechanics
Finding text improperly marked up with blockquote is tricky. On some
sites, there are no real blockquotes, so a quick search for <blockquote></blockquote>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Refactoring for Accessibility

A

The Web has the potential to more fully integrate people with seeing,
hearing, physical, learning, and other disabilities into society. By limiting
the interaction necessary to communicate, as well as enabling delayed
communications so that participants can move at their own pace, the
Web has transformed our relationships with one another. Properly
designed web pages neither know nor care whether you’re reading them
with a CRT or a screen reader. Properly designed forms neither know nor
care whether you’re inputting data with a keyboard, a mouse, or voice
recognition software.
However, accessibility does not come automatically. Many pages are
locked into one modality of use, most commonly visual. Many pages are
designed with the assumption that the user will view the page in the
same way the designer does. Such pages can lock out people with
different levels of eyesight, attention, motor skills, and a dozen other
characteristics.
Accessibility is not just about supporting people with extreme physical
impairments such as blindness either. Ability and accessibility are both
continuums. People don’t merely see or not see. They see better or
worse. Most of us see worse with age. By age 40, we’ve either
discovered the Ctrl-+ keyboard shortcut for increasing the font size of our
browser or we’ve begun to curse 20-something web designers as we surf
(or both). The changes you make to improve accessibility don’t just help
people who meet the legal definition of disabled. They help everyone
whose seeing, hearing, or motor skills are less than perfect. At least
some of the time, that’s all of us. If it isn’t today, it will be tomorrow. As we
age, eyesight and motor skills decline, and accessibility becomes more
important. When I started on the web, college students represented a
majority of the population on the Net. Today they’re probably less than
10%, and they are vastly outnumbered by senior citizens.
Accessibility also improves your site for people accessing it with
nontraditional devices. A 28-year-old Wall Street trader may prefer to
view your news through the small screen of her BlackBerry. Even an
airline pilot with 20/20 vision may as well be blind when listening to your
page on his cell phone while jogging.
Of course, accessibility isn’t just about supporting people with physical or
device impairments. Wheelchair ramps are far more commonly used by
parents with strollers, students with bicycles, and delivery people with
hand trucks than they are by people in wheelchairs. When properly done,
increasing accessibility for the disabled increases accessibility for
everyone. That’s as true on the World Wide Web as it is in the physical
world.
In many jurisdictions, accessibility is not just a good idea. It’s the law. In
the United States, the Americans with Disabilities Act requires that all
web sites built or procured by the federal government be accessible to
users without regard for physical handicap. In the United Kingdom, the
Disability Discrimination Act imposes similar requirements, and many
other nations either already or soon will have equivalent laws.
If all that isn’t enough to convince you that it’s important to invest time
and resources in making your pages accessible, consider this. The most
profoundly disabled user of your page is going to be a search engine
robot. Robots can’t see, hear, touch, or think. They are unbelievably
stupid. Although a person can eventually make sense out of a strange
layout or text encoded in an image, a robot never will. Almost everything
you do to make your pages more accessible to and usable by people will
be paid back tenfold in search engine optimization.
Simply making documents valid XHTML makes documents a lot more
accessible than they otherwise would be. Making them strict XHTML
rather than transitional goes even further. Removing presentational
elements such as b and replacing them with semantic elements such as
strong helps a little. Separating the content from the presentation using
CSS stylesheets helps a lot.
However, that’s the beginning of accessibility, not the end. If you aren’t
careful, you can create completely valid but almost totally inaccessible
pages. Validation is an automatic and unthinking process. It focuses
purely on the syntax. It can’t tell whether you’ve chosen green or red text
that will be impenetrable to many color-blind visitors. It doesn’t know that
the first 20 KB of your page are advertising and navigation that blind
users have to slog through before getting to the actual content. It can’t
distinguish between a well-designed data table containing monthly
financials and a layout table that rearranges the linear flow of text into
unintelligible gibberish.
Making web sites accessible requires applying human intelligence to
recognize and then fix problems such as these. As usual, tools are
available that can help. The W3C HTML validator discussed in Chapter 2
notes many accessibility problems as well as pure well-formedness and
validity errors. Other tools are available that check more deeply for
accessibility. The W3C maintains a list of many such tools at
www.w3c.org/WAI/ER/tools/complete/. These tools are helpful, but they
are relatively stupid. They may find problems a validator won’t, such as
green text on a red background, and they may suspect that certain tables
are likely being used for layout. However, they don’t know this, and there
are many problems they will never find. You must spend some time
looking at the site with accessibility in mind.
Accessibility is ultimately about people, not about following a fixed set of
rules. If your site is open and accessible to all users, you’ve done your
job, even if you’ve violated a rule here or there. If your site is confusing
and hard to use, you haven’t, even if it validates and passes all the
automated checks. To really tell how well you’ve succeeded, you have to
do user testing. Observe real people navigating your site. Watching even
a single user will reveal problems you didn’t know you had. Time and
budget permitting, you should observe many people, and include users
with different skill sets and abilities. Watching a senior citizen navigate
your site will tell you very different things than watching a teenager.
Watching a blind user navigate with a screen reader will reveal issues
you won’t encounter with a sighted user. Try to test as many different
classes of users as you can. Even if your budget does not permit formal
user testing, do some informal testing by recruiting your friends, family,
and coworkers for simple tests.
Sometimes even seeing the difficulties other users experience isn’t
enough. We have to experience them for ourselves. If you do not have
easy access to blind users, you can simulate their experience. First, try to
surf your site through the text mode browser Lynx. Second, try using a
voice browser. Turn off your monitor and surf your own site. If you use a
Mac, VoiceOver is built in (though it does take some time to get used to).
However, most blind users prefer the more powerful payware Windows
program, JAWS. Either one will give you a decent approximation of how
a blind user views your site. Next, turn the monitor back on, disconnect
the mouse and the keyboard, and try to navigate with voice recognition.
This will help to teach you how some physically disabled people will
approach the site and where their pain points are likely to be.
Web-site accessibility is still quite poor, and in 2008 there’s no excuse for
that. Most users are inconvenienced, some critically so. However, there
are some simple changes and improvements you can make to the design
of your sites to improve matters.

Convert Images to Text
Replace any images that contain text with the text they contain, along
with the markup and CSS rules that mimic the styling.
Motivation
Visually impaired users can’t see images, but they can hear text with a
screen reader or feel it with a Braille printer. An alt attribute helps, but it
is not a substitute for real, marked-up text.
Converting images to text dramatically improves search engine
optimization. Search engines pay a lot of attention to text and relatively
little to images. They pay special attention to text that appears early in
the document and in headings. Thus, it’s particularly important to make
sure that headings are real text, not images or word art.
Replacing images with text also improves web-site performance,
especially over slow or overloaded connections. It will save you
bandwidth costs and save your readers time.
Potential Trade-offs
The text will likely not look exactly like it was mocked up in Photoshop,
even after you’ve styled it with CSS. Furthermore, its appearance is likely
to change slightly from one person to the next depending on their
operating system, fonts installed, default fonts chosen, and browser.
Readers almost never care about this, but sometimes designers do.
This may also bother the company lawyers in the very specific case of
trademarked logos. If the lawyers cannot be reasoned with, keep the
logos as img elements (with appropriate alt attributes), but change all
other text images to real text.
Mechanics
Begin by looking at your pages to see where text is hidden inside images.
Start at the home page and work your way through the site. If you’re
uncertain whether something is or isn’t text, try to select the individual
letters. If you can, it’s text. If you can’t, it’s an image. Alternatively, rightclick on the suspect text and see whether you have an option to View
Image, Save Picture As, or some such thing. If you can do this, it’s a
picture, not text.
Once you’ve ascertained that you’re dealing with an image rather than
text, you need to replace the image with text, while retaining as much of
the formatting as possible. Fortunately, CSS gives you a lot of power.
CSS can easily change the colors of the foreground and background of
the text. Indeed, with a CSS background image you may be able to use
the same background picture the text has. You’ll also be able to adjust
font styles and weights: Make the text bold or italic, and so forth. CSS
can specify the same font that was used in the image, though not all
browsers may have that font installed, and many readers may have to
substitute a slightly different font.

Add Labels to Form Input
Make sure each nonhidden input, textarea, select, or other form
element has an associated label.
Motivation
Visually impaired users with screen readers cannot always use the twodimensional layout of a page to determine which labels go with which
fields. It is important to explicitly tag each nonhidden field with a label so
that it is properly identified by screen readers.
There are more visually impaired users than you might think. This
includes not only physically blind users, but also people using cell phone
browsers while driving, and others who may not be able to immediately
look at the screen but can listen to it. This class of user is set to grow
significantly over the next few years.
Adding explicit label elements, possibly with id and class attributes,
will also make it easier to style the labels with CSS or provide additional
hints with JavaScript or smarter browsers. For example, a browser might
highlight the associated label when the user tabs or clicks into an input
field.
Potential Trade-offs
None. This should not affect your existing layout for most users and will
improve it for some.
Because you’re introducing new elements and changing the parents of
some elements, a few programs that access the DOM or use XPath may
need to be updated. However, such programs are uncommon.
Mechanics
For every form input, select, or textarea element, there must be at
least one label element. (I tend to think there should be exactly one, but
multiple labels are allowed.) The label element can either enclose the
input element or have a for attribute that contains the ID of the element
it refers to.

Introduce Standard Field Names
Rewrite your forms and form processing scripts to use conventional
names for conventional things such as e-mail addresses, credit card
numbers, phone numbers, and so forth.
Motivation
A browser can autofill much information, even on a form it’s never
encountered before, if the form uses standard names for input fields. This
helps all of us who hate to waste time retyping repetitive content.
However, it’s especially helpful to physically impaired users (including the
very young and very old) who have much greater difficulty typing than
average.
You’re also more likely to collect accurate and correct information if the
browser automatically fills in the values than if the user types them. Not
only is the browser less likely to make random typos, but many users
actively fake the information they input into many web forms.
Potential Trade-offs
You’ll probably have to rewrite some back-end code to support this.
You may also need to introduce an additional level of indirection if the
database or program that receives data from the form uses the field
names in its own code. This is probably a net positive, though, because it
will increase the flexibility of the back-end code.
Mechanics
Search your forms for common input. In particular, look for the following:
- Personal names
- Contact information: snail mail addresses, telephone numbers, email addresses
- Credit card details: number, name, expiration date, billing address,
and so on
- Usernames and passwords

Turn on Autocomplete
Remove autocomplete=”off” attributes where appropriate.
Motivation
Autocompletion helps users avoid wasting time retyping repetitive
content. It’s especially helpful to physically impaired users (including the
very young and very old) who have much greater difficulty typing than
average.
Autocompletion also improves security in login forms by avoiding the
need for users to write down passwords or to reuse the same password
from site to site. Login forms that prevent users from using autocomplete
are far more likely to be compromised by out-of-band mechanisms such
as shoulder surfing.
Potential Trade-offs
Many webmasters believe that autocompleting logins is a security risk.
Indeed, it may be so on a shared computer, such as one in a public
library. However, only the end-user can determine whether their computer
is shared. Users are always free not to remember a username or
password or to tell the browser to forget stored information, if they use a
shared computer. That being said, I do recommend that lab managers
configure their computers to forget all stored information (not just forms,
but also cookies, bookmarks, history, and other potentially private data)
between browser restarts.
Mechanics
Search your HTML pages for autocomplete=”off”. This can appear
on the form element or on individual input elements. When you find it,
consider whether this is really appropriate.
Some forms really do expect different input each time. For instance, the
main query field in a search engine likely doesn’t see a lot of repeated
content from the same user, or at least not enough to make autocomplete
helpful. Most users search for something different every time they visit.
These forms may legitimately use autocomplete=”off”. Therefore,
you should not perform a blanket search and replace that removes all
autocomplete=”off” attributes.
However, in the vast majority of cases, autocomplete=”off” merely
inconveniences users for little or no good reason. If you’re in doubt,
remove it. The user never has to use autocompletion, but should not be
prevented from doing so by the server’s whim.

Add Tab Indexes to Forms
Add a tabindex attribute to every editable, nonhidden form control.
Motivation
Keyboard navigation is greatly simplified if the user can tab from one
control to the next. This is especially important on forms that will be used
frequently—for example, by a data entry clerk. It is also important for
users with lesser manual dexterity who aren’t able to reliably or easily
target fields with a mouse. However, even dexterous, one-time users
expect to be able to tab between fields and will attempt to do so. Make
sure that when they press the Tab key, the focus advances to the next
logical field.
Potential Trade-offs
The proper tab order is not always obvious, and it may vary from one
user to the next, especially in forms where input fields advance both
horizontally across the screen and vertically down the screen.
Nonetheless, any carefully considered and assigned tab order is likely to
be better than the default order the browser guesses when no tab order
is specified by a form.
Mechanics
Seven elements support the tabindex attribute:
a
area
button
input
object
select
textarea
Unifying these is the fact that they are all some form of user input. Thus,
each can have an explicit tabindex attribute.
The value of the tabindex attribute is an integer between 0 and 32,767.
(If you have more than 32,768 of these elements, split the page. It’s too
large.) Tabbing begins with 1 (or the lowest positive value) and continues
in order to the highest value.
On a page whose main purpose for existing is to get the user to fill out a
form, it’s reasonable to guess that the tabs should hit the form fields first.
Give each form input element a tabindex attribute, ordered from start to
finish, and make the submit button the last tabindex. I either don’t
assign tabindexes to links on such a page or I assign higher tabindexes
to them than to the form fields so that they’ll be tabbed through after the
form.
In many forms, you need to consider not only the logical order of the
fields, but also which fields are likely to be filled out. This is sometimes a
hard call to make, but if a field is used only infrequently and is positioned
off to the side, I sometimes leave it out of the tab order to enable the user
to more quickly advance through the common fields.
The tabindex attribute has page scope. Consequently, you need to
consider the logical order of the forms, links, and other controls on the
page, not merely the order of controls within any one form. It may seem
as though 32,767 is more indexes than you’ll need, but it does allow you
to do things such as assign numbers from 1 to 500 to the first form; 501
to 1,000 to the second; and so forth.

Introduce Skip Navigation
Place an “invisible” link at the beginning of each page that jumps straight
to the main content on the page.
Motivation
Reading a site with a screen reader is hard enough without being forced
to slog through a long sidebar or header on every page. Blind users really
appreciate being able to jump straight to the unique content of each
page.
Potential Trade-offs
None.
Mechanics
The first step is to identify the pages where skip links are likely to be
helpful. On some sites with common sidebars and headers, this is pretty
much every page. On other sites, it is only certain pages. The usual
pattern is that a header or left sidebar, or both, precede the actual
content of the page when viewed in HTML:

<div>Blah blah blah</div>

<div>Blah blah blah</div>

<div>Blah blah blah</div>

The visual layout of what comes first does not matter as much, though
how much it matters can vary from one screen-reading program to
another. (Some screen readers just follow the raw HTML. Others try to
scrape the text off the screen after the browser has laid it out and
rendered it.)

Add Internal Headings
Place h1–h6 elements at reasonable breaks throughout long pages.
Motivation
Assistive software enables both visually and physically impaired readers
to jump to the next headline on a page with a single keystroke. However,
this works only when those headings are identified with proper HTML
markup.
Potential Trade-offs
You may need to rewrite the stylesheets for the page to restore the
original look and feel. However, this shouldn’t be hard.
Mechanics
There’s no easy way to find mislabeled headings. They can be p
elements, div elements, even span or dt elements. On most sites,
though, the problems tend to be consistent from page to page. Once
you’ve identified how a site is formatting headings, you can devise a
search and replace to find and fix them. For instance, if a site has
identified each heading as a headline class, it’s simple to search for
class=”headline”.
One thing you may wish to consider is adding subheads to medium-tolong pages that don’t already have them. Users of all abilities tend to
scan pages rather than reading them from beginning to end. They zero in
on only the sections they’re most interested in. Descriptive subheads on
the page make the scanning process easier

Move Unique Content to the Front of Links and
Headlines
Place the most important, most distinct content first in each heading and
link.
Motivation
Readers listening to a page with a screen reader scan by jumping from
link, list item, or heading to the next item without listening to the entire
item. Do not make readers listen to more than they have to in order to
determine whether the link or headline is relevant to them.
Potential Trade-offs
On occasion, the language can become a little stilted, especially when
complete sentences are involved.
Mechanics
Visually impaired users often scan pages by listening to the first two or
three words of each successive link or heading. Those words have to
count.
You can inspect easy link, heading, and table title to see whether it needs
to be reordered. It’s easy enough to write an XPath expression that will
find all of these in any given document.

Make the Input Field Bigger
Make sure all your forms have enough space for the user to comfortably
type in the requested values.
Motivation
There’s nothing quite as frustrating as trying to write an essay in a 40-
column by 20-row box. Make sure all text areas have enough space to
allow the users to enter what they need to enter. It’s better to have too
large a box than too small.
Potential Trade-offs
Expanding a form’s width may require some adjustment of the
surrounding layout to provide more space for the form, especially on
three-column pages, or pages with a sidebar on the right. However, it
should have no effect on the back-end processing. Small text areas do
not prevent users from entering large quantities of text. They just make it
inconvenient for them to do so.
Mechanics
You can find many pages you need to check just by searching for

If in doubt, err on the side of too much room rather than too little. It’s no
big deal if the user has some blank space in the form, but it’s much more
troublesome if they can’t fit the text. Always allow for extra room. Many
users will have different, larger fonts than you do, whether because of
different platforms, different preferences, worse eyesight, or other
reasons.

Introduce Table Descriptions
Add a caption element and/or a summary attribute to each table. Add a
th element for each row or column label.
Motivation
Although tables are an excellent means of presenting certain kinds of
data to sighted readers, they challenge blind readers who must access a
page linearly. Consider the code immediately preceding this paragraph.
Presented linearly in HTML, does it really make a lot of sense? This is
how a blind user is likely to see it
Many sight-impaired users prefer to just get a quick summary of a table
rather than trying to read the entire thing. When they do need to drill
down into a table, it’s very helpful to have marked-up headers for rows
and columns that help them determine where they are.
Potential Trade-offs
Captions are shown to sighted users as well as users with screen
readers. If you really don’t want a caption, this can be a problem. In this
case, you might choose to provide a title attribute instead.
However, even fully sighted users often prefer to be told what a table
means rather than carefully inspecting the data for themselves. Indeed,
often the table is really a reference for readers who want to know more,
rather than something intended for everybody to read. A caption is
usually a good addition for everyone, not just users listening to the page
with a screen reader.
Mechanics
Neither the caption element nor the summary attribute is required by
the XHTML strict DTD. You can search for
Of course, some sighted and nonsighted users alike are going to want to
drill down into the table, at least some of the time. To assist with this, you
should mark up each header in a th element rather than in a td element.
This element can be used for both row and column headers and may
appear anywhere a td element can appear. Browsers often style the
header differently than a regular cell, and if they don’t, CSS can.
Furthermore, screen readers can repeat table headers as necessary to
keep a listening user from getting lost in the table.
The th element is used for both row and column headers. To indicate
which it is, each such element should have a scope=”row” or
scope=”col” attribute. You can also set scope to rowgroup or
colgroup to cover the group to which the header belongs. Visual
browsers don’t make much use of the scope attribute, but screen
readers do.
In more complicated tables, it may not be possible to cleanly associate
each th header with exactly one row or column. In this case, individual
table cells (td elements) may each have a headers attribute that
contains a whitespace-separated list of the IDs of the headers (th
elements) that apply to that cell. A screen reader can read the names of
the headers before reading the content of each cell.
Because screen readers do repeat table headers from time to time, each
multiword header should have a shorter abbr attribute (not the same
thing as an abbr element) that screen readers can use in preference to
the full heading. The longer the heading is, the more important this
becomes.
Finally, simplify your tables to the extent possible. Do not nest tables, and
try to avoid columns and rows that span more than one cell. Even when a
table is truly a data table and not a layout table, it still poses a challenge
for screen readers and sight-impaired users. Complicated nested table
markup can move difficult but possible-to-read content over the line into
unintelligible.

Introduce Acronym Elements
Wrap abbr and acronym tags around abbreviations and acronyms.
Motivation
Screen readers need to know when they should try to pronounce an
entire word and when they should just spell it out.
Not all your readers necessarily know all the acronyms that you use.
Many browsers will show a tool tip to tell the reader what the acronym
means if you mark it up appropriately in the source document. This
avoids the need to explain everything for the larger portion of your
audience who does know what the acronym means.
Potential Trade-offs
Some browsers put some really ugly dotted lines under marked-up
acronyms and abbreviations. This also throws off the line spacing.
However, you can counter this with CSS.
Mechanics
For purposes of HTML, an abbreviation is made up of the first letters of
the words in a phrase. It is pronounced by spelling out the words. For
example:
<abbr>BBC</abbr>
<abbr>GNP</abbr>
<abbr>IBM</abbr>
By contrast, an acronym is normally pronounced like a word, rather than
by spelling it out. Examples include:
<acronym>NAFTA</acronym>
<acronym>GATT</acronym>
<acronym>Inc.</acronym>
These aren’t quite the dictionary definitions of abbreviation and acronym
—in fact, an acronym is really a type of abbreviation—but they do reflect
how speech synthesizers decide to pronounce each unfamiliar
abbreviation.

Introduce lang Attributes
Add lang and xml:lang attributes to each root element identifying the
primary language of the document. Add superseding lang and
xml:lang attributes to any element in that document that is written in a
different language.
Motivation
Proper language identification is important for pronunciation by screen
readers.
Language identification also assists search engines. Your French pages
are more likely to be picked up by google.fr and your German pages by
google.de if the content is properly tagged.
Finally, language identification assists you when authoring pages,
especially when working in something other than a system’s primary
language. It enables editors to choose the proper dictionary for spell
checking.
Potential Trade-offs
None. This is only for the good.
Mechanics
If you know none of your documents already contains a lang or
xml:lang attribute, and that they’re all written in the same language, it’s
easy to search for
This will find most cases you need to deal with.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly