web-dev-qa-db-ja.com

動的で弱く型付けされた言語では、デザインパターンとOOPプラクティスの考え方はどのように変わりますか?

これらの行に沿ってかなり役立つ質問があります( " Non-OOP Design Patterns? ")が、私は動的で弱く型付けされたばかりの人の移行の観点についてもっと興味があります言語。

つまり、私が長年C++、C#、またはJavaでプログラミングしていて、GoF設計パターン、FowlerエンタープライズアプリケーションアーキテクチャのパターンSOLIDの原則 など。今、Ruby、Python、JavaScriptなどに手を出しています。おそらく私は多くの場合直接翻訳を行うことができますが、ほとんどの場合、それは私の新しい設定を最大限に活用することにはなりません。アヒルのタイピングだけで、インターフェイスベースの多くの考えが頭に浮かびます。

何が変わらないのですか?何が変わりますか?動的言語の初心者が知っておくべき、SOLIDのような基本原則、または標準パターン(おそらくまったく新しいもの)はありますか?

11
Domenic

何が変わらないのですか?何が変わりますか?

パターンは同じです。言語技術が変わります。

SOLIDのような指導原則はありますか、

はい。実際、それらは依然として指針となる原則です。何も変わりません。

または、動的言語の初心者が知っておくべき標準パターン(おそらくまったく新しいパターン)ですか?

いくつかはユニークです。主な影響は、実装手法が変わることです。

パターンは-まあパターンです。法律ではありません。サブルーチンではありません。マクロではありません。それは良いアイデアなので、繰り返されるのは良いアイデアです。

優れたアイデアが時代遅れになったり、劇的に変化したりすることはありません。

その他の注意事項。 Pythonは「弱く型付けされていません」。キャスト操作がないため、JavaまたはC++よりも強く型付けされています。[はい、ファッジする方法があります。オブジェクトに関連付けられたクラスですが、うるさい、合法的な点を証明することを除いて、それは行われる種類のことではありません。]

また。ほとんどのデザインパターンは、ポリモーフィズムを利用するさまざまな方法に基づいています。

例としてStateまたはCommandまたはMementoを見てください。それらは、ポリモーフィックな状態、コマンド、または状態変化の記念品を作成するためのクラス階層を持っています。 Pythonでこれを行っても、大きな変化はありません。 Pythonの多態性は、共通の祖先ではなく共通のメソッドに依存するため、マイナーな変更には、正確なクラス階層の緩和が含まれます。

また、一部のパターンは、遅延バインディングを実現するための単なる試みです。ほとんどのFactory-関連パターンは、アプリケーション内のすべてのC++モジュールを再コンパイルせずにクラス階層を簡単に変更できるようにする試みです。これは、動的言語での興味深い最適化ではありません。ただし、実装の詳細を隠す方法としてのFactoryには、依然として大きな価値があります。

一部のパターンは、コンパイラーとリンカーを駆動する試みです。 Singletonは、たとえば、混乱するグローバルを作成するために存在しますが、少なくともそれらをカプセル化します。 Pythonシングルトンクラスは快適な見込みではありません。しかしPythonモジュールはすでにシングルトンなので、多くの人はモジュールを使用するだけなので、 シングルトンクラス。

7
S.Lott

Peter Norvigは1998年にまさにこの質問に取り組みました。彼が気付いた一連の詳細な情報については http://norvig.com/design-patterns/ppframe.htm を読んでください http:/ /c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures この点に関する詳細な議論のために。

短いバージョンは、言語に多くの機能がある場合、反復的なデザインパターンは単純になる傾向があります-多くの場合、目に見えなくなるほどで​​す。彼は、GoFが特定したほとんどの設計パターンにこれが当てはまることを発見しました。

8
btilly

動的オブジェクト指向言語でのプログラミングは、同じパターンと原則の多くを使用しますが、環境により、いくつかの微調整と違いがあります。

インターフェイスをダックタイピングで置き換える-ギャングオブフォーが抽象基本クラスを純粋な仮想関数で使用するように指示し、動的言語でJavaのインターフェイスを使用する場合は、理解。任意のオブジェクトをどこでも使用でき、実際に呼び出されるメソッドを実装している場合は問題なく機能するため、正式なインターフェースを定義する必要はありません。 文書化する価値があるかもしれないので、実際に何が必要かが明確になります。

関数もオブジェクトです-決定をアクションから分離することに関するパターンはたくさんあります。コマンド、戦略、責任の連鎖など。ファーストクラスの関数を使用する言語では、.doIt()メソッドを使用してオブジェクトを作成するのではなく、単に関数を渡すことが理にかなっていることがよくあります。これらのパターンは、「高次関数を使用する」に変わります。

[〜#〜] sold [〜#〜]-インターフェースがないため、ここではインターフェース分離の原則が最大の影響を受けます。原則を考慮する必要がありますが、コードに具体化することはできません。個人的な警戒だけがここであなたを守ります。利点として、この原則に違反することによって引き起こされる痛みは、一般的な動的環境では大幅に軽減されます。

"...自分の特定の部分...イディオム!"-各言語には、良い習慣と悪い習慣があり、最高のものを望むなら、それらを学び、それに従う必要があります。それらの言語のコード。たとえば、完全に記述された反復子パターンは、組み込みのリスト内包表記がある言語では笑われることがあります。

8
Sean McMillan

私の経験では、いくつかのパターンはまだPythonで役立ち、より静的な言語よりもセットアップが簡単です。シングルトンパターンのように、一部のパターンOTOHは不要であるか、嫌われさえしています。代わりに、モジュールレベルの変数または関数を使用してください。または、ボーグパターンを使用します。

多くの場合、作成パターンを設定する代わりに、オブジェクトを作成する呼び出し可能オブジェクトを渡すだけで十分です。 Pythonにはnew()がないため、関数自体、__call__メソッドを持つオブジェクト、またはクラスの可能性があります。クラス自体の呼び出しのみです。

def make_da_thing(maker, other, stuff):
    da_thing = maker(other + 1, stuff + 2)
    # ... do sth
    return da_thing

def maker_func(x, y):
     return x * y

class MakerClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
...
a = make_da_thing(maker_func, 5, 8)
b = make_da_thing(MakerClass, 6, 7)

状態と戦略パターンは、C++やJavaなどの言語で非常によく似た構造を共有しています。 Pythonではそれほどではありません。戦略パターンはほぼ同じままですが、状態パターンはほとんど不要になります。静的言語の状態パターンは、実行時のクラスの変更をシミュレートします。 Pythonでは、それを行うことができます。実行時にオブジェクトのクラスを変更します。制御されたカプセル化された方法で実行する限り、問題はありません。

class On(object):
    is_on = True
    def switch(self):
        self.__class__ = Off

class Off(object):
    is_on = False
    def switch(self):
        self.__class__ = On
...

my_switch = On()
assert my_switch.is_on
my_switch.switch()
assert not my_switch.is_on

Static Type Dispatchに依存するパターンは機能しないか、まったく異なる動作をします。ボイラープレートコードをそれほど多く記述する必要はありません。ビジターパターン:JavaおよびC++では、すべてのビジブルクラスにAcceptメソッドを記述する必要がありますが、Pythonでは、ミックスインクラスを介してその機能を継承できます。訪問可能のように:

class Visitable(object):
    def accept(self, visitor):
        visit = getattr(visitor, 'visit' + self.__class__.__name__)
        return visit(self)
...

class On(Visitable):
    ''' exactly like above '''

class Off(Visitable):
    ''' exactly like above '''

class SwitchStatePrinter(object): # Visitor
    def visitOn(self, switch):
         print 'the switch is on'
    def visitOff(self, switch):
         print 'the switch is off'

class SwitchAllOff(object): # Visitor
    def visitOn(self, switch):
         switch.switch()
    def visitOff(self, switch):
         pass
...
print_state = SwitchStatePrinter()
turn_em_off = SwitchAllOff()
for each in my_switches:
    each.accept(print_state)
    each.accept(turn_em_off)

静的言語でのパターンの適用を必要とする多くの状況は、Pythonではそれほどではありません。高次関数(デコレーター、関数ファクトリー)やメタクラスなど、他の技法で解決できることはたくさんあります。

3
pillmuncher