Reliable JavaScript. Lawrence Spencer

Чтение книги онлайн.

Читать онлайн книгу Reliable JavaScript - Lawrence Spencer страница 9

Reliable JavaScript - Lawrence Spencer

Скачать книгу

or toHex, were not.

      This is the “scripting” heritage of JavaScript at work. In the old days, when your script was probably the only one on the page, there was little harm in adding to the global namespace. With today’s JavaScript applications, that is never the case.

      Your script is in no way isolated because it is in its own .js file. If your file starts with

      as this one did (the names have been changed to protect the guilty), then myVariable is visible to all the other scripts in your application, and the makeValue function evidently is, too.

      JavaScript presents an unusually diverse menu of choices for creating modules that properly encapsulate their data and functions. Script files are not one of them! (You will read more about data encapsulation in Chapter 3.)

      Nested Functions Control Scope

      In C# or Java, one class can contain another. However, this practice is not widespread. Microsoft even cautions against it. Code Analysis warning 1034 is “Nested types should not be visible” and their rationale is “Nested types include the notion of member accessibility, which some programmers do not understand clearly” (https://msdn.microsoft.com/en-us/library/ms182162.aspx).

      JavaScript does not have classes, but nested functions serve the same purpose of organizing the code hierarchically. Crucially, the hierarchy not only helps the programmer find what he’s looking for; it also helps the program minimize the scope of its variables and functions. That’s key to keeping a large system under control, and it is the warp and woof of the best JavaScript code.

      Recall this snippet from Listing 1-1:

      The inner line function has a member function, line.x. Although x is a member of line, it cannot see line’s local variables, such as segments. Both line and line.x can see the getX variable in the enclosing function. Combine this sort of artfulness with closures, and you have some very powerful tools for keeping large JavaScript systems under control.

      Coding by Contract

      There is no better way to make a large system more manageable than to make it smaller. JavaScript, with the extraordinary flexibility of pervasive duck-typing, lets you write a little code that can do a lot. (Recall the variety of inputs handled in the D3 case study earlier in the chapter.)

      The flip side is that you never know what someone is going to throw at your software.

      If your function expects its arguments to meet certain requirements, consider validating them. In Chapters 16 through 21, you will see one way to do this as unobtrusively as possible: the ContractRegistry.

      In a nutshell, the registry allows you to verify anything you wish about an argument or return value, without adding any code to your function. It does this through the magic of aspect-oriented programming (covered in Chapter 2) and in such a way that the overhead of validation can be eliminated in the shipped version.

      Applying the Principles of Software Engineering

      Have you ever been to a concert by a virtuoso musician? Maybe you play the same instrument, and you’ve marveled that the performer makes it look so easy. The truth is, he makes it look easy because it is easy – for him. And the reason it’s easy for him is that he has trained his fingers to move efficiently, trained his body to relax and breathe, trained his mind to listen to the music rather than be distracted by anxiety.

      He probably learned the piece by playing it very, very slowly at first. Only when he had mastered it completely at that pace did he take the metronome up one notch. Thus, he did not practice-in any mistakes. One of us, a classical guitarist, went to a masterclass taught by one of the world’s best. The teacher boasted, “I bet I can play this piece slower than any of you.” He has learned that the quickest way to learn to play a piece flawlessly is to play it slowly.

      When you have mastered the principles in this section, you will write flawless software more quickly and with less effort. Your fellow developers will look at your code and say, “He makes it look so easy!”

      The SOLID Principles

      The acronym SOLID was coined by Michael Feathers as a way to remember the five principles of object-oriented design that Robert Martin set forth in the late 1990s (summarized at http://www .objectmentor.com/resources/articles/Principles_and_Patterns.pdf). They are:

      ● The Single Responsibility Principle

      ● The Open/Closed Principle

      ● The Liskov Substitution Principle

      ● The Interface Segregation Principle

      ● The Dependency Inversion Principle

      The Single Responsibility Principle

      Stated in its most extreme form, the Single Responsibility Principle is that a class (or function, in JavaScript) should have only one reason to change.

      That is a very tall order. Surely every line of code represents something that could change. Must every function consist of just one line of code?

      No, but don’t give up on this principle too quickly. Consider once more the rj3.svg.line function in Listing 1-1. As you saw, it is able to generate SVG line paths from just about any data source you can imagine, but what about it might change? It takes almost every cue from outside, even down to how it obtains the x and y coordinates for each data point.

      By the way, one of the casualties of our abridgement of D3’s code was the interpolate function. In the full version, D3 lets you specify this just as you can specify the functions that obtain x and y. And what does interpolate do? It connects the points in an SVG path. The default is to connect the points with straight line segments, but you could plug in an interpolator that constructs graceful curves instead, and D3 supplies several such interpolators.

      Thus, when it comes right down to it, rj3.svg.line really doesn’t “know” much. All it does is return a function (the inner line) that can create an SVG path out of an array of data points – somehow.

      What reasons could there be for rj3.svg.line to change? Its one responsibility is to produce an SVG path from an array. Everything about how it carries out that responsibility is external to the function and therefore not a reason for it to change!

      All together now: “Mike Bostock, you make it look so easy!”

      The Open/Closed Principle

      This principle states that “Software entities should be open for extension, but closed for modification” (http://www.objectmentor.com/resources/articles/ocp.pdf).

      In other words, you should never change working code.

Скачать книгу