I was writing some D3 for work the other day (if you haven’t played around with D3, I thoroughly recommend it - it’s remarkably easy to get a beautiful visualization up and running), and found myself accidentally conducting some Deep Thinking about programming styles. D3 has a very distinct style remininiscent of jQuery, which stems from its heavy use of selections and joins. After some time spent furiously programming, I stepped back, only to realize I had (accidentally!) completely disregarded D3’s canoncial style and unconsciously used what was to me a much more familiar object oriented pattern.

I had events coming in as dictionaries, and had written some quick and sloppy code to plot them on a timeline in order to visualize when the event occurred, when local news picked it up, and when a global news network covered it. After some D3 boilerplate that doesn’t matter, was (a longer version of) this function:

function occurrence(someEvent) {

  this.time = someEvent.time;
  this.title = someEvent.title;
  this.type = someEvent.type;

  this.vis = wrap.append("g")
                 .attr("x",x(this.time));

  this.smallDot = this.vis.append("circle")
                      .attr("cx",0)
                      .attr("cy",0)
                      .classed(this.type,true)
                      .attr("r",5);

  this.bigDot = this.vis.append("circle")
                      .attr("cx",0)
                      .attr("cy",eventHeight[this.type])
                      .classed(this.type,true)
                      .attr("r",15);

  this.times = this.vis.append("text")
                      .text(this.time.format('HH:mm'))
                      .attr("x",0)
                      .attr("y",-38)
                      .style({"fill":"#DBDBDB","stroke":"#DBDBDB"});

  this.header = this.vis.append("text")
                      .text(this.title)
                      .attr("x",0)
                      .attr("y",-58)
                      .style({"fill":"#DBDBDB","stroke":"#DBDBDB"});

  this.vis.selectAll("text").transition().duration(1000).attr("x",x(this.time));
  this.vis.selectAll("circle").transition().duration(1000).attr("cx",x(this.time));
}

occurrences = data.map(function(d) { return new occurrence(d); });

Which is interesting, since this blatantly violates everything D3 tries to be. Instead of joining data to elements, I was (gasp!) adding elements one at a time, as part of an object. A much more D3-esque method would have been to filter the data (using Underscore, probably) into the three categories - actual, local, global - and then to use D3 to selectAll("circle") and join to the data.

With that said, although it was an unconscious decision at first, I would write this code the same way again. Despite my initial knee-jerk reaction to not using the canonical D3 design patterns, OOP makes more sense. When I (inevitably) have to go back and operate on this data again - to remove an event, or something of that sort - having it nicely bundled in an object makes manipulation easy. With the classic D3 method, I would likely have no way to select a single event without resorting to something hacky like putting each event in an svg “g” element with a unique ID - still viable, but it feels a little odd.

The standard D3 style would probably work just as well, to be honest - but, for better or worse, I’m still more used to standard OOP methods, and when it’s time to crank out some code and there are several equivalent paths, that’s what I’ll fall back to.