私は最近d3.jsのプラグインを書き込もうとしていて、おそらく些細なことと混同されています。再利用可能なチャートの作成方法については、 d3のWebサイトに説明があります。パターンは次のようになります(最も重要な詳細のみ、完全なコードはここにあります):
デザインパターン1:d3Webサイトから
function timeSeriesChart() {
var margin = {top: 20, right: 20, bottom: 20, left: 20},
...
area = d3.svg.area().x(X).y1(Y),
line = d3.svg.line().x(X).y(Y);
function chart(selection) {
selection.each(function(data) {
// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.
data = data.map(function(d, i) {
return [xValue.call(data, d, i), yValue.call(data, d, i)];
});
// Update the x-scale.
...
// Update the y-scale.
...
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
...
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg").append("g");
...
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) { }
// The x-accessor for the path generator; yScale ∘ yValue.
function Y(d) { }
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
return chart;
}
特にd3の作成者自身が提案したため、このパターンが堅牢であることは間違いありません。ただし、その投稿に出くわす前は、次のパターンを問題なく使用してきました(プラグインの一般的な作成方法と同様)。
デザインパターン2:プラグインを作成する一般的な方法
(function() {
var kg = {
version: '0.1a'
};
window.kg = kg;
kg.chart = {};
// ==========================================================
// CHART::SAMPLE CHART TYPE
// ==========================================================
kg.chart.samplechart = {
// ----------------------------------------------------------
// CONFIGURATION PARAMETERS
// ----------------------------------------------------------
WIDTH: 900,
HEIGHT: 500,
MARGINS: {
top: 20,
right: 20,
bottom: 20,
left: 60,
padding: 40
},
xRange: d3.time.scale(),
yRange: d3.scale.linear(),
xAxis: d3.svg.axis(),
yAxis: d3.svg.axis(),
data: {},
// ----------------------------------------------------------
// INIT FUNCTION
// ----------------------------------------------------------
init: function() {
// Initialize and add graph to the given div
this.update();
},
// ----------------------------------------------------------
// Redraws the graph
// ----------------------------------------------------------
update: function() {
var parentThis = this;
var newData = parentThis.data;
// Continue with adding points/lines to the chart
},
// ----------------------------------------------------------
// Gets random data for graph demonstration
// ----------------------------------------------------------
getRandomData: function() {
// Useful for demo purposes
}
};
// ==========================================================
// HELPER FUNCTIONS
// ==========================================================
}());
// EXAMPLE: This renders the chart.
kg.chart.samplechart.vis = d3.select("#visualization");
kg.chart.samplechart.data = kg.chart.samplechart.getRandomData();
kg.chart.samplechart.init();
私はしばらくの間デザインパターン2を問題なく使用しています(私はそれがあまりきれいではないことに同意しますが、私はそれに取り組んでいます)。デザインパターン1を見た後、冗長性が高すぎると感じました。たとえば、内部変数にアクセスできるようにするコードの最後のブロック(chart.margin = function(_) {}
など)を見てください。
おそらくこれは良い習慣ですが、これはさまざまなチャートタイプごとに繰り返す必要があり(現在開発中のNVD3と呼ばれるライブラリで見られるように)、開発作業とバグのリスクの両方が増加するため、メンテナンスが面倒になります。
パターンを続けた場合にどのような深刻な問題に直面するのか、またはパターンをどのように改善したり、デザインパターン1の精神に近づけることができるのかを知りたいです。完全な書き直しが必要になり、やや安定したミニライブラリに新しいバグが発生するため、この時点でパターンを変更しないようにしています。助言がありますか?