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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

546閲覧

Python オブジェクト指向 クラス設計 デメテルの法則

_Victorique__

総合スコア1392

オブジェクト指向

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2017/08/07 10:28

###前提・実現したいこと
オブジェクト指向のクラス設計で困っています。以下のコードについて説明すると、
Comment1,2,3はそれぞれCommentクラスを継承しており、ラッパークラスです。
ReportクラスはComment1,2,3以外にもDate,Nameというラッパークラスを所持しています。
まず、何故Comment1,2,3と分けているかというと、1,2,3それぞれで異なる処理を行うからです。同じ処理を行うこともあるので継承という形にしています。

※各クラスのメソッドは省略しています。

ここでなのですが、デメテルの法則に従うと、Comment1,2,3共通の処理をラッパーメソッドとしてReportクラスに3回同じものを実装しなくてはなりません。これじゃ継承した意味もなくとてつもなく汚く無駄なコードになってしまいます。ですが、ここでデメテルの法則を無視すると、Reportクラスにプロパティを実装するだけで済みます(例:Report.Comment1.length())

そこでなのですが、一般的にデメテルの法則は必ず守った方が良いものなのでしょうか?
また、このケースにおいて、デメテルの法則を守ってかつコードに無駄がないような実装にするにはどのような解決策があるでしょうか?

元々はcomment1,2,3をCommentという1つのクラスで管理しており、引数に数字を与えることで処理するコメントを選んでいました。しかし、commentによって違った処理をすることがあるので、それぞれ変数をラッピングした方が良いのではないかという考えにいたり、今回のような問題が発生したために質問させていただきました。

###該当のソースコード

python

1class Comment: 2 def __init(self,comment): 3 self._comment = comment 4 5class Comment1(Comment): 6 def __init(self,comment1): 7 super().__initi(comment1) 8 self._comment1 = comment1 9 10class Comment2(Comment): 11 def __init(self,comment2): 12 super().__initi(comment2) 13 self._comment1 = comment2 14 15class Comment3(Comment): 16 def __init(self,comment3): 17 super().__initi(comment3) 18 self._comment1 = comment3 19 20class Report: 21 def __init__(self,comment1,comment2,comment3,date,name) 22 self._comment1 = Comment1(comment1) 23 self._comment2 = Comment2(comment2) 24 self._comment3 = Comment3(comment3) 25 self._name = Name(name) 26 self._date = Date(date) 27

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

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

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

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

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

guest

回答2

0

ベストアンサー

Reportクラスにプロパティを実装するだけで済みます(例:Report.Comment1.length())

おっしゃるように、今回ですとそのように書くほうがスマートです。

オブジェクト指向の設計・原則はあちらを立てばこちらが立たず...のようなトレードオフの関係になることがあったり、場合によっては従わない方がいい、というのはご存知かと思います。
また、言語自体の設計思想であったり、そのコミュニティで生まれた考え方がこれらの原則やお約束と衝突することもあります。

例えば、Pythonにおける属性のへのアクセスは基本的にオープンにする方がいい、というものがあります。
他のいくつかの言語と違い、クラスの変数に対してとりあえずゲッター、セッターを付ける、ということはあまりしないですし、今回の例でいえばReport.Comment1.length()という書き方でそのままアクセスするのも別におかしくありません。

一般的にデメテルの法則は必ず守った方が良いものなのでしょうか?

場合によるとは思いますが、Pythonではそこまで固執しなくても良いのかなぁと思います。
Pythonの禅に
「特殊条件だからといって原則を破っていいわけではないが、実用性は純粋性に勝る」
という旨の格言があるように、あるルールや原則を守るために冗長になったり、複雑になる実装は避けたほうが良いように感じます。

投稿2017/08/07 17:18

toritoritorina

総合スコア972

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

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

0

オブジェクト指向とは、そもそも読みやすくするためにあるはずなので、オブジェクト指向を実践したいからと、読みにくいコードを作ったら、本末転倒だと思います。デメテルの法則があると、設計が綺麗にならないのならば、それはデメテルの法則を使うべきときではないと思います。

私の肌感覚では、あらゆる設計について完璧に正しい「法則」があるとは思えません。全ては設計のヒント、ぐらいだと捉えておくほうが良いと思います。

投稿2017/08/07 10:36

sannye

総合スコア40

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

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

_Victorique__

2017/08/07 13:18

質問文にも書いていますが、法則に全て従わないといけないなんて思っていません。 この質問は設計を見直すことでデメテルの法則を無視しないで済むかという問いかけです。具体的なクラス設計について答えていただけると嬉しいのですが。
sannye

2017/08/07 13:22

なぜデメテルの法則を使いたがるのかがわかりません。ご自身で書かれているように、無視したほうが綺麗になる可能性が高いです。YAGNIです。
_Victorique__

2017/08/07 13:28

良いとされているものを使うのは普通だと思いますが何がおかしいんですか? ちょっと勘違いされすぎではないでしょうか?質問をよく読んでくださると助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問