Contracts: The Practical Side of Semantics

We all recognize that we should be writing semantic code. Maybe, you're even using <section> or <em> correctly, and feel pretty good about yourself. But, are you also considering the implied contract that exists when you code?

Let's imagine that a customer requests a text link, “See More,” which should reveal additional text on the page. <a href="#">see more</a> with a click handler should work perfectly, right? Hey, it looks and functions as requested!

No, it will not always work correctly, as it violates the contract between you and the browser. In particular, I'm referring to the one that says the href attribute must have a value that is a valid URL.

There are practical problems which can arise when violating contracts, and those are much better reasons to write semantic code than things you usually think of when you hear the term, “semantic”.

Popular Arguments for Semantic Code

There are, however, much more practical reasons to care about semantics: contracts.

If you ask an average developer what the value of semantic code, you'll likely hear something along the lines of:

  • It assists the disabled
  • Properly describing code makes it easier for machines to interpret

Both are, unfortunately, very easy to neglect. “Blind people and robots are not the target audience” is too simple of a response, regardless of how misguided or ignorant it might be.

In other cases, you might even hear cyclical reasoning, such as “non-semantic code is bad, because it is not meaningful.” It is such a popular notion to the point that parodies on it have already sprung up around the web!

There are, however, much more practical reasons to care about semantics: contracts.

Usage Contracts

Any time that you use some functionality provided by browser vendors, your programming language, or an API, you are relying on a contract.

On one side of the contract exists a provider of functionality. For example, when you use an <a> tag, browser developers are promising to you that they will provide an easy way for the user of your application to navigate to the specified URL.

As always, however, there's the other side of that contract. The implementer of the functionality promises to use the functionality as specified. As soon as he misuses this functionality, all bets are off - leading to potential failure.

Browser functionality contracts

Let's return to the “See More” example from earlier. In the early days of JavaScript, developers would write their JavaScript using a pseudo protocol, javascript:

Relatively quickly, they began to realize that this approach has at least one practical flaw: the JavaScript code is displayed in the status bar of the browser, which doesn't look professional. The answer to this dilemma was to move the code to an onclick handler, and replace the href attribute with an empty hash identifier, like so:

Of course, this didn't solve everything. If ShowMore has an error, return false is never called, and the page is scrolled to the top - certainly not desired behavior.

Today, developers separate their HTML and JavaScript and use proper event prevention techniques:

But guess what? There are still plenty of problems with this approach: opening in a new tab, bookmarking or copying the link does not work as the user might expect (especially, if there is a <base> tag on the page), which results in confusion, and possibly, a lost customer.

Notice how all the problems described so far arose from a single fact. Developers have been violating their part of the contract with the browser makers: href attribute must contain a correct URL, but, instead, developers were inserting all kinds of garbage.

If we try to conform to our contract, we must ask ourselves: "Why does the contract not allow us to do what we need?" The answer is simple: we misuse the <a> tag. We only use it, because we want the text “See More” to appear and behave like a link. However, when we use words, such as "look" and "appear," is this not the domain of CSS? Isn't this "See More" link, in reality, just a button? This is easy to implement:

Regardless of how many new ways to interact with links are added to future iterations of the browsers, this approach will continue to work, because we are not violating any contract with the browser. We are using elements to convey their meaning, and, instead of constantly working around new problems, we know that the browser will treat this correctly, as it understands what we want.

Sure, it might require a few extra lines of CSS to reset some of the default button styling. It's worth it! Don't be lazy.

Specifications as contracts

...those who did know the semantics, and knowingly ignored them.

In 2005, a large portion of the web development community learned the hard way that ignoring HTTP requirements is bad. The newly released Google Web Accelerator prefetches URLs on a page to minimize the user’s waiting time on a click.

This wrecked havoc in applications, which ignored HTTP, and put destructive operations behind simple links. And there were many such applications.

The problem did not rest in the hands of the developers who didn't understand the semantics of HTTP methods. No, the problem came from those who did know the semantics, knowingly ignored them, and did not share the knowledge.

Maintenance Contracts

Confusing code is bad!

Contracts also exist between developers. Every time you write a line of code, you make a promise to future developers that it does exactly what it appears to do. In other words, confusing code is bad!

For example, using a filtering function (such as filter in Python) to loop over items is incorrect, because there is an implied contract that filtering functions only modify the list, without having any side effects:

Instead, use explicit looping over a list:

On the other hand, if you can rely on a contract, it, as a result, allows you to clarify your code. For instance, using array_filter instead of a for loop in PHP to filter items allows other developers to understand what is happening after a single glance:

Compare the snippet above to using a for loop:

The second version is worse, not only because it is longer, but also because array_filter provides an expectation. It is clear that $profits is a subset of $incomes. There is no such convention with a generic for loop, which explains why we can't make any assumptions, without first deciphering the internals of the loop.

Writing Properly Semantic Code

How do you distinguish between code that is and isn't semantic? How do you notice these contracts? For the most part, simply asking yourself questions should suffice.


“I am using an <a> tag and I need to put something in an href attribute. href stores the link target destination. So where does my <a> tag link to?” Nowhere? Well, I can then conclude that I am probably misusing this tag.

Named Functions

“I need to print out the contents of my list in a filter function. Is printing out items part of the filtering process?” Not really. That means I am misusing filter.

Functions That Do Too Much

“I am writing a getFoo method, and need to add some modification code within it. Does modifying state make sense as part of getting foo? Would anyone who simply wants to get foo expect that something else happens?” Likely not!

Separation of Concerns

“I want to add some JavaScript within an HTML onclick attribute. Is this correct?” The file you are modifying is .html, right? Instead, place your JavaScript and CSS within .js and .css files, respectively. Always.

Of course, in many cases, some additional knowledge might be required to properly assess the situation. What matters most is to begin thinking about these things, and to avoid the principle “it (kinda) works, so it is fine enough.” Instead, always ask yourself, "What does the code I am writing actually mean?"


Violating a contract ensures that cooperation will break.

Cooperation always depends on effort from both parties. Most of software development reduces to cooperation: cooperation between hardware manufacturers, system programmers, browser developers, library authors, website developers, and many others. Violating a contract ensures that cooperation will break.

Code semantics is one such contract. Care about it for your own good!


Semantic: The term “semantic” is often misunderstood. In the context of this article, I use the term to distinguish the meaning of the code from the results the code produces. For example, semantic meaning of an <a> tag is representation of a link, while the simple, practical meaning of it is clickable, underlined text.

Strictly speaking, an empty fragment identifier # might be considered valid in this context. This technicality, however, misses the point I make in the article.



Related Articles