JavaScriptMVC's development process

Learn how JavaScriptMVC guides you to building maintainable applications.

posted in open-source, in javascriptmvc, in Development on August 13, 2013 by Justin Meyer

JavaScriptMVC is the result of 6 years of intense JavaScript development by Bitovi. We’ve worked with huge teams and mixed skill levels on a wide variety of applications. Technology choices are important, but we’ve discovered that getting everyone on the same page, and doing the right thing matters much much more.

Because JavaScriptMVC is a full framework, it’s able to encourage a development process that results in:

  • tested
  • documented
  • modular

and ultimately maintainable code. This is likely JMVC’s best feature! You don’t build a large application with JavaScriptMVC; instead, you build lots of little applications that get glued together.

We created two videos showing this process with Rebecca Murphey’s Srchr application. The first video shows how and why we broke the application up into individual modules.

The second video shows how we built the modules.

Every component of Srchr is it’s own little application. It has:

  • a demo page,
  • documentation,
  • tests, and
  • its source code

all in its own folder. For example, Srchr’s tabs widget’s folder has:

  • tabs.html - demo page
  • tabs.js - source code
  • tabs.less - LESS / styles
  • tabs_test.js - tests
  • test.html - test page

You can develop the tabs widget, or any other module of Srchr independent of all the other parts!

This type of modular, maintainable architecture is a result of JavaScriptMVC and Bitovi’s development process:

Step 0: Architect

An architect breaks up an application and provides a rough API for each module or widget. This part is explained in the first video.

Step 1: Demo

With the rough API, another developer creates a demo page that shows how the module will be used. Here’s the tab widget’s demo page and demo page’s source. Demoing a tabs widget looks like:

steal('ui/tabs', function(Tabs){

  var enabled = can.compute(['flickr','yahoo'])

  new Tabs('#resultsTab',{
    enabled: enabled
  });

  $("#enable").click(function(){
    enabled(['flickr','upcoming'])
  })
})

At first this page is not functional. We build it to make sure the module’s functionality is understood and it’s API is easy to use.

Step 2: Document

After the architect verifies the demo page matches expectations, the developer writes high-level documentation for the module. We typically add documentation inline or in a markdown file in the module’s folder. Here’s the tab widget’s generated documentation page and inline documentation. Similar to a demo page, documentation has the triple benefit of making sure:

  • the functionality needed to be built is well understood
  • the module’s api is easy to explain
  • the module is easier to reuse and understand later

Tabs documentation starts like:

/**
 * @constructor ui/tabs
 * @parent srchr
 * @inherits can.Control
 * @test ui/tabs/test.html
 * @alias Tabs
 * 
 * A Tabs widget for showing and hiding content. 
 * ...
 */

Step 3: Test

We are huge fans of test driven development. This is why every module in a JMVC project should have its own tests and its own independent test page.

After the architect verifies the documentation looks good, the developer writes tests. At this point, we usually only test the external API. Here’s the tabs widget’s test page and test source code.

One of Tab’s tests looks like:

test('setting enabled to a type enables a tab', function(){

  var enabled  = can.compute([]);
  new Tabs("#resultsTab",{
    enabled: enabled
  });
  enabled(['flickr'])

  ok( ! this.flickrLI.hasClass('disabled'),
      "first button disabled" );
      
  ok( this.upcomingLI.hasClass('disabled'),
      "second button disabled" )
	
})

Note: We create demo pages and documentation before writing tests. Demo pages and documentation polish the API and provide a better idea of the API being tested.

Step 4: Code

It’s time to write the module. Fortunately, CanJS makes it easy to build complex, but high performance applications. Here’s the tabs widget’s source code, implemented as a can.Control. This looks like:

steal('can','./tabs.less', function(can) {

  return can.Control.extend({
  
    // hide tabs and call update
    init: function(){ ... },
    
    // if enabled changes, call update
    "{enabled} change": "update",
    
     // show the first enabled tab
    update: function(){ ... },
    
    // given an li, return its tab button
    tab: function( li ) { ... },
    
    // activate a tab button and show its content
    activate: function( el ) { ... }
    
    // on click, if enabled, activate the tab button
    "li click": function( el, ev ) { ... }
  })
  
});

Step 5: Verify

After the code is complete, we check to make sure all tests pass. At this point, the module is tested, documented, and maintainable.

Step 6: Repeat

After completing one module, we repeat the same steps with other modules. For example, Srchr has a list module with its own tests, documentation, and demo.

Step 7: Assemble

Once several low-level modules are complete, we assemble them into higher order modules. For example, the srchr/results module combines the tabs and list widget. But notice that srchr/results is built the same way. It has its own:

This combining of modules into higher order modules continues upward. srchr/srchr.js, which is the starting point of the application, combines srchr/results with two other modules to create the final application. Like everything before it, the application has its own:

  • page (not a demo page in this case)
  • documentation - how to build / test / deploy
  • test page - runs all other modules tests, and then functional tests the actual application.

Conclusion

If you’re not writing tests and documentation, do it! It’s difficult to over emphasize its importance in larger development efforts. But if you are using JavaScriptMVC, its integrated generators, dependency management, documentation engine, and testing tools make it a whole lot easier.

comments powered by Disqus
Contact Us
(312) 620-0386 | contact@bitovi.com
 or cancel