どの様な処理を関数化するかについて
どの様な処理を関数化するかについて
こんにちは。
私は今テトリスを作っていまして、ふとコーディングで疑問に思った事を質問したいと思います。
テトリスに限らず一般的な場合ですが、あるプログラムの中で一度しか行わない処理を関数にする意味はあるのでしょうか。
今後そのプログラムを改良していった時に、その処理を別の所で使う可能性があるかもしれないなら、念の為にそれを関数化しておく事は良いと私は思います。
ただ、その様な可能性が全く予測できない時に、とりあえず何もかも関数化してしまう事は避けた方が良いのでしょうか。
私は今テトリスを作っていまして、ふとコーディングで疑問に思った事を質問したいと思います。
テトリスに限らず一般的な場合ですが、あるプログラムの中で一度しか行わない処理を関数にする意味はあるのでしょうか。
今後そのプログラムを改良していった時に、その処理を別の所で使う可能性があるかもしれないなら、念の為にそれを関数化しておく事は良いと私は思います。
ただ、その様な可能性が全く予測できない時に、とりあえず何もかも関数化してしまう事は避けた方が良いのでしょうか。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: どの様な処理を関数化するかについて
そういう場合は、その方が分かりやすいか、コードが簡潔になるか、そのコードが探しやすいかで決めれば良いと思います。
例えば初期化ですが、関数にまとめた方が明確になるし修正箇所も探しやすくなります。
WinMainに沢山コードがあるようなら関数分けが必要なコードと言えると思います。
例えば初期化ですが、関数にまとめた方が明確になるし修正箇所も探しやすくなります。
WinMainに沢山コードがあるようなら関数分けが必要なコードと言えると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: どの様な処理を関数化するかについて
これは個々人の趣味が出るかもしれませんが、私は一回しか使わない処理でもそれが一つの機能を成していれば関数化します。確かCプログラミング診断室という書籍だったかと思うのですが、
「main関数に処理は書くな」
という一文が有り、エラく納得してそれ以降main関数の中に処理は書かないように心がけています。
というか、mainも一つの関数なワケですから、
「関数は出来るだけ単機能に」
という大原則を守っていれば、main関数の本来の機能以外の機能をバカバカと入れるのはおかしな気がすると思うのです。
「main関数に処理は書くな」
という一文が有り、エラく納得してそれ以降main関数の中に処理は書かないように心がけています。
というか、mainも一つの関数なワケですから、
「関数は出来るだけ単機能に」
という大原則を守っていれば、main関数の本来の機能以外の機能をバカバカと入れるのはおかしな気がすると思うのです。
Re: どの様な処理を関数化するかについて
昔、1つの関数は1ページに収まるように書けと誰からか言われました。昔の、ラインプリンター頃の話です。1ページっていうと、
何行だったかなぁ?横は136文字ぐらいだったかな?ラインプリンターなんて知らないだろうなぁ。
何行だったかなぁ?横は136文字ぐらいだったかな?ラインプリンターなんて知らないだろうなぁ。
non
Re: どの様な処理を関数化するかについて
皆さんの回答を見ていると、見やすさが大切だと思いました。
所で、ファイルを分割する場合がありますが、これはどの様な場合に行うのが最良でしょうか。
関数1つ1つで分けていればファイルが多くなりますし、メイン関数と自作関数の2つで分けるなら、ファイル分割の意味も薄れると私は思うのです。
所で、ファイルを分割する場合がありますが、これはどの様な場合に行うのが最良でしょうか。
関数1つ1つで分けていればファイルが多くなりますし、メイン関数と自作関数の2つで分けるなら、ファイル分割の意味も薄れると私は思うのです。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: どの様な処理を関数化するかについて
機能単位で分けることが重要です。
テトリスだとあまり分けるところが無いですが、アクションゲームならステージ関連、敵の処理、プレーヤーの処理などの単位で分けることができます。
Dixq(管理人)さんの龍神録も機能単位で分けられていますので参考にしてください。
「龍神録プログラミングの館」
http://dixq.net/rp/
ついでに私のRPG講座も。
「マイ 日記 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&sd=a&c=2
テトリスだとあまり分けるところが無いですが、アクションゲームならステージ関連、敵の処理、プレーヤーの処理などの単位で分けることができます。
Dixq(管理人)さんの龍神録も機能単位で分けられていますので参考にしてください。
「龍神録プログラミングの館」
http://dixq.net/rp/
ついでに私のRPG講座も。
「マイ 日記 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&sd=a&c=2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: どの様な処理を関数化するかについて
迷った時は他人の目線で考えてみるといいかもしれません。そのプログラムに他人が手を加えるといったときに、Zisaku1.cpp、Zisaku2.cpp、Zisaku3.cppのどこかにステージ処理を入れてるのとStage.cpp、Block.cpp、GameLogic.cppのStage.cppにステージ処理が入ってるの、他人からしたらどちらがしっくりくるかとかですね。
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 14年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: どの様な処理を関数化するかについて
> あるプログラムの中で一度しか行わない処理を関数にする意味はあるのでしょうか。
関数化の利点は、複数の処理をまとめるだけではありません。
コードの可読性を上げる意味もあります。
例えば
こんなコードがあったとしましょう。
set関数はdatに何か代入するものなんだろうな・・とは想像できますが、具体的に中で何が行われているか想像できないですよね。
実はset関数はこんな実装だったんです。
これは引数の順番を完全に理解していなくては使えませんし、一つ入れ間違うとバグの元になります。
一方main関数が以下のように書かれていたらどうでしょう。
今度は、関数名を見れば、何が行われているか想像できますね。
・角度をセット
・スピードをセット
・座標をセット
という処理が行われていそうです。
関数の定義内容を見てみると
恐らく想像できた通りの定義になっているかと思います。
ステップ数は増えてしまいましたが、コードの可読性は上がりました。
この辺はトレードオフで、自分の裁量で決めると良いでしょう。
私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
一つの関数の中でやってることが複数あったり、
関数名から内部が把握できなかったりしていると、恐らく物語を読んでいるようにはならなくなることでしょう。
コーディングスタイルとして「1行になってもいいからとにかく関数化しろ」と提案している人もいる位です。
行っていることが分けられれば、とにかく関数化していっても問題無いでしょう。
書いているうちにどの程度で関数化すればいいかは分かってくると思います。
受け売りではありますが、「自分のコードは物語になっているか」を確認しながらコーディングしてみてはいかがでしょうか。
関数化の利点は、複数の処理をまとめるだけではありません。
コードの可読性を上げる意味もあります。
例えば
こんなコードがあったとしましょう。
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関数が以下のように書かれていたらどうでしょう。
今度は、関数名を見れば、何が行われているか想像できますね。
・角度をセット
・スピードをセット
・座標をセット
という処理が行われていそうです。
関数の定義内容を見てみると
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行になってもいいからとにかく関数化しろ」と提案している人もいる位です。
行っていることが分けられれば、とにかく関数化していっても問題無いでしょう。
書いているうちにどの程度で関数化すればいいかは分かってくると思います。
受け売りではありますが、「自分のコードは物語になっているか」を確認しながらコーディングしてみてはいかがでしょうか。
Re: どの様な処理を関数化するかについて
関数は何かを行う道具だと思うと、関数の集まったファイルは道具箱の様に感じました。softya(ソフト屋) さんが書きました: 機能単位で分けることが重要です。
一つの道具箱に全ての道具を入れてしまうと探すのも大変ですね。
非常に面白いと思いました。Dixq (管理人) さんが書きました: 私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
プログラムを本にすればすらすら読める、と言う事ですね。
Re: どの様な処理を関数化するかについて
美しいコードにはコメントが必要ないのですよ。Fimbul さんが書きました:非常に面白いと思いました。Dixq (管理人) さんが書きました: 私がプログラマーの先輩から教わったことは
「コードは物語をかくように書け」
です。
プログラムを本にすればすらすら読める、と言う事ですね。
他人からコメントを書けと言われるうちはまだまだだと言うことですね。
Re: どの様な処理を関数化するかについて
再度話が変わります。スレッドを乱立する事は避けたいのでこの場で質問します。
ヘッダーファイルの中で他のヘッダーファイルをインクルードすると可読性が下がるので避けたいのです。
例えば
main.cpp
の様なメインルーチンの書かれているファイルで
set_module.h
get_module.h
の様な2つのヘッダをインクルードするとします。対応するソースファイルは
set_module.cpp
get_module.cpp
とします。
2つのヘッダの中には
void setValue(int nValue);
int getValue(void);
の様な2つの関数が対応して定義されているとします。このままなら問題は無いのですが
の様な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
とすれば、ヘッダの中でヘッダをインクルードする事は避けられますが、ファイル分割が出来なくなってしまいます。
上記の様な場合で、ヘッダの中でヘッダをインクルードすることなくファイル分割をする方法はあるのでしょうか。
ヘッダーファイルの中で他のヘッダーファイルをインクルードすると可読性が下がるので避けたいのです。
例えば
main.cpp
の様なメインルーチンの書かれているファイルで
set_module.h
get_module.h
の様な2つのヘッダをインクルードするとします。対応するソースファイルは
set_module.cpp
get_module.cpp
とします。
2つのヘッダの中には
void setValue(int nValue);
int getValue(void);
の様な2つの関数が対応して定義されているとします。このままなら問題は無いのですが
の様な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
とすれば、ヘッダの中でヘッダをインクルードする事は避けられますが、ファイル分割が出来なくなってしまいます。
上記の様な場合で、ヘッダの中でヘッダをインクルードすることなくファイル分割をする方法はあるのでしょうか。
Re: どの様な処理を関数化するかについて
// 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: どの様な処理を関数化するかについて
3重にインクルードでもしない限り可読性が下がると思えません。
わたしなら、
set_module.h
get_module.h
で、各々インクルードすると思います。
わたしなら、
set_module.h
get_module.h
で、各々インクルードすると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: どの様な処理を関数化するかについて
ありがとうございます。こんな単純な事に気づきませんでした(笑)。たいちう さんが書きました: ソースファイルでのインクルード順を注意することで解決できます。
私だったらヘッダーファイルからインクルードすることに抵抗はありません。
ヘッダでヘッダをインクルードする事は普通にあるんですね。
コーディング方法と言えば良いのか、ゲームプログラミングにおいてのファイル、関数の分け方の書籍があればほしいところです。
綺麗に分割する事があまり出来ていない様な気がしているので・・・。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: どの様な処理を関数化するかについて
ゲームプログラミングでもアプリプログラミングでも基本は同じです。
ファイル=モジュールと考えて分割がちゃんとできていれば機能的なプログラミングになります。
参考にしてください。
「モジュールの強度と結合度<システムの調達<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
ファイル=モジュールと考えて分割がちゃんとできていれば機能的なプログラミングになります。
参考にしてください。
「モジュールの強度と結合度<システムの調達<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(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。