You are currently browsing the Agile archives.

Function Modules in RequireJS

Wednesday, October 16th, 2013

Having leveraged RequireJS as part of my preferred client-side web stack for some time now, I find it rather surprising how often I recall various features from the API docs which I have yet to use, and how they may apply to a specific solution I am implementing.

One such feature is the ability to define a module as a function. While at first this may seem a rather basic feature, and indeed it is, there are quite a few practical purposes in which returning a function as a module definition can prove useful.

Function Modules

As one may expect, returning a function as a Module in RequireJS is rather straight-forward. For example, a simple random function can be defined as a module as follows:

Then, the function module can simply be invoked as follows:

Function Modules as Factories

Perhaps a more practical example of implementing a function module is in the context of a Factory Method.

For instance, a function module can be used as a convenient means of creating a specific type of object on a clients behalf based on certain conditions.

Take (an intentionally simple) example of a function module which, given a specific role type, returns a corresponding view implementation (in this example, a Backbone View) for an Editor feature:

Client code can then simply invoke the factory in order to retrieve the appropriate Editor view implementation based on the specified role type:

Defining modules as functions which serve as factory methods can help simplify client code implementations, as the responsibility of determining the type of object to create, configure, etc., can be delegated to a dedicated object; thus allowing for simpler designs which better facilitate code reuse, testing, and maintenance.

As a general rule of thumb, I typically reserve implementing modules as functions for cases in which a package level method would be appropriate, or for factory implementations. However, there are other scenarios in which function modules may apply, and so they are certainly worth noting.

You can fork the above example here.

Fluent APIs and Method Chaining

Thursday, August 1st, 2013

Of the vast catalog of Design Patterns available at our disposal, often times I find it is the simpler, less prominent patterns which are used quite frequently, yet recieve much less recognition; a good example of which being the Method Chaining Pattern.

Method Chaining

The Method Chaining Pattern, as I have come to appreciate it over the years, represents a means of facilitating expressiveness and fluency when used articulately, and mere convenience in it’s less sophisticated use-cases.

Design Considerations

When considering Method Chaining, one should take heed not to simply use the pattern as merely syntactic sugar from which writing fewer lines of code can be achieved; but rather, Method Chaining should be used, perhaps more appropriately, as a means of implementing Fluent APIs which, in turn, allow for writing more concise expressions. By design, such expressions can be written, and thus read, in much the same way as natural language, though they need not be the same from a truly lexical perspective.

The resulting terseness afforded by Method Chaining, while convenient, is in most cases not in-of-itself a reason alone for leveraging the pattern.

Implementation

Method Chaining, when considered purely from an implementation perspective, is perhaps the simplest of all design patterns. It’s basic mandate simply prescribes returning a reference to the object on which a method is being called (in most languages, JavaScript in particular, the this pointer).

Consider the following (intentionally contrived) example:

As can be seen, implementing Method Chaining requires nothing more than simply having methods return a reference to this.

API Simplicity

Method Chaining is typically used when breaking from traditional Command Query Seperation (CQS) principles. The most common example being the merging of both getters (Queries) and setters (Commands). I especially like this technique, as, aside from being very easy to implement, it allows for an API to be used in a more contextual manner from the developers perspective as oppossed to that specified by the API designer’s preconceptions of how the API will be used. For example:

As can be seen, the message method serves as both a getter and setter, allowing users of the API to determine how the method should be invoked based on context, as well as affording developers the convenience of needing only to remember a single method name. This technique is used quite heavily in many JavaScript libraries and has undoubtedly contributed to their success.

We could further expand on this concept by determining a method’s invocation context based on the arguments provided, or the types of specific arguments, thus, in turn, merging various similar methods based on a particular context.

An important design recommendation to consider is that if you are writing an API which violates CQS (which is quite fine IMHO), as always, API consistency is important, thus all getters and setters should be implemented in the same manner.

Fluency

As was mentioned, in most cases, Method Chaining is leveraged to facilitate APIs which are intended to be used fluently (e.g. an Internal DSL). Such implementations typically provide methods which, by themselves, may have little meaning; however, when combined, allow for writing expressions which are self-descibing and make logical sense to users of the API.

For example, consider the way one might describe a Calendrical Event:

Vacation, begins June 21st, ends July 5th, recurs Yearly.

We can easily implement a Fluent API such that the above grammar can be emulated in code as follows:

The same methods can also be chained in different combinations, yet yield the same value:

Given the above example, we could further improve on the fluency of the implementation by adding intermediate methods which can, by themselves, simply serve to aid in readability, or, provide an alternate modifier for chaining:

When implementing Fluent APIs, we can design such that different logical chaining combinations can yield the same result, thus affording users of the API the convenience of determining the most appropriate expressions based on context or personal preference, even grammatically so. Illogical chaining combinations can be handled by either throwing an exception, or they can simply be ignored based on the context of a preceding invocation – though, of course, one should aim to avoid designs which allow for illogical chaining.

The Ubiquitous Example – jQuery

While Method Chaining and Fluent APIs, as with most design patterns, are language agnostic, in the JavaScript world perhaps the most well known implementation is the jQuery API; for example:

In addition to jQuery, there are numerous additional JavaScript Method Chaining and Fluent APIs of note, Jasmine in particular has a very expressive API which aligns excellently with it’s design goals. The various libraries which implement the Promises/A spec also provide very clear and concise Fluent APIs.

Concluding Thoughts

Over the years I have leveraged Method Chaining to facilitate the design of Fluent APIs for various use-cases. The two patterns, when combined, can be especially useful when designing Internal DSLs; either third-party libraries, or APIs specific to a particular business domain.

Pseudo-abstraction in Backbone

Thursday, May 2nd, 2013

As has been mostly disseminated, JavaScript, being a dynamic, prototypal language, affords developers the ability to design outside the rigid confines inherent to statically typed languages. Interestingly, perhaps even somewhat paradoxically, this same flexibility also allows for programmatically simulating specific features commonly found in statically typed languages, if desired.

While JavaScript does not have a traditional type system, nor does it provide traditional constructs by which user defined types are specified, it is still, necessarily so, a common and desirable design goal to implement a system with the notion of classes in order to provide data types which encapsulate domain logic and facilitate reuse; both of which being key design attributes which help mitigate the complexity of large applications.

Nearly all JavaScript MV* frameworks provide such facilities, and do so in a consistent and convenient manner; most of which allowing for practical circumvention of the prototype system almost entirely. It is also worth noting that while most libraries themselves are generally implemented in the succinct and terse, large applications typically call for a more traditional object oriented design, while also being prudent to do so in alignment with the conventions and idioms particular to JavaScript itself.

Abstraction

At times it will be necessary to design a system with reusable abstractions. In fact, it is quite hard to imagine a modern SPA of even marginal complexity as being maintainable without some level of base class functionality.

For instance, it can be particularly useful to implement base Models and Collections which provide general functionality common amongst all Models and Collections; such as the parsing and appropriate routing of service API exceptions to error callbacks, and successful service results to success callbacks, and so forth.

Since such base classes generally do not provide any concrete behaviors themselves (hence the abstraction), they are of considerable value, specifically when reused amongst various large scale, distributed projects; and, from a design perspective, it is often important for one to ensure such classes are only used as intended.

While one can convey the intended usage of a base class easily enough simply by means of comments alone, indicating their usage as such (and that is quite fine if you prefer), it is also just as easy to ensure base classes are only used as intended programmatically by implementing a simple conditional which checks an instance’s constructor against the base class’ constructor function. For example (in the context of backbone, though any framework applies):

Then, one can simply extend the base class, invoking defaults as needed:

Concluding Thoughts

Like many in the JavaScript community, I, too, am of the opinion that JavaScript should not be made to reflect that which is common to other languages simply for the sake of familiarity; but rather, one should be prudent to leverage the flexibility inherent to the language itself, and this example serves as a demonstration of how such flexibility can be utilized to provide what a specific design calls for at the discretion of the developer.

Test First Workflow – A Short Story

Saturday, February 2nd, 2013

As a depiction of the typical approach taken when solving a problem with Test First practices in mind, below is a brief excerpt from a recent conversation with a collegue who inquired of me as to how one generally goes about solving a problem using Test First methodologies. My explanation was rather simple, and read somewhat like a short story, though I describe it as being more of a step by step process from a Pair Programming perspective.

The general workflow conveyed in my description, while brief, covers the essentials:

  1. We have a problem to solve.
  2. We discuss the problem, asking questions as needed; then dig a bit deeper to ensure we understand what it is we are really trying to solve; and, most importantly, why.
  3. We consider potential solutions, identifying those most relevant, evaluating each against the problem; then agree upon one which best meets our needs.
  4. We define a placeholder test/spec where our solution will be exercised. It does nothing yet.
  5. We implement the solution in the simplest manner possible, directly within the test itself; the code is quite ugly, and that is perfectly fine, for now. We run our test, it fails
  6. We adjust our implementation, continuing to focus solely on solving the problem; all the while making sure not to become too distracted with implementation details at this point.
  7. We run our test again, it passes. We’re happy, we’ve solved the problem.
  8. We move our solution out of the test/spec to the actual method which is to be implemented, which, until now, had yet to exist.
  9. We update our test assertions/expectations against the actual (SUT). We run our test, it passes.
  10. We’re happy, we have a working, tested solution; however, the implementation is substandard; this has been nagging at us all along, so we shift focus to our design; refactoring our code to a more elegant, performant solution; one which we can be proud of.
  11. We run our test again, it fails. That’s fine, perhaps even preferable, as it verifies our test is doing exactly what is expected of it; thus, we can continue to refactor in confidence.
  12. We adjust our code, continuing to make design decisions and implementation changes as needed. We run our test again, it passes.
  13. We refactor some more, continuing to focus freely, and without worry on the soundness of our design and our implementation. We run our test again, it passes.

Rinse and Repeat…

While the above steps are representative of a typical development work-flow based on Test First processes, it is worth noting that as one becomes more acclimated with such processes, certain steps often become unnecessary. For example, I generally omit Step #5 insofar as implementing the solution within the test/spec itself is concerned; but rather, once I understand the problem to be solved, I then determine an appropriate name for the method which is to be tested, and implement the solution within the SUT itself, as opposed to the test/spec; effectively eliminating the need for Step #8. As such, the steps can be reduced down to only those which experience proves most appropriate.

Concluding Thoughts

Having become such an integral part of my everyday workflow for many years now, I find it rather challenging to approach solving a problem without using Test First methodologies. In fact, attempting to solve a problem of even moderate complexity without approaching it from a testing perspective feels quite awkward.

The simple fact is, without following general Test First practices, we are just writing implementation code, and if we are just writing implementation code, then, in turn, we are likely not thinking through a problem in it’s entirety. Consequently, it follows then that we are also not thinking through our solutions in their entirety, and hence our designs. Because of this, solutions feel uncertain, and ultimately leave us feeling much less confident in the code we deliver.

Conversely, when following sound testing practices we afford our team and ourselves an unrivaled sense of confidence in terms of the specific problems we are solving, why we are solving them, and how we go about solving them; from that, we achieve a concerted understanding of the problem domain, as well as a much clearer, holistic understanding of our designs.

Simplifying Designs with Parameter Objects

Tuesday, January 22nd, 2013

Recently, while reading the HTML5 Doctor interview with Ian Hickson, when asked what some of his regrets have been over the years, the one he mentions, rather comically so as being his “favorite mistake”, also happened to be the one which stood out to me most; that is, his disappointment with pushState; specifically, the fact that of the three arguments accepted, the second argument is now ignored.

I can empathize with his (Hixie’s) frustration here; not simply because he is one of the most influential figures on the web – particularly for his successful work surrounding CSS, HTML5, and his responsibilities at the WHATWG in general – but rather, it is quite understandable how such a seemingly insignificant design shortcoming would bother such an obviously talented individual, especially considering the fact that pushState's parameters simply could not be changed due to the feature being used prior to completion. Indeed, the Web Platform poses some very unique and challenging constraints under which one must design.

While the ignored pushState argument is a rather trivial issue, I found it to be of particular interest as I often employ Parameter Objects to avoid similar design issues.

Parameter Objects

The term “Parameter Object” is one I use rather loosely to describe any object that simply serves as a wrapper from which all arguments are provided to a function. In the context of JavaScript, object literals serve quite well in this capacity, even for simpler cases where a function would otherwise require only a few arguments of the same type.

Parameter Objects are quite similar to that of an “Options Argument” – a pattern commonly implemented by many JavaScript libraries to simplify providing optional arguments to a function; however, I tend to use the term Parameter Objects more broadly to describe a single object parameter from which all arguments are provided to a function, optional arguments included. The two terms are often used interchangeably to describe the same pattern. However, I specifically use the term Options Argument to describe a single object which is reserved exclusively for providing optional arguments only, and is always defined as the last parameter of a function, proceeding all required arguments.

Benefits

Parameter Objects can prove beneficial in that they afford developers the ability to defer having to make any final design decisions with regard to what particular inputs are accepted by a function; thus, allowing an API to evolve gracefully over time.

For instance, using a Parameter Object, one can circumvent the general approach of implementing functions which define a fixed, specific order of parameters. As a result, should it be determined that any one particular parameter is no longer needed, API designers need not be concerned with requiring calling code to be refactored in order to allow for the removal of the parameter. Likewise, should any additional parameters need to be added, they can simply be defined as additional properties of the Parameter Object, irrespective of any particular ordering of previous parameters defined by the function.

As an example, consider a theoretical rotation function which defines five parameters:

Using a Parameter Object, we can refactor the above function to the following:

Should we wish to remove a parameter from the function, doing so simply requires making the appropriate changes at the API level without changing the actual signature of the function (assuming of course, there are no specific expectations already being made by calling code regarding the argument to be removed). Likewise, should additional parameters need to be added, such as a completion callback, etc., doing so, again, only requires making the appropriate API changes, and would not impact current calling code.

Additionally, taking these potential changes as an example, we can also see that with Parameter Objects, implementation specifics can be delegated to the API itself, rather than client code insofar that the provided arguments can be used to determine the actual behavior of the function. In this respect, Parameter Objects can also double as an Options Argument. For example, should the arguments required to perform a 3D rotation be omitted from the Parameter Object, the function can default to a 2D rotation based on the provided arguments, etc.

Convenience

Parameter Objects are rather convenient in terms of there being less mental overhead required than that of a function which requires ordered arguments; this is especially true for cases where a function defines numerous parameters, or successive parameters of the same type.

Since code is generally read much more frequently than it is written, it can be easier to understand what is being passed to a function when reading explicit property names of an object, in which each property name maps to a parameter name, and each property value maps to parameter argument. This can aid in readability where it would otherwise require reading the rather ambiguous arguments passed to a function. For example:

With Parameter Objects it becomes more apparent as to which arguments correspond to each specific parameter:

As mentioned, if a function accepts multiple arguments of the same type, the likelihood that users of the API may accidentally pass them in an incorrect order increases. This can result in errors that are likely to fail silently, possibly leading to the application (or a portion thereof) becoming in an unpredictable state. With Parameter Objects, such unintentional errors are less likely to occur.

Considerations

While Parameter Objects allow for implementing flexible parameter definitions, the arguments for which being provided by a single object, they are obviously not intended as a replacement for normal function parameters in that should a function need only require a few arguments, and the function’s parameters are unlikely to change, then using a Parameter Object in place of normal function parameters is not recommended. Also, perhaps one could make the argument that creating an additional object to store parameter/argument mappings where normal arguments would suffice adds additional or unnecessary overhead; however, considering how marginal the additional footprint would be, this point is rather moot as the benefits outweigh the cost.

A Look at pushState’s Parameters

Consider the parameters defined by pushState:

  1. data: Object
  2. title: String
  3. url: String

The second parameter, title, is the parameter of interest here as it is no longer used. Thus, calling push state requires passing either null or an empty String (recommended) as the second argument (i.e. title) before one can pass the third argument, url. For example:

Using a Parameter Object, pushState could have been, theoretically, implemented such that only a single argument was required:

  1. params: Object
    • data: Object
    • title: String
    • url: String

Thus, the ignored title argument could be safely removed from current calling code:

And simply ignored in previously implemented calls:

As can be seen, the difference between the two is quite simple: the specification for pushState accepts three arguments, whereas the theoretical Parameter Object implementation accepts a single object as an argument, which in turn provides the original arguments.

Concluding Thoughts

I certainly do not assume to understand the details surrounding pushState in enough detail to assert that the use of a Parameters Object would have addressed the issue. Thus, while this article may reference pushState as a basic example to illustrate how the use of a Parameter Object may have proved beneficial, it is really intended to highlight the value of using Parameter Objects from a general design perspective, by describing common use-cases in which they can prove useful. As such, Parameter Objects provide a valuable pattern worth considering when a function requires flexibility.

Managing Client-side Templates with RequireJS

Sunday, July 15th, 2012

When developing single page web applications, patterns of structure, organization and reuse become ever more important. This especially holds true when there is a need to maintain mulitiple web applications, each of which targeting a specific form factor, while also sharing many of the same underlying core APIs.

In the context of client-side templating, such patterns begin to emerge, quite naturally so, when leveraging RequireJS modules and the RequireJS text plugin.

Template Modules

One specific pattern I have found myself implementing is that of a single Templates Module which provides a centralized location from which all compiled templates within an application can be referenced. A rather simple pattern, Template Modules are only concerned with loading, compiling and providing a public API to access compiled templates; that is, a Templates Module simply requires all external templates, and provides named methods for retrieving the compiled template functions of each.

A basic implementation of a Templates module is as follows (while Handlebars may be used in this example, any template engine would suffice):

The main benefit of implementing a Templates Module is reuse, as different modules can use the same templates without a need for redundantly requiring and compiling the templates themselves. Additionally, Template Modules provide a convenient means of abstracting away the underlying template engine from client code, thus reducing the amount of refactoring needed should the template engine itself ever need to change.

When using the RequireJS Optimizer, each external template will be included in the optomized build and loaded synchronously, and so there is no additional overhead in terms of HTTP requests when requiring each template in a single location.

You can check out a basic example implementation of a Templates Module (in the context of Backbone) here.