Part two programming practice

There are two ways to build a software design: one is to make the software so simple that defects are obviously not found; The other is to make it so complicated that there are no obvious flaws. —-C.A.R.Hoare, recipient of the Turing Award in 1980

In the first part of this book, we focused on JavaScript code style specifications. The purpose of a code style specification is to make code consistent in multiple writing scenarios. A discussion of how to solve general problems is not covered in a style specification; it is part of programming practice.

Chapter 5: Loose coupling at the UI layer

In Web development, the user interface is defined by three separate yet interacting layers:

  • HTML is used to define the data and semantics of a page
  • CSS is used to style pages and create visual features
  • JavaScript is used to add behavior to pages to make them more interactive

To add even more legitimacy to layering and eliminate dependencies, we believe that CSS and JavaScript are equally important in all Web UIs. For example, JavaScript should not rely on CSS to run properly — it should work without CSS, although there may be some interaction between the two.

5.1 What is loose coupling

Many design patterns are designed to address the problem of tight coupling. If the two components are too tightly coupled, one component is directly related to the other, so that if you change the logic of one component, the logic of the other component also needs to be changed.

When you can modify one component without changing the others, you have loose coupling. For large, multi-person systems, where many people are involved in maintaining the code, loose coupling is critical to code maintainability. You definitely want developers to change one part of code without breaking other people’s code.

It is important to note that components working together cannot be “decoupled.” In all systems, components share some information to do their job. This makes sense, and our goal is to ensure that changes to one component do not frequently affect other parts.

5.2 Removing JavaScript from CSS

One feature in IE8 and earlier browsers that people love less and hate more is CSS expressions.

// It's a bad way to write.box{
    width: expression(document.body.offsetWidth + 'px');
}
Copy the code

CSS expressions are wrapped in a special expression() function that can be passed to any JavaScript code. Browsers reevaluate CSS expressions at a high rate, which severely affects performance.

In addition to performance issues, embedding JavaScript code in CSS can be a code maintenance nightmare. The author spent a whole day looking for script errors in JavaScript, and the culprit was CSS.

Fortunately, CSS expressions are no longer supported in IE9, but older versions of IE can still run CSS expressions. Although we rarely use CSS expressions to implement rare features that make older browsers perform as well as advanced browsers, resist the urge to unnecessarily waste time and effort.

5.3 Removing CSS from JavaScript

Sometimes, maintaining a clear separation between CSS and JavaScript can be challenging. The two languages work well together, so we often mix style data with JavaScript. One of the most popular ways to script styles is to modify the style property of a DOM element directly.

// It's a bad way to write
element.style.color = "red";
Copy the code

This approach is problematic because the style information is carried through JavaScript rather than CSS. When there is a style problem, you usually look for CSS first, and only look for style information in JavaScript when you have exhausted all possibilities.

Another way developers can modify the style object is to assign the entire CSS string to the cssText property, as shown in this example:

// It's a bad way to write
element.style.cssText = "color: red; left: 10px; top: 100px; vidibility: hidden";
Copy the code

Using the cssText property is just a shortcut to setting multiple CSS properties at once. This pattern is also problematic, for example when setting individual properties: writing style information to JavaScript creates maintainability issues.

Pulling CSS out of JavaScript means that all style information should be kept in CSS. When you need to modify the style of an element in JavaScript, the best way is to manipulate the className of the CSS.

5.4 Separate JavaScript from HTML

One of the first things many people do when they learn JavaScript is embed a script in HTML to run. There are many ways. The first is to bind an event handler using an ON attribute, such as onclick.

// It's a bad way to write<button onclick="dosomething()" id="action-btn"></button>
Copy the code

This was so popular in 2000 that most websites adopted it. HTML code is filled with onclick and other event handlers, and many elements contain such attributes. Although this code works in most scenarios, it is a deep coupling between the two UI layers (HTML and JavaScript), so this approach is problematic.

First, the doSomething() function must exist when a click event occurs on the button.

The second problem is maintainability. If you change the function name of doSomething(), you need to change both the JavaScript and the HTML code. This is classic tightly coupled code.

Most (but not all) of your JavaScript code should be contained in external files and referenced in pages via

5.5 Detach HTML from JavaScript

The most common use of HTML in JavaScript is when assigning a value to the innerHTML attribute, such as:

// It's a bad way to write
var div = document.getElementById("my-div");
div.innerHTML = "<h3>Error</h3><p>Invalid e-mail address.</p>";
Copy the code

Embedding HTML in JavaScript code is bad practice. There are several reasons for this: first, it increases the complexity of tracking text and structural issues, and second, it is detrimental to code maintenance.