Modularity

    Modularity in Websites

    Modularity is something that has come up several times in this course, in different guises. We'll discuss this important principle both in general and how it specifically might apply to the web sites we'll build.

    Modularity: The Big Picture

    In this reading, we'll be looking at several ways to make your website more modular — i.e., created out of reusable parts that make the website easier to maintain.

    Reusability

    Reusability has become one of the watchwords of the environmental movement, and for good reason. Reusing objects that have taken much time, energy, and other resources to create is eminently sensible.

    Reusability makes a lot of sense in the programming world, too. Suppose that a programmer has spent a lot of time developing code that solves a problem. This code can often be reused by the same programmer in a different program, or by other programmers in their programs.

    In JavaScript, we've seen that functions are a good way to make code reusable. Once code is encapsulated in a function, that function can be invoked in many different contexts.

    Groups of related functions and data structures are often collected together in reusable units called modules or libraries that are used by large communities of programmers. These play an important role in the adoption of programming languages. Languages like Java, C/C++, Fortran, and Python have become popular in large part because of the impressive modules/libraries that have been built for these languages. jQuery is a library that makes JavaScript programming easier.

    Modules are particularly reusable when they have been designed to be used in mix-and-match ways — think Legos, standard parts from a hardware store, USB peripherals, mix-and-match clothing, etc. That's the idea behind the logo at the top of this section. Crafting a module that is easy and useful to reuse is more art than science, but it's a worthy goal.

    As a concrete example with web pages, suppose that you've figured out how to make a beautiful navigation bar for one page in a website. You'd like a way to package up your navbar code into some sort of module that you can reuse on other pages for the same site, and perhaps for pages in other sites. What you don't want to do is simply copy & paste your navbar code into other pages, because that's a nightmare to maintain. Which brings us to the topic of ...

    Maintenance

    What is maintenance and why is it important? We all know what, say, car maintenance is: changing the oil, keeping the tires inflated, fixing stuff that breaks. It keeps your car running better and longer. But that doesn't have anything to do with web sites, since they don't have physical parts that wear out.

    But they do need to be changed and updated from time to time, which computer scientists have come to call maintenance. Countless studies have shown that, over the lifetime of a software project, about two-thirds of the overall cost is in maintenance. Surprising, but true. You may not be maintaining your cs110 project, but someone will, and we should make their job easier.

    You're already doing some of the most important steps:

    • keeping the HTML simple, neat and clean, which makes it easier to add new content, and
    • keeping the style information in a external style sheet, so that stylistic changes to the site can be easily made in just one place.

    The techniques we will see today are similar to the idea of an external style sheet, because they allow us to put shared code in a single file that is used by more than one page. This general idea is known by computer scientists as modularity: a module is any kind of distinct, separable thing that can be used more than once.

    JavaScript Code Files

    As we saw when we introduced JavaScript, very often you have some JavaScript code that you'd like to use on several web pages. The best example would be a collection of useful functions, all stored in a single file. You could have the browser load the file of functions, and then your web page could invoke the particular functions you want. Let's look at some examples.

    Accessibility Bar

    The top of this page features a set of font sizes formatted in various sizes, where clicking on them changes the font-size for this page to the selected size. We're calling this the accessibility bar (like a navigation bar, but with accessibility controls). All the code is in a separate file, so the only thing we had to do to put the accessibility bar on this page was the following:

    <script src="accessibility-bar-jq.js"></script>
    

    Let's look at the contents of the accessibility-bar-jq.js file. You don't have to read every line, but the first three functions are important (lines 20-45). The rest of the code defines function to add clickable items to the page.

        
    
    
    
    

    Some key things to look at and think about are:

    • How does JavaScript control and change style elements? Could we make a control that would change, say, the thickness of the bar in the H2 elements?
    • Why didn't we supply a stylesheet along with the accessibility bar? Why did we specify the style rules separately?
    • What functions are parameterized and what aren't? Can you think of ways to make this accessibility bar more general and therefore more useful?

    Tax Rate Functions

    Another example is some JavaScript that processes a form. Here's an example:

    The HTML for the form is straightforward. We'll learn about this a bit later in the course, so don't worry about the details. The main point is that we can get the amount of the bill from the user, rather than usingprompt().

    
    
    
    

    The JavaScript code associated with this form is the following, which uses the jQuery .val() method to get the value that the user filled into the form. Again, we'll cover this a bit later, so don't worry about the details.

        
    
    
    
    

    (The change() method attaches a handler that is invoked whenever the value in the form changes. We'll learn about event handlers very soon.)

    As you've probably guessed, the taxRate variable and the calculateTax function are defined in the external JavaScript file, tax-calculations.js:

    
    
    
    
    

    The latter part of this example assumes that the form, in addition to the bill input, also has outputs named tax_amount and total_amount. When the user fills out the bill amount, the JavaScript code calculates the other two. It puts the values into form inputs so that they can be sent to the CGI script if desired.

    The calculateTax function is defined in the tax-calculations.js file. One nice effect of this technique is that if the tax rate changes (say, the state legislature declares a tax holiday), we can change the definition of the function in that file, and any web page that uses the file will immediately start using the new definition.

    Improved Modularity

    If we create a file of JavaScript code for reuse in other web pages, it could just be a collection of random, unrelated, and disorganized functions. There's nothing in this mechanism to enforce any kind of conceptual organization to the JavaScript code. You could simply have one file, say mystuff.js, and put anything you want in it.

    That would work, but it has the disadvantage that you probably will end up loading code you don't need (a small drag on page loading time). More importantly, it's harder to find the code you want and to keep things organized. Instead, you could divide your code into conceptually coherent groups. For example:

    <script type="text/JavaScript" src="date-functions.js"></script>
    <script type="text/JavaScript" src="form-validation.js"></script>
    <script type="text/JavaScript" src="rollovers.js"></script>
    <script type="text/JavaScript" src="lightbox.js"></script>
    

    These files are more worthy of the term module. If someone asks to use your lightbox code, you can point them to that file, and they won't have to wade through irrelevant stuff to use your code.

    (Unfortunately, dividing your code into several small files increases the loading time of your website, since the browser needs to make a separate connection for each one. Therefore, professional web designers use tools to combine a bunch of modules into one file, thereby getting the best of both worlds.)

    Protecting Your Implementation

    Suppose you're the one who implemented the tax-calculations.js module above, and other web designers are using your code on their websites. You know that the variable taxRate is the rate that we pay, and so can anyone reading your code. However, you worry that someone might mistakenly or maliciously set that variable to the wrong value. If the true tax rate is 5 percent, they could set the variable to 5 (which would be a 500 percent rate) or accidentally set it to 0.50 instead of 0.05 (just a typo), or even set it to a non-numerical value.

    To avoid these mistakes, one thing you could do is provide a programmatic way to set the tax rate, rather than just assigning to the variable. For example, something like this:

    function setTaxRate (newRate) {
        if( isNaN(newRate) ) {
            alert("Error: the new value is not a number: "+newRate);
        } else if( newRate < 0 ) {
            alert("negative tax rates don't make sense");
        } else if( newRate > 0.3 ) {
            alert("This tax rate is higher than any legal rate "+newRate);
        } else {
            taxRate = newRate;  // finally, set the global variable.
        }
    }
    

    Then, people set the tax rate using this function, instead of just assigning to the variable taxRate. Of course, our setTaxRate can't check for every possible error, but it could be a help.

    But, you object, a malicious person could still set the taxRate variable directly, instead of using this function. That's true. However, there are programming techniques (which we won't go into) that protect values absolutely, so that you must go through a setter function like this in order to set the value. Thus, our module can build up walls around itself, controlling how it is used.

    Computer scientists endeavor to create programming languages that are powerful, easy to use, and also encourage and enforce useful modularity. This makes programming better and more effective.

    Modularizing Headers and Footers

    Suppose we have three pages, A, B, and C, all of which should share a common header (with banner image and navbar) and common footer.

    We've already studied one way that this common markup can be shared among the pages, namely using the jQuery .load() function to load the code from a master copy, probably on the main page. In the following sections, we'll describe a second approach.

    We would like to be able to describe these pages in such a way that we generate the shared parts so that they are easy to change. For example, to add a new menu item or footer item, we should only have to change one piece of code, not code on each of the pages.

    Modularity via JavaScript Functions

    Another way to achieve the modularity we desire in the A, B, C example is to use JavaScript functions to generate the shared HTML code in each file.

    As shown below in the HTML source code for A.html, we can accomplish this using the JavaScript functions addHeader() and addFooter(). (The code for B.html and C.html is exactly the same except for a different content paragraph.)

    
    
    
    
    

    The file header-footer-jq.js contains definitions of addHeader() and addFooter(), which are responsible for generating the HTML elements that are shared between all the pages.

    
    
    
    
    

    Any change to the functions addHeader(), addBannerPic(), addNavbar(), addMenuItem(), and addFooter() will affect all of the web pages in the website. For instance, it's easy to add a new menu item to the menu bar or a new icon to the footer list.

    See the header-footer example in action

    © Wellesley College Computer Science Staff. This work is licensed under a Creative Commons License. Date Modified: Sunday, 28-Aug-2016 13:07:46 EDT