質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

6回答

5012閲覧

データメンバが増えすぎたクラスのリファクタリングについて

ai2playgame

総合スコア15

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2019/02/23 15:44

編集2019/02/23 15:44

C++タグをつけさせてもらいましたが、プログラミング全体に関わる設計に関しての質問です。

例えば、Playerクラスを作成しようと思った時、攻撃力、防御力、HP、経験値、誕生日などなど……複雑な仕様を盛り込むことになりました。

この時、攻撃力、防御力、HPを一つのStatusクラスにまとめたりなどするして、Playerクラスのデータメンバを減らす工夫をすることになるでしょう。

ですが、Playerクラスは仕様上、沢山のデータを持つ必要があります。これが3,4クラス以内に纏められるのなら良いのですが、それ以上となると、メンバ初期化の為のコンストラクタの引数が、バカみたいに多くなってしまいます。

こういった時、皆さんならどのようにリファクタリングするでしょうか?是非、教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ですが、Playerクラスは仕様上、沢山のデータを持つ必要があります。これが3,4クラス以内に纏められるのなら良いのですが、それ以上となると、メンバ初期化の為のコンストラクタの引数が、バカみたいに多くなってしまいます。

N個メンバ変数があってコンストラクタの引数がN個であるとき、

// 長方形 class rect { int x0, y0; // 左上隅の座標 int x1, y1; // 右上隅の座標 public: rect(int x0, int y0, int x1, int y1); ... }; rect r(1,2,3,4); // 4個

これを纏めたところで

class point { int x,y; public: point(int x, int y); }; // 長方形 class rect { point topleft; // 左上隅の座標 point rightbottom; // 右上隅の座標 public: rect(point topleft, poiny rightbottom); ... } ... rect(point(1,2), point(3,4)); // やっぱり4個

初期化にはやっぱりN個の引数が必要でしょ?
何か問題ですか?

投稿2019/02/23 18:15

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずリファクタリングという観点であれば、クラス図などにした上で、具体的にアプローチし、範囲を限定して、特定のパターンで行うと思います。仮定の話では難しいと思います。

というのをふまえた上で、戦闘用のパラメータもあれば、生産用のパラメータ用もあれば、トレード用のパラメータもあるでしょう。目的ごとに可搬性のいいパラメータにしておけば後で受け渡しも楽でしょうから、そのように小分けにします。

構築時はCompositeなものであれば、メンバに入れて、プレイヤーオブジェクトが作成されるときにそのまま構築します。そうでなければ後からattach/setするような作りにします。プレイヤーやパラメータが汎化できるようなものであれば、Factoryパターンかそれ系の仕組みを持たせます。本当に種類が多ければDIまで作るかもしれません。

いずれにしても、パラメータの数についてはあまり気にしません。目的や用途に応じて、使いやすい構成にするだけです。パラメータの数が多くなった/クラスの種類が多くなったときは、またそれぞれ工夫していきますが、それらは原則ケースバイケースです。既存のデザインパターンで効果的な場合もあるし、そうでない場合もあります。

投稿2019/02/23 18:58

wwbQzhMkhhgEmhU

総合スコア343

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

Playerクラスは仕様上、沢山のデータを持つ必要があります。

であれば、そのままたくさんのデータ・メンバを持つのも有りと思います。無理してデータ・メンバを纏める必要はないでしょう。纒めたほうが好ましいメンバのみ纏めるべきかと。

コンストラクタが問題ということですが、その多数のデータ・メンバの初期化元のデータはどこから取ってくるのでしょうか? 一般にはハード・コーディングではなく何か設定ファイルで設定することの方が多いように感じます。(多数の初期値を調整するたびにビルドするのはあまり現実的ではないケースが少なくないですから。)
コンストラクタでは小数の重要な値のみをパラメータとし、他の値はその重要な値に応じて設定ファイルから読み出すのがスマートな設計のように思います。そのような設計ならデータ・メンバの数が種別(class)によって異なっても、使う側は大差ない記述ができますし。(ファクトリー・パターンを使って全く同じにすることもできますね。)

それらのデータ群をファイルやデータ・ベースへ保存・回復するような機能も必要になるのではないでしょうか? その回復処理と初期化処理を共通化することも視野に入ると思います。

投稿2019/02/23 16:23

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

... メンバ初期化の為のコンストラクタの引数が、バカみたいに多くなってしまいます。 ...

1. default 引数を設定する。

2. builder パターンを検討する。
参考

  • なんぞこれ。コンストラクタパラメータが異常に大杉る・・・。バカなの?死ぬの?そういう場合はBuilderパターンを検討してみよう。

http://zecl.hatenablog.com/entry/20091117/p1

  • 生成に関するパターン Builder

https://fa11enprince.hatenablog.com/entry/2014/05/07/011000

投稿2019/02/24 08:53

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

他の方の回答とかぶっているところが多いですが、以下のような感じにすると思います。

  • コンストラクタとは別に初期化メソッドを作成する。
  • 初期化メソッドに渡す引数を最小限にする。
  • メンバ変数の初期化処理もファクトリーパターンメソッドに分ける。
  • 初期化時の値が決まっているパラメータは外部ファイルから読み込む。

例:

C++

1class Player 2{ 3private: 4 // 位置座標 5 int posion_x; 6 int posion_y; 7 8 // ステータス 9 Status status; 10 11public: 12 // コンストラクタ 13 Player() 14 { 15 // ここで重い処理はしない 16 } 17 18 // 初期化メソッド(引数は最小限にする) 19 void Initialize(int posion_x, int posion_y) 20 { 21 this->posion_x = posion_x; 22 this->posion_y = posion_y; 23 this->status = Factory::CreatePlayerStatus(); 24 } 25};

投稿2019/02/24 00:49

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

リファクタリングじゃないので、回答になってないかも知れませんが、、、

初期化済みのオブジェクトを用意し、そのコピーを作成するようにする、、ではだめでしょうか?
ゲームだったら、戦士系とか、魔法系とか、、の主要なものを用意する。

投稿2019/02/23 15:59

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問