Pythonミックスインはアンチパターンですか?


34

私はpylint、他の静的分析ツールがすべてを知っているわけではないことを完全に認識しています。(これは、conventions だけでなく、さまざまなクラスのメッセージに適用されます。)


私のようなクラスがある場合

class related_methods():

    def a_method(self):
        self.stack.function(self.my_var)

class more_methods():

    def b_method(self):
        self.otherfunc()

class implement_methods(related_methods, more_methods):

    def __init__(self):
        self.stack  = some()
        self.my_var = other()

    def otherfunc(self):
        self.a_method()

明らかに、それは不自然です。あなたが好きなら、これはより良い例です

このスタイルは「ミックスイン」を使用して呼び出されると思います。

他のツールと同様に、pylintレートでこのコードを-21.67 / 10、主にそれは考えているためmore_methodsrelated_methods持っていないselfか、属性otherfuncstack、annd my_varのコードを実行せず、それは明らかに見ることができないためrelated_methodsmore_methods混合でにしていますimplement_methods

コンパイラーと静的解析ツールが停止問題を常に解決できるとは限りませんが、これは確かに、継承されたものを見るとimplement_methodsこれが完全に有効であることを示す場合であり、それは非常に簡単なことです。

なぜ静的解析ツールがこの有効な(私が思うに)OOPパターンを拒否するのですか?

どちらか:

  1. 彼らは継承をチェックしようとさえしません

  2. mixinは慣用的で読みやすいPythonでは推奨されません


#1は明らかに間違っています。なぜなら、を使用し pylintて継承する私のクラス(でのみ定義されているもの)について教えてもらえば、文句を言わないからです。unittest.TestCaseself.assertEqualunittest.TestCase

ミックスインは非Pythonpythonですか、落胆しますか?


1
これは悪い質問ですか?トピック外ですか?答えられない?私は愚かですか?人々はDVを実行できますが、DVを改善したくありません。

1
人々に「これは(アンチ)パターンですか」または「これは(un)pythonicだ」と尋ねさせるのにうんざりしている人もいます。

9
@MichaelTそれは結構です。質問のレビューを停止できます。
Katana314

2
@tacの人々はさまざまな理由でダウン投票しますが、その理由を言う必要はありません。受け入れられる答え。8のアップと1のダウンは、特にダウン票が無料の場合は特に問題があります。落胆させないでください。乾杯。
アーロンホール

@AaronHall私は、人々が自分の票で好きなことをすることを許可されていることを知っています。実際、同じことを不満を言う新しいユーザーに伝えます。

回答:


16

ミックスインは、ツールによって考慮されたユースケースではありません。だからと言って、必ずしも悪い使用例ではなく、Pythonの珍しい使用例にすぎません。

特定のインスタンスでミックスインが適切に使用されるかどうかは別の問題です。私が最も頻繁に見るミックスインのアンチパターンは、ミックスインを1つだけ組み合わせることを意図している場合にミックスインを使用することです。それはただ神のクラスを隠す回り道です。ミックスインの1つをスワップアウトまたは除外する理由を今すぐに考えられない場合、それはミックスインではないはずです。


ええ、それは神のオブジェクトです、私は認めます。この場合、CPUが神のオブジェクトであってもかまいません。

15

Mixinsは絶対にPythonicにできると信じています。ただし、リンターを黙らせる-およびMixinsの読みやすさを向上させる-慣用的な方法は、(1)Mixinの子が実装する必要があるメソッドを明示的に定義する抽象メソッドを定義すること、および(2)None子が初期化する必要があるMixinデータメンバーの値フィールド。

このパターンを例に適用します。

from abc import ABC, abstractmethod


class related_methods():
    my_var = None
    stack = None

    def a_method(self):
        self.stack.function(self.my_var)


class more_methods(ABC):
    @abstractmethod
    def otherfunc(self):
        pass

    def b_method(self):
        self.otherfunc()


class implement_methods(related_methods, more_methods):
    def __init__(self):
        self.stack  = some()
        self.my_var = other()

    def otherfunc(self):
        self.a_method()

2
が、あなたの答えのための1、abstract other(self): pass事は私のためリンターの混乱を取引

@abstractmethodがないとさらに混乱します;-)最初にJavaから始めたので、これは私にとっては問題ありません。
クリスファンリーバー

9

私は考えてミックスインは良いことができますが、私はまた、pylintが、この場合には正しいと思います。免責事項:意見に基づいたものが続きます。

ミックスインを含む優れたクラスには、1つの明確な責任があります。理想的には、ミックスインは、アクセスするすべての状態と、それを処理するロジックを保持する必要があります。たとえば、優れたミックスインはlast_updated、ORMモデルクラスにフィールドを追加し、それを設定するためのロジックを提供し、最古/最新のレコードを検索するメソッドを提供します。

宣言されていないインスタンスメンバー(変数とメソッド)を参照するのは少し奇妙に見えます。

適切なアプローチは、手元のタスクに大きく依存します。

状態の関連ビットが保持されているミックスインの場合があります。

ミックスインを介して現在配布しているメソッドが基本クラスにあり、下位レベルの実装の違いがサブクラスに属する別のクラス階層である場合があります。これは、スタック操作の場合に最も適しているように見えます。

メソッドを1つまたは2つ追加するクラスデコレータでもかまいません。これは通常、メソッド生成に影響を与えるためにデコレータに引数を渡す必要がある場合に意味があります。

あなたの問題を述べ、あなたのより大きなデザインの懸念を説明してください。そして、あなたのケースで何かがアンチパターンかどうかを議論することができます。


6

リンターは、クラスをミックスインとして使用していることを認識していません。Pylintは、クラス名の末尾に接尾辞「mixin」または「Mixin」を追加すると、リンターが文句を言うのをやめると、ミックスインを使用することを認識します。

linter_without_mixins linter2_with_mixin

ミックスイン自体は悪いものでも良いものでもありません。単なるツールです。あなたはそれらを良い使用または悪い使用にします。


2
これは、より多くのコメントのように読み、見回答する方法
GNAT

2
私は私が今までそれ以外のそのヒントを知っているだろうとは思わないので、これは貴重な答えである

1

ミックスインは大丈夫ですか?

Pythonミックスインはアンチパターンですか?

ミックスインは非推奨ではありません-多重継承の良いユースケースです。

リンターが文句を言うのはなぜですか?

Pylintは、それがどこを知っていないので、明らかに不平を言っているotherfuncstackmy_var から来ています。

つまらない?

この2つのメソッドを個別の親クラスに分離する理由は、問題の例またはここに示すより単純なリンクされた例のいずれにおいても、すぐには明らかな理由はありません。

201
202 class OpCore():
203     # nothing runs without these
204
205 class OpLogik(): 
206     # logic methods... 
207 
208 class OpString(): 
209     # string things
210 
211 
212 class Stack(OpCore, OpLogik, OpString): 
213 
214     "the mixin mixer of the above mixins" 

ミックスインとノイズのコスト

あなたがしていることのコストは、リンターレポートを騒がせることです。そのノイズは、コードに関するより重要な問題をあいまいにする可能性があります。これは重量を量る重要なコストです。別のコストは、相互に関連するコードを異なる名前空間に分離することであり、プログラマーがその意味を発見するのを難しくする可能性があります。

結論

継承により、コードを再利用できます。ミックスインでコードを再利用できるとすれば、他のコストを上回る可能性のある価値を作成してくれます。コードの行のコードの再利用/重複排除を取得していない場合、おそらくミックスインの価値はあまりないでしょう。その時点で、ノイズのコストはメリットよりも大きいと思います。


リンクされた自明でない例でそれらを分離するのには十分な理由があります-数学を実装する完全なクラスの一部、文字列を実装する別のクラスなどがあり、それらを一緒に混ぜるとコードを整理しやすくなりますForth Soupを入手します。

「もう1つのコストは、プログラマーがコードの意味を発見するのをより困難にする可能性のある異なる名前空間にコードを分離することです」-いいえ、そうではありません。クラスの名前空間は、それが簡単な方法のグループが何を伝えるために作る、と誰かがスタックを使用したい場合、彼らはフォーススープではなく、個々の成分実装する/呼び出す必要があります

@catは、おそらく実際の大規模なプロジェクトで使用されておらず、作られていないため、どちらの例もミックスインの使用のポイントを実際にサポートしていません。両方とも、ミックスインが使用されるのは一度だけです。この場合、実装を1か所に置くだけでスタイルと組織が改善されます。ここで、クラス全体で共通の機能が必要であるが、共通の基本クラスは必要ない場合を示すことができる場合は、そこでミックスインを使用します。あなたのリンティングの質問の横にあります(UltraBirdはよく答えました)。しかし、これはミックスインの適用性に関する一般的な質問に答えます。
dlamblin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.