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

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

ただいまの
回答率

89.12%

メソッドチェーンさせたい場合のクラスのデザイン

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 7,524

syuilo

score 385

例えば「色」クラス(Color)を作っていたとして、その色を反転させたり、明るくしたり暗くしたりできるものだとします(メソッドで)。
ここでこの Color をメソッドチェーンを利用できるようにしたい場合、二通りの方法が思いつきました。(ここでは色を反転させるメソッドとして考えます)

  1. 自分の色を反転させた色を持つ Color のインスタンスを返す。(自分は変更されない)
  2. 自分自身の色を反転して自分を返す

これはどちらが良いのでしょうか?
普通はこういう実装をする、とかありますか?

要するに

var baseColor = new Color(12, 34, 56);
var anotherColor = baseColor.Invert().Lighten(0.2).Saturate(0.5);

みたいにしたときにbaseColorが変更されているべきか否か、ということです。

自信を変更したくないときのために、Cloneとかいうメソッド(自分と同じ色をもつインスタンスを生成し返す)を作って対処する方法も浮かびましたが、普通こういった実装をしたりしますでしょうか?

皆様のご意見をお聞かせください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+4

その言語の特徴やメソッドチェーンする対象によって傾向があると思います。

自分自身を変化させるような場合はmutableなオブジェクト、自分自身は変化させずにそのままにする場合はimmutableなオブジェクトと言ったりします。この用語に合わせてmutableなメソッドチェーン、immutabelなメソッドチェーンとして説明します。なお、mutabelなオブジェクトには両方あり得ますが、immutableなオブジェクトはimmutableなメソッドしかありません。

メリットとデメリット

メリットとデメリットをまずは見ていきましょう。

mutableなメソッドチェーン

利点

  • オブジェクトの生成が無いため、速い
  • メモリの消費量が少ない
  • メモリ管理が不要

欠点

  • 副作用があるため、何をしているかを把握しないと危険

immutableなメソッドチェーン

利点

  • レシーバを変更されるといった副作用が無いため、安全

欠点

  • オブジェクトを逐一生成するため、遅い
  • 途中に作成されたオブジェクトの分だけメモリが消費されていく
  • メモリ管理が複雑になるため、GCが無いと難しい

上を見るとわかるように対比になっています。基本的には、「パフォーマンス」を取るか、「安全性」を取るかです。また、GCが無い言語でimmutableなメソッドチェーンを作るには工夫がいります。途中でメモリの動的確保により生成したオブジェクトがある場合、そのままではメモリ解放することができなくなってしまうからです。

どのような場合に多いのか

上を踏まえて、対象となるオブジェクトや言語によって傾向があります。(言語は偏っていますし、私感です)

mutableなメソッドチェーン

  • IOオブジェクト … 読み込みや書き込みは必ず副作用を伴う物ですので、レシーバは必ず変更されます。そのため、わざわざ新しいIOオブジェクトを作るメリットがありません。C++のstd::iostream、RubyのIO等。
  • C++ … GCがないためimmutableで作ること自体が難しいです。また、C++では安全性よりパフォーマンスを重視しており、使用する人もいかに速くできるかに関心があります。遅いimmutableは敬遠される傾向になります。
  • 昔のJava … 昔のJavaは全体的に遅いと言うこともあり、速くできるところは速く使用としていた傾向があります。

immutableなメソッドチェーン

  • ストリーム(リスト)オブジェクト … 関数型で見られるような処理ができるパターンです。ストリーム(リスト)を抽出、射影、並び替えなどを次々行います。JavaのStream、C#のLINQ、RubyのEnumerable等。
  • 今のJava … 最近のJavaに追加されたクラスはimmutableな場合が多い傾向にあります。パフォーマンスもよくなったため、速度よりも安全を取るという選択です。
  • Ruby … Rubyのオブジェクト自体はmutableなものが多いですが、ほとんどの場合で、新たに生成したオブジェクトを返すメソッドが用意されています。それらとは違い、副作用を伴うメソッドは破壊的メソッドとよんでなるべく区別できるようにしています。それら破壊的メソッドはnilを返す事もあるようにして、わざとメソッドチェーンをしにくくしています。自然と破壊的メソッドではないimmutableなメソッドチェーンを使うように洗脳する恐ろしい言語です。

まとめ

昔はマシンも貧弱であり、パフォーマンスが重視されていたため、mutableな傾向が強かったと思います。しかし、近年は、マシン速度が向上し、関数型プログラミングの流行に伴い、immutableな実装が主流ではないかと思います。速度と安全は二律背反であり、どちらがか正解という物ではありません。用途や目的などに合わせて選ぶと良いかと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/07/03 07:34

    > 自然と破壊的メソッドではないmutableなメソッドチェーンを使うように洗脳する恐ろしい言語です。

    文章の流れからすると、immutableなメソッドチェーン、では?

    キャンセル

  • 2016/07/03 07:52

    > eripong さん
    はい・・・その通りです。修正しましたー。

    キャンセル

  • 2016/07/05 02:10

    詳しくありがとうございます。mutableとimmutableのメリットとデメリット、よく分かりました。
    今回は immutable なパターンを採用してみようと思います!

    キャンセル

+3

個人的には,どっちが正解とかはないように思います.

わかりやすさのために新しいインスタンスを返す場合もあるし,わざわざ別オブジェクトを確保するのが嫌だからそれ自体を変えてしまう場合もある.

ただ,全体として統一されたルールで動くことと,メソッド名との兼ね合いだけは重要だと思っていて,例えば例示されているような場合,オブジェクト自体を変更するときはinvertで,新しいオブジェクトを返すときはinvertedにするとか,ルールを決めています.

実際ライブラリとかでは,動詞の原形(命令形)と受身形(過去分詞)で両方の動作を提供する実装なんかもありますし.

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/07/03 00:15

    なるほど~、正解はないんですね。設計って難しいですね

    > 実際ライブラリとかでは,動詞の原形(命令形)と受身形(過去分詞)で両方の動作を提供する実装なんかもありますし.
    そんな実装もあるんですね!とても参考になりました。

    キャンセル

  • 2016/07/03 00:17

    もちろん実装上 `inverted` は clone -> invert の単なるエイリアスになるのですが…

    キャンセル

+2

正解は無いと思います、時と場合によるとしか言えないというか。
普通はこうするではなくて、こういう場合はこうするというベストプラクティスはあるのかも知れませんが。

何かの問題に対しての解決方法で、1つあれば完璧ということはまずなくて、
必ずメリット・デメリットがあるわけで、
重要なのは選択肢が沢山あってその時々に応じて最適なものを選べるかです。
ソートアルゴリズムなんてたくさんありますよね。

つまり何かを解決する際にひとつしか選択肢が無いという状態が一番ダメなわけで、
何パターンも考えつく質問者様は、素晴らしい思考の持ち主だなぁと思いました。

まぁ、換装だけ述べても何なので、クラスのデザインというものに関して言えば
古?よりデザインパターンというものが存在しますので、そちらを研究するのも良いのではないでしょうか。

メソッドチェーン デザインパターン で検索すればいろいろなパターンが見つかります。

結果の中には、GoF(ギャング・オブ・フォー)のチェインオブリポジトリーも出てきますので、
それがメソッドチェーンとイコールになるのか不勉強で分かりませんが、参考になると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/07/03 00:26

    ありがとうございます!

    GoFの本は見よう見ようと思っていてまだ見てないんですが、やっぱり技術者たるもの見ておいた方が良いんですね...。

    設計に正解はないとのことで、今回は自分が気に入ったパターンを採用してみようと思います。
    貴重なご意見ありがとうございました。

    キャンセル

  • 2016/07/03 02:32 編集

    横から失礼します。

    BJCRobot様

    > GoF(ギャング・オブ・フォー)のチェインオブリポジトリー

    チェイン・オブ・レスポンシビリティー (Chain of Responsibility) のことでしょうか?
    https://ja.wikipedia.org/wiki/Chain_of_Responsibility_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3

    であれば、メソッドチェーンとは異なります。

    チェイン・オブ・レスポンシビリティー パターンとは、
    「渡された命令のうち、自身が対応できないものをチェーン内の次のオブジェクトに移譲する」
    というものですので(内部的にメソッドチェーンを使用したチェイン・オブ・レスポンシビリティーの実装は、あるかもしれませんね)。

    キャンセル

  • 2016/07/03 09:04

    ありがとうございます。
    なので不勉強だとw

    キャンセル

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

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる