PPPUC++ #8
6. Writing a Program
"Programming is understanding." Kristen Nygaard の言葉。Simulaの生みの親の言葉はMr.S 的にも心に強くハマっている言葉なんだろうとか思いつつ、巨人に黙祷。
#理解・分解・再合成、、、、はハガレンでしたね・・・
この章(&次の章)では、実際にもやっとしたアイディアからプログラムを開発する例を行います。
解析、設計、実装、テスト、再設計、再実装、、、、という流れ。
6.1 A Problem
- プログラムを作るにはまず「問題」から。問題の理解こそが良いプログラムのキーポイントです。
- 問題設定が悪いと、いかにそれが優雅だろうが使い物にならないことが多い
- 必要なのは、解こうと思った問題を、単純、かつ明確に解くことなのだよ、ワトスン君
- どんな例にすべきか?
- 設計とプログラミングの技術について示唆を与えるモノ
- 数々の決断とかその理由について考える機会を与えるモノ
- あまりいろんな言語機能を使わないモノ
- 設計に関して、ある程度の考察が必要になるくらいには複雑なモノ
- 解法が複数あるようなモノ
- 簡単に理解できるようなモノ
- 解決するに値するようなモノ
- 完全に紹介できて完全に把握できるくらいに小さなモノ
- というわけで、これらの条件を全て兼ね備えるスーパーデリシャスグレートゴージャスな計画を発表します
- 「コンピュータにキーから入力した式を計算させるプログラムの作成」!!!!!!!!!!!! どーだ思いつかなかったろ (注: 流石のMr.Sもそこまでは言ってません)
- このプログラムは最高に使いどころ満載。なにせほとんどのデスクトップにはこの手のソフトが入ってるし、そのための専用コンピュータまであるくらい。
(違
(注: 流石のMr.Sもそこまでは言ってません)
-
- 唯一の問題点は、まあ、なんでしょう、真新しいことは何も無いって・・・(ぉ
6.2 Thinking about the problem
- 問題をどうやって解くかをちょっと考えてみる
- その後にプログラムでどう表現するかを考える
- まずはちょっとしたスケッチを書いてみよう
- なにかまずいところ無いか、というのを探す
- また、友人と議論したりも
- ソリューションの問題点を浮き彫りにするには大変良い方法。紙やコンピュータは言い返したりしてくれないからね。
- 孤独じゃないのよプログラミングは(設計は(理想は))
- ソリューションの問題点を浮き彫りにするには大変良い方法。紙やコンピュータは言い返したりしてくれないからね。
- あらゆる人, あらゆる問題に通用する銀の弾丸は当然、ない
- 世間には、「問題解決力アップ!今日からあなたもプロフェッショナル」、、、とのふれ込みの本だとか、プログラム設計のための膨大な文献が溢れかえってるけど、本書はソレジャナイ。
- よく出くわすような、もっと小さい部分での戦略を提案をしていって、それからさっさと我々の
スーパータイニー計算機での実証に進むつもり
- 常に懐疑的であれ
- 嘘っぽくならないように、ここではプログラムを徐々にバージョンアップしていくストーリ形式をとる
- と、なると当然だけど、途中のプログラムは不完全だったり、下手すると間違っていることすらある。
- ハッピーエンドはラストまでおあずけ
- と、なると当然だけど、途中のプログラムは不完全だったり、下手すると間違っていることすらある。
- 道程重要
6.2.1 Stages of development
- 解析ステージ:何をすべきかを検討し、その時点での理解した内容の説明=要求集合と仕様を作成する。大きな問題では仕様書が得に重要。
- 設計ステージ:全体構造をつくる。どんな部品で構成されるか? それらがどう相互作用するか? どんなツール(ライブラリなど)を使うか?
- 実装ステージ:コーディングデバッグテスト!
6.2.2 Strategy
- 解決しようとしている問題は何?
- ユーザー視点で考えるべし. Howはこの時点では考えちゃダメ。
- 「このプログラムは何をしてくれる?」「このプログラムとどうやって対話したい?」
- 問題文は明確になっている? 現実的なプロジェクトでは(たとえトイプロですら)まずそれはありえない。
- 最初から詰め込みすぎない(重要)。"2.0"にバージョンアップするのは後からいつでもできる。
- 問題サイズは適切? 時間、技術力、使えるツール、などの制約から。無理そうならリソース増強を考えるのが理性的って、んー、なぜだろう、悲しくないのに涙で目が曇るよおっかさん・・・*1
- 問題を扱いやすい部分に分割する。現実的なプログラムであれば、最小のものでさえ分割するに十分過ぎるほどに大きい(確かに。。あーやってぇ、こーやってぇ、って言った瞬間に2つに分割できてるものね)
- 主要部分だけに絞った小さな、機能限定バージョンを作る。
- 最初は問題を完全に把握することはできない。分かってると思っていても案外分かっていないもの
- 問題の解析と実験を組み合わせて理解を補間・増強させながら開発する。これが唯一の堅実な理解への道
- プロトタイプとも呼ぶ
- 薄ら汚いコードなどはとっとと捨てて新しい簡易バージョンを書くべき(*!!*)。ゴミはゴミにしか成長しない。そのための簡易版なのだ(ああ、なぜだろう。悲しくないのに(ry *2
- 完全版を作る。
- 前ステージで作った部品を組み合わせて作れると最高
6.3 Back to the calculator!
注:デロリアンはでません。
- さて計算機とのI/Fはどうするか。
- いやこりゃ簡単。GUIは16章までお預けなので、勝手知ったるcin, cout I/Fで
Expression: 2+2
Result: 4
Expression: 2+2*3
Result:8
Expression: 2+3-25/5
Result:0
みたいな感じ。確かに、「明確かつ正確」にはまだなってない。空白入れていいの?とか()は使えるの?とかエラーがあったらどうなるの、とか瞬間的に聞こえてくる
- しかしながら要求定義においてこーゆー具体的なのは「最小限やること」を定義できてわかりやすい。
- こーゆーのはユースケースと呼ばれていて、実用的な定義として重要
- さてここまでの考察から大抵の人が連想するメインロジックは下のような感じ
read_a _line
calculate // do the work
write_result
- こーゆーのは擬似コードと呼ぶ。具体的にどう実装するか分かってない時点での考察結果の記述に便利。
- 例えばcalculateはdiscreteなのかfunctionなのか? そうなら引数はどんなん? とかまだわからない。
- けど、僕は3歩歩くと全部忘れてしまうし、コード以外で人にうまく説明できないので、何かにコードっぽい何かに書いておきたいなー、というあなたに最高の方法
- 例えばcalculateはdiscreteなのかfunctionなのか? そうなら引数はどんなん? とかまだわからない。
6.3.1 First attempt
- この時点でまだ計算機プログラムを書くのに十分な情報は集まっていない
- というわけで許可されましたので僕も独自に書いてみました http://d.hatena.ne.jp/tkuro/20110208/1297137741
- ここでは単純に決め打ち cin リードをして lval, op, rval の順によむコードが紹介されている
- +,- オンリーでしかもint って、こりゃなかろう、とか思ったんだけど、「プログラミングが初めての人」向けかつ試行錯誤戦略だった。わすれてた
- で、↑をカイゼンして。 1+2+3+ ... みたいな連式もいけるようにしたヤツが次。
- しかし式を x で終端する、しかもそれを無説明でコード中の cout<< にしか書いてないって、そりゃなかろう、とか思ったんだけど(ry
- しかし、このままだと掛け算割り算の優先順位が守れないねーって話
- 「こんな古くセー慣習なんぞクソ喰らえ!」と俺数学の開祖になるのも一考だけど、数百年以上の伝統を持つこの慣習をオレコーディングを簡単化するためだけに変えるなんて・・・!