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

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

新規登録して質問してみよう
ただいま回答率
85.48%
オブジェクト指向

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

Q&A

解決済

3回答

12046閲覧

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

syuilo

総合スコア393

オブジェクト指向

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

2グッド

0クリップ

投稿2016/07/02 14:48

編集2016/07/02 14:58

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

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

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

要するに

C#

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

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

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

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

yuji38kwmt, raccy👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

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

自分自身を変化させるような場合は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/02 22:25

編集2016/07/02 22:51
raccy

総合スコア21735

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

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

eripong

2016/07/02 22:34

> 自然と破壊的メソッドではないmutableなメソッドチェーンを使うように洗脳する恐ろしい言語です。 文章の流れからすると、immutableなメソッドチェーン、では?
raccy

2016/07/02 22:52

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

2016/07/04 17:10

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

0

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

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

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

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

投稿2016/07/02 15:12

tamy

総合スコア442

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

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

syuilo

2016/07/02 15:15

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

2016/07/02 15:17

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

0

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

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

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

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

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

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

投稿2016/07/02 15:21

Mr_Roboto

総合スコア2208

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

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

syuilo

2016/07/02 15:26

ありがとうございます! GoFの本は見よう見ようと思っていてまだ見てないんですが、やっぱり技術者たるもの見ておいた方が良いんですね...。 設計に正解はないとのことで、今回は自分が気に入ったパターンを採用してみようと思います。 貴重なご意見ありがとうございました。
KiyoshiMotoki

2016/07/02 17:33 編集

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

2016/07/03 00:04

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問