ページ 11

【悩み】コードの流れを把握できません

Posted: 2014年9月17日(水) 09:19
by rupin13
初めまして。rupin13と申します。
今回、C言語の質問ではありませんが悩みがあり、相談させていただきます。

普段は仕事にてコードを書いていますが、処理の流れが複雑になると
すぐに処理を追えなくなってしまいます。
例えば、関数A, B, C があり、Aの中でBを、Bの中でCを呼び出すとき、
Aから順にコードを読み進め関数Cに達した時点で、関数Aの中で行っていた処理が
何であったのかを忘れてしまいます。

このような簡単な例ではまだ良いのですが、途中で複雑な分岐の存在する場合や
別スレッドの処理、イベントにより駆動するものが含まれた場合は特にひどく、
頻繁に前の処理を見返しても処理を追うのに時間がかかることがあります。

複雑な場合はA→B→Cの流れを記憶することができないので、
A→B、B→C、A→C(Bの処理内容を記憶せず)のパターンを覚えるようにしています。
(もっとも、3つ目のA→Cの時点でB→Cの処理内容を忘れていることも多いです)

せめて3段階くらいの流れは常に頭の中で把握したいと思っているのですが、
良い方法はないでしょうか。

上記なような関数が3つだけの流れであればウィンドウを3つ開き、
同時に表示することで解決できるのですが、これ以上複雑になったり
会話の中で「Aの中でBを呼んで、処理結果がこうだからCの引数に渡して…」と言われると
すぐに分からなくなってしまいます。


コーディング自体がそこまで苦手というわけではないと思っています。
私は学生時代に教科書レベルではありますが、C/Java/PHPの基礎を学び、
その後SEとして就職、主にJavaやRubyでの業務システム開発プロジェクトに入り、
コーディング〜結合試験までをこなしています。(就職して3年目です)
また家ではDxLib/C++でのゲーム作成を1年半続けています。
また複雑になりがちなコードへの対応として、デザインパターンは勉強しました。

もちろん経験不足もありますが、自分には才能がないのかと悩んでおります。
(才能というより記憶力でしょうか)
他人の書いたコードならまだ良いのですが、自分の書いたコードでも同じことが起こります。

どうすればこの状況を解決できるでしょうか。

Re: 【悩み】コードの流れを把握できません

Posted: 2014年9月17日(水) 09:50
by MoonGate
無理に全部を頭で処理する必要はないでしょう。
処理しきれないのであれば、紙に図や言葉で書き出せばいいだけだと思いますけど、「頭で処理する>紙に書きだす」と思われている理由は何でしょうか?
私は逆に、紙に書き出すことを疎む作業者は、細かいところで必ずミスを作り出すので信用できません。

Re: 【悩み】コードの流れを把握できません

Posted: 2014年9月17日(水) 10:12
by usao
rupin13 さんが書きました: 例えば、関数A, B, C があり、Aの中でBを、Bの中でCを呼び出すとき、
Aから順にコードを読み進め関数Cに達した時点で、関数Aの中で行っていた処理が
何であったのかを忘れてしまいます。

コード:

void A()
{
  ...

  //↑ここまでで,何をやっていたのか というのを読み解いた結果を ここに要約などをコメントとして書く.
  //(自身の記憶力などを過信せず,後から見返したときに十分な助けとなるように書く)

  B();  //B()の中でも同じことやる

  //B()を呼んだことで,何をしたことになるのか,を同じようにここに書く

  ...
}
のように,適宜注釈文としてメモを残していけばよいのではないでしょうか.
(簡単な図ならAAで記述する勢いで.それじゃとても済まないようなら別途紙に書いてみるとかする)

Re: 【悩み】コードの流れを把握できません

Posted: 2014年9月17日(水) 10:43
by softya(ソフト屋)
MoonGateさんの言われるように紙などに整理する自分なりの良い方法を見つけると良いと思われます。
あと、頭の中にコードを全容を把握できる出来る人のコードはすごく汚い場合も多いので、自分のわかりやすくすることで他人にもわかりやすコードを書く習慣を作りやすいとも言えます。

Re: 【悩み】コードの流れを把握できません

Posted: 2014年9月17日(水) 19:06
by ISLe()
短期記憶(ワーキングメモリ)が弱いということなら、クロスワードパズルとかをたくさん解くと鍛えられるのではないでしょうか。
脳トレはけっこうむかしからありますが、ワーキングメモリはちかごろ特に取り上げられることが多くなっていると思います。

rupin13 さんが書きました:例えば、関数A, B, C があり、Aの中でBを、Bの中でCを呼び出すとき、
Aから順にコードを読み進め関数Cに達した時点で、関数Aの中で行っていた処理が
何であったのかを忘れてしまいます。
それは何か問題があるのでしょうか。
わたしも関数Cを追っているあいだに関数Aのことも関数Bのことも忘れてしまうと思います。
むしろ意図的に忘れるようにしてますけど。
rupin13 さんが書きました:会話の中で「Aの中でBを呼んで、処理結果がこうだからCの引数に渡して…」と言われると
すぐに分からなくなってしまいます。
おそらく関数のネストの問題ではなくて、引数の入れ物に注意が向いているせいではないですかね。

関数原型は宣言を見れば分かるので覚えておく必要はないですよね。
その会話で覚える必要があるのは「Aの中でB→Cの順に呼ぶ」ということだけではないでしょうか。

ちょうど他のトピックで構造化の話題が進行中ですが、細かい部分が気になり過ぎて脳内で抽象化ができていないのだと思います。
いくら複雑な分岐でも、分岐はひとつの処理とみなせます。
コードを追っているときに他の分岐点で呼び出されている関数の中身を気にする必要なんてありません。


わたしもC言語を覚えて数年目あたりでちょっと大きなプログラムを作るようになったとき同じようなことがありました。
けっきょく、気にしないように気を付ける、ことを常に心掛けるという対処しかできませんでしたけど。
しはらくしたら、目の前の関数(で使っている定義含む)以外は覚えてなくてもプログラミングできるようになりました。

Re: 【悩み】コードの流れを把握できません

Posted: 2014年9月18日(木) 09:10
by ookami
以下あくまで自分ルールの主観で書かせていただきますが、何かしらご参考になれば幸いです。

私は、
 ・コメント行は2~5行ずつ固めて書く[1]
 ・[1]の固まりに対応するソース行数は[1]の3倍程度 (つまり6~15行程度)
 ・コメントの文脈がネストをまたがない
と決めています。
以下の例は、{コメント,ソース}が、{3,9}行、{2,6}行の例です。

コード:

void 関数() {

	// なになにをする関数。まず何を何して何する。
	// つぎに...とする。
	// これはxxxを考慮するためである ←単に挙動だけでなく、「意図」を書くのも大事
	
	int xxxx;
	xxxxxxx();

	xxx=xxxxxxx();
	xxxxxxx();
	xxxxxxx();
	for(xxx=xxx;xxx<xxx;xxx) {
		xxxxxxx();
		xxxxxxx();
	}

	// 最後に、xxxの場合はxxx、
	// xxxの場合はxxxを実施する。

	if(!xxxxxx()){
		xxxxxxx();
	}
	if(xxx<=xxx && xxx<=xxx){
		xxxxxxx();
	}
	
}
こうすることで、
 ・単なる命令の羅列ではなく、流れや意図を把握しやすくなる
 ・文字色にまとまりができるので、目がチカチカしない(笑)
などの効果があります。

逆に、ソース1行ごとにコメント1行、に近いことをやると以下のようになります。
情報量は同じですが、乱雑に感じます。

コード:

void 関数() {

	// なになにをする関数。まず何を何して何する。
	int xxxx;
	xxxxxxx();

	// つぎに...する。
	xxx=xxxxxxx();

	// xxの処理を行うことでxxxxとする。xxxのためである。    ←意図も書いてはいるけど、他のコメント行との見た目の差異がない。
	xxxxxxx();

	// つぎに...する。
	xxxxxxx();
	
	// xxxxxxを繰り返し...
	for(xxx=xxx;xxx<xxx;xxx) {
		// xxxにする。            ←コメントの文脈がネストをまたぐ。
		xxxxxxx();
		// xxxにする。
		xxxxxxx();
	}

	// 最後に、xxxの場合は...
	if(!xxxxxx()){
		// xxxを実施する。            ←コメントの文脈がネストをまたぐ。
		xxxxxxx();
	}

	// またxxxの場合は...
	if(!xxxxxx()){
		// xxxを実施する。            ←コメントの文脈がネストをまたぐ。
		xxxxxxx();
	}
}
というか自分のルールを決めることが大事ですね。
逆に自分にとって読みやすいソースを見つけたら、どうして読みやすいのか観察する、とかでしょうか。