Contracts: The Practical Side of Semantics

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:

<a href="javascript:ShowMore()">See More</a>

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:

<a href="#" onclick="ShowMore();return false;">See More</a>

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:

<a href="#" class="show-more">See More</a>
$('a.show-more').on('click', function(event) {
    event.preventDefault();
    ShowMore();
});

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:

<button type="button" class="link-style show-more">See More</button>
$('button.show-more').on('click', ShowMore);
a, .link-style {
    color: @your-shade-of-blue;
    text-decoration: underline;
}
.link-style {
    font: inherit;
    background: none;
    border: none;
    cursor: pointer;
}

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:

def show(item):
    print(item)

fruits = ['orange', 'apple', 'lemon']

filter(show, fruits)  # Incorrect usage of filter

Instead, use explicit looping over a list:

def show(item):
    print(item)

fruits = ['orange', 'apple', 'lemon']

for fruit in fruits:
    show(fruit)

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:

$incomes = [20, 15, -7, 19];
$profits = array_filter($incomes, function($i){
    return $i > 0;
});

Compare the snippet above to using a for loop:

$incomes = [20, 15, -7, 19];
$profits = [];

foreach ($incomes as $i) {
    if ($i > 0) {
        $profits[] = $i;
    }
}

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.

HTML Tags

“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?”


Conclusion

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!


Footnotes

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.

Tags: semantics
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.facebook.com/jesus.bejarano.948 Jesus Bejarano

    Good article, very helpful, but will nettuts in some future publish article about ARIA feature in html5?.I would love to read that.

    • jeff_way

      We’ve touched on it in the past, but I agree we could do more.

  • http://twitter.com/IncendiaryMedia Fire

    On first glance I thought this was going to be about actual legal contracts for small-time web developers so we don’t get screwed on projects… Turned out not to be exactly what I was looking for, but a nice article regardless ( I’d honestly never thought about using a button element instead of an anchor ).

  • mattsah

    Solution

    Write Backend Code and HTML first
    Write CSS Second
    Write JS Third and Final

    In between each round, test the site and make sure it works and is suitable enough for use. This is the true progressive enhancement approach where CSS itself is a progressive enhancement on top of HTML. You can of course divide that further and say, use only CSS Level 2 (as a baseline) in your first CSS writing, then add CSS level 3.

    • MPinteractiv

      More and more apps have their server-side acting only as a Rest service, the client being fully js powered ( the server doesnt render html code , all the templating is done on the client ). So much for accessibilty and progressive enhancement but that’s a trade-off.

      • mattsah

        @MPinteractiv:disqus

        I thought about bringing this up, but I didn’t want to open that can of worms. I would generally recommend in such circumstances that basic HTML and CSS pages be served (at least for information and certain methods).

        Also, if something is fully JS powered it’s generally a “single page” — this means you could easily have a single page JS app which is 100% dynamic, and pull from a bunch of endpoints without much conflict for plain old HTML and CSS as a simple fallback.

        One easy solution is to serve your homepage as you might normally, and the first thing the JS does is just drop all nodes then rebuild.

        Also, I’d still like more of a distinction to be made by most people these days between websites and webapps. I understand they have become closer to the same than they have been previously, and they can be sorta layered on top of one another, but the fact is, if you’re building a website (predominately informational) with a majority of somewhat static content…. doing it in JS seems rather foolish.

    • Denis
      Author

      That is a very good approach, but, if I am not missing something, it neither undermines nor proves the point I make in this article.

      • mattsah

        @Denis,

        No, it is just a method by which that contract can essentially be ensured. It also happens to produce very flexible and extensible code.

      • http://www.kksmith.me/ K.K.Smith

        This is how I work… although I haven’t been splitting CSS up into two stages. I like that idea though, and I will try it out.

        (Of course, some sites just are not going to work without JS/AJAX. To try to create a functional non-JS version is just a timesink.)

  • Premke

    Sometimes an anchor is a better (more practical) choice than button. For example: “Back to Top” should be an anchor; <a href="#top" class="link-style ease">Back to Top</a> . You would then bind jquery animation to ‘.ease’ and style ‘.link-style’.

    This way If jquery isn’t working link functionality won’t be broken but button’s will.

    • Denis
      Author

      Good point, Premke. Of course, in your example a link is a better choice than a button. In fact, it a link, as it has a destination, so it is correct to use an <a> tag not only for practical reasons, but also for semantics (or contracts).

  • http://www.clippingpathcenter.com/clipping-path-service.php mamun

    fantastic informative information……:D

  • http://www.graphicexpertsonline.com/clippingpath.html mam_raj07

    nice information.
    thanks to share this information

  • Jeremy at Cubicle Ninjas

    I have never thought of it this way. It is very important to understand the proper use of each tag. Although it can be difficult to be truly HTML 5 semantic only because of browser support. Bad code is my biggest pet peeve. Not only bad, as in poorly written, because I understand nobody is a pro right from the start and bad code is a part of writing better code or dare I say, GOOD code. Messy code is the worst thing to run into. If you open a file and it looks like a crossword puzzle and you are searching for functions or div elements, most of your time is spent cleaning it up in order to modify it. This article is great, and it will definitely be shared amongst my peers. Jeremy at Cubicle Ninjas

  • http://cubicleninjas.com/ Tyler Etters

    Semantics will become increasingly important moving forward. The more unified our practices, the better the internet will work as a cohesive whole. But! We must never forget the hacker spirit and the potential benefits that come from abusing our respective technologies.

  • Vaclovas

    First – sorry for my english.
    Second: i didn’t get authors idea. prevent default in jquery is totally equal to button reset in css. both are incorrect approach.
    in href you can provide id/correct url or even don’t provide href attribute and html will be valid. why to use button tag?
    i think, that people, before writting about semantics, firstly should read about them:
    http://www.w3.org/TR/2011/WD-html5-20110525/text-level-semantics.html#the-a-element

    • Denis
      Author

      prevent default in jquery is totally equal to button reset in css

      What is “button reset”? And if that is just a button, then how are those equal?
      You’ve provided the specification link yourself, compare the semantics of the elements.

      in href you can provide id/correct url or even don’t provide href attribute and html will be valid.

      Your linked material clearly describes, that if you provide href attribute, then the a element represents a hyperlink, which in the case shown in the article it is clearly not. Please note, the example in the article describes an element, which would use JavaScript to reveal a portion of the text on the page, not navigate to another page, or even another part of the same page. Admittedly, the example might not have been a perfect one, given that it is easy to confuse it with a genuine hyperlink.

      • Vaclovas

        1. preventDefault “ignores” default functionality then clicking anchor. Reseting button css to have it styled like link = same, incorrect approach. you have to “reset” functionality or visual styling to have something done.

        2. your example “See More
        why developer have to define “href=”#”? there is absolutely no point to do this. if you want to have trigger for fading hidden text, then just create Fade text and thats all… if it looks like button – use button, if it looks like link – why to use button tag and reset it? you can also have named anchors, not only linked ones.

        3. you have used button tag in your examples just to prevent anchor link without href or i am incorrect? because i can’t see any other reason.

      • Denis
        Author

        Reseting button css to have it styled like link = same, incorrect approach. you have to “reset” functionality or visual styling to have something done.

        you have used button tag in your examples just to prevent anchor link without href or i am incorrect? because i can’t see any other reason.

        But here is your mistake. You think in terms of “what actions do I have to take to achieve my goal”.

        What I try to explain in the article is that this is a wrong approach. An <a> or a <button> elements are not defined by how they look or how they act, they are defined by their semantics.

        The semantics of the “See more” text in the article is those of a button, not those of a hyperlink.

      • Vaclovas

        why are you talking about anchor tag, like it is only hyperlink?

        http://www.w3.org/TR/html4/struct/links.html

        “Destination anchors in HTML documents may be specified either by the A element (naming it with the name attribute), or by any other element (naming with the id attribute).”

      • Denis
        Author

        In HTML5 the element <a> no longer has any special role as a destination anchor. It can still be used without a href attribute, yet the meaning of that is entirely different.

      • Vaclovas

        official source or it didn’t happen

  • http://www.facebook.com/people/Krasimir-Stefanov-Tsonev/617578836 Krasimir Stefanov Tsonev

    Greate article. I wasn’t think about the word semantic in the context of coding. Till now I connect it more with the html markup :)

  • http://www.joshuarivers.net/ Joshua Rivers

    Good article to remind us to keep clean code.

  • mrugen deshmukh

    Interesting article, really brings the point ahead of semanticity, enjoyed reading it and learned a new way and reason to do things they ought to be done!

  • flake

    “return $i > 0;” returns boolean whereas ”
    $profits[] = $i;” $i is a signed int
    Those two php snippets do not do the same thing.

    • Denis
      Author

      I suppose you are confusing `array_filter` with `array_map`.

      The return value of a closure passed to `array_filter` is a boolean, which answers the questions “should we include the original value in the resulting array or not”, so, if we answer “true”, the value included will be $i.

  • http://www.omnificdesign.com.au/ Wes Towers

    As a web and graphic designer, I don’t do much coding. But, I have a programmer who does and I bet he will eat up everything that you’ve written here, Denis. I will gladly forward this to him since I can gather that it has really valuable information. Thanks, mate.

    • Denis
      Author

      Thank you for your kind words, Wes!