ジャトミカ学習帳

プログラミングとかデジタル信号処理とかのメモ書き

プログラムの複雑さはロジック側ではなくデータ側に寄せる

「プリンシプルオブプログラミング」をざっと読みました。
定期的に読み返してじっくり自分の中に植え付けていきたい、と思える内容でした。
為になった点をピックアップし考察していきます。

表現性の原則

UNIX思想の一つで「情報はデータに寄せて表現」ということらしいです。理由を見てみると、そちらの方が容易に理解できるから、とのこと。
UNIXには抵抗感がありましたがこの本を読んでからだいぶ消えました...(^^;

例を挙げて考えてみます。以下のfuncAはどんな処理をしているのでしょうか。

int funcA(int value){
        if(value<=1) return 1;
        return funcA(value-1)+funcA(value-2);
}

関数名はあえて分かりにくい名前にしています。
ピンと来る人は一瞬でしょうが、そうでない人は理解するのに数分かかってもおかしくありません。

さて次の場合はどうでしょうか。

static const int table[10] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55};
int funcB(int value){
        return table[value];
}

こちらの場合は見ただけでパっと気が付く人も多いと思います。フィボナッチ数列ですね。 人間はロジックを追うよりもデータを見た方が理解にかかる時間が短くなるわけです。

このように「どちらの記述を採用しようかな?」と思う場面は多々あります。

ロジックが2つある場合どちらシンプルにするか

デジタル信号処理の仕事をしていると頻繁に遭遇するのが、デジタル回路の構成もしくはその制御をしているプログラムのどちらのシンプルさを保つか、という問題です。 言い換えると、「回路のロジック」と「制御のロジック」のシンプルさの選択です。

例えば、「複数の入力信号から一つ選択し出力するスイッチ制御」を考えてみます。
なるべく省資源で抑えたいケチル君と資源を気にしないムダヅカさんの2人に回路設計を頼みました。2人の作品は以下です。

f:id:tommy_dsp:20171202220459p:plain

ケチルくんの回路はスイッチ1つのみで構成されており、回路を見ただけでどちらか一つの入力のみを使うことが分かるので完璧です。 ムダヅカさんの回路はスイッチを2つ使ってしまったため、「もしかしたら入力1と入力2が両方出力される場合もあるのかな?」と、回路を見ただけでは分かりません。 お題は「複数の入力信号から一つ選択し出力する」ことであるので、この回路構成は間違いではないですが不親切です。

では、入力信号が4つの場合はどうでしょう?再度2人に設計を頼みました。

f:id:tommy_dsp:20171202205629p:plain

ケチルくんの考え方は、1~4までの数字が2進数で00, 01, 10, 11 と2bitで表現できるのと同じように、4種類の入力も2種類のスイッチがあれば切り替えられるだろうというものです。 ムダヅカさんはスイッチの種類や量を気にすることなく入力に対して別々に用意しました。

ここらへんから何となくムダヅカさんの回路の方がパッと見て綺麗に感じませんか? 確かにケチルくんの回路は合理的で制御する際にも誤った動作になることもなく、資源も少なく済んでいます。ムダヅカさんの回路は上手くスイッチの制御をしないと出力信号が4倍になるケースもあり得ますが、回路の見た目としては非常にシンプルです。

さて、この2人の回路をあなたが引き継ぐことになりました。そして上の人から「入力5つに増えたから仕様変更よろしく」と言われたとします。 5つ目の入力用経路を組み込みやすいのはどちらの回路でしょう?
説明するまでもなさそうですが貼ってみます。

f:id:tommy_dsp:20171202211423p:plain

ムダヅカさんの回路を引き継いだなら「はーい」と二つ返事で受け入れてこう再設計するでしょう。5つの入力が並列であることが一目で分かります。 ケチルくんの回路を引き継いだ場合は多少モヤモヤ感があり、苦し紛れに最後の部分にプラスアルファした形跡が残ります。 後から見た人は、入力5だけなんか特別扱いしてる?と変な想像をしてしまいます。スイッチだけ見てもAに比べB, Bに比べCが強い力を持っており粒度が揃っていません。
2つの切り替えの時はケチルくんの考え方のほうが、機能拡張していくことが想定されるならムダヅカさんの考え方のほうが回路・制御を含めた全体のロジックとしてシンプルなんですね。

このように2つ以上のロジックのどちらをシンプルにするか迫られた場合は、全体を俯瞰して考えてみることが大事だと思います。 もちろん制御の処理スピードを優先したいなどの条件があれば正解は定まりますが、基本的にはなんらかのトレードオフの関係になることが多いです。

ちなみに今回の話は「最適化を求めると運用・保守が難しくなる」という原理にも通じていると思います。

おわり。