電子書籍の厳選無料作品が豊富!

保守性の高いコードを書きたいです。JavaScriptでdocument.write("<div id='main'></div>")みたいに書いて、後でこの要素にいろいろなコードでdocument.getElementById('main').innerHTMLします。しかし、その後id名mainを他の名前に変えると、多くのソースコードを手作業で変更しなくてはなりません。この手間を削減するJavaScriptの書き方はありますか?

例えば、
<table id="board">
  <tr>
   <td id="b0_0">A</td>
   <td id="b0_1">A</td>
   <td id="b0_2">A</td>
   <td id="b0_3">A</td>
 ・
 ・
 ・

上記のようなHTMLを作成する、以下のようなコードがあります。

<table id='board'></table>

<script>
 var content = "";
 for(i = 0; i < 5; i++){
  content += "<tr>"
  for(j = 0; j < 4; j++){
   content += "<td id='b"+ i + "_" + j +"'>A</td>"
  }
  content += "</tr>"
 }
 $('table#board').html(content) // JQueryを使っているつもりです
 
</script>

このコードの問題点は少なくとも2つあって、
1つは、2重ループ内の「content += "<td id='b"+ i + "_" + j +"'>A</td>"」が読みづらいことです。
2つ目は、今は td id='b0_1'のような形式ですが、このid名を変更しようと思ったときに、変更が容易ではないことです。

特に2つ目は、いろいろな場所にあるコードから$('table#board td#b1_1').html('B')のような操作をしていると、かなり変更が大変です。

こういったことを乗り越えるためのJavaScriptのコード設計法(?)やIDEやライブラリなどがありましたら教えて下さい。よろしくお願いします

A 回答 (4件)

保守性を高めたい、ということですよね。

であるならば、オブジェクト化を進めることだと思います。

・マジックナンバー、マジックストリングを排除する
コード内に直接書かれている意味がわからないリテラルのことです。idのmainなどもそうですね。こうしたものはすべてオブジェクト内に定数プロパティとしてまとめておき、それを参照する形で記述します。例えば、こんなオブジェクトを定義しておき、

function Literal() {
var main = "main";
this.main = function(){ return main; }
}
var literal = new Literal();

innerHTMLではこのようにします。

document.getElementById(literal.main()).innerHTML = ……

コード内で"main"を参照する部分はすべてliteral.main()を使います。こうすれば、後で名前を変更したいときは、Literalのvar mainの値を書き換えるだけです。

・処理のメソッド化
処理専用のオブジェクトを用意し、そこに具体的な処理をすべてメソッドとしてまとめます。例えばテーブルを変数contentにまとめている処理なども、こんな感じにします。

function ContentBuilder() {
this.getTable = function(prefix, arraydata){
var content = "";
for(i = 0; i < arraydata.length; i++){
var row_array = arraydata[i];
content += "<tr>";
for(j = 0; j < row_array.length; j++){
content += "<td id='" + prefix + i + "_" + j +"'>" + row_array[j] + "</td>";
}
content += "</tr>";
}
return content;
}
}
var builder = new ContentBuilder();

これで、builderのgetTableを呼び出すことでテーブルのコードが得られるようになります。こんな感じですね。

var data = [
['a','b','c'],
['あ','い','う'],
[1, 2, 3]
];
document.write(builder.getTable("xxx",data));

生成されるタグのidがどのように設定されているか確認してみてください。引数のプレフィクスを変えればIDもすべて変わります。

このように、「変数・定数をすべて1つのオブジェクトにまとめる」「処理はオブジェクトのメソッドにまとめる」というようにしていき、全ての値や処理は必ずこれらのオブジェクトのメソッドを呼び出すようにします。

こうすれば、後で修正する場合も、オブジェクトのプロパティなどを変更すれば、すべてのところで反映されます。更に、定義したオブジェクト類は別ファイルに切り離し、そのスクリプトファイルをロードするようにすれば、ページデザインと処理(ビジネスロジック)も切り離し別々に管理できます。

JavaScriptはオブジェクト指向言語ですから、それを活用しない手はありません。オブジェクト指向についていろいろ調べてみるとよいでしょう。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます!

JavaScriptでのオブジェクト指向の活用法がわかった気がします!私はJavaをやっていて、より洗練されたオブジェクト指向をもつScalaにも魅力を感じてるので、オブジェクト指向の発想は分かります。JavaScriptは、はっきりとしたクラスはないし(と思っていて)、オブジェクト指向で組もうとすることはありませんでした。

Javaで磨いたオブジェクト指向をこれからはJavaScriptでも発揮したいと思います。ありがとうございました。

お礼日時:2014/05/19 21:10

そういったケースでは、IDを1つ1つ付けるべきではありません。



行数、列数が分かっていれば('#board td')で一連のリストとして取得するか、
どうしても二次元リストが良ければ('#board tr')で取得してその後('td')で取得すればできます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます

私の例が悪すぎました。別に例はtableでなくても良かったです。単に幾つか入れ子になる自然なHTMLを書こうとしただけなんです。

お礼日時:2014/05/19 21:14

こんな感じでどうでしょう。

2つ目の「変更が容易ではない」の意味がイマイチよく分かりませんが、1つ目の「読みづらいこと」は改善しているし、もしかしたらこれで2つ目も解決したことになるのではと思います。


// コードの先頭辺りに定数として書く。「var content = "";」の前かな
var TD_BASE = "<td id='【ID】'>A</td>";



for (var j = 0; j < 4; j++) {
  var id = "b" + i + "_" + j;
  content += TD_BASE.replace("【ID】", id);
}


また、「var TD_BASE = "<td id='【ID】'>A</td>";」ではなく
「var TD_BASE = "<td id='b【row】_【col】'>A</td>";」などとし、replaceを2つ続けるようにしてもいいと思います。


それからfor文内のインデックス変数の部分ですが、「var j = 0」と明示的に書いた方がいいですよ。そうでないとグローバル変数を使うことになります。このケースでは問題は起きませんが、例えばループ内で関数を呼んでいて、その関数の中でもfor文を使っている場合には、同一の変数を使うことになってしまい正しく動かなくなりますので。

この回答への補足

お礼に書き忘れました。

for文の件ありがとうございます。varつけていいことを知りませんでした。for(i=...だと for(window.i= ...になっちゃうんですかね?

補足日時:2014/05/19 21:12
    • good
    • 0
この回答へのお礼

ご回答有難うございます。

私の言葉が足りなかったです。
結局やりたいことは、Javaの開発環境Eclipseにある変数名変更する機能がある開発環境とかがあるといいんですけどね。Eclipseだと変数にカーソルを当てて特定のショートカットキーを押すとその変数を使用しているすべての箇所の変数名が編集できるんです。そういった感じ、簡易にid名を変更できたらいいなと思っていました。

しかし、JavaScriptは文字列のなかにコードがあるので、Javaのようにある識別子がどこで使われているか解析するのは困難そうなので、無理なのは覚悟しているのですが。

Webサービスを大規模開発している人たちはどのようにid名などをを管理しているのか気になります。

お礼日時:2014/05/19 20:59

少々面倒ですが、JavaScript に備わっている DOM を利用するのがもっとも素直でしょう



// 行を作る
var row = document.createElement('tr');
document.getElementById('board').appendChild(row);
// 欄を作る
var cel = document.createElement('td');
cel.id = 'b' + i + '_' + j;
cel.textContent = 'A';
row.appendChild(cel);

jQuery を使っているならば、DOM の記述を多少は簡略化できます

// 行を作る
var row = $('<tr/>').appendTo('table#board');
// 欄を作る
$("<td/>").attr('id', 'b' + i + "_" + j).text('A').appendTo(row);
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

DOMを使うのもひとつの手ですね。ただ、結局innerHTMLを使う時と変わらないですね。'b' + i + '_' + jは結局ありますし、
"b{i}_{j}"みたいな記法出来なんですかね?
もしくは、Cのフォーマット指定のようにformat("b%v_%v", i, j)のような関数が文字列を返すとか?ないですかね?

お礼日時:2014/05/19 20:47

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!