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

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

ただいまの
回答率

90.33%

  • Java

    14473questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • オブジェクト指向

    298questions

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

  • MVC

    236questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

ロジック処理と出力処理の分け方

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 741

mightyMask

score 63

前提

javaのswingを用いてGUIの将棋ソフトを作成しています。
ほぼ趣味プログラマーであり、プログラミング初心者です。
厳格で純粋なオブジェクト指向に近いコードで綺麗に書く事を目標とします。
そのため、早く軽快な動作は期待しません。
ソースコードを短くするという事も期待しません。

制作途中のクラスの関係

MVC(Model View Controller)の考え方に添い、3つのパッケージに分割しています。
Controller
入力制御クラス(入力から盤面クラスに指示)
View
画面出力クラス
Model
駒クラス(抽象)
歩、金、成桂などのクラス
升クラス(1つの駒クラスと、先手後手どちらの駒であるかを保持)
盤面クラス(81つの升クラスを保持)

質問

画面出力クラスが盤面クラスの情報を知り、その情報から表示する駒の画像を決める。
この処理をどうすれば良いのかどうしても思いつきません。
何かアイディアをください。

ただ実装すれば良いだけなら2通りの方法が思い浮かびましたが、どちらも良い方法ではありません。
1.盤面クラスのメソッド(引数は座標)を呼んで升クラスを返して貰えば、画面に表示させるのに必要な情報がわかる。
その情報からifかswitchを使い画像を選択する。
これは全くオブジェクト指向的ではないので問題外です。
2.駒クラスが最初に画像を読み込み保持しておく。そして盤面クラスのメソッド(引数は座標)を呼び、駒の画像を返してもらう。
この場合MVCの役割が破綻しています。

追記

目的に対して適切な手段を取るのが正解との事で、ModelとViewに分ける目的をある程度はっきりとさせておきます。
後にコンソールで動く将棋ソフトを作る際、Model部分を変更させずに再利用できる様にすると言う事が目的です。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

こんにちは。

面白い問題ですね。Stateパターンを使って駒の描画を切り替えたいけど、それではモデル側に描画処理が入ってしまいMVCから逸脱するので、何か良い案はないか?ってことですね。
スキンを切り替えた時、駒のデザインも切り替えたいような場合に実際に発生しそうな問題です。

駒のデザイン切り替えをサポートする場合、モデルがビューに依存しない構造はたいへん好ましい設計と思います。となると、2.はモデルがビューに依存するため、1.をベースに考えざる得ないと思います。
なので、そこにstateパターンを適用できないか考えるべきでしょう。

例えば、モデル側の駒クラス経由で駒オブジェクトを受け取り、駒画像を返却するような機能を持つビュー側駒クラスを考えることは可能ですね。
そして、そのビュー側駒クラスはデザイン毎に派生クラスを作りStateパターンを適用すると、デザインの拡張に対応しやすいです。
問題はその中身が駒の種類毎にifかswitchによる分岐が発生するので、当初の問題を解決できていないことです。

デザインは通常 駒にインデックス番号などを振って駒画像をテーブルで管理すると思います。駒画像のメンテナンスもそうしておかないと辛いですし。
であれば、駒オブジェクトからインデックス番号などを受け取って、そのテーブルを引いて画像を返却する構造にすれば、駒の種類が増えてもテーブルの要素を増やすだけで済み、分岐コードの改造は不要ですのでStateパターンのメリットと同様なメリットを享受できます。表の追加の方がクラス追加より手間は少ないです。そして、これはデザイン切り替えしない時にも適用できます。

しかし、このアイデアはオブジェクト指向プログラミングかというと、微妙です。
少なくともStateパターンからは外れています。また、オブジェクト指向プログラミングは配列の取扱について特別な何かを提案している手法ではありませんので、配列(表)を使うことが「厳格で純粋なオブジェクト指向」に則っているかと言うと微妙です。


【余談ですが】
では、使うべきでなはいかと言うとそうではないです。
オブジェクト指向プログラミングを使うことでメリットがある時はたいへん多いのでどしどし使うべきですが、オブジェクト指向は万能ではないので使えない時まで無理して使うのは愚かと思います。(MVCも同様です。)

オブジェクト指向プログラミングもMVCも、なんらかの目的(主にメンテナンス性や再利用性)を満たすための手段です。オブジェクト指向に拘ってメンテナンス性を劣化させては本末転倒です。「手段のために目的を選ばない」のは、学習や研究時だけに限定しておくことをお勧めします。
手段自体を学んだり研究したりすることが目的の時はもちろん手段重視でOKですし、今回のようなテーマはたいへん興味深いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/25 20:41

    となると、駒ごとのインデックス番号はModelの方の歩クラスなどで定義すると言う事ですよね。
    駒毎のインデックス番号の定義などをModel側でしてしまうと言う事は、本来Viewがするべき処理をModelがしてしまっていると言うことにはならないでしょうか。

    キャンセル

  • 2017/02/25 21:25

    駒の種類を決めるのはモデルですね。ですから駒に通し番号を振るのもモデルの仕事です。

    キャンセル

+2

Chironianさんが回答されていることにかぶっている気もしますが・・

問題はその中身が駒の種類毎にifかswitchによる分岐が発生するので、当初の問題を解決できていないことです。 

if/switchを無くしたいあるいは「金が銀の状態に変化することがないのに駒の種類をstateパターン的に捉えるのはいやだ」ということであれば、駒の種類に応じたクラスを作るという方向になると思います。

classView {
  private Image image;

  protected 駒View(Image image) {
    this.image = image;
  }

  @Override public void paintComponent(Graphics g) {
     g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
  }
}

classView extendsView {
  王View() {
    super(loadImage("王.png"));
  }
}

classView extendsView {
  王View() {
    super(loadImage("玉.png")); // 王と玉は違うから...w;
  }
}
...

さて、先手と後手で画像が180度回転させたものになる点はどうでしょうか。厳密に言えば「先手駒」「後手駒」を作ることもできますし「先手」「後手」をstateとして捉えることもできます。ここからは作りの問題にもからみますが盤面にある状態では先手・後手が変化することはありえないのでstateじゃいやだという考え方なら先手駒・後手駒のクラス分けにしてもいいのかも知れません。しかし駒が取られるとその駒の先手・後手が逆転するのだからこれはstateと考えることもできます。

前者だと駒が取られたら盤面から消えるとともに駒Viewインスタンスも消えて新たに先手後手が逆転したインスタンスを生成してそれを「駒台View」に追加なんて実装になります。一方後者なら取った駒は先手・後手のstateを変更しそのインスタンスそのものを「駒台View」に追加になるでしょう。(盤面Viewとは別に駒台Viewがあると仮定してます)if文やstateを排除して作りたいことにこだわるなら前者でしょうし、現実の動きに即したインスタンスのライフサイクルに即して作りたいと思ったら後者になるでしょう。

さらに成った時に画像が変わりますがこれはstateパターンで実装するのが自然な感覚がしますが、やはりif/switch/stateじゃいやクラス分けをして成る前の駒は消失し新たに成った状態の駒を生成してそれを盤面Viewへ配置とすることもできます。

Chironianさんもおっしゃっているように「絶対にこうしなければならない」というより「より適切な方法を適宜とる」というのがプログラミングでの心構えだと思います。より厳密にというのが「現実世界での振る舞いと極力合わせて」ということなのか「プログラム上からif/swichを排除する」ことかによって取るべき方法は変わると思いますが、自分で納得できるまで厳密に考えてみるのも面白いと思います。個人的にはif/switchを排除することより現実世界の振る舞いに似たものにすることの方が有用と感じることが多いです。また「クラスを分けて作ることはできるけど手軽だから配列とコードで違いを表現」という手もはやりよく使います。厳密なクラス分けの価値と配列ルックアップの手軽さを天秤にかけるわけですw;

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/25 13:21

    横から失礼します。
    "王View"や"玉View"のインスタンスをView側でnewする必要がありますが、View側は静的には駒の種類を保持していないため、ifやswitchで動的に判別してnewするしかないです。(一見できそうでできないんですよ。)
    と思ってましたが、すいません、これはC++思考でした。

    リフレクションを使えば動的にモデル側の型名をとれますし、それを加工してビュー側のクラス名へ変換して、そのインスタンスをたぶん作れますね。(Javaではやったことないですが、C#ではできました。)
    リフレクションは折角の型チェックをスルーするので、使わないで済む時は使わない方がよいですが。

    キャンセル

  • 2017/02/25 18:25

    おっしゃるとおりだと思います。個々のインスタンスの振る舞い自体はis-aによる関係でif/switchの排除が可能ですが、あるModelクラスとあるViewクラスの対応関係については結局のところ「王Modelなら王Viewを使う」ということをどこかに定義しなければならずそれはif/switchを書かないようにするためになんらかの連想テクニックを使ったとしてもよく考えてみるとその本質は「if」であることにはかわりないように思えます。唯一メタ情報をhas-aとしておき、

    駒View createView(駒Model km) {
     return km.getViewFactory().newInstance();
    }

    とするとif/swtich的なものを排除できる気もしますがこうやると「ModelがViewのファクトリーを返さなきゃいけなくなるなぁ・・・」という点があまり気持ちよくない気がします。メタ情報なんだから「よいではないか」という心の声も聞こえますが。

    やはりこのあたりは「このこだわりって何か意味あるのかな」となってしまいどこかで妥協することになる気がします。もっと厳密にif/switch的なものを排除する方法論があるのでしょうか・・・自分には思いつけませんw;

    キャンセル

  • 2017/02/25 20:00

    目的に対して適切な手段を使うのが正解と思います。
    もし、MVCが有効となるケース(スキンを切り替えたい、デザイナーが独立して作業できるようにしたいなど)では、モデルがビューに依存するとかなり辛いので、メタ情報といえど依存するべきでないでしょう。
    しかし、この質問のケースもそうですが、モデルをビューから独立させる際にそれなりのデメリットを伴うケースも少なくありません。そのような時で、しかもMVCを採用するメリットがそれ程大きくないプロジェクトなら、MVCに拘るのは本末転倒と思います。
    要は手段に拘って目的を見失わないことが大事と思います。

    > もっと厳密にif/switch的なものを排除する方法論があるのでしょうか

    if/switchに較べて表は自由度は低いですが、その分プログラムのバグが入り込む余地が少ないです。
    なので、今回のようなケースで、かつ、MVCが有効な時は私なら表を使うと思います。

    でも、そもそもMVCが無駄な場合も少なくないので、そのような時は躊躇なくモデルをビューに依存させ、メンテナンスしやすいようにすると思います。

    キャンセル

同じタグがついた質問を見る

  • Java

    14473questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • オブジェクト指向

    298questions

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

  • MVC

    236questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。