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

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

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

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

2272閲覧

【Unity】クラス設計に違和感があるのでアドバイスが欲しい。

masatopia009

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

1グッド

2クリップ

投稿2022/03/15 05:36

編集2022/03/15 08:23

前書き

はじめてテラテイルを利用する者です。質問の仕方に不備があったらすみません。

質問への導入

現状を大雑把に書くと、Unityでゲームを作っていて、途中からクラス設計というものを知り書き直してみたものの、しっくり来ない/直感に反する、という感じです。リズムゲームを制作中なので、それを基に話します(一部改変)。

全てのクラスはMonoBehaviorを継承しているとします。

質問に登場するクラスは、わかりにくいかもしれませんが図を添えています。良ければ参考にしてください。

イメージ説明

上下関係をつけてみた

昔、Javaの講義でクラスを階層構造のようにしていたのを思い出し、Unityで良くある〇〇Managerクラス等は上層。ゲームを構成するNote(ノーツにアタッチ)クラス等は下層として、現在制作中のコードを書き直しました。

Noteクラスの工夫

ノーツは大量に生成される故になるべくフィールドを持ちたく無いので、ノーツ間で共通の値はNoteInfoクラスにまとめる事にしました。これでNoteはNoteInfoの参照を持っていればOKです。(ゲーム実行後に確定する値もあります)

NoteInfoの中身

ノーツを動かす処理(Noteクラス)では、「合計3つのクラス」が保持する値が必要です。NoteInfoクラスではその3クラスへの参照を格納しており、Noteクラスはこの3つの参照を適宜取得して必要な値を得る仕組みです。

違和感

NoteInfoクラスが参照する3つのクラスは、Noteだけでなく他の色々なクラスでも必要です。つまりその3クラスは全体に関わる情報ということです。しかし、冷静に考えてみると違和感があります。それは、全体に関わるクラスが下層に来ていることです。

上下関係と捉えるのが間違い?

パフォーマンスとコードの質はトレードオフと何処かで聞いた覚えがあります。

という事は「Noteにはフィールドをたくさん持たせたく無い」というパフォーマンス重視の状況が、コードの質(今回で言えばクラスの上下関係)を狂わせているのではないかと考えました。

質問

この違和感はどう克服すれば良いのでしょうか。クラス設計はケースバイケースとも聞くので「上下関係という認識を捨てる」のも選択肢なのでしょうか。はたまた私が知らない「もっといい方法がある」のでしょうか。アドバイスを頂きたいです。

※なるべく誤解の無いように詳しく書いたところ、かなりの長文になってしまいました。ここまでお読みいただきありがとうございます。ここに書かれていない事情もあるのですが、それを書き始めるととんでもなく長くなるので、適宜お伝えします。

追記・修正について

ご依頼ありがとうございます。

【上下関係について】
上下関係というのはhas-a関係や規模の大小などで決めています。基本はhas-aで決めていこうと心に誓っていたものの、複数のクラスが共通して1つのものを持ってる場合等、よくわからなくなった時は、規模で決めています。

とはいえ、実体があるものとないものが混在しているため、何をもって規模が大きいかは感覚で決めています。そのため、具体的な意味は上記のような曖昧な基準となります。

例えば車と法律の規模を比べてと言われたら、そもそも比べるのが間違いかもしれませんが、「法律>車」という事がイメージされます。

上下関係はこれくらい曖昧です。なので「上下関係と捉えるのが間違い?」という項目で、そもそも上下関係なんて付けるから、感覚に反する構造になるのでは?という事を語るつもりだったのですが、忘れていました。言葉足らずとなってしまいすみません。

【違和感について】
これは「困っているけど質問が言語化できない」という段階から何とか言語化した質問になります。「違和感」というのは何故困っているのかを言語化した時に最も現状に当てはまる表現だったので使いました。しかし、質問本体を「違和感」一語で済ませるとわかりにくかったかもしれません。すみません。

私はその違和感の正体は「全体に関わるクラスが下層に来ている」ことであると書きました。つまり、違和感の克服とは「全体に関わるクラスが下層に来ている」という状態を克服することです。

では何故「全体に関わるクラスが下層に来ている」かというと、Noteクラスがパフォーマンス重視であるため・そもそも上下関係を付ける事が間違っているため…と見当を付けています。

なので質問本体を書き換えるなら、
「全体に関わるクラスが下層に来ている原因は上記の通りですが、上下関係という認識を捨てるべきなのでしょうか?それとも私の知らない方法があって、それを使えば解決できるのでしょうか?みなさんの経験から考えて、どのように対処すべきか教えてください。」
となると思います。

想定する回答には「上下関係という認識は捨て、具体と抽象で考える方が適切に思えます(上下関係の是非)」や「〇〇を継承するとデータだけ別の括りで管理できます(知らない方法)」のようなものを期待しています。

Bongo👍を押しています

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

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

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

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

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

ozwk

2022/03/15 06:53 編集

「上/下層」や「上下関係」はどういう意味で使っていますか?
fana

2022/03/15 06:51

問題点が「違和感」というのでは, teratailが「推奨していない質問」としている「問題・課題が含まれていない」に該当するとも見えます.
guest

回答2

0

ベストアンサー

1初心者の感覚ですが……
「層」って言われたらもっと違う物(例えばMVCがどうのとかそういうの?)をイメージします.

そういう意味ではそれらの登場人物(Note, NoteInfo, 3つの何か)は特段意味のある異なる「層」に属しているような存在とも思えず,
そこに「上下」と言えるような関係をあえて考える必要もない話と思えます.


{Note, NoteInfo,3つの何か}が異なる層に存在する物だと考えるとしたら,
「Note から 3つの何か を直には触らず,NoteInfo が適切に仲介する」だとかそういう話になるように思えますが,

NoteInfoクラスではその3クラスへの参照を格納しており、Noteクラスはこの3つの参照を適宜取得して必要な値を得る仕組み

という話だと Note がダイレクトに3つの何かを用いるという話に見えるので,そういうことでもなさそうですし…

投稿2022/03/15 10:37

fana

総合スコア11658

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

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

fana

2022/03/15 10:55

これも個人的な感覚ですが, 「まず全体に関わるコアなデータがあり,それに基づいて動くような末端が複数ある」 というとき, その状況をあえて階層っぽく絵に描くとしたら,コアなデータ側の方を「下側」に置くかなぁ…? とか. (なので,何らかの上下関係と考えるとして「全体的なのが下側」ってのは私ならそれで違和感無い…のか……な?)
fana

2022/03/15 11:01

あるクラスAが自身への参照を持つ末端クラスBのオブジェクトを生成するとき,一体どっちが「上」でどっちが「下」なのか? BがAへの参照を持っているからBの方が「上」だというのか? じゃあAもBへの参照を握っているとしたら…? 同じ高さ?
fana

2022/03/15 11:23

「上下」を想像してるものを90度回して「左右」にしても同様の違和感があるのだろうか? あるいは「層」を考えるにしても コア←→末端 ならバウムクーヘンみたいなイメージの方が合ってるとか.
masatopia009

2022/03/15 11:56

回答ありがとうございます。 【1つ目のコメントについて】 層という概念があるモデルがあるんですね。私はあまり意識せずに使っていましたが、少し気をつけようと思います。 また、Noteクラスが直接3つのクラスを触るという事で合ってます。 【2つ目のコメントについて】 なるほど、コアな「データ」を下にまとめておくというのも、不自然というわけでは無いんですね。 全体を管理するクラスとしてGameManagerを良く使いますが、これは大抵上の方にあって、その下にぶら下がってるクラスを動かす等するので、全体に関するものは上の方にあるべきという先入観のようなものがありました。 【3つ目のコメントについて】 私もその疑問に至った事があります。なるべく参照は上から下へという制約でやっていたので現在は相互の参照はありませんが、そのような事態になった場合に困りますね。 上下という概念に囚われすぎるのが良く無いのかもしれません。現在の構造を言い換えるなら「一方通行」でしょうか。一旦上とか下とかを考えるのをやめるという選択肢も良さそうですね。 【最後に】 上下関係であったり、何が上で何が下であるべきかであったりに執着しすぎていたかもしれないという気づきを得られました。コアや一方通行の視点に少し考え方を変えてみようと思います。 この回答で新たな視点を持つことができました。 ありがとうございます。
fana

2022/03/15 12:01

複数の Note が同一の値を持つから~ っていうなら,その纏め方は例えば class 複数のNoteとそれらに共通する値をまとめたもの {//以下を有する ・値が同一である Note の集合 ・1つの NoteInfo void DoSomething(){ 全Noteのメソッドを引数にNoteInfoを与える形で呼ぶぜ! } } とかもあり得るように思う. これなら,Note と NoteInfo には上下関係を感じない気がする(コードの見た目に同じ場所にあるので) #まぁUnity知らんから,こういう形が「MonoBehavior がどうの」いう話と噛み合うのかわからんけども… (「Noteの集合」is MonoBehavior みたいな話だとダメなのか? とか)
masatopia009

2022/03/16 11:08

1つのクラスが両方のクラスを利用するという方法ですね。とても良さそうです。ひとりで考えてると頭が凝り固まるのでこういう意見を聞けて良かったです。 MonoBehaviorを継承するとゲーム画面上の何か(オブジェクト)にスクリプトをくっつけて座標や他のスクリプト等を操作する事ができるようになります。継承するとnewできなくなってしまうのですが、この場合はあまり気にしなくても良さそうです。
fana

2022/03/17 01:57

(多分何の参考にもならないだろう妄言) 私は > NoteはNoteInfoの参照を持って… というようなアイデアが出てきたとき,そこにとりあえず違和感みたいなのが生じるというか「本当にそうすべきかな」みたいなのを考える感じ? (未熟さ故に「そうかな? どうかな? そうかも…?」とか結構考えないと決められない感じ,というか.) 「Noteの処理(メソッド)には NoteInfo が必要だ」っていうのを,まずは素直(?)に表現するならば 「そのメソッドの引数が NoteInfo 型になってる」っていう形になるんじゃないかな,とか思うわけです. なのに(?),そこを何らかの都合のことを考えて 「コレ,Note に NoteInfo型オブジェクトへの参照を持たせとけばよくね?」って考えはじめたときには, 「でもなんか今,素直じゃない方向に向かっているような…」と,一旦思いとどまる,というか,もうちょっと考えてみる……みたいな. 【Note という存在は,「常に」前もって NoteInfo との結びつきを作っておかねば使えない存在なのだ】ということならば, コンストラクタあたりで NoteInfo への参照を突っ込んでもらって,メンバに参照値を持つので良いように思うけど, 【Note と NoteInfo の対応を前もって作っておくのが便利な「場面がある」】ということなら,そうしないでおく:そういう場所では先の例(複数のNoteとそれらに共通する値をまとめたもの)みたいなのを Note の外側で用意すればそれで済むくね?とかなんとか.
fana

2022/03/17 02:07 編集

何だろう, 「他者(:自身がnewして抱えて管理しているようなものではないやつ)への参照を長期間保持する形でしか動けないやつ」が増えていくほど複雑になって何だか嫌な感じ(というか自分の把握能力キャパを超えちゃうような感じ)がする. (もちろん,本当にその形が必要ならばそうなるんだけど)
guest

0

まず最初に、全体に関わる「合計3つのクラス」は、NoteInfo クラスと has-a 関係なのか?を確認してください。
もし has-a 関係でないのであれば、NoteInfo クラスのメンバーとして相応しくありません。

また、パフォーマンスの低下を懸念されているようですが、実際に計測されていますでしょうか?
実際にはパフォーマンスに影響ない可能性もあり、憶測でクラス設計を複雑にしてしまうのは、あまり良くないやり方のように思います。

参考:
has-a
https://ja.wikipedia.org/wiki/Has-a

投稿2022/03/15 08:17

nskydiving

総合スコア6500

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

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

masatopia009

2022/03/15 09:22

回答ありがとうございます。 【前半について】 has-aの判断が主観になってしまいますが、少なくとも1クラスはhas-a関係では無いなと感じました。改善の余地ありですね。他2つのクラスはいづれも情報(値)が格納されているだけなので、こちらはhas-a関係と言えるかもしれません。 現時点でかなりクラス数が増えているので、これ以上細分化するのは抵抗がありましたが、一旦該当の1クラスを分割し、まとめられる場所はまとめてみようと思います。 【後半について】 計測はしていません。PCの性能が周囲の人間より低いという事を前々から気にしており、Unityの動作もやや重いという環境であったため、憶測が先行してしまいました。 計測はあまり頭になかった考えでした。この回答で解決へのヒントを得られてとても嬉しく思います。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問