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

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

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

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

オブジェクト指向

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

Q&A

3回答

1162閲覧

getter/setterをやめるべき について、改善例を教えてください

omg

総合スコア11

Java

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

オブジェクト指向

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

2グッド

4クリップ

投稿2018/03/28 13:38

https://qiita.com/Yahagi_pg/items/1bf59fc75d7f17c3b731

こちらの記事が参考になり、getterをやめるべきについては
改善例を理解しました。

int totalPrice = book.getPrice() * quantity;

int totalPrice = book.calculateTotal(quantity);

ではsetterについてはどのように改善できるのでしょうか?
bookのpriceを500に変更したい場合、やはりsetterを実装する事になるかと考えております。

教えていただけると助かります。

yuji38kwmt, m0a👍を押しています

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

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

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

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

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

guest

回答3

0

こんにちは。

getterやsetterを乱発したくなる時は、設計が甘い時が多いと思います。
きちんとそのクラスの役割を明確に設計していれば、内部の実装を外部に公開するようなgetterやsetterを乱発することがありえないのです。

つまりちゃんと設計しましょうということであり、getter,setterを止めましょうという主旨ではありません。ちゃんと設計した結果getter, setterを使うべきと判断したところにまで使うなという話ではないです。
GUIフレームワークのウィンドウ・クラスはTop, left, Width, Heightなどはgetter, setterを持ちますし、それは妥当な設計と思います。

投稿2018/03/28 15:33

Chironian

総合スコア23272

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

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

omg

2018/03/30 14:59

ご回答ありがとうございます、極端に捉えすぎていました。
guest

0

コンストラクタで値段を指定するのが自然だと思います。

Java

1class Book { 2 private final int price; 3 4 Book(int price) { 5 this.price = price; 6 } 7}

**『後から値段を変更できる』というのがそもそも間違いではないか?**とまず考えた方が良いです。


ただし、値段が変わることが妥当な場合もあります。
その場合はセッターやそれに準ずるものを使うしかないですが、意味合いがあると良いですね。
単に新しい値段をセットするのではなく、『何割引き』か指定するとか。

これはご提示のリンク先の記述にも沿いますね。

A. オブジェクトをデータの入れ物として扱うのではなく、そのデータの加工を任せる

投稿2018/03/28 13:48

LouiS0616

総合スコア35660

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

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

KSwordOfHaste

2018/03/28 16:55

to:質問者さん,LoiuS0616さん 「後から値段を設定できる」のが問題という点をもう少し言えば「値段を外部から設定するなら、それはもはや公開情報なのでgetter/setterを設けるかどうか以前のはなし」であるような気がしました。記事の筆者さんは「外部への公開情報をいかに最小限に絞り込む設計をするか」を主題としています。自分の意見では「setterにより外部から設定を許す=>値段を公開属性として捉えている=>それ自体が主題とミスマッチ」だと思いました。LouiS0616さんの「そもそも間違い」という指摘はほとんど同じ考えではないかという気がします。 ちなみに値段を意識させないことをつきつめるならコンストラクターで指定すること自体も避けたいのかなぁとそんなことを思いました。もっとも「商品」の「単価」を本当に隠蔽すべき例として挙げるのは・・・実は却って分かりにくくしているのではないかと思います。普通「単価」って公開属性として捉えることが多いのではないでしょうか?商品一覧に単価を表示したりしますし・・・
LouiS0616

2018/03/28 17:23

『原価』と『販売価格』を分けて考えるべきなのかな、と少し思いました。 そうすれば原価は完全な読み取り専用に出来ますよね。 単価を取得するのはアクセサを用意するのに充分正当な理由に思えます。 リンク先では話の主題に沿って『getPrice』を排除していますが、これは本来有っても良いものかと。
omg

2018/03/30 14:58

お二方、ご回答ありがとうございます! 確かに、記事の主題として公開しなくていい情報を公開しない、という方向性のため priceを本当に公開情報として扱う必要があれば、gtterもsetterも使う事は問題ないのですね。 極端に捉えすぎていました。
omg

2018/03/30 15:01

> 『原価』と『販売価格』を分けて考えるべきなのかな、と少し思いました。 > そうすれば原価は完全な読み取り専用に出来ますよね。 改善案としては、このような事が言えますでしょうか。 setSellingPrice(利益率, 税率); // 原価(price)を意識せずに販売価格を設定
LouiS0616

2018/04/01 05:58 編集

私はもうちょっとシンプルなものをイメージしていました。 setDiscountRate(割引率); しかしこの場合、『原価』ではなく『元値』と書くべきでしたね。 omgさんの setSellingPrice の方が現実的で良いかと思います。 --- 細かく考えだすときりがないのですが、 ひょっとしたら『原価』―利益率・税率→『元値』―割引率→『販売価格』の方が良いのかな? 必要以上に複雑になっていくのも良くないので、ちょっと悩みどころです。
guest

0

最後まで読みましたか?
この場合はやはり getPrice() があった方がいいという結論になっています。

とにかく何も考えずゲッターセッターを作れと言う入門書への批判でとにかくゲッターセッターは作るなという記事ではありません。

仕様をちゃんと考えようねという記事です。

投稿2018/03/28 23:34

Zuishin

総合スコア28660

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

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

Zuishin

2018/03/28 23:59 編集

この記事の肝は最後の Buy オブジェクトです。追記が肝と言うのもおかしいことですが。 例えばそれまでは消費税が無かったとして、急に導入されたとしましょう。ソースのあちこちで合計金額を求めていたらどこを直せばいいのかという調査から時間がかかります。 しかし売値が Buy オブジェクトに一任されていたならそこさえ直せばいいのです。 消費税だけでなく、何点買えば割引とか何円以上買えば割引とか一定の時間であれば割引とか、突然色んな仕様が舞い込んでもこれなら対応は容易です。 買った商品の数による割引率などは個々の Book では対応できません。 最初に書いていますよね? 「どちらも正解」と。 商品の価格を後から変えることがないならセッターは必要ありません。 しかし変える必要があるならフィールドを公開するのではなくセッターを作るべきです。
Zuishin

2018/03/29 00:08

もう一点。 セッターをどこでも使えるよう公開したくない場合には、セッターを使えるオブジェクトを限定してしまえばいいのです。 setPrice(int) ではなく setPrice(IValueSetter) として IValueSetter.getNewPrice(Book) を内部で呼び出せば抽象化できます。
omg

2018/03/30 15:10

ご回答ありがとうございます! > 商品の価格を後から変えることがないならセッターは必要ありません。 > しかし変える必要があるならフィールドを公開するのではなくセッターを作るべきです。 初期に変える必要が無くとも、変える可能性があれば、やはり特に処理の無いgetter/setterを作るほうがいいですか? フィールドを直接公開していると後から消費税が導入されたとき大変ですが、 処理のないsetterを使うようにしていれば、setterを1つ直すだけで済むかもしれません。 (引数で消費税を渡さなければいけない場合は、結局大変そうですが)
Zuishin

2018/03/30 22:24

消費税の計算は一度の買い物の金額によって変わってきます。 なぜなら小数だからです。 ですから個々の商品がそれをすべきではありません。 Buy オブジェクトを作ってそれに任せるべきです。
Zuishin

2018/03/30 22:27

例えば 10 円の商品の消費税は 1 円です。個々の商品で計算した場合、それを 10 個買うと消費税は 10 円になってしまいます。 しかし実際には 8 円です。 ですから買い物単位でしか求められません。
Zuishin

2018/03/30 22:39

金額を変える必要がある時というのは実際には避けられることがほとんどだと思います。 ですが金額を間違って入力していたのを営業中に直したい時、金額が変更できないなら元々の商品オブジェクトを破棄して作り直さなければなりません。 そのオブジェクトが既に他のオブジェクトに所有されていた時に破棄する処理を適切に行わないと不具合が発生する恐れがあります。 こういう場合はセッターを持っていたら金額だけ差し替えられるので楽で堅牢な設計ができます。
Zuishin

2018/03/30 22:50

calculateTotal() の決定的にまずいところは、現実とそぐわないことです。 消費者は一部例外を除いて同じ本ばかり大量に買ったりしません。 合計金額を求めるのは Book の責務ではないというのはそういうことです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問