2012年10月23日
川俣晶の縁側ソフトウェア技術雑記 total 3522 count

失敗のケーススタディ「仮想ストレージクラス」

Written By: 川俣 晶連絡先

「このクラスはなぜ没になったのか。その事例を検証してみよう」

「なぜ検証するの?」

「まあ、多少はネットでも先生じみたことをするかな、ということで」

「君の失敗だろ」

「明日の誰かの失敗かもしれない」

仮想ストレージクラスの設計 §

「まず、以下のようなクラスが設計されていた」

「純粋な抽象クラスだね。interfaceでも良かったのでは?」

「結果論としてはその通り」

    public abstract class AbstractStorage

    {

        public abstract XDocument GetObject(string id);

        public abstract void SetObject(XDocument doc, string id);

        public abstract IEnumerable<string> EnumObject(string classid);

        public abstract bool IsReadOnly { get; }

        public abstract void DeleteObject(string id);

    }

「このクラスの役割は?」

「ストレージを仮想化したかったのだ。idを振られたXML文書の集合体として、仮想のストレージを準備し、後からいくらでも実装を増やせるようにしたかった」

「なぜそんな回りくどいことを?」

「クラウドとオンプレミスとデスクトップアプリとストアアプリでストレージに差がありすぎるからさ」

「なるほど」

「データの取得、書き込み、列挙。読み出し専用であることの通知、削除という機能メソッドを持つ」

失敗の問題 §

「なぜこの設計ではダメだったの?」

「うむ。遅すぎたのだ」

「なぜ?」

「理由は複数ある」

  • idの列挙は具体的なデータを読み出さないで実行できるはずなので、列挙は軽いと思った。しかし、実際にはid以外の情報も必要だった。(UIで内部識別子のidを見せるわけには行かない。Human Readableな名前を取得しなければならない)
  • 実はいちいちXDocumentクラスを経由してやり取りすると過剰に重くなる
  • 数百件のデータを暗に想定したら実際には万単位のデータだった

「結局なに?」

「ファイルシステムを使った実装だと、数万のファイルを開いて読み取って解析して閉じるという作業が必ず発生してしまうことになり、けっこうスローダウンした」

「待たされるのはいやだね」

「メモリも食うしね。データ構造的にメモリが乏しい環境での動作も視野に入っていたのだ」

解決は? §

「まだこれに相当する新しいクラスは書いてないけど、アーキテクチャを再設計したよ」

「どうすればいいわけ?」

  • idだけ列挙して効率を上げようという姑息なアーキテクチャは上手く行かないので廃した
  • データの分離分割性を強化し、一度に扱うデータを数百件単位に絞り込んだ (メモリ効率優先だ)
  • 複数のデータをまとめてXML文書にパッキングして保存するようにし、開く頻度を減らした

「これで万事解決?」

「次の問題が出てくる可能性はあるが、一山は超えた気分だな」

「油断は禁物ってことだね」

教訓 §

「ボトムアップに積み上げていくと、目的地まで行けない可能性がある」

「高尾山でいくら上を目指しても、富士山の山頂には行けないわけだね」

「結局、その場合はコードを棄てて再設計する勇気も必要なのだな」

「それでいいの?」

「いいぞ。コードの断片は生きるかも知れないし、実際にやってみて分かったノウハウが活かせればずっといいコードが書けるようになる」

「他に何か対策はないの?」

「トップダウンのアプローチの方がこういうミスは起きにくいな。まず最終形をイメージせよ、ということだ」

「最終形はイメージしなかったの?」

「最終形はイメージしたが本当の最終形ではなかった。そこが敗因だな」

「データ件数の見積もりが甘かったわけだね」

「あるいはスパイクせよ、でもいいぞ」

「事前に気になる部分をコーディングして確かめろってことだね」

「とりあえず、最低限をコードに落として動かせば見落としもバッチリ分かる」

「じゃあまとめは?」

「論よりソース」

「またそれか」