JSAD_MEAP_ch1

27

Transcript of JSAD_MEAP_ch1

MEAP Edition Manning Early Access Program

JavaScript Application Design: A Build First Approach Version 1

Copyright 2013 Manning Publications

For more information on this and other Manning titles go to www.manning.com

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

Welcome

Thank you for purchasing the MEAP edition for JavaScript Application Design: A Build First Approach! It's been a very rewarding experience so far, and I feel a lot of enthusiasm about getting to touch the print book with my own hands. This is an intermediate level book about application design and architecture, aimed at anyone with an interest in JavaScript development, build processes, or a mixture of both.

I've aimed to make the book as approachable as possible, while not diluting the content too much. I'm giving special attention to the code samples, because I know just how important it can be to read code which works, and is well documented As a result, all the code is thoroughly documented, and you'll be able to find everything you need online, at http://bevacqua.io/buildfirst.

In general I tried to avoid relying too much in a back-end language, but in cases where I felt this was necessary, I resorted to Node.js, a back-end language where you can write JavaScript code. Grunt, a build tool which is used to apply the principles discussed in the book, is written in Node.

To kick things off, we're releasing the first three chapters. In Chapter 1, I'll talk about the problems that can stem from not having a formal build process in place, and I'll champion the notion to build first; automating everything as we go, rather than as an afterthought. The other side to Build First is designing modular applications, and that'll also be discussed in this chapter. Then, you'll write your first build task, to start keeping code quality in check.

Chapter 2 defines exactly what comprises a build task, and its components. It also covers the kinds of tasks that you can perform, and how they can be automated using Grunt. In this chapter, we also explore an example where you'll automate database creation, database schema updates, and rollbacks, if one of these updates presents any problems. You'll learn how to create your own build tasks in pure JavaScript, using Grunt.

Lastly, Chapter 3 goes over application environments and different approaches to configuring them securely. You'll spend time setting up a continuous development environment, where the builds run themselves, your files auto-save, the browser refreshes itself, and your application gets re-executed whenever files change, so you can focus on your development efforts.

Soon, Chapter 4 will become available, and it will focus on production environments and the release and deployment flow. You'll learn how to build an application for release, and everything that a release entails. Then you'll deploy the built application to a hosting platform such as Heroku. Later, you'll learn about Continuous Integration, and how you can benefit from it to test your application in a remote environment. You'll also learn how to enable Continuous Deployments, and take a look at application monitoring and alerting.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

Eventually we'll make our way to Part II, which covers complexity management in JavaScript. Topics include code encapsulation, modularity, package management, dependency injection, promises, callbacks, evented programming, DOM interaction, MVC, Angular.js, and unit testing. Part III takes what we've learned in Parts I and II, and uses that to walk us through an application built from scratch, where you'll implement a REST API, a layered application architecture, MVVM client-side code using Angular, and even take care of the database layer. You'll then deploy it to a hosting environment, where it'll be publicly accessible.

I highly encourage you to become an active contributor to the Author Online forum. You'll be able to suggest changes, ask questions, and give much appreciated feedback to collaborate on building a great book. I'll personally read and address any concerns you might post there. Alternatively, you are welcome to contact me directly at [email protected], I'll be happy to reply and address your concerns or feedback!

— Nicolas Bevacqua

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

brief contents

PART I: BUILD PROCESSES

1 Introduction to Build Processes

2 Build Tasks

3 Environments and the development workflow

4 Release, deployment and monitoring

PART II: MANAGING COMPLEXITY

5 Modularity and Dependency Management

6 Asynchronous JavaScript

7 Patterns and practices

8 Testing in JavaScript

PART III: APPLICATION DESIGN

9 Build First in Action

10 Rest API

11 Growing up

12 Deploying!

APPENDIXES:

Appendix A Staying productive

Appendix B Recommended reading

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

1 Introduction to Build Processes

This chapter covers:

• Problems in Modern Application Design

• What Build First Is

• Code Quality with Lint

• Introduction to Grunt

Properly developing applications is hard, much like writing a book. You want to jump to the meat. You want to write something that matters. Before long you might notice there isn't any real structure to your code. The problems start pouring in, and they become really hard to track down. Your application is now live, and you have a decent user base. Every decision you make has the potential to damage your reputation, for a number of reasons. You can't afford a lot of downtime; humans hate that. Bugs aren't any good for you either, and you have a release schedule to maintain. So, you compromise.

1.1 The Problem You might want to deploy a new feature to production, so humans can try it out. How many steps do you have to take to do that? 8? 5? Why would you risk a mistake in a routine task such as deployments? Deploying should be no different than building your application locally. One step. That's it.

Yet, every so often, we face the challenging position of having to manually take many of these steps. Sure, we can compile the application in a single step, or we might be using an interpreted, server-side language that doesn't need any pre-compilation. Later, we may need to update our database to the latest version. We might even have created a script for those updates, and yet we log into our database server, upload the file, and run the schema updates ourselves.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

1

Cool, you've updated the database. However, something's not right, and the application is throwing an error. You look at the clock. Your application has been down for more than ten minutes. This should've been a straightforward update. You check the logs; you forgot to add that new variable to your configuration file. Silly! You add it promptly, mumbling something about wrestling with the code-base. You keep forgetting to alter the config file before deploys; it slipped your mind to update it before deploying to production!

Sounds like a familiar ritual? Fear not, this is an unfortunately common illness, spread through a lot of different applications. Big picture; we need to discuss two sides to application development: the build process and architecture design. The build process encompasses several possible stages: compilation, testing, optimization, release, and deployment. These are examined exhaustively in the next few chapters. Let's dig into a more concrete example about the web front-end and JavaScript.

1.1.1 Writing, Building, and Validating Front-end Code As a general rule of thumb, front-end best practices require us to do three things consistently: write “clean” code; test it to make sure it works as expected; and perform operations on our code. “Clean” code entails a number of things. It means writing code that is modular, meaning a piece of code only attends to one concern. For example, a piece of code that deals with recording logging calls and handing each of those to a persistence layer might be one module; the module that's tasked with writing to the database would be another module. These modules should be reusable, meaning the database module shouldn't be tightly coupled to its implementors (the modules which consume it). In turn, the consumers should act as if they don't know anything about it other than its public interface, as if it were an external API. Additionally, our code should be written with testability in mind, since that can hardly be mixed in later: it needs to be there from the get-go. Figure 1.1, below, overviews these clean code principles, which you will soon see are also key in the “build-first approach” to JavaScript applications this book advocates.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

2

Figure 1.1 The pillars of clean coding

Testing is one of many tasks we have to perform during a release. For example, we'll want to optimize our images, by making them smaller, so that they don't take very long to download. I'm sure you've heard of minification, where script or stylesheet files are optimized and reduced in size, we should be doing that before a release as well. Deploying shouldn't be as taxing on you and your team as it often is; it should be just a simple matter of executing a command, or even merely pushing to our version control system (VCS), triggering a Continuous Integration build, as we'll go over at length in chapter 4.

Testing, along with all those other tasks isn't something we can leave up to team members alone; it has to be part of the process too. That means automated testing should happen on every deployment, or maybe every time we send changes to the VCS. That's where a build process might come in handy, as it's exactly that automation that helps us mitigate human error during these conversion processes, which are tedious to perform manually, anyways.

This book is about the Build First approach, which at its core, encourages not merely establishing a build process, but also clean application design. In Part II we'll learn concepts, techniques and patterns we can apply to our applications, making them more modular, testable, and maintainable. Here is what embracing the Build First approach gives us right off the bat:

• Less error-proclivity since there's no human interaction

• Improved productivity by automating repetitive tasks

• Deployed code always gets tested before a release

• Releases follow performance best practices

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

3

• Modular, scalable application design

• Testability, and maintainability as a result of looser coupling and decreased complexity

As we'll see in section 1.1.3, building isn't just about releasing the application, as it also provides us with benefits while developing the application in our day-to-day development, but before we get into those details, let's go over a recent case study.

1.1.2 Why Build? I bet you would consider losing almost half a billion dollars as a pretty serious issue, and that's exactly what happened to Knight's Capital [1]. They had developed a new feature which, like many of their features, depended on a flag to be on or off. Presumably, this flag was on a database, so they could flip the switch without re-deploying if something went amiss. The codebase had a discontinued feature sitting behind that same flag, which was swapped out in favor of the newer feature, so all was good. Or at least they thought so, until the point when they flipped the switch. Deployments had no formal process, and thus they were executed by hand by a single technician. This person forgot to deploy the code changes to one of their 8 servers; meaning that in the case of the 8th server, the discontinued feature would be behind that flag. The didn't notice anything off until a week later, when they turned on the new feature, along with the 9-year-old one.

Attempts to amend the situation only further aggravated it, and – long story short – they lost somewhere in the vicinity of 460 million dollars in less than an hour. When we consider that all they needed to do to avoid their downfall was have a more formal build process in place, the whole situation feels outrageous, irresponsible, and in retrospect: easily averted. Granted, this is an extreme case, but it boldly illustrates the point: build processes mitigate the odds of slip ups that might cost you and your bosses lots of money.

When it comes to JavaScript, given that interpreted languages don't need a compiler, the naive developer might think that is justification enough to ditch the build process entirely. The problem when going down that road is you'll be shooting in the dark; you won't know whether your code works until it's executed by a browser; you won't know whether it does what you expect it to, either. Later on, you might find yourself manually deploying to a hosting environment, and logging into it remotely to tweak a few configuration settings to make it work.

In Part I of the book, on Build Processes, I'll describe a build-oriented approach to application design, which I have dubbed Build First, which directly addresses these concerns.

In Build First we will: Build, copying things around and compiling anything that needs compilation, such as a pre-processor language; Test, making sure our code upholds the quality standards we set for it; and Release, preparing our application for an eventual

1 [1.1] http://bevacqua.io/bf/knight

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

4

Deployment, when our application will go live (or receive an update). Figure 1.2 below describes the Build First approach on a high level.

Figure 1.2 High level view of the Build First approach to application building

In this chapter we'll scratch the surface of the methodology, learning about the philosophy behind Build First, and later in the chapter we'll get our hands dirty with some code, introducing the Grunt.js JavaScript build tool. Chapter 2 digs deeper into the build tasks, both in theory and in code, detailing some of the more common goals of a build process. Environments as a whole, and the development environment in particular will be extensively discussed in Chapter 3, along with different approaches to environment configuration. Release and deployment are discussed in Chapter 4, detailing what it means to release the application, the deployment process, the trade-offs of automated deployments, and the benefits of continuous integration. We have much more immediate concerns: let's explore a little deeper into the meaning of Build First.

1.1.3 What is Build First? Before we dive into the uncharted terrains of Build First, I want to mention that this is not a set of principles that only apply to JavaScript. For the most part, it's a set of principles that people usually associate with back-end languages, such as Java, C#, or even PHP. I'm just applying them to the development process for JavaScript applications.

Imagine you've designed the initial prototype for your application, showed it to the interested parties; it paid off, and now it's time to build the real thing. Scrap the prototype, and start over. That tracer bullet might've been fine for pushing the idea through, but it probably wasn't an adequate foundation for a long-lived application. Once you are out of the

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

5

prototype stages of a project, you need to either perform a meticulous re-factoring of the prototype, or start afresh.

Starting afresh might seem like a silly idea; you just did that a month ago! Be that as it may, you've probably collected critical understanding you didn't have a month ago. You might've taken shortcuts when coding the first draft, aware of what you were doing, but considering it just a quick prototype; it was fine as long as it worked. Therefore, it's often best to start anew. In doing so, you'll be able to reinforce the ideas that were right in the prototype stage, as well as rebuild the parts of the application that were lacking in design.

The Build First approach puts a stop to manual labor when it comes to tedious tasks, while also improving our productivity from the get go. Build First acknowledges the significance of the build process to shaping a maintainable application iteratively. Once the prototype is out of the building stage, we start putting together an application that will one day go live so humans can consume it.

“Users” are people too! Throughout the book, I use the term humans frequently (and interchangeably with users), as a reminder that, more often than not, people using applications we build aren't as technically inclined as we (apologists 2 as Alan Cooper insists on calling us) are, but rather strangers to the world of algorithms we thrive in. This serves as an unconscious nod to the fact that we're ultimately building applications with a human being, and not a fellow software developer, as the foremost priority when pondering about design decisions.

Let's taste a sample of the benefits you could attain and automate, if you decide taking a Build First approach.

• Building an icon spritesheet so that iconography HTTP requests are reduced to a single one

• The ability to spin up new environments effortlessly, neglecting to differentiate between development and production

• Restarting a web server, and recompiling assets, is done for us whenever related files change

• Repetitive tasks such as compilation, minification, and testing can be automated

• Single-step deployments that are flexible enough to support multiple environments

• Business course-correction thanks to a faster feedback loop

2 [1.2] http://bevacqua.io/bf/apologist

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

6

We'll dig a little deeper into build processes in a moment, but first let's round out the definition of Build First by delving into the architectural aspects involved.

1.1.4 Architecture in JavaScript? It used to be the case that exceptions in client-side code weren't that bad [3].Things would work regardless of browsers having trouble following a particular code path, kind of. A decade ago this was fine; JavaScript wasn't so ubiquitous, and being able to use the page with it disabled wasn't optional. Then AJAX, asynchronous emerged and established itself as a predominant pattern of the web, making the scenery much more diverse than we were used to, and enabling more interactive applications able to update individual portions of a page without affecting everything else. Today AJAX is everywhere; applications are seldom built statically anymore, and rich JavaScript applications such as Gmail aren't the exception anymore, but rather commonplace.

The AJAX Web I'm sure you know AJAX stands for “Asynchronous JavaScript and XML”, and that although its name doesn't have anything to do with what AJAX really means today, it fundamentally changed the face of web development and web interaction design, forever. Today AJAX means providing a fast, and reliable, interactive user experience.

Libraries like jQuery made it extremely easy for anyone to build an AJAX web application. However, much like PHP code, JavaScript can pretty easily become a spaghetti nightmare, callback hell, as well as many other names for poor quality code.

Fast-forward to the present day. Nowadays, web applications provide a much richer experience than they used to: the front-end is now a major player in the design of modern web applications. More than ever, the browser is being abused with responsibilities which used to be delegated to back-end servers. It's not just about handling events, doing some AJAX, and maybe changing the UI a bit anymore. Modern applications tend to do a lot more than that. Rendering templates, managing dependencies, even routing!

Today, the Model-View-Controller (MVC) pattern, which separates data, its representation, and business logic, is all around us, and has made its way into the browser, as well. Mobile browsing also introduced a whole new layer of complexity to web application design, and now isn't an oddity, but something we should be solving before thinking about the desktop experience.

Then there's the architecture; there's a lot we should be doing about that. Part II of the book is dedicated to application design, following an outward spiral: we start right in the eye of the storm, learning how to craft modular JavaScript that doesn't break apart as soon as

3 [1.3] http://bevacqua.io/bf/browser-errors

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

7

we start combining pieces of code. We'll also be looking at lots of patterns to improve the quality of our programs, such as using Callbacks, and how to avoid the infamous callback hell; promises, as an alternative to the more traditional callback-based asynchronous coding style; Dependency Injection, positioning ourselves to write easily testable code, and many more.

Once that's covered, we'll develop a full-blown mystery application in Part III, which is entirely dedicated to its design, build, and development process. Figure 1.3 below might help you understand the progression we'll follow in Part II.

Figure 1.3 Application Design concerns discussed in Part II

Modularization, managing dependencies, understanding asynchronous flow, sane error handling, as well as following the right patterns for our application, and testing are all crucial if you expect your code to work at a certain scale, regardless of language. Some of these practices fall in the category of build tasks. We'll come back to application design topics later in the chapter. For now, let's sink our teeth in yet another concept, the definition of a lean model.

1.1.5 A Lean Model The Lean Startup [4] is a methodology popularized by Eric Ries, which proposes an approach to application development where we are constantly questioning the merits of individual features. This model was inspired by Toyota's lean manufacturing revolution, in a cycle

4 [1.4] http://bevacqua.io/bf/lean

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

8

regarded as the Build-Measure-Learn feedback loop. In this definition, Build is actually developing our product; Measure means gauging how humans interact with it, and Learn would be the stage where we decide where we keep a feature, or ditch it. Figure 1.4, below, describes this development model.

Figure 1.4 shows the Build-Measure-Learn feedback loop

In our case, we are going to focus on the Build aspect of the lean methodology that Eric proposes, which involves not just the build process itself, but also the application design process, as well as actually baking the features into our product. Let's kick things off by digging a bit deeper into what we really mean when we say "build process."

1.2 Build Processes Building is the process through which we convert our source code into something that can be executed. In the case of web applications, the execution is performed in conjunction by a web server such as `iis`, `apache`, `node`, or `nginx`, and a user-agent such as Chrome, Safari, or the command-line programs `curl`, and `wget.`

The build is intended to automate repetitive tasks such as installing dependencies, compiling your code, running unit tests, and performing any other important functions. Being able to execute all of the required tasks in a single step, called a one-step build, is critical because of the powerful opportunities it unveils. Once we have a one-step build in place, we should be able to execute it as many times as required, without the outcome being any

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

9

different. This is a property commonly known as idempotence: no matter how many times you invoke the operation, the result will be the same.

There are many advantages to an automated build process. Possibly the most important of those, is the ability to deploy as frequently as required to production. Providing our humans with the latest features as soon as they are ready, allows us to tighten the feedback loop through which we can gain better insights into product we should really be building. The main disadvantage to setting up an automated build process is the time we'll need to spend in putting the process together, before we can start seeing the real benefits. The benefits, such as automated testing, higher code quality, a leaner development workflow, and a safer deployment flow, far outweigh the effort spent in putting together that process. As a general rule, we'll set up the process once, and then be able to replay it as much as we'd like, tweaking it a little as we go.

1.2.1 Continuous Operations With the right setup, we might end up with a code-base that re-compiles affected components (and executes a test suite) every time related files change. This is called Continuous Development, and it presents a numbers of benefits, as we'll discuss in Chapter 3. For one, we avoid manual interaction with the build, meaning this automated set of tasks also takes care of itself. This not only allows us to focus on the thinking, but it also boosts code quality, since we get immediate feedback whenever a test fails.

On another level, but not dissimilar to continuous development, we might trigger a build (on a remote server) whenever a commit is pushed; that way we'll learn about how our changes impact the codebase, independently of the environment the tests are executed in. This is usually done by adding a commit hook to our version control system. Does the code still compile? Do all the tests pass? If something goes wrong, we can get notified via email. A simple "Hey, the build broke!" and a link to a log would do. This is called Continuous Integration (CI), and we'll go over it in Chapter 4.

The benefits of having an automated build process, from a business standpoint, largely lie in the fact that it enables us to perform many deploys (as many as we deem necessary) throughout the course of an iteration, in a week, or even a given day. This reduces the friction and stress that we're used to see when a release deadline approaches, since each change we push is also accounted for by our version control system. If and when things go awry, and considering the fact that we are now performing these deploys on a regular basis, pinpointing offending changeset becomes easier, too. Not only that, but if we can't fix the issue quickly enough, we might be able to roll back the deployed application to an earlier version that doesn't present the same inconvenience.

We've been mentioning environments, but what exactly are we talking about? How do they relate to one another? Let's go over them and their interconnectedness.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

10

1.2.2 Application Environments When we are developing an application, we commonly do so on our own devices (presumably, your PC or notebook); things we can touch. I'll refer to this device as the local, or development environment.

We usually take our testing elsewhere, to a remote server for example; somewhere many members in the team have access to, and are able to deploy to, helping test features, give feedback to their teammates during code reviews, show off the application to potential clients, and where we can also make sure the application is not acting up, or misbehaving in some way. This is called a staging, or testing environment. Sometimes, a staging environment isn't used, and code gets pushed directly to production, instead. This is riskier, but it can be acceptable, depending on the scope and magnitude of our project.

Imagine environments as tests our application has to endure, before making it to the humans. Tests in the traditional sense of the word; not the technical sense we are so used to. If the code doesn't pass the "build test," we shouldn't let it go any further than the local environment. When that's ready, we might want to give it a shot at the staging environment, play around a little, and when we think the application passes that test too, then we can move it up a notch, to production.

In this sense the local environment is referred to as the lowest environment; the code should comply with an absolute minimum of requirements to move up the ladder. As we get closer to the upper environments, the constrains are going to get tighter, making it deliberately harder, limiting our odds to deploy a faulty build.

Even though the tasks may diverge a little for each of those environments, we should strive to keep them very intimately related. If we minimize the gap between the different environments, we are making it easier to reproduce bugs in lower environments. We'll look at environments, as well as alternative ways to configure our build in Chapter 3.

It is now time to inspect the other side to Build First: clean application design and architecture.

1.2.3 Pragmatic Architecture in Build First I've come to realize that if a project isn't well designed, structured, and documented, it is going to become a problem for anyone working on it. That will only get worse if new members, who know nothing about the project structure, are assigned to the team. They can hardly learn on their own from the get go, since the code is so hard to follow, and you need to do a lot of hand-holding as a result. Build First puts the knowledge about a project in the earth, rather than the heads of the people that first built it.

The Pragmatic Programmer[5] is one of my favorite books of all time, and you can find a quote below, taken from that book, where the authors poetically describe a theory about

5 http://bevacqua.io/bf/pragmatic

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

11

"broken windows." Seemingly innocent issues, when left unattended, can have disastrous repercussions.

BROKEN WINDOW THEORY One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment - a sense that the powers that be don't care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short space of time, the building becomes damaged beyond the owner's desire to fix it, and the sense of abandonment becomes reality.

Taken in context, it means that you shouldn't leave holes in your work with hopes that someone else will take over and finish the job, because more often than not the contrary will happen, and others will follow suit in creating a mess, assuming someone else will clean up after them. This often produces an unmaintainable project as a result, doomed to make everyone working on it miserable.

Sure, we might have our reasons, coding ourselves to death without doing a lot of prior planning is indeed tempting; but it often translates into code that's hard to interpret by others, or even ourselves, in the not so distant future (I wrote that!?)

Writing well designed and structured code isn't something you do once and then forget about. Yes, you have to start somewhere; but after your application has an initial structure it is our job to ensure that the code sticks to a cohesive set of principles, and that it follows the rules and conventions you prepared. The Build First approach won't save you from impending disaster, only a strong team of developers can help your project with that. However, it'll help you establish a dependable code-base that'll be ready to go to production effortlessly on any given day, and which will be less likely to slowly turn into an unworkable mess.

A Build First approach also enables new collaborators to get set up quicker, since they won't have to spend a few hours getting their environment to work. Ideally, they should be able to execute a single command, two at most, and be ready to start hacking away at your project. Similarly, distributing our application among environments won't be as painful. If you don't approach a new project in a Build First way, chances are you won't automate the setup process for new environments, and this would end up hurting your ability to deploy as well, because you'd need to take manual steps.

We need to construct a framework we're able to progressively develop upon, where pieces of code are organized in components which don't compete with each other, but rather collaborate. We need to be able to work without fear that things might break apart on any given line of code, because of tight coupling. What we need, is a pragmatic approach to application architecture.

AVOID BROKEN WINDOWS Much more often than I'd be happy to admit, I've worked on code-bases where the client-side JavaScript code was designed as an after-thought, if at all. You probably had to work with long JavaScript files, deeply nested functions in what's often referred to as "callback

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

12

hell," or excruciating situations such as code embedded directly in the HTML, tight coupling between JavaScript and the HTML DOM, and similarly undesirable projects nobody wants to work on.

This situation is aggravated mostly by the broken windows theory, and tight schedule deadlines. Realistically speaking, we can't do that much about the latter. Our development efforts must yield some value to move the business forward. Project leaders will rarely sign off on rewriting a piece of code without any functional gains, and for good reason. What can be done, is rewrite code that's related to a functional improvement, bug fix, or similar. This kind of improvement is however a slow process, and it doesn't allow for large scale redesigning.

We could've done something about the broken windows. We could've written an interface to mediate between a legacy component and a newer one, rather than integrate our latest development into the code fondue that we're letting the application become. That way, at least the newer piece of code would have a brighter future. The harsher reality, though, is that the foundation you define when hatching a project will have a strong correlation to the quality of the code that follows that foundation.

A good foundation would keep different logic concerns such as presentation, business rules, and persistence in separate layers, and each of these layers would keep different modules which are decoupled from each other. This kind of structure is common enough in back-end implementations, but it just now has started seeing adoption in front-end code as well.

Part II will be devoted to the aforementioned architecture concerns, and examine plenty of real-life scenarios we'll be able to relate to. Let's Build, First. It's time to jump into the trenches, armed with our Build First weaponry.

1.3 Diving into Build First Now that we've gone over a brief overview of the topics we'll be covering throughout the book, it's time to get comfortable and start getting into the specifics of Build First. We'll begin our journey talking about Lint, a code quality tool that's perfect to keep an interpreted language such as JavaScript in check. Rather than firing a browser to check if our code is working, we might use a program that will tell us about potential problems in our code, such as undeclared variables or missing semicolons.

1.3.1 Keeping Code Quality in Check Lint is the process of determining if a given piece of code contains any syntax errors and it also enforces a set of best practice rules, which we'll be covering at the beginning of Part II, in Chapter 5. Around ten years ago Douglas Crockford released JSLint, a harsh tool that checks our code and tells us all the little things that are wrong with it. Linting exists to help us improve the overall quality of our code.

A lint program can tell us about the potential issues with a snippet, or even a list of files, straight from the command-line, and this has the added benefit that we don't even have to

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

13

execute the code to learn what might be wrong with it. This process is particularly useful when it comes to JavaScript code, since the lint tool will act as a compiler of sorts, making sure that, to the best of its knowledge, your code can be interpreted by a JavaScript engine.

On another level, linters (the name given to lint programs) can be configured to warn us about code that's too complex, such as functions that include too many lines, obscure constructs that might confuse other people, or enforce us to follow some other best practice. Take the snippet below, as an example.

function compose_ticks_count (start) { start || start = 1; this.counter = start; return function (time) { ticks = +new Date; return ticks + '_' + this.counter++ } }

There are plenty of problems readily apparent in this small piece, but some might not be that easy to spot. When analyzed through JSLint, we'll get both expected and interesting results. It'll complain that we must declare our variables before we try to use them; that we are missing some semicolons, and depending on the lint tool we use, it might complain about our usage of the “this” keyword. Most linters will also complain about the way we're using || rather than using a more readable if statement. You can lint this sample online at http://jslint.com, the original JavaScript linter Crockford maintains. Figure 1.5 below shows us the output of his tool.

Figure 1.5 Lint errors found In our snippet of code

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

14

In the case of compiled languages, these kinds of errors are caught whenever we attempt to compile our code, and we don't need any lint tools. In JavaScript though, there is no compiler, because of the dynamic nature of the language. This is decidedly powerful, but also more error-prone than what we might expect from compiled languages, which wouldn't even allow us to execute the code in the first place.

JavaScript code is, instead, interpreted by an engine such as V8 (as seen in Google Chrome), or SpiderMonkey (the engine powering Mozilla Firefox). Even where some engines indeed do compile the JavaScript code, most famously the V8 engine, we can't really benefit from their static code analysis outside the browser [6]. One of the perceived disadvantages of dynamic languages such as JS, is that we can't know for sure whether our code will even work when we execute it. While that's true, we can vastly diminish the uncertainty using a lint tool. Furthermore, JSLint advices us to stay away from certain coding style practices, such as using eval, leaving variables undeclared, omitting braces in block statements, and so on.

Has your eye caught a potential problem in the above function? Check out the sample to verify your answer! Hint: the problem lies in repetition. The fixed version is also found in that example; make sure to check out all of that good stuff.

Source Code In the source code included with this book, you'll find a few more nuggets of information, including a tweaked version of the function we saw earlier, which passes the lint verification, also fully commented to let you understand the changes made to it. The sample also goes on to explain that linters aren't bullet-proof.

This code is organized by chapter, and the samples appear in the same order as they do in the book, for convenience. Some of the samples in the accompanying code are only discussed at a glance in the book, but all of the samples are fully documented, and ready to use. The reason for this is that sometimes I wanted to explain a topic but there was too much code involved to be included in the book. In those cases, I didn't want to drift away too much from the chapter in question, but I still wanted you to have the code.

Linting is often referred to as the first test you should set up when writing JavaScript. Where linters fail, Unit Tests come in. Unit Testing is going to help you ensure your code behaves in the way you expect it to. Unit Testing is discussed in Chapter 8, where we'll learn how to write tests for the code we've been developing throughout Part II, dedicated to writing modular, maintainable, and testable JavaScript code.

6 [1.6] In Node.js, a server-side JavaScript platform that runs on V8; we can see it in effect in the console instead, but by the time V8 detects syntax issues it'll be too late for our program, which will implode. Thus, it's always best to lint first, regardless of the platform.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

15

Next up, we'll start putting together a build process from scratch. We'll start small, just setting up a task to lint the code, and then being able to run it from the command-line. Much like what the process looks like if we were to use a compiler, we'll make a habit of running the build every time we make a change and learn whether the code still "compiles" against the linter. Chapter 3 will teach us how to have the build run itself, so we don't have to repeat ourselves like that, but it'll be fine for the time being. How can we actually use a lint tool like JSLint straight in our command-line? Well, I'm glad you asked.

1.3.2 Lint in the command-line One of the most common ways to add a task to a build process, is being able to execute that task using a command line. If we are able to execute the task from the command-line, then it'll be really easy to integrate it to our build process. We are going to use JSHint [7] to lint our software. JSHint is a powerful linter that can be used in a variety of ways, we will install their Node.js distribution, which will allow us to use it from the command line. There are a few steps to follow, but I'll be sure to get into the details in each case.

Node.js Explained Node is a relatively new platform which you've surely heard of by now, it was initially released in 2009, and it follows event-driven and single-threaded patterns, which translates into highly performant concurrent request handling. In this regard, it is comparable to the design in nginx, a highly scalable multi-purpose - and very popular - reverse proxy server, meant to serve static content and pipe other requests to an application server (like Node). Node has been praised as particularly easy to adopt by front-end engineers, considering it's merely JavaScript on the server-side (for the most part), but it also made it possible to abstract the front-end from the back-end entirely [8], only interacting through data and REST API interfaces, like the one we'll be building in Part III

JSHINT INSTALLATION Step 1: Visit http://nodejs.org, as shown in figure 1.6, and click on the INSTALL button

to download the latest version of node. Step 2: Execute the downloaded file and follow the installation instructions.

7 [1.7] http://jshint.com 8 [1.8] http://bevacqua.io/bf/node-frontend

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

16

Figure 1.6 The http://nodejs.org website

Once you've downloaded and installed Node.js, you'll get a command-line tool called npm (which stands for Node Packaged Modules) for free, as it comes bundled with Node. This package manager, npm, can be used from your terminal to install, publish, and manage modules in your Node projects. Packages can be installed on a project-by-project basis, or they can be installed globally, making them easier to access directly in the terminal. In reality, the difference between the two is that globally installed packages are put in a folder which is in the PATH environment variable, and those which aren't, are put in a folder named node_modules in the same folder we're on when we execute the command. To keep projects self-contained, local installs are always preferred. However, in the case of utilities such as the JSHint linter, which we want to use system-wide, a global install is more appropriate. The -g modifier tells npm to install jshint globally. That way, we can use it on the command-line just as jshint.

Step 3: Open your favorite terminal window, and execute: npm install -g jshint, as shown in Figure 1.7. If it failed, you might need to use sudo to get elevated privileges. e.g: sudo npm install -g jshint.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

17

Figure 1.7 Installing jshint through npm

Step 4: Run: jshint --version. It should output the version number for the jshint program, as shown in Figure 1.8 below.

Figure 1.8 Verifying jshint works in our terminal

LINTING YOUR CODE If all went well, you should have jshint installed in your system, and accessible in your terminal, as we've just verified. To lint our code using JSHint, you can simply change directories using cd to your project root, and then type in jshint . (the dot tells JSHint to lint the current folder).

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

18

When the command completes, you will get a detailed report indicating the status of your code. If there are any problems with your code, the tool will report the expected result and line number for each of those problems. Then, it will exit with an error code, allowing us to "break the build" if the lint fails. Whenever a build task fails, a build is aborted in its tracks. This presents a number of benefits, as it prevents work to continue if something goes wrong, refusing to complete a build until we fix the issues we're seeing. Figure 1.9 below shows the results of linting the first sample snippet in the book.

Figure 1.9 Linting with JSHint from our terminal

Once JSHint is all set, we might be tempted to call it a day, since it's our only task, however that wouldn't scale up very nicely if we want to add extra tasks to our build. We might want to include a unit testing step to our build process; this would become a problem because we now have to run at least two commands: jshint, and another one to execute our tests. That doesn't scale very well; imagine remembering to use jshint, and half a dozen other commands complete with their parameters? It'd be too cumbersome, not to mention hard to remember, and error-prone. You wouldn't want to lose half a billion dollars, would you? Then we better start packing our build tasks together, even if we only really have a single one for now, we'll soon have a dozen!

Every language has its own set of build tools you can use; most have a tool that stands out among them, and which sees far wider adoption than the rest. Considering this is a book about JavaScript, we will learn to use Grunt: the clear winner when it comes to JavaScript build systems. If you are writing a build process for another language, you'll probably want to do some research of your own. Even though the examples in the book are written in JavaScript, the principles I describe should apply to pretty much any language.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

19

1.3.3 Introducing Grunt Grunt [9] is a task runner that helps you execute commands, run JavaScript code, and configure different tasks; configuration is written entirely in JavaScript. As you'll see in a minute, we'll be able to put together a build process with relative ease, and adding tasks to that will be even easier. Grunt comes bundled with a CLI (command-line interface) called grunt, which will provide us with a very simple API to execute the build tasks we've created, and also pick which configuration target we'll use, straight from the command-line. Ok, let's get Grunt set up so we can start writing some JavaScript!

INSTALLING GRUNT We already have npm, which came bundled with Node, from our JSHint installation in the previous section. Getting started with grunt is really simple. Just type npm install -g grunt-cli, and it will install the grunt CLI for us, so that it can be used from our command line from any directory, since it will be registered to our system's PATH environment variable.

If you aren't already working on a Node.js project, you'll need to take one additional step, which is creating a package.json manifest file. These files are used in Node projects to describe them, and they are also used to indicate a list of packages the project depends upon. For Grunt to work in our project, we need to add it as a development dependency in our package.json. It needs to be a development dependency because we won't be using Grunt anywhere other than our local development environment. We can create a bare minimum package.json file containing the following JSON code.

{}

That'll be enough. npm can add the dependency to our package.json as long as the file exists and it contains a valid JSON object. Next up, we'll need to install the grunt package. This time, the -g modifier won't do us any good, because we need it to be a local install, not a global one[10] - that's why we created the package.json file. We should use the --save-dev modifier instead, to indicate the module is a development dependency.

The command would look like this: npm install --save-dev grunt. Once npm completes the installation, our package.json manifest will end up like below.

{ "devDependencies": { "grunt": "~0.4.1" } }

9 [1.9] http://bevacqua.io/bf/grunt 10 [1.10] Grunt requires us to make a local install for the grunt package, and any task plugins. This keeps our code working across different machines, as we can't include global packages in our package.json manifest.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

20

In addition, the module will be installed to a node_modules folder, rather than being somewhere where the PATH variable points to. This folder will contain all the modules we'll be using as part of our Grunt setup, and they'll be declared in the package manifest as well. The last step we need to take, is creating a Gruntfile.js file. Grunt uses this file to load any tasks that are available, and configure them with any parameters we need. The bare minimum Gruntfile.js module is below.

module.exports = function (grunt) { grunt.registerTask('default', []); };

There are a few things to note about that innocent looking file. Gruntfiles are Node modules, which subscribe to the CommonJS Modules spec[11], which basically means that code we write in each file isn't immediately accessible to others, the implicit "global" object is the local module object, and when we import other modules, all we get is the public interface exposed in module.exports. This makes Node programs more modular than client-side Javascript, and it helps us write more decoupled code, too. If you run the grunt command at this point, nothing will happen, since the only task we've registered doesn't do anything.

We have plenty of tasks at our disposal, however. Installing JSHint for Grunt is almost as easy as installing the actual tool, but easier to configure, and using JavaScript! We should execute npm install --save-dev grunt-contrib-jshint, to fetch, install, and save the plugin to our package.json file as a development dependency.

Finally, we'll need to tweak our Gruntfile, telling Grunt to lint the Gruntfile itself, since it's JavaScript. We'll also need to tell it to load the JSHint plugin package, which contains the task that sets up the actual linting, and update our default task so that we can lint our code just by using grunt in our command-line.

module.exports = function(grunt) { grunt.initConfig({ jshint: ['Gruntfile.js'] }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.registerTask('default', ['jshint']); };

GRUNT MANAGES THE BUILD PROCESS Backing up a little, we're pretty much in the same position as we were a section ago, except that we're not. Grunt will help us put together the full blown build process that's at the heart of the Build First philosophy. With relative ease, we'll be able to focus on different tasks depending on whether we're building for local development or diagnostics, or building the

11 [1.11] http://bevacqua.io/bf/commonjs

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

21

end product humans will ultimately consume. Let's examine a few properties found in build tasks.

The lint task we just set up will serve as the basis for a much more powerful build as we expand our understanding throughout Chapters 2, 3, and 4. Innocently, the lint task shows off one of the fundamental properties of build tasks, and that's that in the vast majority of the cases, they'll be idempotent: repeated execution of a task shouldn't produce different results. In the case of the lint task, that might mean getting the same warnings every time, as long as we don't change the source code. Most often than not, build tasks are a function of one or many provided input files. The idempotence property, when paired with the fact that we shouldn't be performing any operations by hand, translates into more consistent results.

Tasks in our build are meant to follow a cleanly defined workflow when put together. Some tasks may definitely be optional for a particular workflow to work. For instance, there is no need to optimize our images, so that they become smaller, when working in our local development environment, and it's perfectly fine to skip that task in that case. However, whatever our workflow is oriented at, we'll probably want to make sure to watch out for issues with our lint task. Chapter 2 is dedicated to build tasks in general, and in particular: how to approach them using Grunt.

1.4 Summary • Modern JavaScript application development is problematic because of the little

regard given to design and architecture.

• Build First helps us establish a foundation we can build upon, and we've taken the first step in that direction by linting some code.

• Grunt is a task runner that will help us lay out both the development and the release flows, as well as configure the tasks that need to be executed in both of those work flows.

• We've barely scratched the surface of what we could achieve using a Build First approach to application design, though. There's a lot of ground to cover! Let's move to Chapter 2, where we'll discuss the most common tasks we might need to perform during a build, and go over implementation examples using Grunt.

©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.

http://www.manning-sandbox.com/forum.jspa?forumID=888

22