PythonでIoC / DIが一般的ではないのはなぜですか?


313

Javaでは、IoC / DIは非常に一般的な手法であり、Webアプリケーション、ほぼすべての利用可能なフレームワーク、Java EEで広く使用されています。その一方で、大きなPython Webアプリケーションもたくさんありますが、Zope(コードで言うと恐ろしいはずですが)の他に、IoCはPythonの世界ではあまり一般的ではないようです。(私が間違っていると思われる場合は、いくつか例を挙げてください)。

もちろん、Pythonで使用できる一般的なJava IoCフレームワークのクローンがいくつかあります(たとえば、springpython)。しかし、どれも実際に使われているようには見えません。少なくとも、私はそのようなものを使用するDjangoまたはsqlalchemy + <insert your favorite wsgi toolkit here>ベースのWebアプリケーションに踏み込んだことはありません。

私の意見では、IoCには妥当な利点があり、たとえばdjango-default-user-modelを簡単に置き換えることができますが、PythonでのインターフェースクラスとIoCの広範な使用は、「pythonic」ではなく、少し奇妙に見えます。しかし、誰かがより良い説明をしているかもしれません。なぜIoCはPythonで広く使用されていないのでしょうか。


2
Ruby、組み込みのミックスイン、オープンクラスではあまり人気がないのと同じ理由だと思います
Sam Saffron

3
あなたはこれまでにスプリングパイソンを試しましたか?宣伝どおりに機能しません。少なくともaop部分では。あなたがJavaから来ており、移行中にある程度の快適さが必要でない限り、そこにある他のすべてはあまり役に立ちません。
トムウィリス

6
DIの使用とIOCフレームワークの使用を区別するように注意してください。前者は設計パターン、後者は前者の自動使用を支援するフレームワークです。
Doug

Dougさん、DIは、Decoratorパターンを使用することで得られる創造的な機能だと言ったと思います。
njappboy 2014年

4
DIが解決する実世界の問題に対処する答えを見つけたいと思います:寿命管理、テストスタブの容易さなど。これらに取り組むためのよりPython的な方法があれば、私はすべての耳にあります。
Josh Noe

回答:


198

私は実際にDI / IoCのがあるとは思わないという Pythonで珍しいです。何珍しい、しかし、DI /のIoCあるフレームワーク/コンテナ

それについて考えてください:DIコンテナーは何をしますか?それはすることができます

  1. 独立したコンポーネントを完全なアプリケーションに配線...
  2. ...実行時。

「一緒に配線する」と「実行時」の名前があります。

  1. スクリプティング
  2. 動的

したがって、DIコンテナーは、動的スクリプト言語のインタープリターにすぎません。実際、言い換えると、典型的なJava / .NET DIコンテナーは、お尻が醜く、時にはXMLベースの構文を持つ、非常に悪い動的スクリプト言語のくだらないインタプリタにすぎません。

Pythonでプログラミングするとき、美しくて見事なスクリプト言語を自由に使えるのに、どうして醜くて悪いスクリプト言語を使いたがるのでしょうか。実際、これはより一般的な質問です。ほとんどすべての言語でプログラミングする場合、JythonとIronPythonを自由に使用できるのに、醜い悪いスクリプト言語を使用するのはなぜでしょうか。

つまり、要約すると、DI / IoCの実践は、まったく同じ理由で、Javaと同様にPythonでも同様に重要です。ただし、DI / IoC の実装は言語に組み込まれており、多くの場合非常に軽量なので完全に消えます。

(ここでは、類似点を簡単に説明しておきます。アセンブリでは、サブルーチン呼び出しはかなり重要なことです。ローカル変数とレジスタをメモリに保存し、戻りアドレスをどこかに保存し、命令ポインタを呼び出しているサブルーチンに変更する必要があります。サブルーチンが終了したら、なんとかしてサブルーチンに戻り、引数を呼び出し先が見つけられる場所に置くなどの準備をします。IOW:アセンブリでは、「サブルーチン呼び出し」はデザインパターンであり、以前は次のような言語がありました。サブルーチン呼び出しが組み込まれているFortranは、独自の「サブルーチンフレームワーク」を構築していました。サブルーチンフレームワークを使用しないという理由だけで、Pythonではサブルーチン呼び出しは「一般的ではない」と思いますか?)

ところで:DIを論理的な結論に導くのがどのように見えるかの例については、Gilad BrachaNewspeakプログラミング言語とその主題に関する彼の著作を見てください。


58
私が同意する間。XMLコメントが間違っています。多くの(少なくとも最新の)IOCコンテナーは、構成(XML)よりも規約(コード)を使用しています。
Finglas

20
Javaで明示的にワイヤリングを書くことを妨げるものは何もありませんが、サービスが増えるにつれて、依存関係はより複雑になります。DIコンテナーはMakeに似ています。依存関係を宣言すると、コンテナーはそれらを正しい順序で初期化します。Guiceは、すべてがJavaコードで記述されているJava DIフレームワークです。宣言的に書き込むことにより、DIコンテナーは初期化の前にdeclerationsの後処理のサポートも追加します(たとえば、プロパティプレースホルダーを実際の値で置き換える)
IttayD

133
「しかし、DI / IoCの実装は言語に組み込まれており、多くの場合非常に軽量なので完全に消えてしまいます。」これは断固として真実ではないため、反対票を投じます。DIは、インターフェースがコンストラクターに渡されるパターンです。Pythonには組み込まれていません。
Doug

146
反対投票、一緒に配線することはスクリプトとは何の関係もありません。DIはパターンであり、スクリプトと同等ではありません
Luxspes

38
私はこれに同意しません。DIは、静的言語での動的スクリプトの欠如を解決しません。これは、アプリケーションのパーツを構成および構成するためのフレームワークを提供します。Ruby開発者が動的言語ではDIは不要であると言うのを聞いたことがあります。しかし、彼はRailsを使用しました... Railsは、ある種の大きなDIコンテナーにすぎません。Railsが彼のためにパーツを見つける問題を解決したので、彼はDIを必要としませんでした。
Brian Genisio 2013

51

その一部は、Pythonでモジュールシステムが機能する方法です。モジュールからインポートするだけで、一種の「シングルトン」を無料で入手できます。モジュール内のオブジェクトの実際のインスタンスを定義すると、すべてのクライアントコードがそれをインポートして、実際に機能し、完全に構築された/生成されたオブジェクトを取得できます。

これは、オブジェクトの実際のインスタンスをインポートしないJavaとは対照的です。これは、常に自分でインスタンス化する必要があることを意味します(または、ある種のIoC / DIスタイルのアプローチを使用します)。静的なファクトリメソッド(または実際のファクトリクラス)を用意することで、すべてを自分でインスタンス化する手間を軽減できますが、それでも実際に毎回新しいメソッドを作成するというリソースオーバーヘッドが発生します。


2
それは理にかなっている。Pythonの実装を変更する場合は、同じ名前を使用して別の場所からインポートするだけです。しかし今、私は静的で完全に初期化されたインスタンスのみを含むMyClassInstancesクラスをMyClassJavaでそれぞれに定義することによって、逆の方法も可能かどうか考えています。それは配線されます:D
tux21b

2
そして別のアイデア:pythonでそのようなインポートを変更する方法を提供することで、すべてのpythonファイルに触れることなく、実装を簡単に置き換えることが可能になります。代わりに、フレームワーク内from framework.auth.user import User に書き込む方がよい場合がありますUser = lookup('UserImplentation', 'framework.auth.user.User')(2番目のパラメーターがデフォルト値である場合があります)。次に、フレームワークのユーザーは、フレームワークにUser触れることなく、実装を置換/専門化できます。
tux21b 2010年

14
単純化して答えてください、実際には、「シングルトン」だけが必要なことはめったになく、スコープを制御する必要があります(スレッドローカルシングルトンやセッションシングルトンなどが必要になる場合があります)。 Pythonで解決された問題は、企業の設定で実際に解決された実際の問題ではありません
Luxspes

3
実際、DIはコードの依存関係をテストして分離できるようにすることです。また、インポート機能はJavaの静的インポートに似ており、オブジェクトの単一のインスタンスをインポートできます。
Richard Warburton 2014年

1
「モジュールからインポートするだけで、一種の「シングルトン」を無料で手に入れることができます。」静的インスタンスフィールドを宣言して値を設定することで、Javaで簡単に実行できます。これはゾルではありません
ggranum

45

IoCとDIは成熟したPythonコードでは非常に一般的です。ダックタイピングのおかげで、DIを実装するためのフレームワークは必要ありません。

最良の例は、次を使用してDjangoアプリケーションを設定する方法ですsettings.py

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL + '/1',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'snowflake',
    }
}

Django Rest FrameworkはDIを多用しています:

class FooView(APIView):
    # The "injected" dependencies:
    permission_classes = (IsAuthenticated, )
    throttle_classes = (ScopedRateThrottle, )
    parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
    renderer_classes = (renderers.JSONRenderer,)

    def get(self, request, *args, **kwargs):
        pass

    def post(self, request, *args, **kwargs):
        pass

思い出させてください(ソース):

「依存性注入」は、5セントのコンセプトを表す25ドルの用語です。[...]依存性注入とは、オブジェクトにインスタンス変数を与えることです。[...]。


8
+1。よく置きます。Pythonプログラマーである私は、C#のDIフレームワークに関するインタビュー全体のプレゼンテーションに完全に困惑しました。フレームワークは必要ないので、Flaskアプリではそれについては何も考えずにずっとやっていることに気づきました。C#/ Java以外に何も知らない人にとっては、この質問は理にかなっています。アヒル型の言語プログラマにとっては自然なことであり、あなたが言うように、「5セントの概念を表す25ドルの用語」です。
Samuel Harmer

5
エラー(インスタンス(IsAuthenticatedScopedRateThrottle)はクラスによってインスタンス化されるため、これは依存関係の注入ではありません)それらはコンストラクタに渡されません。
ドパトラマン

5
IsAuthenticatedそしてScopedRateThrottleインスタンスではありません、これらはクラスです。FooViewが構築されるとき(実際には、FooViewがリクエストを処理するとき)にインスタンス化されます。とにかく、これは単なる実装の詳細です。IsAuthenticatedそして、ScopedRateThrottleの依存関係です。それらはに注入されますFooView。これがいつどのように行われるかは重要ではありません。PythonはJavaではないため、これを実装する方法はいくつかあります。
Max Malysh、

3
@MaxMalysh私はこれについてドパトラマンに同意します。クラス自体が特定のクラスへの「ハードコードされた」依存関係を持っているため、これはIoCでさえありません。IoCでは、ハードコードの代わりに依存関係を提供する必要があります。その上、Dependency Injectionでは、各サービスのライフサイクルを管理するエンティティがあり、その場合はそれらを挿入します。これらのいずれにも提供されていないソリューション。
Ricardo Alves

3
@alexいいえ、別のレンダラーを使用するためにコードを変更する必要はありません。複数のレンダラーを同時に使用することもできますrenderer_classes = (JSONRenderer, BrowsableAPIRenderer, XMLRenderer)。モッキングはと同じくらい簡単@unittest.patch('myapp.views.FooView.permission_classes')です。「何かを渡す」という必死の必要性は、Javaが強力なメタプログラミング機能を持たない、コンパイルされ静的に型付けされた言語であるため、「Javaのやり方」の結果です。
Max Malysh

35

Djangoは制御の反転をうまく利用しています。たとえば、データベースサーバーは構成ファイルによって選択され、フレームワークは適切なデータベースラッパーインスタンスをデータベースクライアントに提供します。

違いは、Pythonには一流の型があることです。クラスを含むデータ型は、それ自体がオブジェクトです。特定のクラスを使用したい場合は、クラスに名前を付けます。例えば:

if config_dbms_name == 'postgresql':
    import psycopg
    self.database_interface = psycopg
elif config_dbms_name == 'mysql':
    ...

その後のコードは、次のように記述してデータベースインターフェイスを作成できます。

my_db_connection = self.database_interface()
# Do stuff with database.

JavaとC ++が必要とするボイラープレートファクトリ関数の代わりに、Pythonは1行または2行の通常のコードでそれを行います。これは、関数型プログラミングと命令型プログラミングの長所です。


4
あなたがコードと呼ぶのは、実際には配線部分です。これは、iocフレームワークのXMLです。実際には、単にと書くこともできimport psycopg2 as database_interfaceます。その行をinjections.pyetvoilàに入れます。
2015年

29
えーと。あなたが何をしているのかというと、ダニエルは教科書に欠かせないものです。
Shayne、2015年

これは絶対に必須のコードですが、callableを値として使用するため、一種の機能的なコードです。
ジェレミー

5
それはただファーストクラスの機能ではありませんか?en.wikipedia.org/wiki/First-class_function持っているからといって使用してもコードが機能するわけではありません。ここではかなりの数の副作用(の変更などself.database_interface)が発生しており、これは必須の叫びです。
hjc1710

15

依存関係の注入と制御の反転が意味することを人々が本当に理解していないことがわかりました。

制御の反転を使用する慣例は、別のクラスまたは関数に依存するクラスまたは関数を持つことですが、関数コードのクラス内でインスタンスを作成する代わりに、パラメーターとして受け取ることをお勧めします。そのため、疎結合をアーカイブできます。テスト可能性が高くなり、リスコフ置換の原理を構築することには、多くの利点があります。

インターフェースとインジェクションを操作することで、コードのメンテナンス性が向上します。これは、動作を簡単に変更できるためです。コードの1行(DI構成では1行か2行)を書き換える必要がないためです。クラスが待機しているインターフェースを実装するクラスは、インターフェースに従う限り独立して変化する可能性があるため、その動作を変更するクラス。コードを分離して維持しやすくするための最良の戦略の1つは、少なくとも単一の責任、置換、依存関係の逆転の原則に従うことです。

パッケージ内で自分でオブジェクトをインスタンス化し、それをインポートして自分でインジェクトでき​​る場合に役立つDIライブラリは何ですか?選択された答えは正しいです。Javaには手続き型セクション(クラス外のコード)がないため、すべてが退屈な構成xmlに含まれるため、遅延ロード方式で依存関係をインスタンス化して注入するクラスが必要になるため、吹き飛ばされませんあなたのパフォーマンス、Pythonではコードの「手続き型」(クラス外のコード)セクションにインジェクションをコーディングするだけ


IoC / DIがオブジェクトを自動的に一緒にワイヤリングすることはまだ見逃しています。実行時にそれを行うことはあまりできません(Javaはリフレクションを介してそれを行うことができます)。フレームワークがそれを処理し、明示的に行う必要がないということです。手続き型セクションがあるかどうかも関係ありません。クラスを静的なサブルーチンと関数の単なるコンテナーとして使用し、OOP機能をまったく使用せずに、Javaで完全に手続き型のアプリを作成することを妨げるものはありません。
zakmck

@zakmck:Pythonの「手続き型」セクションは、実際には手続き型コードの記述に関するものではありません。Pythonの「手続き型」セクションが静的言語と異なるのは、クラス本体に手続き型コードを配置し、クラス定義時に実行し、インポートステートメントをifステートメント内に配置し、クラスを定義するだけでクラスファクトリを作成できることです。ファクトリメソッド内。これらは、静的言語では実際には実行できないことであり、IOC / DIが解決しようとしたほとんどの問題を解決します。Pythonのメタプログラミングは、通常のPythonコードのように見えることがよくあります。
リーライアン

@LieRyan、リフレクションを使用してそれを行うことができます。または、頻繁にまたは実行時に必要な場合は、Groovy(Javaで簡単に再生できるように設計されています)などの別の言語、またはPython自体から静的言語を呼び出すことができます。それでも、IoC / DIフレームワークとはほとんど関係がありません。その目的は、ほとんどの手続き型オブジェクトワイヤリングを、定義のみを利用して自動的に行うことです。悲しいことに、ここの回答のほとんどはこの点を逃しています。
zakmck

12

数年前にPythonを使用していませんが、動的型付け言語であることは、何よりも関係があると思います。簡単な例として、Javaで何かが適切に標準出力に書き込まれたことをテストしたい場合は、DIを使用して任意のPrintStreamに渡し、書き込まれているテキストをキャプチャして検証できます。ただし、Rubyで作業しているときは、STDOUTの「puts」メソッドを動的に置き換えて検証を行うことができるため、DIを完全に除外できます。抽象化を作成している唯一の理由がそれを使用しているクラスをテストすることである場合(ファイルシステム操作またはJavaのクロックを考える)、DI / IoCはソリ​​ューションに不要な複雑さを作成します。


3
システムがどのように機能するかをテストするためにシステムがどのように機能するかを喜んで変更することに驚かされることは決してありません。次に、テストが副作用を引き起こさないことをテストする必要があります。
基本的な

2
彼はputsメソッドの変更について、テストスコープでのみ話します。これは、注入されたオブジェクトのモックメソッドのようなものです。
dpa 2016年

2
中にはかなり普通のことだという@Basic ユニットテスト、実際にあなたが、コードの複数のブロック(テストされているもの)を使用してテストケースのカバレッジを汚染したくないとして、これらの試験でそれを行うことをお勧めします。統合テストでそれをするのは間違っているでしょう、おそらくそれがあなたのコメントで言及していることでしょうか?
samuelgrigolato

1
私にとって、テスト容易性は第一級の関心事です。デザインがテスト可能でない場合、それは良いデザインではありません。テストしやすくするためにデザインを変更しても問題はありません。それがまだ機能することを再検証する必要がありますが、問題ありません。テスト可能性は、コードIMOを変更する完全に正当な理由です
Carlos Rodriguez

10

実際、DIを使用して十分にクリーンでコンパクトなコードを書くのは非常に簡単です(おそらくPythonicであり続けるでしょうが、とにかく:))、たとえば、私は実際にこのコーディング方法を好みます。

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

はい、これは関数/クラスをパラメーター化する単純な形式と見なすことができますが、機能します。したがって、Pythonのデフォルトに含まれているバッテリーで十分かもしれません。

PS私はまた、Pythonでの単純なブール論理の動的評価で、この素朴なアプローチのより大きな例を投稿しました。


3
機能する可能性がある単純なケースの場合、さまざまなモデル(投稿、コメント、ユーザー)を使用する単純なWebブログコントローラーを想像してみてください。ユーザーに独自のPostモデル(それを追跡するための追加のviewcount属性を含む)と、より多くのプロファイル情報などを含む独自のUserモデルを挿入する場合、すべてのパラメーターが混乱する可能性があります。さらに、単純なCookieベースのセッションなどではなく、ファイルシステムセッションをサポートするために、ユーザーはRequestオブジェクトも変更する必要がある場合があります。そのため、まもなく多くのパラメーターが作成されます。
tux21b 2010年

1
@ tux21bさて、ユーザーがアプリケーションに実装することを望む「本質的な複雑さ」があり、それに対するアーキテクチャソリューションがあります(開発およびおそらくメンテナンス時間、実行速度などの点で、他のものより劣っいないものもあります)。 )、APIとソフトウェアアーキテクチャを理解する人間の能力があります。人間が理解できる解決策がまったくない場合((DIの(任意の形式の)DIを使用しているものだけでなく))まあ、すべての問題は解決可能だと誰が言ったのでしょうか。また、デフォルトで割り当てられた(ただし、ユーザーの選択によって交換可能な)パラメーターがたくさんある場合は、実際には十分な場合があります。
mlvljr 2010年

9

IoC / DIはデザインコンセプトですが、残念ながら特定の言語(またはタイピングシステム)に適用されるコンセプトと見なされることがよくあります。依存関係注入コンテナがPythonではるかに一般的になるのを見たいです。Springがありますが、これはスーパーフレームワークであり、「Pythonの方法」をあまり考慮せずにJavaの概念を直接移植したもののようです。

Python 3のアノテーションを考慮して、フル機能を備えたシンプルな依存関係注入コンテナーであるhttps://github.com/zsims/dicに亀裂を入れることにしました。これは.NET依存関係注入コンテナの概念(その領域でプレイしている場合はIMOは素晴らしい)に基づいていますが、Pythonの概念で変更されています。


6

Pythonの動的な性質により、人々は別の動的なフレームワークの必要性をしばしば目にすることはないと思います。クラスが新しいスタイルの「オブジェクト」を継承する場合、新しい変数を動的に作成できます(https://wiki.python.org/moin/NewClassVsClassicClass)。

つまり 、プレーンpythonの場合:

#application.py
class Application(object):
    def __init__(self):
        pass

#main.py
Application.postgres_connection = PostgresConnection()

#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()

しかし、https://github.com/noodleflake/pyiocを見て、これがあなたが探しているものかもしれません。

つまり、pyioc

from libs.service_locator import ServiceLocator

#main.py
ServiceLocator.register(PostgresConnection)

#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()

2
どちらのバージョンでも同じ量のコードを使用するという事実は、フレームワークの使用があまり人気がない理由を説明するのに大いに役立ちます。
2015年

other.pyライン1、自動化された依存関係の解決方法はありますが、にもかかわらず依存性注入とそれをカウントしません。
andho

サービスロケーターは通常、アンチパターンであり、ただ言っているだけです。
PmanAce

6

私は "JörgW Mittag"の答えを返します: "DI / IoCのPython実装は非常に軽量なので完全に消えます"。

このステートメントをバックアップするには、JavaからPythonに移植された有名なMartin Fowlerの例を見てください。Python:Design_Patterns:Inversion_of_Control

上記のリンクからわかるように、Pythonの「コンテナ」は8行のコードで記述できます。

class Container:
    def __init__(self, system_data):
        for component_name, component_class, component_args in system_data:
            if type(component_class) == types.ClassType:
                args = [self.__dict__[arg] for arg in component_args]
                self.__dict__[component_name] = component_class(*args)
            else:
                self.__dict__[component_name] = component_class

42
これは、最も弱いDIコンテナーでさえはるかに不十分です。ライフタイム管理、再帰的な依存関係の解決、モックを作成する機能、またはすべてを失敗した構成はどこにありますか?これは、IoCと同じではないタイプのルックアップとキャッシュにすぎません。
基本的な

2
数年前、私は練習としてメタクラスを使用して小さなDIフレームワークを書きました。全体としては、インポートとdoctestを含まない単一のファイルであり、説明が必要です。基本的な機能は「Python的」でさえ実装するのがそれほど難しくないことを示していますが、Springのような完全なソリューションがJavaで大きな牽引を得ておらず、誰もがカスタムプラグインアーキテクチャを行っているのは悲しいことだと思います。
Andrea Ratto

2

私の2セントは、ほとんどのPythonアプリケーションではそれを必要としないことであり、たとえそれが必要な場合でも、多くのJava嫌い者(および開発者であると信じる無能なフィドラー)は、それがJavaで人気があるという理由だけで、それを何か悪いものと見なす可能性があります。

IoCシステムは、オブジェクトの複雑なネットワークがあり、各オブジェクトが他のいくつかのオブジェクトへの依存関係であり、それ自体が他のオブジェクトへの依存関係である場合に、実際に役立ちます。そのような場合、これらのオブジェクトをすべて一度定義し、できるだけ多くの暗黙のルールに基づいてそれらを自動的にまとめるメカニズムを用意する必要があります。また、アプリケーションのユーザー/管理者が簡単な方法で構成を定義する必要がある場合は、IoCシステムが単純なXMLファイルのようなもの(構成となる)からコンポーネントを読み取ることができるようにする必要があります。

典型的なPythonアプリケーションははるかに単純で、スクリプトの束であり、そのような複雑なアーキテクチャはありません。個人的に私はIoCが実際に何であるかを知っており(ここで特定の回答を書いた人とは対照的)、限られたPythonの経験でその必要性を感じたことはありません(また、どこでもSpringを使用していません。開発オーバーヘッドを正当化しないでください)。

そうは言っても、IoCアプローチが実際に役立つPythonの状況があり、実際、Djangoがそれを使用していることをここで読みました。

上記と同じ理由がJavaのアスペクト指向プログラミングにも当てはまる可能性がありますが、AOPが本当に価値のあるケースの数はさらに制限されます。


djangoがIoCを使用している情報源への参照URLはありますか?
Sajuuk、

@Sajuuk、私はこの質問のスレッドでDjangoについて知ったので、私にはわかりません。他の回答者に質問する必要があります。
zakmck

この回答の最初のalineaは私の意見に0の値を追加します...私のpythonコードがIoCから恩恵を受けるときを決定することができると思います、そして私は開発者が何が悪いと思うかについて気にしません。私は根拠のない意見よりも実用主義を評価します。
Mike de Klerk

@MikedeKlerk私の提案は、(ここに多くの回答が証明するように)未知であり、プレジャッジの犠牲者の両方が、客観的であり、あなたのような少数の人によく知られていても、人気になる可能性は低いということです。そしてもちろん、これがPythonでIoCの使用があまり見られない理由かどうかはわかりません。主な理由は、低/中程度の複雑性のアプリがそれらを必要としないことです。
zakmck

The typical Python application is much simpler, just a bunch of scripts, without such a complex architecture.-かなり仮定
hyankov


-1

PythonでDI / IoCが可能で、簡単で、さらに美しいという点で、@ Jorgに同意します。不足しているのはそれをサポートするフレームワークですが、いくつかの例外があります。私の頭に浮かぶいくつかの例を指摘すると:

  • Djangoコメントを使用すると、独自のCommentクラスをカスタムロジックおよびフォームに関連付けることができます。[より詳しい情報]

  • Djangoでは、カスタムプロファイルオブジェクトを使用してユーザーモデルにアタッチできます。これは完全にIoCではありませんが、良いアプローチです。個人的には、コメントフレームワークと同じように、ホールユーザーモデルを置き換えたいと思います。[より詳しい情報]


-3

私の意見では、依存性注入のようなものは、厳格で複雑なフレームワークの症状です。コードの本体が非常に重くなり、簡単に変更できない場合は、コードの小さな部分を選択し、それらのインターフェースを定義し、それらのインターフェースにプラグインするオブジェクトを介して動作を変更できるようにする必要があります。それで十分ですが、そもそもそのような複雑さを回避することをお勧めします。

これは、静的型付け言語の症状でもあります。抽象化を表現するために必要な唯一のツールが継承である場合、それはどこでも使用するものです。そうは言っても、C ++は非常に似ていますが、Java開発者が行ったあらゆる場所でビルダーとインターフェースの魅力を取り上げたことはありません。あまりにも多くの一般的なコードを書いてコストを犠牲にして柔軟性と拡張性を実現するという夢があれば、本当のメリットはほとんどなく、あふれ出すことは簡単です。です。文化的なものだと思います。

通常、Pythonの人々は、ジョブを実行するための適切なツールを選択することに慣れていると思います。これは、何でもできる1つの真のツール(千の可能なプラグインを使用)ではなく、考えられる一連の可能な構成の組み合わせを提供するものではありません。 。必要に応じて互換性のある部分はまだありますが、ダックタイピングの柔軟性と言語の比較的単純さにより、固定インターフェースを定義する大きな形式は必要ありません。


4
言語そのものではなく、フレームワークではありません。ダックタイピング言語が享受するような柔軟性を作成するには、静的に型付けされた言語に非常に高度なフレームワークとルールが必要です。DIはそれらのルールの1つです。Pythonの人々は二度と考えません。Javaの人々は本当にそれに取り組む必要があります。
S.Lott

6
@ S.Lott-私はあなたに完全に同意しますが、C ++の人々は、Javaの制限と同様の制限に取り組んでいるにもかかわらず、デザインとアーキテクチャのパターンの急増なしでうまくやっているようです。これは文化的な違いを意味していると思います。Javaの人々は何かをするための2つの可能な方法に直面すると、戦略パターンを促進するために別のインターフェースを抽出することを好むのに対し、C ++の人々はboolとifステートメントを追加します...
カイロタン

3
@Finglasなので、すべてを使用するクラスが12個あり、EmailSenderそれをで置き換えることにしたDesktopNotifier場合、12クラスを手動で編集する必要があります。そして、INotifierインターフェースに書き込んでコンテナーに詳細を処理させるだけの方が、よりシンプルでクリーンだと思いますか?
基本的な

1
残念ながら、ある程度の複雑さは、プロのソフトウェア開発者が直面しなければならない現実です。私は批判を目にしますが、この答えには解決策はありません。この問題の「pythonic」ソリューションは何ですか?私はライブラリを書いていて、ロギング(PHPのPSR-3 LoggerInterfaceのようなもの)のためのフックを提供したいと思っています。ログレベルの使用方法は知っていますが、プログラムが実際にどのようにレポートするかは気にしません。クライアントアプリがその実装の詳細を挿入できるようにするためのクリーンな方法は何ですか。注:アプリケーションの他の部分では、このインターフェースの実装が異なる場合があります。
Rob

2
私の質問は、標準のロギングライブラリをどのように使用するかではなく、ロガークラスの異なるインスタンスを作成することでもありません。私の質問は、アプリケーションのさまざまな部分が異なる実装を使用できるようにアプリケーションをどのように構成し、それらの詳細に関心を持たないか(インターフェイスの使用方法を知っている場合)です。これは、私が取り組んだ複数のPHPアプリケーションでDIが解決した非常に現実的な問題です。私は同等のpythonを探しています。また、「アプリケーションをそれほど複雑にしないでください」という提案は、私が探している答えではありません。
Rob

-5

Javaの強い型付けの性質とは異なります。Pythonのダックタイピング動作により、オブジェクトの受け渡しが非常に簡単になります。

Java開発者は、物事を柔軟に保ちながら、クラス構造とオブジェクト間の関係の構築に注力しています。IoCはこれを達成するために非常に重要です。

Python開発者は、作業を完了することに集中しています。必要なときにクラスを接続するだけです。クラスのタイプを気にする必要さえありません。ガクガクできる限り、それはアヒルです!この性質のため、IoCの余地はありません。


4
あなたはまだいちゃつくものを見つける必要があります。
andho
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.