Modernizing Web Application JavaScript

Refactoring is a process of revisiting code and attempting to make it ‘better’. The code is no longer useful due to its age, functionality, or preference and it has been decided to  be replaced with an equal set of ‘better’ code. At no point does a developer learn the best way to refactor code. Refactoring is a skill learned through experience. JavaScript refactoring is notoriously hard due to scope and dynamic accessing of object properties. There is a clear pattern, however, that can be followed that promotes success and is pragmatic.

Apply syntax rules
Whether using jslint, jshint, eslint or jscs; automating the removal of simple bugs is a critical step. It can and probably should be broken up into smaller chunks by applying rules a few at time. A few rules that will help and drive future refactoring and are highly recommended are strict mode, requiring semicolons, not mixing tab and spaces, deleting unused variables, requiring block statements and type equality. Once syntax changes are implemented, enforce them with hooks to the code repository and/or part of the build process. Git, Subversion and Mercurial all implement hooks that are perfect for this. Your builds in grunt can also deal with git hooks too.

Apply closures ( skip if already in a module format )
Closures are not the final form but as a professional, pragmatic developer, the goal is to make incremental steps that can be released. By not allowing global scope inside the closure, you can emulate imports (the arguments) and exports (global namespace additions). The code should split up into 1 file per globally name-spaced “exported” object or function. Surprisingly, the code still hasn’t logically changed ( unless you were abusing a syntax error ). There could be a lot of files now if splitting them up when closuring (recommended), where before there only had a few.

The code is following a script loading procedure. JavaScript will load and run files in the order they are dropped on the page. Related, each request for a file slows down the initial page load due to the extra round trip HTTP calls. It should be obvious then to concatenate files. But now that the files are in closures, with strict mode, the values passed into the closure might be undefined depending on where they are loaded ( you can’t import a value that hasn’t been set yet, so it is undefined ). The order the code is concatenated in ( or loaded on the page in ) matters greatly. When using a build tool, make sure to name the files in an alphanumerical order that ensures values are set before included.
This necessary step has the potential clean up code dramatically without requiring logical changes to the code.

Start adding unit tests
It isn’t safe to rewrite code if without knowing what the code’s input and output is. Unit testing is ubiquitous in JavaScript  and there are more than a few frameworks for this. Adding and maintaining tests is an ongoing step, but its important that it’s possible to add a test easily to the code and run it before beginning logic changes. Begin with setting up the ability to test and then write a few tests. Add headless testing to a Push Hook or during a build process after the linting code. Make it a habit to write a test for complicated code before reworking. Karma and Testswarm make this easy to test in browsers as well (and can be extended to SauceLabs or BrowserStack). Unit testing should be at the functional level. If you feel you also want to take it to the next level with integration testing, then you can take a look at my favorite, Nightwatch.

Initialize code purposefully
Proper code waits to be initialized and not run immediately on page load. Immediate invocation of code does introduce race conditions and has a lot of sides effects. The first issue most developers run into is running JavaScript before the DOM is ready and then wondering why there are errors when looking for elements. In jQuery, you can add code like that in a $.ready block that waits for the DOM load event to trigger. But that is still not enough, because some code will run before the rest of the code has been loaded.  It’s best that all app code can be loaded without actually running any code. Then,  trigger the code to begin initializing. That means, if the code was on a blank page, nothing would actually run. No code would initialize, until it was told to. This also allows for much better unit testing now that the code doesn’t run unless it’s been initialized so the test environment cleans up right away.

Begin deleting unused code
In the introduction I stated that JavaScript is very difficult to refactor due to its dynamic parameter nature. That makes this step dangerous. If you have been following along, your JavaScript is now either in modules or single file closures. We now know each files input and output (what’s outside code is being used, and what the code is exposing to others). Deleting code is a manual process of removing files that are never imported by others at the highest level. But wait, there is a big gotcha. JavaScript allows for functions and values to be dynamically accessed; so even if `myFunc` doesn’t exist, `my`+`Func` might!  A simple search/replace on the code is not enough. So be careful when removing functions that might not be used. It is easy to delete code that is used without finding a place it’s being used. Doing a ‘debugger;’ statement and then running the application’s functionality would help reassure that code is not being triggered (assuming you can trigger all of the functionality easily). Or add logging notes and watch for usage in the logs. Also if code is running prior to initialization, then regardless if no other code is importing it, then it cannot be safely removed until debugged.

Perform statistical analysis
Many red flags in JavaScript are hidden and static analysis (SA) can be used to find the code that needs refactored first. Code complexity can be tracked, as well as a maintainability and parameter usage. SA should be in the build or continuous integration process. It helps guide where code is needing the most  attention without guessing or randomly refactoring. With JavaScript being such a magnet for young developers, the science of SA has not been at the forefront. That condition has quickly changed, and now it’s very hard to argue that SA isn’t useful or needed. Simple, useful tools are freely available like Plato and SonarQube can be used to track high level stats and to even set limits to certain things (like how many lines a function can be). SA is also useful for things like code coverage (or even the linting we did earlier) in tools like Istanbul.

Add logging
Before doing any large scale, breaking changes,  pay attention to the production ready code. Logging for errors and having a visual layer to perceive errors over time is something any size team will benefit from. When changing out large swaths of code, there will always be a breakage somewhere you aren’t expecting and tracking the errors will highlight that. NewRelic provides common tools to get the job done, but this is also one of those areas where rolling your own isn’t too difficult.

Create many small functions from large functions
Using the statistical analysis, you should be able to find high cyclomatic complex functions. Begin turning these into multiple functions that call each other, rather than a single large function. Try to find the generic patterns in the code so generic, testable functions can be created. Make sure to write tests too. Don’t worry just yet about completely refactoring the logic because it’s still not going to be entirely clear what the code is attempting to do in all cases. Focus on making small testable functions. Take notes for odd code or code that you feel needs revisited. It will take a long time to get to small, purposeful functions, but keep at it.

Modularize the code
The code is probably modular in a sense at this point, but it’s important to apply 2015+ best practices. Look at the ES6 module structure and look at using transpilers like Babel or SystemJS to rewrite your code in a module format. Still valid, but less future proof, would be using CommonJS (Node style modules) or Require with a Browserify step. In any case, going from script loading to module loading is a key performance and structural change to the code. It’s not a step that can be done quickly and without error; which is why all the previous work was done. However, once using best practices with modules, the code becomes much more manageable and adaptable for any future efforts.

The code is modular, small, syntax free and known. The last set of tasks is to basically re-think the application. The nitty-gritty implementation details should be rethought for clarity and performance. Are the events properly bound in the DOM? Is a pubsub model in place for non-DOM eventing? Is the data immutable? The amount of work could be endless, but it’s important to understand that these questions are only now possible due to the heavy work done already. The argument is no longer revolving around making better code, it’s now making smarter code. It’s a continuous process, but we’ve hit all the high level architecture changes that provide a framework for the really deep questions on performance and application hierarchy.  Go forth and improve.

Trimming Strings; Stripping Text in JavaScript

Strings are one of the most basic structures in any development language. Developing with strings happens in common ways across languages. Sometimes languages don’t offer the common gamut of tools and leave the developer to implement their own methods.  One of these cases occurs with a proper `strip` method in JavaScript. JavaScript added the `String.Trim`[1] with EcmaScript5, which is a specialized version of a generic `strip`, so that leaves developers to implement it themselves.

Continue reading Trimming Strings; Stripping Text in JavaScript

The HTML5 Input Event

In the DOM a special event occurs on an <input> or <textarea> element known as the `change` event [1] [2]. The `change` event gives a developer the ability to catch input changes. However, it falls short when instant feedback is needed because it will only trigger once the input has lost focus. Immediate feedback could be handled using the `keydown` or `keyup` events. Those events are costly (happening often and requires the code to keep state to know of changes actually occurring) and are potentially buggy due to extra logic needed.
Continue reading The HTML5 Input Event

Setting up Ansible for multiple environment deployments

Ansible is a tool for automating the task of installing software via SSH. You can run it against a server, a VM or even a desktop; anything that can be a target of SSH!  If you haven’t had the chance to use Ansible then go get a basic understanding before attempting to follow the things I will talk about.

The goal of Ansible is to be able to setup a server the same way, every time (immutability). This fits well with code development and the need to have production-like servers. Ansible does not smooth the transition between different environments, however. In fact, there is a special variable (environment) that has nothing to do with the concept that I’m writing about, making it a confusing thing to describe.

Continue reading Setting up Ansible for multiple environment deployments

My must have grunt plugins of 2014

Over the course of the year, I’ve been tracking what Grunt plugins that I have enjoyed the most.

Time-Grunt plugin
Time adds really helpful charts to the grunt process to allow for a visual inspection of where things are being slowed down. The graphs keep a very clear indicator of what is taking up time in the grunt processes. When caching layers are involved, is tends to show off the difference as well.
Continue reading My must have grunt plugins of 2014