連想配列を使う時の些細な一手間について。連想配列は自由度が高い機能だ。反面、その連想配列をどう使っているのかがコードを書いた本人にしかわからない。そこで、コードの中で連想配列の使い方を明示する方法を紹介する。
あなたは刻々と流れてくる売り上げ情報を集計し、リアルタイムな商品ごとの売り上げを出したいとする。次のような流れのコードを書こうと思う。
アウトライン
- 連想配列のkeyを商品IDにする
- valueを通算の売り上げにする
- 商品の売り上げ情報が流れてくるごとにvalueに値を追加する
- ただし初めてそのIDの商品が来た時に足し算をするとエラーになるので0を代入する
まず、このようなコードを書いた。
Map<String,int> sales = {};
// 売り上げイベントが流れてくる
void onSales(String productID , int price) {
// この商品IDが初めてきた時は0を代入する
if(!sales.containsKey(productID)) {
sales[productID] = 0;
}
// 商品代金を売り上げに加算する
sales[productID] += price;
}
コードが短いのであまり効果が実感できないかもしれないが、このコードの改善できる点として
- 上にあげたアウトラインがコードで表現できていない
- 連想配列をどのように使うかのルールがコメントと書いた人の頭の中にしかない
- コードを書いている最中にそのルールを覚えていなければいけない
もっと複雑なデータ構造(例えばMapのなかにMapがあり、その中にListがあるような状況)であればこの問題は大きくなる。では、どう改善できるだろうか。連想配列を包んだクラスを定義しよう。そしてそのクラスのメソッド経由で連想配列を操作しよう。
class ProductSales {
Map<String, int> map = {};
void productInitialize(String productID) {
if (map.containsKey(productID)) {
map[productID] = 0;
}
}
void addSales(String productID, int price) {
map[productID] += price;
}
}
final productSales = new ProductSales();
// 売り上げイベントが流れてくる
void onSales(String productID, int price) {
productSales.productInitialize(productID);
productSales.addSales(productID,price);
}
余計長くなってしまったが 、それでも
- 連想配列をどう使うかプログラムで表現できた
- 一番上流のメソッドから連想配列の具体的な操作を除去でき、代わりに分かりやすい名前のメソッド呼び出しが出現した
- onSalesを書いてる時(と読んでいる時)は連想配列の存在や使い方についてのことを忘れていられる
と言う効果が実感できると思う。普段はこんなことをしなくてもいいが、すごく長くて複雑なメソッドができてしまった場合にぜひ使ってみて欲しい小手先のテクニックだ。