ソフトウェアを開発していると、
問題を簡単にすることが絶えず求められている。
そこで、私が心がけているポイントを述べる。
問題を簡単にするためのコーディング上のポイント
- 将来あると便利かもしれない機能は、必要になるまで実装しない。
- データ構造を隠すようなカプセル化をしない。
- 利用方法が十分に決まりきっていない時点では、データメンバーをprivateにしない。
- インスタンスのデータメンバーへのアクセッサを書かない。
- クラスに意味合いの異なるメソッドを追加しない。
- 不必要な継承はしない。
- std::vectorやstd::mapなどで十分なことを、わざわざ実装しない。
- 文字列定数で十分なことをenum型やマクロ定数としない。
- 関数名や引数名、const修飾子などで十分に意味が自明になるようにして、わざわざDoxygen用のドキュメンテーションコメントを書かない。
まず、正しく動くコードを作る段階では、物事を単純化することが必要だ。
正しく動くことが分かった後で、ライブラリとして共有化するときには、別に基準を設定して考えよう。
KISSと呼ばれていることですね。
巨大なプログラムの一部としない。
そのやり方がうまくいくことをなるべく簡単な方法で検証する。
アルゴリズム自体を検証する時点では、べた書きのコードでもいいから意味がとりやすく、早い段階で検証できる方法を実装する。
追記:
- 過度に最適化を求めない。最適であるよりも、許容できるものであるかどうかを気にしよう。
許容できる水準にあれば実用上十分出す。それ以上の最適化は、手間がかかるコストに比べて改善の度合いが割りにあわなくなります。
最適化がどれだけ厄介かは、「今日の昼の食事として一番最適な食事は何か」を要件定義から検証して、実行するのをしてみれば分かると思います。そんなことより「今日は**でいいや」で十分なことがわかります。
- 自分の抱えている問題は、既によく解かれてている問題とどこが違うのかを考える。
ある1つの点を除けば、よく知られた定式化になっている。その1点を取り除けば、既存の枠組みを利用できるのに。その1点の他は、既によく解かれてている問題で必要とされる工夫の全てを参考にすればいい。自分の抱えている問題が、既によく解かれてている問題とどこが違うのかを考えることがヒントになるはずです。
- 込み入った問題の中から簡単と言い切れる内容を切り出す。
ものごとを検証する際には、一度に全てのことが明確になることはまれです。
全てのことを一度に解決しようとして解決できることはまれです。
込み入った問題の中から簡単と言い切れる内容を切り出していくことです。
そうして未解決のまま残っている内容を明確に言い切りましょう。
自分ひとりの力で全てが解決できることもまれです。
少しでも簡単と言い切れて切り出された部分が増えると、
残りの部分が扱いやすくなります。
扱いやすくなった残りの部分は、他の人の協力で解決することもあります。
-
プロジェクト・マネジャーが知るべき97のこと: 複雑よりもシンプルな方がいい
-
プロジェクト・マネジャーが知るべき97のこと: シンプルにいこう
-
プロジェクト・マネジャーが知るべき97のこと: 巧妙なコードはメンテナンスが困難
付記:
「問題は簡単に解けるようにしてから解け」by 金出武雄
コンピュータビジョンの分野でたくさんの業績を出している金出武雄 氏の言葉。出典はたどれていません。
「独創はひらめかない―「素人発想、玄人実行」の法則 」 などの金出さんの本を読むとヒントになる考えが多数紹介されています。
物事を成し遂げた人の記録を何でもよいから読んでみよう。
物事を簡単にすることがいかに大切かが分かる。
まだ、だれも作り上げたことのない分野で「物事を簡単に」したことが、
どれほど才能を必要とするものかが分かる。
どのように考えることで、「物事を簡単にする」ことができるのか、
それらの本の中から読み取ってほしい。
結果として採用しない山ほどのアイディアを考えること
物事を解決していく際の優先順位の設定、ある手法を採用するまでの間に、結果として採用しない山ほどのアイディアを電車の中で考えておくこと。
ドキュメンテーションコストを下げられる「あいつが言っていることは信用できる」となる人間関係の構築。
物事が解決不能で終わってしまう理由は時間です。物事を難しくしてしまうと、正しいことよりも、「政治的配慮」が優先されてしまうようになって、リスクを高めてしまいます。
最小化問題として定式化されたアルゴリズムは、そうでない問題よりも理解が簡単になる。
画像認識や機械学習の問題の多くは、最小化問題として定式化されています。それによって、達成した状況とは、どのような状態なのかがわかりやすくなります。最小化問題として定式化されると、試行錯誤のためのぐちゃぐちゃのアルゴリズムという状況にはなりにくくなって、問題の扱いが簡単になります。最小化するための手法は、数学や物理学や各種の最適化問題によって、さまざまな手法が作り上げられています。拘束条件つきの最小化問題などもあります。
あなたの考えている問題が、最小化問題として定式化できないかを、簡単にする手法のひとつとして考えてみてはどうでしょうか。
扱いやすい定式化をすることが成功につながる
扱いやすい定式化にすることは、とても大切なことです。
-
例:方程式を解く代わりに最小化問題を解く - 変分法
微分方程式の解を求めるという問題を、ある量の最小化問題としてとらえなおす手法です。厳密に解くことはできない場合でも、その量が小さい方が、真の答に近い値であるとすることができます。
フェルマーの原理
量子化学の変分法
厳密解を求めることが困難な量子化学計算の分野で、最低固有値の状態を近似により求める方法。
- 例: 拘束条件を満たす解を見つけるための定式化 ラグランジュの未定乗数法
ラグランジュの未定乗数法は、拘束条件のあるときの最小化問題を解く枠組みです。何を最小化するのかという適用分野にはよりません。ミクロ経済学の分野では、予算制約式という拘束条件の中で効用関数を最大化する効用最大化問題の解法にも使われている。
- 例:IntelのCPUの流れを作ったチップIntel 4004の開発は、電子式卓上計算機のために、多くの種類のチップを同時に開発するのではなく、ワード長が4ビットであることを除けば、汎用のコンピュータそのものという構成を採用した。
- 例: 多体問題専用計算機の最初のモデルGRAPE-1 は簡略化のためにデータ幅を8ビットとし、全ての演算を ROM のテーブル参照で済ませるようにした。
- 伊藤智義『スーパーコンピューターを20万円で創る』 - 例:Pythonは予約語が少ない。正規表現などもライブラリに任せていて、文法は簡潔である。そのことが、Perlよりも各段に使いやすい言語になっている理由の1つです。
- 例:特殊相対性理論は、ローレンツ変換に不変な形であることを基準に力学を組み立てなおしたものと言える。光速が慣性系によらず一定であるとすることで、少数の少ない原則にしたがって簡単にしたものと私には思える。最初から簡単なのではなく、読み解いていくことによって簡単になっていっているように見える。
- 例 Heisenberg形式の行列力学の量子力学よりも、シュレディンガーの波動方程式の方が、より理解しやすい枠組みとして受け入れられています。微分方程式による定式化の方が、視覚的にも分かりやすいものになっています。
付記:ここに書いてある「問題を簡単にするためのコーディング上のポイント」の問題点
- アルゴリズム自体は枯れていて、そもそもうまく実装できるかどうかの心配などしなくていいときには、ここに書いている流儀は明らかに不適切だ。
- また、アルゴリズムの開発に確認を持てて、モジュールとして提供するには、「問題を簡単にするためのコーディング上のポイント」は不適切である。
- モジュールとして提供する際には、どういう使い方を許可して、どういう使い方を許可しないかを考え必要がある。
- 何をpublic として何をprivateとするのか。
- public とするメソッドでは、何を引数とするのか
- classのdata memberには何をもたせるべきか
- そういった内容は、アルゴリズムが動くようになってから考えるしかない。
- (もしくは、十分にアルゴリズムの使われ方が既に標準化されているような状況では、そのAPIと同じインタフェースを最初から目指しながら開発するという手もある。)