どの様な処理を関数化するかについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Fimbul

どの様な処理を関数化するかについて

#1

投稿記事 by Fimbul » 14年前

こんにちは。
私は今テトリスを作っていまして、ふとコーディングで疑問に思った事を質問したいと思います。

テトリスに限らず一般的な場合ですが、あるプログラムの中で一度しか行わない処理を関数にする意味はあるのでしょうか。
今後そのプログラムを改良していった時に、その処理を別の所で使う可能性があるかもしれないなら、念の為にそれを関数化しておく事は良いと私は思います。
ただ、その様な可能性が全く予測できない時に、とりあえず何もかも関数化してしまう事は避けた方が良いのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: どの様な処理を関数化するかについて

#2

投稿記事 by softya(ソフト屋) » 14年前

そういう場合は、その方が分かりやすいか、コードが簡潔になるか、そのコードが探しやすいかで決めれば良いと思います。
例えば初期化ですが、関数にまとめた方が明確になるし修正箇所も探しやすくなります。
WinMainに沢山コードがあるようなら関数分けが必要なコードと言えると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
ゆーずぃ
記事: 62
登録日時: 14年前
住所: 埼玉県

Re: どの様な処理を関数化するかについて

#3

投稿記事 by ゆーずぃ » 14年前

これは個々人の趣味が出るかもしれませんが、私は一回しか使わない処理でもそれが一つの機能を成していれば関数化します。確かCプログラミング診断室という書籍だったかと思うのですが、

「main関数に処理は書くな」

という一文が有り、エラく納得してそれ以降main関数の中に処理は書かないように心がけています。

というか、mainも一つの関数なワケですから、

「関数は出来るだけ単機能に」

という大原則を守っていれば、main関数の本来の機能以外の機能をバカバカと入れるのはおかしな気がすると思うのです。

non
記事: 1097
登録日時: 14年前

Re: どの様な処理を関数化するかについて

#4

投稿記事 by non » 14年前

昔、1つの関数は1ページに収まるように書けと誰からか言われました。昔の、ラインプリンター頃の話です。1ページっていうと、
何行だったかなぁ?横は136文字ぐらいだったかな?ラインプリンターなんて知らないだろうなぁ。
non

Fimbul

Re: どの様な処理を関数化するかについて

#5

投稿記事 by Fimbul » 14年前

皆さんの回答を見ていると、見やすさが大切だと思いました。

所で、ファイルを分割する場合がありますが、これはどの様な場合に行うのが最良でしょうか。
関数1つ1つで分けていればファイルが多くなりますし、メイン関数と自作関数の2つで分けるなら、ファイル分割の意味も薄れると私は思うのです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: どの様な処理を関数化するかについて

#6

投稿記事 by softya(ソフト屋) » 14年前

機能単位で分けることが重要です。
テトリスだとあまり分けるところが無いですが、アクションゲームならステージ関連、敵の処理、プレーヤーの処理などの単位で分けることができます。

Dixq(管理人)さんの龍神録も機能単位で分けられていますので参考にしてください。
「龍神録プログラミングの館」
http://dixq.net/rp/

ついでに私のRPG講座も。
「マイ 日記 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&sd=a&c=2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
ゆーずぃ
記事: 62
登録日時: 14年前
住所: 埼玉県

Re: どの様な処理を関数化するかについて

#7

投稿記事 by ゆーずぃ » 14年前

迷った時は他人の目線で考えてみるといいかもしれません。そのプログラムに他人が手を加えるといったときに、Zisaku1.cpp、Zisaku2.cpp、Zisaku3.cppのどこかにステージ処理を入れてるのとStage.cpp、Block.cpp、GameLogic.cppのStage.cppにステージ処理が入ってるの、他人からしたらどちらがしっくりくるかとかですね。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: どの様な処理を関数化するかについて

#8

投稿記事 by Dixq (管理人) » 14年前

> あるプログラムの中で一度しか行わない処理を関数にする意味はあるのでしょうか。

関数化の利点は、複数の処理をまとめるだけではありません。
コードの可読性を上げる意味もあります。
例えば

コード:

int main(){
	dat_t dat;
	set(&dat, 0.0, 1.0, 10, 20);
}
こんなコードがあったとしましょう。
set関数はdatに何か代入するものなんだろうな・・とは想像できますが、具体的に中で何が行われているか想像できないですよね。
実はset関数はこんな実装だったんです。

コード:

void set( dat_t *dat, double angle, double speed, int x, int y ){
	dat->angle = andle;
	dat->speed = speed;
	dat->x = x;
	dat->y = y;
}
これは引数の順番を完全に理解していなくては使えませんし、一つ入れ間違うとバグの元になります。
一方main関数が以下のように書かれていたらどうでしょう。

コード:

int main(){
	dat_t dat;
	set_angle(&dat, 0.0);
	set_speed(&dat, 1.0);
	set_pos  (&dat, 10, 20);
}
今度は、関数名を見れば、何が行われているか想像できますね。
・角度をセット
・スピードをセット
・座標をセット
という処理が行われていそうです。
関数の定義内容を見てみると

コード:

void set_andle( dat_t *dat, double angle ){
	dat->angle = andle;
}

void set_speed( dat_t *dat, double speed ){
	dat->speed = speed;
}

void set_pos( dat_t *dat, int x, int y ){
	dat->x = x;
	dat->y = y;
}
恐らく想像できた通りの定義になっているかと思います。
ステップ数は増えてしまいましたが、コードの可読性は上がりました。
この辺はトレードオフで、自分の裁量で決めると良いでしょう。

私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
一つの関数の中でやってることが複数あったり、
関数名から内部が把握できなかったりしていると、恐らく物語を読んでいるようにはならなくなることでしょう。

コーディングスタイルとして「1行になってもいいからとにかく関数化しろ」と提案している人もいる位です。
行っていることが分けられれば、とにかく関数化していっても問題無いでしょう。
書いているうちにどの程度で関数化すればいいかは分かってくると思います。

受け売りではありますが、「自分のコードは物語になっているか」を確認しながらコーディングしてみてはいかがでしょうか。

Fimbul

Re: どの様な処理を関数化するかについて

#9

投稿記事 by Fimbul » 14年前

softya(ソフト屋) さんが書きました: 機能単位で分けることが重要です。
関数は何かを行う道具だと思うと、関数の集まったファイルは道具箱の様に感じました。
一つの道具箱に全ての道具を入れてしまうと探すのも大変ですね。
Dixq (管理人) さんが書きました: 私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
非常に面白いと思いました。
プログラムを本にすればすらすら読める、と言う事ですね。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: どの様な処理を関数化するかについて

#10

投稿記事 by ISLe » 14年前

Fimbul さんが書きました:
Dixq (管理人) さんが書きました: 私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
非常に面白いと思いました。
プログラムを本にすればすらすら読める、と言う事ですね。
美しいコードにはコメントが必要ないのですよ。
他人からコメントを書けと言われるうちはまだまだだと言うことですね。

Fimbul

Re: どの様な処理を関数化するかについて

#11

投稿記事 by Fimbul » 14年前

再度話が変わります。スレッドを乱立する事は避けたいのでこの場で質問します。

ヘッダーファイルの中で他のヘッダーファイルをインクルードすると可読性が下がるので避けたいのです。
例えば

main.cpp

の様なメインルーチンの書かれているファイルで

set_module.h
get_module.h

の様な2つのヘッダをインクルードするとします。対応するソースファイルは

set_module.cpp
get_module.cpp

とします。
2つのヘッダの中には

void setValue(int nValue);
int getValue(void);

の様な2つの関数が対応して定義されているとします。このままなら問題は無いのですが

コード:

typedef struct tagSIZE {
	int nWidth;
	int nHeight;
} SIZE;
の様なSIZE型を定義した場合で、2つのヘッダの中に新しく

void setSIZE(SIZE *size);
SIZE *getSIZE(void);

の様な関数を対応させて定義します。
SIZE型をどこかで定義しないとエラーになりますので、とりあえずset_module.hの方で定義したとします。
しかし、そうしますとget_module.hにはSIZE型は見えていないので、エラーになります。
それならばと、両方のヘッダで定義すると多重定義でエラーになります。
そこで

commom.h

の様なヘッダを新規作成しこの中にSIZE型を定義します。
このヘッダをset_module.hとget_module.hの中でインクルードすればエラーは出ません。
ですが、ヘッダの中でヘッダをインクルードしなければなりません。
set_module.cppとget_module.cppの関数を

set_get_module.cpp

の様なソースファイルにまとめて定義し対応するヘッダを

set_get_module.h

とすれば、ヘッダの中でヘッダをインクルードする事は避けられますが、ファイル分割が出来なくなってしまいます。
上記の様な場合で、ヘッダの中でヘッダをインクルードすることなくファイル分割をする方法はあるのでしょうか。

たいちう
記事: 418
登録日時: 14年前

Re: どの様な処理を関数化するかについて

#12

投稿記事 by たいちう » 14年前

コード:

// main.cpp
#include "commom.h"
#include "set_module.h"
#include "get_module.h"
...

// set_module.cpp
#include "commom.h"
#include "set_module.h"
...

// get_module.cpp
#include "commom.h"
#include "get_module.h"
...
ソースファイルでのインクルード順を注意することで解決できます。

> ヘッダーファイルの中で他のヘッダーファイルをインクルードすると可読性が下がるので避けたいのです。

可読性の良し悪しは評価する人によっても変わります。
私だったらヘッダーファイルからインクルードすることに抵抗はありません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: どの様な処理を関数化するかについて

#13

投稿記事 by softya(ソフト屋) » 14年前

3重にインクルードでもしない限り可読性が下がると思えません。
わたしなら、
set_module.h
get_module.h
で、各々インクルードすると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Fimbul

Re: どの様な処理を関数化するかについて

#14

投稿記事 by Fimbul » 14年前

たいちう さんが書きました: ソースファイルでのインクルード順を注意することで解決できます。
私だったらヘッダーファイルからインクルードすることに抵抗はありません。
ありがとうございます。こんな単純な事に気づきませんでした(笑)。

ヘッダでヘッダをインクルードする事は普通にあるんですね。

コーディング方法と言えば良いのか、ゲームプログラミングにおいてのファイル、関数の分け方の書籍があればほしいところです。
綺麗に分割する事があまり出来ていない様な気がしているので・・・。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: どの様な処理を関数化するかについて

#15

投稿記事 by softya(ソフト屋) » 14年前

ゲームプログラミングでもアプリプログラミングでも基本は同じです。
ファイル=モジュールと考えて分割がちゃんとできていれば機能的なプログラミングになります。

参考にしてください。

「モジュールの強度と結合度<システムの調達<Web教材<木暮」
http://www.kogures.com/hitoshi/webtext/ ... index.html
「目から鱗が落ちるように分かるプログラミング講座 モジュール化の概念 エスエムジー株式会社 SMG」
http://www.smg.co.jp/~toyo/Program/index18.html
「モジュール分割 - 【programming.org】」
http://www.pc-programming.org/program_mojyuru.html
「ソフトウェア設計」 PDF
http://www.info.shonan-it.ac.jp/lecture ... eng1-4.pdf
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Fimbul

Re: どの様な処理を関数化するかについて

#16

投稿記事 by Fimbul » 14年前

サイトを閲覧しました。
抽象的な話で掴み辛かったですが、何とかものにしたいと思います。
皆さん長々とありがとうございました。

Fimbul

Re: どの様な処理を関数化するかについて

#17

投稿記事 by Fimbul » 14年前

解決のボタンをチェックし損ねました。

閉鎖

“C言語何でも質問掲示板” へ戻る