Mobile in Minutes with Sinatra

Sinatra is described as a DSL for quickly creating web applications in Ruby with minimal effort. Sinatra makes it extremely easy to host a web application and expose RESTful services. Here we’ll show how this allows you to get mobile applications up and running in minutes with Sinatra.

Quick Introduction to Sinatra

The following ruby file is a valid RESTful service with Sinatra:

require 'sinatra'
require 'json/pure'

get '/hello/:name.json' do
  content_type :json
  {
    "message" => "Hello #{params[:name]}!"
  }.to_json
end

Here we are telling Sinatra to respond to any GET requests to the URI pattern /hello/.json. The inserted name is passed to the method as a parameter through the params hash. We set the returned content_type to JSON to ensure correct handling from the client and our hash is converted to a JSON response using json_pure.

To run this example, save the above code snippet to file named hello.rb. Then install and run your new application with Sinatra:

$ gem install json_pure
$ gem install sinatra
ruby -rubygems hello.rb

Now navigate to the URL http://localhost:4567/Jacob (feel free to use your own name) and you will be presented with:

{"message":"Hello Jacob!"}

Now we can easily consume that service with a jQuery script and host the script with Sinatra:

<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script>
      $.getJSON('/hello/Jacob.json', function(data) {
        alert(data.message);
      });
    </script>
  </head>
  <body>
  </body>
</html>

Here we use jQuery’s getJSON method to retrieve the JSON data from our service. The message from the JSON result is then alerted to the user.

To run the example, create a folder named public in the same directory where you created your hello.rb file. Inside that folder copy the above code snippet into a file named hello.html. Now navigate to the following page in your browser http://localhost:4567/hello.html. You will be alerted with the message “Hello Jacob!”

Creating a Mobile App with Sinatra

That was easy enough, but let’s see how we can apply this to a mobile setting. For this example, let’s create and consume a Sinatra service using jQuery Mobile.

Downloading and Running the Example

The example can be downloaded in its entirety here. To run the example, unzip the downloaded file to a known directory and execute the following commands:

$ cd /unzipped/folder/directory
$ gem install json_pure
$ gem install sinatra
$ ruby -rubygems cameras.rb

Now navigate to the following page in your browser http://localhost:4567/cameras.html. You will see the list of cameras for selection.

Exposing the RESTful Service

Let’s first create our RESTful service which will provide a top 10 list of popular DSLR cameras:

require 'sinatra'
require 'json/pure'

get '/cameras/top10.json' do
  content_type :json
  [
    {
      'id' => 1,
      'title' => 'Canon Rebel T3 DSLR',
      'description' => '...',
      'price' => '499.99
    },
    {
      'id' => 2,
      'title' => 'Canon Rebel EOS DSLR',
      'description' => '...',
      'price' => '349.99'
    }
    # ... ...
  ].to_json
end

In this case we are just constructing a hash that we then return back to the client in the same manner as our previous example. We could also retrieve the list of cameras from a database call, through an aggregation service, etc.

Setting up jQuery Mobile

Now we can consume the service with jQuery Mobile and host our mobile application with Sinatra. There will be two parts to our jQuery Mobile application, the HTML page which performs the setup for jQuery Mobile and a script which consumes our service. Let’s first take a look at the HTML page:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Top 10 Cameras</title>
  <link rel="stylesheet"
    href="//code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
  </script>
  <script src="cameras.js"></script>
  <script src="//code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js">
  </script>
</head>
<body id="page_body">
  <div id="cameraListPage" data-role="page">
    <div data-role="header">
      <h1>Camera List</h1>
    </div>
    <div data-role="content">
      <ul id="cameraList"></ul>
    </div>
  </div>
  <div id="cameraDetailPage" data-role="page">
    <div data-role="header">
      <h1>Camera Detail</h1>
    </div>
    <div id="cameraDetailContent" data-role="content">
    </div>
  </div>
</body>
</html>

The logic above is really just standard jQuery Mobile. We specify two pages, a #cameraListPage and a #cameraDetailPage. The #cameraListPage has an empty <ul> element which we intend to dynamically fill with cameras from our service. Similarly, the details page has no content which will be dynamically determined by selecting a camera from the list.

Rendering the Camera List

Now let’s have a look at the script that populates this logic. You can view the script in its entirety by downloading the example. The render method populates our <ul> by invoking our newly created camera service:

function render() {
  $.getJSON('/cameras/top10.json', function(data) {
    this.cameraData = data;
		
    var cameraListHtml = '';

    $.each(this.cameraData, function(i, camera) {
      cameraListHtml += '<li><a data-index="' + i + 
        '">' + camera.title + '</a></li>';
    });
		
    var $cameraList = $('#cameraList').append(cameraListHtml).listview();

    $cameraList.find('a').click(function() {
      displayCameraDetailPage(this, data);
    });
  });
}

Notice that the service data is retrieved in the same manner as our example above. The key difference is that we dynamically construct list items for each camera with a link that holds the index of the camera it refers to. The list items are then appended to the #cameraList which is rendered as a jQuery Mobile listview.

Showing the Camera Details

The final step is displaying the camera details. The displayCameraDetailPage method is bound to each camera link that was generated. The method is passed the <a> element and the camera data we retrieved from the service.

function displayCameraDetailPage(element, cameraData) {
  var camera = cameraData[$(element).data('index')];

  var detailsHtml = 
    '<div data-role="content"><h2>' + camera.title + '</h2>' + 
    '<p><strong>Price:</strong> ' + camera.price + '</p>' +
    '<p>' + camera.description + '</p>' +
    '</div></div>';
	
  $('#cameraDetailContent').html(detailsHtml);

  $.mobile.changePage('#cameraDetailPage');
}

Here we make use of the jQuery data method to retrieve the index of the camera that was selected. A markup representation of the details of the camera is generated and the #cameraDetailPage content is updated. Once the update is complete, the jQuery Mobile changePage method is used to show the #cameraDetailPage.

Sinatra makes it easy to develop web applications quickly. Try it and your sure to get your next mobile application up and running in minutes.

Upgrading a Seam 2 app to JBoss 7

I recently went through the process of upgrading a Seam 2.X application to JBoss 7.1.1. While Marek Novotny’s tutorial will lead you down the right path, there was one issue that led me down a rabbit hole.

Initially, the intention was to use Hibernate 3 as a JBoss module allowing it to be shared among applications. This deviates from the tutorial, but simplifies the library requirements if you are deploying several Seam 2 applications to the same server. Unfortunately, this issue cropped up:

14:54:13,042 WARN  [org.jboss.modules] 
  (MSC service thread 1-4) Failed to define class 
  org.jboss.as.jpa.hibernate3.infinispan.InfinispanRegionFactory 
  in Module "deployment.jboss-seam-booking.ear:main" from Service Module 
  Loader: java.lang.LinkageError: Failed to link org/jboss/as/jpa/hibernate3/
  infinispan/InfinispanRegionFactory (Module "deployment.jboss-seam-
  booking.ear:main" from Service Module Loader)
...
Caused by: java.lang.NoClassDefFoundError: 
  org/hibernate/cache/infinispan/InfinispanRegionFactory
...
Caused by: java.lang.ClassNotFoundException: 
  org.hibernate.cache.infinispan.InfinispanRegionFactory from 
  [Module "deployment.jboss-seam-booking.ear:main" from Service Module Loader]

Apparently this problem will be resolved in JBoss 7.1.2, but in order to get something working now an alternative approach was necessary.

The next step was to attempt to bundle the Hibernate 3 jars within the application as discussed in the tutorial. This worked fine except that JBoss still attempted to manage Hibernate 3 as a JPA provider. This produced the same exception shown above.

After researching the issue, the following setting was discovered. This setting is specified for each persistence unit in persistence.xml:

<properties>
   <property name="jboss.as.jpa.managed" value="false"/>
</properties>

Success! This setting stops the JBoss container from managing Hibernate 3 as a JPA provider. Once this setting was changed, the application deployed successfully.

By |JBoss Seam|Comments Off on Upgrading a Seam 2 app to JBoss 7

Re-imagining the App Store in the Cloud

The app formerly known as PhoneGap (now Apache Cordova) started out with a very telling name. PhoneGap/Cordova bridges the gap between a native application’s and a browser’s access to device APIs, thereby allowing you to develop apps in pure HTML5, CSS3, and JavaScript. In addition, you can wrap up and deploy your web-standards-based application to an app store.

But a native OS could provide the same API through the browser. The major drawback to this approach is the loss of revenue generated by the app store through app purchases and in-app purchases. This gives little incentive for OS manufacturers to implement these APIs through the browser. But let’s re-imagine the app store in the cloud for a moment and see how browser support for native APIs could enable this.

Mobile Devices as a Portal

A recent article on Technorati described Google’s new hardware offering which essentially provides a “portal into Google-land.” Chrome essentially becomes the OS for the device and Google Drive becomes the hard-drive. Expanding this idea into the mobile realm is not difficult to imagine, but what value does this provide other than giving us a common place to store documents and photos?

Right now the focus of the cloud in terms of consumers has seemed to revolve around storage. How can I get all of my “stuff” in one place where I can access it from anywhere? Think DropBox, Google Drive, etc. This is an interesting problem, but only the beginning. The next step is taking our Apps and making them accessible from anywhere. After buying a new App for my phone, it would be great if I had immediate access to this same App from my other devices, my tablet, my laptop, etc. and vice versa without the need to download anything on those devices.

App Store in the Cloud

Chrome recently released the ability to login, making your tabs and bookmarks accessible across all devices that are running Chrome. This is a novel concept and could be further applied to the App Store. The starting point in your browser could be a layout of all of the Apps that you have purchased and would look very similar to the native OS representation of your App icons. In addition, one of those Apps could guide you to the App Store which allows you to purchase these Apps. Each App then runs directly in your browser and stores all its data on an external server.

This may appear to have little value initially, but now I could login to my tablet and immediately have access to the same App that I just purchased through its browser. All of my data would be accessible and there is no requirement to find and download anything further. By implementing Apps using web standards (HTML5, CSS3, and JavaScript), the adjustment between devices could all be handled through styling differences. This allows the OS manufacturers to continue to reap revenue from App store purchases, while giving the consumer the advantage of ubiquitous access to their Apps. You could even imagine a pricing model that differs based on which devices you want to enable access from.

The Future is Here… Almost

Firefox OS takes exactly this approach. From the introduction:

The idea is essentially to have all user-accessible software running on the phone be a Web app that uses advanced HTML5 techniques and device APIs to access the phone’s hardware directly via JavaScript. For Web developers, the most important part to understand is that the entire user interface is a Web app, one that is capable of displaying and launching other Web apps. Any modifications you make to the user interface and any applications you create to run on Firefox OS are Web pages, albeit with enhanced access to the mobile device’s hardware and services.

To publish a web application as a Firefox OS App, you simply have to add an app manifest, “a JSON file that describes your app, including its name, its icons, and a human-readable description.” The Marketplace then uses the information provided by the manifest to publish your web application to Firefox OS users.

Firefox OS will likely spurn competition between the OS manufacturers and it appears that Google is already making inroads into the approach with their recent releases. At the moment, the following issues remain although several will likely be solved in the next few years:

  • Native APIs – the Android and iOS browsers just don’t have access to them… yet. Apache Cordova has been a well-recognized stop-gap approach, but as browsers continue to adapt, will no longer be necessary in the future.
  • Performance – Facebook CEO Mark Zuckerberg recently discussed the issues with browser performance on mobile devices after choosing HTML5 as their strategic approach. This will only improve as time goes on and devices become more capable.
  • Connectivity – ubiquitous connectivity just doesn’t exist yet. In the basement of the parking garage, on a remote island… still having access to certain applications is beneficial in these scenarios.
  • Games – as with desktop computing, games require an extensive amount of native API access and have performance requirements that put general Apps to shame. Unless there are breakthroughs in SVG support that make gaming a snap in the browser, games will likely remain native.

Being a believer in web standards and seeing the exciting possibilities of HTML5, Firefox OS truly presents a breath of fresh air. Let’s hope that the other OS manufacturers take notice.

Stimulating Creativity for an Agile Team

I’ve always noticed that my creativity level drops when my routine becomes predictable. Suddenly my mind moves into cruise control. I find it difficult to come up with creative ideas and innovative approaches. I write fewer blog postings, my software solutions are more brute force, and I’m less likely to come up with fun new games to entertain my kids.

There is some science behind this as discussed in the Fast Company article, 7 Ways to Stimulate Your Capacity for Creativity. Essentially the article discusses how context violations spur creativity.

The idea is that our minds need exposure to a variety of contexts to keep us innovative:

Your most creative insights are almost always the result of taking an idea that works in one domain and applying it to another. Every “new” idea you have, personally, is based on some combination of previous concepts in your own mind, even if you combined these concepts subconsciously.

Studies in neurology have also shown that forcing our mind to think through new scenarios and differing contexts creates new neural pathways.

While the article focuses on stimulating creativity for an individual, a similar list of ideas can be applied to Agile teams. Try these ideas to boost creativity within your team:

  • Change the team environment. Have meetings in unusual locations and try switching seating arrangements regularly. How’s the weather? Have a meeting outside if the corporate campus is suitable.
  • Brainstorm different ways to use a common tool (grep, ls, ftp, whatever your team uses regularly). This may not only stimulate creativity, but can lead to new useful ways that the team uses tools you’re already familiar with.
  • Spend 30 minutes a day for two or three weeks learning a new programming language. Make it a story to be addressed during a sprint and set aside time. You may even decide the language is useful for product development.
  • Have the team talk with one new product user every week. This forces developers to socialize and it has the advantage of creating opportunities for learning. Each product user likely has a different take on the system and what they find useful.
  • Play Agile games. Ever been to TastyCupcakes.org? Other than the creepy clown picture on the front page (think It, Stephen King), this is a great site for finding games that allow a team to learn more about Agile while spurring innovation.
  • Take on a story for innovation time. It works for Google, could it work for your team? Try bringing in a story during your next sprint focusing time on innovation (this should be only a few story points). Make sure you set acceptance criteria so the team can demonstrate their effort.
  • Try a daily 10 minute break for exercise. One of my clients is a wellness company and they take 10 minutes a day to leave the cubicle farm to get some brief exercise. Walk the stairs, jog in place, do some situps, change it up daily. Not only will it change the daily routine, it promotes good health!

Do you have ideas of your own? Leave them in the comments.

By |Agile|Comments Off on Stimulating Creativity for an Agile Team

You can’t afford to ignore DevOps

DevOps is a huge movement in IT at the moment. It applies lean practices across an IT organization. While Agile has promoted lean practices in the development of software for years, DevOps is a more recent movement. The movement recognized the interdependence of the delivery of software with the infrastructure that the software relies on.

Enabling Agility with DevOps

Lean practices recognize that software is only providing business value once it is released. Any time that feature is awaiting a deployment is wasted money. If we can release features as soon as they are complete, we can achieve the maximum business value from each feature that we implement.

In an Agile environment our measure of success is the release of working software and DevOps is a cornerstone to that achievement. An Agile team can achieve amazing velocity while developing the software itself, but without infrastructure and deployment, releasing is impossible. By automating QA tasks, deployment tasks, and configuration of infrastructure, we increase the speed the delivery of software.

While there are a number of organizations that have shown amazing success with DevOps (Flickr, Etsy, Amazon, Facebook, DropBox just to name a few), this approach doesn’t only apply to startups. Large organizations must begin to take on these tactics in order to stay competitive. I’ve seen vast improvements in productivity for organizations that take even the smallest steps toward a DevOps approach.

Getting started with DevOps

A great book that provides a good primer to DevOps through lean practices is Lean Startup. I also highly recommend the DevOps Zone at DZone. There are great articles there to keep up to date with the world of DevOps.

If you are just ready to get started and are looking for tools to fully automate your infrastructure, take a look at Puppet and Chef. These are the industry leading tools for infrastructure automation and both provide a great alternative.

If you haven’t started looking at DevOps in your organization, I highly recommend you do. Not only will it keep you competitive, but it may be the key factor to differentiating your organization from the rest of the market.

Cleanup your jQuery by Deferring

The asynchronous nature of AJAX sometimes makes jQuery code a bit hard to follow. Embedding callbacks in AJAX calls starts off reasonable, but enough callbacks can quickly become unwieldy. If your code base is suffering from this issue, have a look at the jQuery Deferred API. jQuery Deferred is an implementation of the CommonJS Promises Spec.

The CommonJS Promises Spec attempts to put an API around the consistent pattern of handling asynchronous callbacks. In the case of jQuery Deferred we are generally talking about AJAX calls. Let’s look at an example that will help to clarify the scenario.

Traditional Approach

Let’s say you have two services you are invoking to show information on a map. One service provides the latitudinal and longitudinal coordinates (geolocation) of an address, while another service provides nearby businesses.

function findGeolocation(address){
    $.ajax({
      url: "http://solutionsfit.com/geolocate",
      data: {json: JSON.stringify({"address" : address})},
      type: "POST",
      success: function(geolocation) { 
        findNearbyBusinesses(address, geolocation);
      }
  });
}

function findNearbyBusinesses(address, geolocation){
    $.ajax({
      url: "http://solutionsfit.com/nearbyBusinesses",
      data: {json: JSON.stringify({"address" : address})},
      type: "POST",
      success: function(businesses) { 
        showLocationMap(geolocation, businesses);
      }
}

It’s difficult to follow the control structure of the above code due to the embedded callbacks. The $.when method from the jQuery Deferred API helps clean this up.

Using jQuery Deferred

Instead of embedding our control flow in the callback functions themselves, we can specify the flow through an API. The $.when method accepts a list of functions that return a Deferred object. The $.ajax API returns a Deferred object allowing us to directly pass the result of AJAX invocations to the $.when method.

Once an AJAX request completes, the Deferred object is considered “done”. The $.when method waits for all Deferred objects to reach the “done” state and then invokes any handler functions that have been specified for the following:

  • done – handlers always called once all Deferred objects complete
  • then – handlers called if all Deferred objects complete successfully
  • fail – handlers called if a failure occurs with one of the Deferred objects

Now let’s rewrite our above code snippet to use the $.when API.

function findGeolocation(address){
    return $.post(
        "http://solutionsfit.com/geolocate",
        {json: JSON.stringify({"address" : address})}
    );
}

function findNearbyBusinesses(address){
    return $.post(
        "http://solutionsfit.com/nearbyBusinesses",
        {json: JSON.stringify({"address" : address})}
    );
}

$.when(findGeolocation(address), findNearbyBusinesses(address))
    .then(function(geolocation, businesses) {
        showLocationMap(geolocation, businesses);
    });

Notice that the readability now clearly defines the control flow. This now reads as:

when we find the geolocation and any nearby businesses, then show the location and businesses on a map

In addition, in the second case we’ve improved performance by allowing our AJAX calls to execute simultaneously. In the first case, the retrieval of nearby businesses was forced to wait on the geolocation call due to the embedded callback.

There is much more to the API and you can review all the details here.

By |jQuery|Comments Off on Cleanup your jQuery by Deferring

Software Consulting, there are Apps for that!

Since starting a consulting firm, I’m always looking for ways to automate the day to day tasks I find less than appealing. A colleague of mine was interested in the mobile applications that are part of my business application suite. So I’ve compiled a list of the iPhone applications, beyond the basics of course, that I use on a day-to-day basis.

Scanner Pro

Scanner Pro has been my favorite addition to my business application suite. You simply take a photo of a document, receipt, or whatever you choose and the application creates a “scan” representation. “Scans” can be saved as a PDF to your favorite online storage source (e.g. Evernote, Dropbox, Google Docs). Multiple “scans” can be combined into a single PDF which is particularly useful for business expense receipts.

Keeping up with receipts for business expenses (e.g. lunches, coffee, a new monitor) was something I never did well. They would remain in my wallet for weeks and if I didn’t lose them, were barely legible by the time they made it to my files. Now I simply take a picture and toss the receipt. This is also a lifesaver for sending documents when you don’t have a scanner immediately handy (e.g. you sign a contract over coffee and the client wants a copy).

Price: $6.99

Benefits:

  • Scan documents from anywhere
  • Stop carrying around expense receipts
  • If you like it enough, throw away your scanner!

Timesheeter

Timesheeter has been the best time tracking application I have found for my phone. Due to the consistency of my schedule, the ability to set defaults for my time entry generally makes tracking my time as simple as selecting “New Entry”, “Save”. While it doesn’t integrate with my invoicing software, it does provide at a glance views that make it easy to determine time worked for invoicing clients.

My favorite feature of Timesheeter is that it generates a customizable PDF report that can be exported to e-mail, Dropbox, or iTunes. This makes it simple to provide timesheets to clients or simply store a backup of your time tracking.

Price: $2.99

Benefits:

  • Very convenient for tracking time
  • Preferences make it quick for adding entries
  • Easily send timesheets to clients
  • Customizable timesheet reports

QuickBooks Mobile

I use QuickBooks online for invoicing. There are quite a few options available, but QuickBooks has served my needs for 6 years now and I find it hard to justify a change. The QuickBooks iPhone application is somewhat lacking in terms of features, but it provides the ability to create and send invoices which is really what I’m looking for from a mobile perspective.

Once you’ve customized your invoices through the general QuickBooks online browser application, creating invoices through the iPhone application is simple. Once created, they can be immediately e-mailed from your device to the client. This makes it simple to send invoices even if you don’t have immediate access to a wifi hotspot (e.g. standing in line at the DMV).

Price: FREE (but, you must subscribe to QuickBooks online)

Benefits:

  • Send invoices from anywhere
  • Convenient for quickly reviewing outstanding invoices

CardMunch

CardMunch was recommended to me by a colleague and I find it extremely useful. As a LinkedIn application, it connects to your LinkedIn account (if you don’t have a LinkedIn account by now, I suggest you get one).

When someone hands you a business card, rather than simply sticking it in your pocket and letting it run through washing machine, never to be seen again, snap a photo of it with CardMunch. The photo is sent off to LinkedIn employees who, within a brief period of time, transcribe the contact into a LinkedIn profile that you can then choose to connect with. CardMunch helps to ensure you don’t lose that valuable connection.

Price: FREE (but, you must have a LinkedIn account)

Benefits:

  • Avoid losing contacts
  • Finds connections for you
  • Save paper by leeting people keep their cards!

If you are a software consultant, and have any applications that you find useful, please feel free to leave them in the comments.

Power up your HTML5 with D3

The power of HTML5 is remarkable. I’ve seen impressive demos in presentations and great looking example pages that people have developed in their spare time, but it always looks highly complex. In addition, the examples are usually just that, examples, with little to no real world application. Here we’ll look at an example that shows how D3 enables HTML5 to provide real business value.

D3 helps to hide some of that complexity, allows you to operate directly on data sets, and provides the capabilities necessary to quickly apply the power of HTML5 in real-world scenarios. This javascript library uses HTML5 standards to generate some of the flashiest (sans Flash) visualizations I’ve seen from a library. While it has a feel similar to jQuery, the use of SVG makes the animations much more advanced.

Let’s look at an example that creates a simple bar graph. You can review the example by itself here. Or, simply click “GO” below the to see the bar graph in action.

This animation uses no images or flash, just HTML5 standards with the help of D3. When you view the source, you’ll notice that an <svg> element is defined, sized to the expected width and height of our bar graph.

<svg id="bargraph" width="800" height="400"></svg>

The bar graph is generated from the following logic:

bargraph().data([10, 18, 12, 24, 15, 13, 22, 17, 8]).plot();

Defining the bargraph object

The first step is to define our object:

function bargraph() {
  var colors = ["#2d578b", "steelblue", "#777"],
    data = [10, 15, 20],
    xCoordinateSpacing = 50,
    yCoordinateSpacing = 70;
	
  function bargraph() {
		
  }
	
  bargraph.data = function(d) {
    data = d;		
    return bargraph;
  }

  // … …
}

The bargraph object defines a set of attributes. The colors attribute defines the various colors the bars will be. The data attribute is an array of numbers that will be plotted on the bar graph. We can change the default list of data points by invoking the data() method. The xCoordinateSpacing and yCoordinateSpacing attributes are simply common attributes for plotting shapes consistently.

Now let’s look at the render() method.

bargraph.plot = function() {
  svg = d3.select("#bargraph").append("g");
		
  renderDataPointsAsStrings(svg);
  renderGoButton(svg);
}

The first step is to define a group within the <svg> element to contain our SVG shapes. Once the group is defined, we pass it to the methods that render our data points and the “GO” button.

Rendering the data points

Now let’s render the data points.

function renderDataPointsAsStrings(svg) {
  var text = svg.selectAll("text").data(data, String);

  text.enter().append("text")
    .text(String)
    .attr("x", function(d, i) {
      return i * xCoordinateSpacing + 20;
    })
    .attr("y", yCoordinateSpacing);
}

This method appends the data points as elements. If you are unfamiliar with the syntax of D3, here is a quick rundown:

  • svg.selectAll(selector) – follows similar selector syntax to jQuery and returns a list of results matching your selector
  • data – defines the data points you want to operate on across the selected elements
  • elements.enter() – for each data point the enter logic will be invoked

This is a common pattern in D3 that you will see consistently. Notice that for every data point we append a text element. The attributes of the text element can be calculated by a function or simply provided directly. Here we show both options.

The actual text we are going to show in each text element is the data element itself. By passing the javascript String function to the text method we are indicating this.

We make use of the xCoordinateSpacing and yCoordinateSpacing attributes to determine the starting points of each data element. The “x” attribute is simply a calculation that evenly spaces the text elements. The functions can receive both a d and i parameter providing both the data point itself and the index of the data point respectively.

Showing the bar graph

The “GO” button itself is rendered by the renderGoButton method, but once rendered, an onclick event is attached that shows the bar graph:

svg.selectAll(".gobutton").on("click", function() {
  showBarGraph(svg);
  // … …
});

Here we select on a CSS class selector and attach a function to fire onclick. The showBarGraph() method performs the magic necessary to render the bar graph:

  function showBarGraph(svg) {
    var rect = svg.selectAll("rect").data(data, String);

    rect.enter().append("rect")
      .attr("class", "bargraph")
      .attr("x", function(d, i) {
        return i * xCoordinateSpacing;
      })
      .attr("y", yCoordinateSpacing + 10)
      .attr("width", xCoordinateSpacing - 10)
      .attr("height", 0)
      .attr("fill", function(d, i) {
        return colors[i % colors.length];
      });
		
    svg.selectAll(".bargraph").transition().duration(1000)
      .attr("height", function(d) {
        return d * 5;
      });
  }	

Here we again follow the pattern we described previously. For each data point we append a rectangle shape below the text we rendered previously. By using the xCoordinateSpacing and yCoordinateSpacing attributes to calculate the “x”, “y”, and “width” attributes, we are provided consistency in the location of are rectangles in comparison to the text.

Notice the use of the “fill” attribute. Here we utilize the index of each data point to vary the color of each rectangle based on our colors array. Finally, we apply a transition to the bars that causes them to expand to a height representative of each data point over the course of 1 second. We are using the most basic transition, but through the use of the ease() method, you can vary the style of transition.

That’s it! There’s more to the example as you review the source code, so if you have any questions please feel free to post them in the comments. Also, for more complex examples and some great tutorials, visit the D3 website.

Getting out of Technical Debt

Do you have a technical debt problem? Just like having too much personal debt can lead to financial ruin, technical debt can ruin a project. In my last post, I discussed the criteria I would like to see out of a solution to tracking technical debt. Now we’ll have a look at some common solutions to the problem with their drawbacks as well as the recommended solution.

Tracking technical debt in TODOs

This type of tracking involves placing a TODO in a comment above the offending code:

// TODO this is a major hack only for the short-term, need to fix this
public void hackyMethod() {
  // ... ...
}

This is a somewhat effective solution, as it consolidates the tracking in the code base, keeps the tracking close to the code, and points out broken windows. But, it creates issues with visibility. When planning time comes for a new iteration, the developers begin the discussion as new features come up. “Feature XYZ huh? I remember looking at the code there, and there’s no way with the complexity there we are going to handle that. We’ll have to refactor quite a bit first, then we can start on that feature.”

Unfortunately from the perspective of the business owner, it’s like going in for routine maintenance and finding out the last person who fixed your car just duct taped the leak in your air conditioner. You’re not going to be happy. If you know up front that there is still an issue that needs to be addressed, you feel much less inclined to throw a tantrum.

In addition, TODOs don’t provide any metrics about the problem. How do I know the complexity of the issue? Is it really that important to address?

Tracking technical debt on a board

This involves dedicating a board with stickies or cards attached that represent technical debt. You will often see axis on the board representing complexity versus value. This solution is generally more effective than TODOs as it provides visibility to the issues as well as metrics. It also allows developers to explain why there is benefit to solving the issue.

The main problem with this solution is its separation from the code. This approach, by itself, doesn’t point out broken windows in the code and it doesn’t identify the exact location of the issues in the code base. You can combine this approach with TODOs, but we then have a consolidation problem and the two tend to get out of sync.

So what’s the alternative?

The Task Scanner Plugin for Jenkins provides the best traits of both of these solutions. This plugin allows you to scan for open tasks in the code base and generate a report that is visible to the entire team after each build.

For example, we could define the following task tags for use in the code base:

  • TECHDEBT_1 – high priority technical debt
  • TECHDEBT_2 – normal priority technical debt
  • TECHDEBT_3 – low priority technical debt

The priorities should first be assigned by the development team and can be revised after discussion with the product owner. These task tags are then defined in the code similar to TODOs. The description should place an emphasis on describing the problem and the reason it should be addressed:

// TECHDEBT_2 this method contains a temporary hack to support HR 
// requirements going into effect on 7/15/2012.  This will affect our 
// ability to make changes to the employee retrieval service in the 
// future.  Story points:  2
public void retrieveEmployee(Long employeeId) {
  // ... ...
}

The Task Scanner Plugin scans the code base for these tags on every build. It then generates a nice report as well as statistics regarding the task tags you have configured. The statistics gathered include:

  • the number of technical debt instances
  • the priority of each technical debt instance
  • the description of the technical debt
  • highlighted code related to the technical debt
  • graphs describing the trends of technical debt
  • and more…

This makes the technical debt visible to the entire team after each build. The build can even be set to become unstable or fail depending on the number of task tags found.

This approach addresses the criteria for dealing with technical debt, but requires discipline among the development team. It relies on appropriate tagging of technical debt as well as quality descriptions of the problem. So let’s evaluate this solution in terms of the criteria we have defined:

  • Consolidate the Debt – technical debt tracking is consolidated in the code base
  • Eliminate Broken Windows – by notating the technical debt clearly in the code base, it’s obvious where the broken windows are
  • Make it obvious to everyone – the report generated by the build is available to the entire team and nothing is more noticeable than a build failure
  • Tell me why there is benefit – the report also contains the comment provided by the developer which provides the reasoning
  • Keep it close to the code – as with TODOs, we have the information about the technical debt directly in the code base
  • Track metrics about the problem – the priority system of the task tags gives a priority for backlog handling. In addition, charts are generated over time showing how much technical debt exists versus what has been addressed

If you have any additional suggestions for the solution or additional solutions you’ve tried that meet the criteria, please leave them in the comments.

Consolidate your Technical Debt!

Do you have a technical debt problem? Just like having too much personal debt can lead to financial ruin, technical debt can ruin a project. Ward Cunningham created the metaphor of technical debt to put a concept around coding cruft that need to be addressed.

The problem I come across in most projects is that the technical debt is scattered. It may be in the heads of the developers, in TODOs through the code base, on a backlog, in JIRA, on a special board devoted to technical debt. The problem becomes that it’s scattered and disorganized. Worse, it’s often invisible or indecipherable to the business owner making the decisions.

This leads to the technical debt piling up over time and rarely being addressed. So what would my perfect solution involve?

Consolidate the debt

First off, track all technical debt in a single location. Tracking it in multiple places only leads to confusion and makes it more difficult to address the problem. In addition, it’s hard to see the relationships between technical debt when the problems are noted in multiple places. Just like an Agile project has a backlog where all work to be done is tracked, technical debt should be tracked in the same way.

Eliminate Broken Windows

Broken window theory was first related to software development in the Pragmatic Programmer. Essentially, we don’t want people thinking sloppy code is the norm, it triggers bad behavior. Just like no one would consider littering in a beautiful, pristine park, developers avoid adding undesirable code to a clean code base. Notating technical debt should look appealing and should call out code that is undesirable to show that it is an exception, rather than the rule.

Make it obvious to everyone

Technical debt should be obvious to the developers, to the agile coach, to the business owner(s), essentially all those involved in the project. Without this, it is difficult to know what needs to be done and get it prioritized appropriately. If you are strictly following a prioritized backlog, not making technical debt obvious means it may never get resolved.

Tell me why there is benefit

When looking at technical debt, everyone should understand why there is benefit to addressing it. This could mean that we give a description of why it is beneficial, or we call out the reasons why not addressing it would be harmful to the project. The key is having everyone understand the reason the problem should be dealt with.

Keep it close to the code

This makes it easier to pinpoint exactly what code is causing the issue. Without this, there may be confusion as developers move on and off of a project as to where the issue was and how it can be addressed. Simply saying, “Address performance issues in the retrieve employee query” may lead me on a chase through the code to determine which employee query we are referring to. This also helps alleviate the broken windows issue discussed previously.

Track metrics about the problem

Metrics are critical to understanding a problem. How can we determine ROI if we don’t understand how difficult the problem is? At the very least we should provide some metrics describing the complexity of the problem and the value of solving it. These numbers may change over time, but at least they give us some quantifiable information about the problem.

So this is what I would like to see out of a solution to the technical debt problem. If you have any additional ideas, please leave them in the comments section. In the next post, I will give the advantages and disadvantages of the approaches I’ve seen to addressing the problem. In addition, I’ll provide an alternative solution that addresses all of these concerns, so stay tuned.