2019年2月22日金曜日

プログラムの設計をする際に考えていること

ふと思うところがあり,自分がプログラムを設計する際に考えていることを言葉にしてみようと思う.

まず,最初に考えるのは,最終的に用意したいデータは何なのか,ということである.

例えば,最終的に予算の合計が知りたい,だったり,最終的に画像ファイルが生成されていて欲しい,だったり,何らかのキーワードの有無が知りたい,であったりだ.

これがはっきりしていない場合,まずはこれをはっきりさせるために,情報収集を行う.例えば,発注者に話を聞いたり,ゲームの場合,仮組みをして動きや見た目を提示して,想定と合っているかの確認を行う.

次に,手元にあるデータから,最終的に必要なデータまでの加工手順を考える.ここで手順が思いつかない場合,最終的なデータを直接生成できるデータを考える.そのデータを生成できるデータを考えて,と逆算を行っていく.どうしても辿り着けない場合,何らかの情報が欠けていると思われるので,欠けている情報を明確にする.

例えば,画像を良い感じに加工して,と言われても,その良い感じがなんなのか分からないので,熱い感じなのか,寒い感じなのか,明るい感じなのか,暗い感じなのか,といったことを追加で入力してもらう必要があるかもしれない.
(そもそもそんな指示を出すのはどうかという話は置いておく)

また,今後追加で拡張などをして欲しい,といった要望があることも考えて,どういった拡張が考えられるだろう,といったことも考えておく.

ここまで来て,ようやくプログラムの設計に入るのだけれど,ここでいきなりクラスやアーキテクチャなどの設計に入るわけではない.

まずは,途中で必要となる要素の実験を行う.例えば,ファイルが作られた日が必要だとして,対象としている環境すべてで取得可能か確認を行う.もし不可能な環境があれば,他の方法を検討する必要がある.

他にも,想定している機能拡張がある場合にやりやすい方法は何だろう,と考える.なるべくシンプルな機能に分解しておいて,それらを組み合わせて実装するようにしておくと,後々組み合わせるだけで済み,追加部分だけのテストで良いこともある.

いくつかの実験を行い,一通りのパーツが揃ったら,ようやくクラスやアーキテクチャの設計に入る.

この段階で考えるのは,用意したプログラムを他のプログラマが利用するかどうか,ということ.

利用しない場合,ぶっちゃけ多少適当に作ったとしても,他に影響は無いので,サクッと作って素早く提供できる方が良い.

問題になるのは,他のプログラマが利用する場合だ.

下手にgetterやsetterを作ろうものなら,思わぬ使い方をされて,下手に修正できなくなる.

他のプログラマがどういう風に利用するかを考え,想定する使い方をする場合は使いやすく,想定しない使い方をしようとすると,途端に面倒になるような形が望ましい.

これは,ある程度利用するプログラミング言語に関する知識が必要となる.

例えば,C++であれば,あるクラスのオブジェクトはコピーできないようにしておく,getterは値のコピーを返し,オブジェクトが持っている値そのものは,簡単には変更できないようにする,などが考えられる.

C++の場合,アドレスが分かれば無理矢理書き換えもできるが,そこまでやる相手のことを考え始めると,実装速度や処理速度が犠牲になるのでやらない.

他にも,インターフェースである関数名や仮引数名を分かりやすいものにする,などで利用するプログラマが勘違いしたりして変な使い方をしないようにする.

例えば,音量を指定する機能を実装する場合に,それを0から1の浮動小数点で指定するのか,0から100のパーセンテージを表す整数で指定するのか,はたまた実際にスピーカーに渡せる最大値と0の範囲で指定するのか,と色々考えられるが,これがvolume,としか書いていなければ,ドキュメントを信じるか,実装を読み解くしか無い.

ちなみに,同一システム内に上記が混在しているのを見たことがある.

また,統一感,というのも重要になる.例えば,セーブロードの機能が,全体的にsaveとloadという名前で実装されているところに,storeとrestoreを導入する,というのは統一感が取れていない.

統一感を出すには,実装しているシステム中で一般的に使われている単語の用法から外れないように単語を選択していく必要がある.

この辺は,驚きを最小にする,ということを意識するようにしている.

また,実装しているシステムだけでなく,利用しているAPIやプログラミング言語の公式ドキュメント,世に溢れるオープンソースから類似の実装を読み,よく使われている名前を検討する.

よく使われている名前を使っておくと,検索する際にも似たような情報を拾いやすくなる.また,意味の取り違えも減る.

ここまでやって,ようやく多少は間違った使い方をされにくい設計ができる.

後は,考えたことをコードに落とし込んでいくだけである.

書いてみたけど,若干とりとめが無い,ポエムになってしまった感があるなぁ・・・・・・