You are currently browsing the Code Review archives.

JavaScript Comma Delimiter Pattern

Tuesday, June 5th, 2012

Perhaps the most common syntactic error I find myself correcting in JavaScript is that of a simple missing comma separator on new lines. Such marginal oversights can become quite a nuisance to correct time and time again. Fortunately, there is a rather simple pattern which can be used to help avoid these errors with very little effort – only requiring code to be rewritten in a manner that reads more naturally while also being syntactically correct.

Typical missing comma scenario

If we are to consider the most common scenario where a comma is unintentionally omitted (and a subsequent exception is thrown), it can most likely be found within The Single var Pattern (irrespective of any personal preference towards or against the pattern itself).

For example, consider a typical block of code implementing a single var:

The above example, being rather typical and admittedly simple, does not pose much of a maintenance issue itself. However, if one is to refactor these declarations into a different order, add additional declarations, or specify more complex assignments, the probability of a comma being omitted unintentionally or becoming out of place increases.

In addition to The Single var Pattern, object literals are also a good source of occasional commas being omitted unintentionally, especially when nested within additional literals:

A Simple Solution

To help avoid such mistakes altogether, we can simply place commas before declarations, rather than after. At first, this may feel a bit awkward, but in time it becomes quite easy to get used to.

With this in mind, by placing commas first, the above could easily be refactored to the following:

As can be seen in the above example, considering we generally read code left to right, it becomes immediately apparent if a comma is missing.

For instance, take note of which implementation is easier to notice the missing comma:

I suspect most would agree that commas placed before stand out much more, and therefore it becomes much more apparent when one is missing. This appears to be so as the difference between the two is such that with commas placed after one needs to look for what is missing, whereas with commas placed before one sees what is missing.

As humans, our tendency towards patterns in general, and visual patterns in particular can not be understated. As developers, considering patterns are a significant part of our work, we should strive to take advantage of the most natural ones especially, even for things as seemingly marginal as placing comma separators first.

Organizing Require JS Dependencies

Thursday, May 17th, 2012

When developing large scale web applications leveraging RequireJS, at times, even the most highly cohesive of modules will require quite a few other modules as dependencies. As such, maintaining the order of these dependencies can become somewhat tedious. Fortunately, RequireJS provides a means of simplifying how modules may define dependencies for such cases.

Ordering Dependencies

If we are to consider how a typical module definition specifies dependencies, it becomes clear that one must ensure each module dependency name and it’s corresponding definition function argument have been listed in the same order:

In the above example, jQuery, Underscore and Backbone are specified as the modules dependencies as a dependency names array passed as the first argument to define(). Once all dependencies have been loaded, the modules definition function is invoked; with each dependency passed in the same order in which they were defined in the dependency array.

From both a design and client implementation perspective, this one-to-one correlation between dependency ordering and definition function argument ordering makes perfect sense, of course, for it would obviously be extremely confusing otherwise. In general this is rarely a concern, though when a module has many dependencies it can become cumbersome.

Adding Dependencies

The necessary side effect of the dependency/argument ordering is that as other dependencies need to be added, time must be spent ordering and re-ordering dependencies if one takes care to group dependencies categorically in order to improve readability (e.g. models…, collections…, views…, etc.).

For example, consider the following:

If we were to decide that this module also needed, say, Handlebars, we could simply add the new dependency to the end of the dependencies array, and then just add it to the end of the factory function’s arguments as follows:

While the above approach will certainly work, it fails to aid in readability as Handlebars is grouped with the application specific dependencies – the Model and Collection, as opposed to being grouped with the module’s framework dependencies. This may seem like a trivial detail, however, considering code is typically read many more times than it is written, it makes sense to organize dependencies as they are added in order to save ourselves and others time in the future when viewing the dependencies.

And so, ideally a team would have an established pattern of grouping dependencies in some kind of logical order. For example, framework specific dependencies could be listed first, followed by application specific dependencies etc. This ordering could be as simple or complex as a team collectively decides, though I would recommend keeping it generally simple.

With this in mind we could improve the above example as follows:

Organizing Dependencies

If we are to consider the above example as being somewhat typical, then it becomes rather clear that with each new dependency added we will likely have to repeat the ordering process. Again, while this may seem insignificant, it can easily lead to exceptions being thrown if any dependencies are out of order.

Fortunately, RequireJS provides a simplified CommonJS wrapping implementation, or Sugar syntax, which can be used to solve such issues. This sytax (which will feel natural to those who use Node) allows one to simply provide a module’s definition function to the module’s define call, and specifiy require as a single argument, as follows:

Using this pattern, we can refactor the above example to be more easily managed as follows:

With this pattern of dependency mapping it becomes much easier to add and remove dependencies as needed, with the added benefit of reading much more naturally. This pattern also feels more familiar as it is similar to import directives in other languages.

Conclusion

Managing module dependencies in RequireJS is quite simple and becomes even simpler when leveraging the Sugar syntax described above. When doing so, it is important to keep in mind that this syntax relies on Function.prototype.toString(), which, while having good support in most modern browsers, does not provide predictable results in certain older browsers. However, as the documentation states, using an optimizer to normalize dependencies – such as the very powerful RequireJS Optimizer – will ensure this approach works across all browsers.

As a general rule of thumb, I typically use the Sugar syntax approach when there are more than 4-5 dependencies and have found it has simplified managing dependencies in modules rather nicely.

Decoupling Backbone Modules

Wednesday, April 18th, 2012

One of the principle design philosophies I have advocated over the years, especially through various articles on this site, has been the importance of decoupling. And while I could go into significant detail to elaborate on the importance of decoupling, suffice it to say that all designs – from simple APIs to complex applications – can benefit considerably from a decoupled design; namely, with respect to testability, maintainability and reuse.

Decoupling in Backbone

Many of the examples which can be found around the web on Backbone are intentionally simple in that they focus on higher level concepts without diverging into specific implementation or design details. Of course, this makes sense in the context of basic examples and is certainly the right approach to take when explaining or learning something new. Once you get into real-world applications, though, one of the first things you’ll likely want to improve on is how modules communicate with each other; specifically, how modules can communicate without directly referencing one another.

As I have mentioned previously, Backbone is an extremely flexible framework, so there are many approaches one could take to facilitate the decoupling of modules in Backbone; the most common of which, and my preferred approach, is decoupling by way of events.

Basic Decoupling with Events

The simplest way to facilitate communication between discreet modules in Backbone is to have each module reference a shared event broker (a pub /sub implementation). Modules can register themselves to listen for events of interest with the broker, and modules can also communicate with other modules via events as needed. Implementing such an API in Backbone is amazingly simple, in fact, so much so that the documentation provides an example in the following one liner:

Essentially, the dispatcher simply clones (or alternately, extends) the Backbone.Events object. Different modules can reference the same dispatcher to publish and subscribe to events of interest. For example, consider the following:

In the above example, the Users Collection is completely decoupled from the UserEditor View, and vice-versa. Moreover, any module can subscribe to the 'users:add' event without having any knowledge of the module from which the event was published. Such a design is extremely flexible and can be leveraged to support any number of events and use-cases. The above example is rather simple; however, it demonstrates just how easy it is to decouple modules in Backbone with a shared EventBroker.

Namespacing Events

As can be seen in the previous example, the add event is prefixed with a users string followed by a colon. This is a common pattern used to namespace an event in order to ensure events with the same name which are used in different contexts do not conflict with one another. As a best practice, even if an application initially only has a few events, the events should be namespaced accordingly. Doing so will help to ensure that as an application grows in scope, adding additional events will not result in unintended behaviors.

A General Purpose EventBroker API

To help facilitate the decoupling of modules via namespaced events, I implemented a general purpose EventBroker which builds on the default implementation of the Backbone Events API, adding additional support for creating namespace specific EventBrokers and registering multiple events of interest for a given context.

Basic Usage

The EventBroker can be used directly to publish and subscribe to events of interest:

Creating namespaced EventBrokers

The EventBroker API can be used to create and retrieve any number of specific namespaced EventBrokers. A namespaced EventBroker ensures that all events are published and subscribed against a specific namespace.

Namespaced EventBrokers are retrieved via Backbone.EventBroker.get(namespace). If an EventBroker has not been created for the given namespace, it will be created and returned. All subsequent retrievals will return the same EventBroker instance for the specified namespace; i.e. only one unique EventBroker is created per namespace.

Since namespaced EventBrokers ensure events are only piped thru the EventBroker of the given namespace, it is not necessary to prefix event names with the specific namespace to which they belong. While this can simplify implementation code, you can still prefix event names to aid in readability if desired.

Registering Interests

Modules can register events of interest with an EventBroker via the default on method or the register method. The register method allows for registering multiple event/callback mappings for a given context in a manner similar to that of the events hash in a Backbone.View.

Alternately, Modules can simply define an “interests” property containing particular event/callback mappings of interests and register themselves with an EventBroker

For additional examples, see the backbone-eventbroker project on github.

Circumventing Conditional Comparisons

Friday, October 14th, 2011

Often during the course of my day I come across code which evaluates the same conditional comparisons in multiple contexts. Understandably, this is rather typical of most software systems, and while it may only introduce a negligible amount of technical dept (in the form of redundancy) for smaller systems, that dept can grow considerably in more complex, large scale applications. From a design perspective, this issue is applicable to nearly every language.

For example, consider a simple Compass class which defines just one public property, “direction” and, four constants representing each cardinal direction: North, East, South and West, respectively. In JavaScript, this could be defined simply as follows:

Technically, there is nothing problematic with the above class signature; the defined constants certainly provide a much better design than conditional comparisons against literal strings throughout implementation code. That being said, this design does lead to redundancy as every instance of Compass which needs to evaluate the state of direction requires conditional comparisons.

For example, to test for Compass.North, typically, client code must be implemented as follows:

Likewise, simular comparisons would need to be implemented for each cardinal direction. And, while this may seem trivial for a class as simple as the Compass example, it does become a maintenance issue for more complex implementations.

With this in mind, we can simplify client code by defining each state as a specific method of Compass. In doing so, we afford our code the benefit of exercising (unit testing) Compass exclusively. This alone improves maintainability while also simplifying client code which depends on Compass. As such, Compass could be refactored to:

Based on the above implementation of Compass, the previous conditional comparison can be refactored as follows:

Comparator API

To simplify implementing conditional comparisons, I have provided a simple Comparator API that defines a single static method: Comparator.each, which allows for augmenting existing objects with comparison methods. Comparator.each can be invoked with three arguments as follows:

type

The Class to which the comparison methods are to be added.
property
The property against which the comparisons are to be made. If the property has not been defined it, too, will be added.
values
An Array of constants where each value will be used to create a new comparison method (prefixed with “is”). If the constants specified are Strings, typically an Array containing each constant should suffice. For example, passing [Foo.BAR] where BAR equals “Bar” would result in an isBar() method being created. To specify custom comparison method names, an Object of name/value pairs can be used where each name defines the name of the method added and the value is the constant evaluated by the method. This is useful for constants which are not strings. For example, {isIOS421: DeviceVersion.IOS_4_2_1} where IOS_4_2_1 equals 4.2.1 would result in an isIOS421() method being created.

Taking the Compass example, the previous comparison methods could be augmented without the need to explicitly define them via Comparator.each:

The above results in the comparison methods isNorth, isEast, isSouth and isWest being added to the Compass type.

Comparator: source | min | test (run)

Multiple Form Factor Software Design

Sunday, March 6th, 2011

I have been giving a lot of thought lately about designing software in a Multi-Form Factor paradigm and felt I would share some initial thoughts on the subject. Keep in mind much of this is still quite new and subject to change; however, I have made an attempt to isolate what I feel will remain constant moving forward.

First, User Experience Design

My initial thoughts on the implications of what an ever growing Multi-Form Factor paradigm will have on the way we think about the design of software are primarily concerned with User Experience Design. While using CSS3 media queries to facilitate dynamic layouts will be needed for most Web Applications, I do not believe these types of solutions alone will allow for the kinds of compelling experiences users have come to expect, especially as they will likely compare Mobile Web Application experiences to their native counterparts. Sure some basic solutions will be needed, and for some simple websites they may suffice. However, in the context Web Applications, as well as just about every application developed specifically for a PC, too, I believe UX Design will need to leverage the unique opportunities presented by each particular form factor, be it a PC, smartphone, tablet or TV. Likewise, UX will need to account for the constraints of each form-factor as well. Architecturally, all of the above presents both opportunity and challenge.

To further illustrate this point, consider the fact that it is arguably quite rare that a UX Design intended for users of a PC will easily translate directly to a Mobile or Tablet User Experience. The interactions of a traditional physical keyboard and mouse do not always equate to those of soft keys, virtual keyboards and touch gesture interactions. Moreover, the navigation and transitions between different views and even certain concepts and metaphors are completely different. In simplest terms; it’s not “Apples to Apples”, as the expression goes.

With this in mind, as always, UX Design will need to remain at the forefront of Software Design.

Second, Architecture

Multi-Form Factor design obviously poses some new Architectural challenges considering the growing number of form factors which will need to be taken into account. The good news is, most existing, well designed software architectures may have been designed with this in mind to a certain degree. That is, the key factor in managing this complexity I believe will be code reuse; specifically, generalization and abstraction. A common theme amongst many of my posts, code reuse has many obvious benefits, and in the context of Multi-Form Factor concerns it will allow for different device specific applications to leverage general, well defined and well tested APIs. A good example being a well designed RESTful JSON service.

Code reuse will certainly be of tremendous value when considering the complexities encountered with Multi-Form Factor design. Such shared libraries, APIs and Services can be reused across applications which are designed for particular Form-Factors or extended to provide screen / device specific implementations.

Some Concluding Thoughts

In short, I believe both users and developers alike will be best served by providing unique User Experiences for specific Form Factors as opposed to attempting to adapt the same application across Multiple Form Factors. One of the easiest ways of managing this complexity will inevitably be code reuse.

I also believe the main point of focus should be on the medium and small form factors; i.e. Tablets and Smart phones. Not only for the more common reasons but, also because I believe PCs and Laptops will eventually be used almost exclusively for developing the applications which run on the other form factors. In fact, I can say this from my own experiences already.

While there is still much to learn in the area of Multi-Form Factor Design, I feel the ideas I’ve expressed here will remain relevant. Over the course of the coming months I plan to dedicate much of my time towards further exploration of this topic and will certainly continue to share my findings.

Practices of an Agile Developer

Thursday, February 10th, 2011

Of the many software engineering books I have read over the years, Practices of an Agile Developer in particular continues to be one book I find myself turning to time and time again for inspiration.

Written by two of my favorite technical authors, Andy Hunt and Venkat Subramaniam, and published as part of the Pragmatic Bookshelf, Practices of an Agile Developer provides invaluable, practical and highly inspirational solutions to the most common challenges we as software engineers face project after project.

What makes Practices of an Agile Developer something truly special is the simplicity and easy to digest format in which it is written; readers can jump in at any chapter, or practically any page for that matter, and easily learn something new and useful in a matter of minutes.

While covering many of the most common subjects on software development, as well as many particularly unique subjects, it is the manner in which the subjects are presented that makes the book itself quite unique. The chapters are formatted such that each provides an “Angel vs. Devil on your shoulders” perspective of each topic. This is quite useful as one can briefly reference any topic to take away something useful by simply reading the chapters title and the “Angel vs. Devil” advice, and from that come to a quick understanding of the solution. Moreover, each chapter also provides tips on “How it Feels” when following one of the prescribed approaches. The “How it feels” approach is very powerful in that it instantly draws readers in for more detailed explanations. Complimentary to this is the “Keeping your balance” suggestions which provide useful insights to many of the challenges one might face when trying to apply the learnings of a particular subject. “Keeping your Balance” tips answer questions which would otherwise be left to the reader to figure out.

I first read Practices of an Agile Developer almost 4 years ago, and to this day I regularly find myself returning to it time and time again for inspiration. A seminal text by all means, I highly recommend it as a must read for Software Developers of all levels and disciplines.