依存性注入と制御の反転に対するいくつかの議論

.NET 1.1および2.0の時代には、多くの場合、主婦はすぐにWebサイトを作成し、プログラムを作成できると言って、Microsoftのエバンジェリストの予言を見ることができました。 ほとんどのプログラマーは笑ったが、結局のところ、誰かがこれを真剣に受け止めた。 いずれにせよ、これは、IoC / DI設計パターンが2000年代に、MS自体の内部でさえも第二の風になった理由を説明します(あなたの人生でSCSFに出会わないことを願っています)









ソフトウェア開発理論の観点から、私は個人的にIoC / DIに関する賞賛の記事やレビューを頻繁に読んだり聞いたりしなければなりませんでしたが、いつものように批判もあります。 たとえば、 ここ (英語)、 ここ (英語)、 ここ (Habr)、 その他 (英語)を見つけることができます。 特に、OOPでのカプセル化の原則への違反は非難されます。



しかし、私は神学的な論争(私は自分自身を専門家とは見なしていない)には入らず、就業日(私の意見では出版物ではほとんど取り上げられていません)に焦点を当てたいと思います。



確かに、コードには常にエラーが含まれていることを示すプログラミングに関する本や記事をたくさん見ましたか(電卓を100%テストでカバーすることはできません)、誰もあなたに任せない生産的な環境でエラーを診断する可能性を挿入する必要がありますスタジオとデバッグ? 製品が価値があると判明し、そのユーザーが見つかった場合、それは確かに確定されますが、トレーニングのレベルが不明な他の人がそれを行う可能性がありますか? それで、私は1つを思い出すことができません。



運命の意思による個人的およびその他の経営上のミスの結果、私はたまたまプロジェクトを立派に孤立させて実行し、以前は特別な欲求がなかったコードに突入しました。 モジュールの1つでIoC / DIを使用することは最大の問題ではありませんでしたが、特に以前の仕事の場所でこの抽象主義の奇跡に対処しなければならなかったので、それは最も鮮明で記憶に残りました。



だから。



理解するのが難しい



私は自分の時間のどこかで-ブルックス、またはリスターとデマルコのいずれか、私は正確に覚えていません-プログラミング言語は機械のためではなく、人々のために発明されたことを覚えています。 最終的に、ゼロと1を手でファイルに打ち込むか、最初にテキストコマンドを記述してから実行可能コードにコンパイルするかは、マシンにとって重要ではありません。 コンパイラーは、プログラマーがコードにコメントを挿入するか、自己文書化することを考慮するかどうかを気にしません。 JavaScriptインタープリターは、難読化され圧縮されたスクリプトをフォーマットし、人間が判読できる変数と関数の名前で処理します。



アーキテクチャとプログラミングのパラダイムについても同じことが言えます。これらはすべて、プログラムを書くタスクを容易にし、複雑さのレベルを上げるために、マシンではなく人のために発明されました。 したがって、IoC / DIテンプレートの最初の最も重要なマイナス点は、プロジェクトのさまざまな部分にロジックを配布することです。これは、ソリューション全体の理解と認識を非常に複雑にします。 より正確には、問題は実際の不連続性にあるのではなく、実行時にのみ静的にこれらすべてを接続することは非常に難しいという事実にあります。



プログラムが12個または2個のオブジェクトで構成されている場合(つまり、これらがクラスとインターフェイスの説明を含む100個以下のファイルである場合)、これを全体としてまとめるのは比較的簡単です。 かつて、Microsoft Smart Client Software Factoryに基づいて作成されたデスクトップアプリケーションに同行しました(MSの代わりにPrismを起動しましたが、IoC / DIも使用されているはずです)。その機能はそれほど複雑ではありませんが、数十のプロジェクト(Visual Studioの観点から)から、これらはDAL、ロジック、ユーザーインターフェイス、およびその下のイベントモデルを担当する数百ものクラスです。 毎回、新しい機能を追加するタスクが地平線に現れたとき、私は内側からわずかに打ち始めました。 見込み客は、データベースのオブジェクトの新しいフィールドの処理をどこに「貼り付ける」のかを把握するために数日を費やすこと、またはどのクラスの依存関係に応じてエキサイティングであるかを表明しました。 弱いつながりのクラスでは、これは最も些細な作業ではありません。



おそらく私の脳は硬直し始め、新しいアイデアの影響を受けにくくなりました(IoC / DIは90年代初期に発明されたようですが)、OOPからのカプセル化の原理が好ましくない理由を理解するのは困難です。



有益でないデバッグデータ



私はbashorgからの引用を思い出します:



#define TRUE FALSE // ,  (*)
      
      





(*) , .



, ? ( ):



Stack Trace
StructureMap.StructureMapException: StructureMap Exception Code: 202

No Default Instance defined for PluginFamily System.Func`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

at StructureMap.BuildSession.<.ctor>b__0(Type t)

at StructureMap.Util.Cache`2.get_Item(KEY key)

at StructureMap.BuildSession.CreateInstance(Type pluginType)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ConstructorInstance.Get[T](String propertyName, BuildSession session)

at lambda_method(Closure, IArguments )

at StructureMap.Construction.BuilderCompiler.FuncCompiler`1.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments args)

at StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments args)

at StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder)

at StructureMap.Pipeline.SmartInstance`1.build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session)

at StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance)

at StructureMap.BuildSession.CreateInstance(Type pluginType)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ConstructorInstance.Get[T](String propertyName, BuildSession session)

at lambda_method(Closure, IArguments )

at StructureMap.Construction.BuilderCompiler.FuncCompiler`1.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments args)

at StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments args)

at StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder)

at StructureMap.Pipeline.SmartInstance`1.build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session)

at StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance)

at StructureMap.BuildSession.CreateInstance(Type pluginType)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ConstructorInstance.Get[T](String propertyName, BuildSession session)

at lambda_method(Closure, IArguments )

at StructureMap.Construction.BuilderCompiler.FuncCompiler`1.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments args)

at StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments args)

at StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder)

at StructureMap.Pipeline.SmartInstance`1.build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session)

at StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance)

at StructureMap.BuildSession.CreateInstance(Type pluginType)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ConstructorInstance.Get[T](String propertyName, BuildSession session)

at lambda_method(Closure, IArguments )

at StructureMap.Construction.BuilderCompiler.FuncCompiler`1.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments args)

at StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments args)

at StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder)

at StructureMap.Pipeline.SmartInstance`1.build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session)

at StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session)

at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session)

at StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance)

at StructureMap.Container.GetInstance[T](String instanceKey)

at NNN.BBB.Integration.Uvhd.Dispatcher.Start() in j:\.projects\DDD\trunk\NNN.BBB.UvhdIntegrationService\Dispatcher.cs:line 30



, ? BBB, DDD, NNN – , -. . Dispatcher.Start() – MS Windows, . StructureMap – IoC. - , .. , .



, « ?», , .





, . IoC/DI Service Locator, . , .



. . , . .



-, 50 [] , .



-, , . , , .. « », . , – , . , . « – » , , , .





. , , . , , . , , , : , , , . «» .

3 .



  1. , , . , , , (, , - , ), . , «» .



  2. , .



  3. , , . - . , « . , ». , - , , , , .




, , DI/IoC, . , , , , , . , :






All Articles