I remember that in the times of .NET 1.1 and 2.0, one could often see the prophecies of the Mayrosoft evangelists, they say, soon any housewife can create websites and write programs. Most programmers laughed, but as it turned out, someone took this seriously. In any case, this explains why the IoC / DI design patterns got a second wind in the 2000s, even inside MS itself (I wish you never to face SCSF in your life).
From the point of view of software development theory, I personally more often had to read or hear articles of praise and reviews about IoC / DI, but, as always, there is criticism too. You can read, for example,
here (English),
here (English),
here (Habr),
more (English). In particular, the violation of the principle of encapsulation in OOP is blamed.
But I would like not to go into theological disputes (in which I do not consider myself an expert), but to dwell on the working days (which, in my opinion, are not covered in publications).
Indeed, have you encountered many books or articles on programming, which would indicate that the code always contains errors (even a calculator cannot be covered with 100% testing) and you need to insert into it the possibilities of diagnosing errors in a productive environment where nobody will let you Studio and debug? What if the product turns out to be worthy and finds its user, then it will definitely be improved, but other people are likely to do so, with what level of training is not known? So I can not remember one.
')
By the will of fate As a result of personal and other managerial mistakes, I happened to launch the project in loneliness and plunge into the code, before which I had no particular desire. The use of IoC / DI in one of the modules was not the biggest problem, but it was the most vivid and memorable, especially since I had to deal with this miracle of abstractionist thought at a previous place of work.
So.
Difficult to understand
I read somewhere at the time — whether it was at Brooks, or Lister with DeMarco, I don’t remember exactly — that programming languages ​​were not invented for machines, but for people. In the end, it makes no difference to the machine whether you put your hands in a file with toes and edinichki or write text commands first and then compile into executable code. The compiler doesn’t care whether the programmer inserts comments into his code or considers that he is self-documented. The JavaScript interpreter will treat the obfuscated, compressed script and formatted with the same names of variables and functions in the same way.
About the architecture and programming paradigms, you can say the same thing: all this is invented for a person, not for a machine, in order to make it easier for him to write programs, to increase their level of complexity. Therefore, in my opinion, the first and most important disadvantage of IoC / DI templates is the distribution of logic across different pieces of the project, which greatly complicates the understanding and perception of the decision as a whole. More precisely, the problem is not in the actual breaking, but in the fact that it is very difficult to tie it all together in statics, only in runtime.
If your program consists of a dozen other objects (i.e., it is not more than 100 files with a description of classes and interfaces), then it’s relatively easy to take all of this together as a whole. I once managed to accompany a desktop application created on the basis of the Microsoft Smart Client Software Factory (then MS launched Prism to replace MS, but I am sure that IoC / DI is also actively involved there), its functionality is not that complicated, but from a couple of dozens of projects (in terms of Visual Studio), and these are hundreds and hundreds of classes responsible for both DAL, and logic, and the user interface, and the event model under it. Every time when the task of adding a new feature appeared on the horizon, I started to be pounded slightly from the inside, because The prospect of a fascinating spend a few days surfaced to figure out where to “stick” the processing of a new object field from the database, more precisely, for which classes the dependencies were pushed. When classes are weakly connected, believe me, this is not the most trivial task.
Perhaps my brain began to coarsen and became less susceptible to new ideas (although IoC / DI were invented, it seems, in the early 90s), but it is difficult for me to understand what the principle of encapsulation from OOP has become.
Low informative debug data
I remember a quote from a bashorga:
#define TRUE FALSE // , (*)
(*) , ., ?
( ):
Stack TraceStructureMap.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 .
- , , . , , , (, , - , ), . , «» .
- , .
- , , . - . , « . , ». , - , , , , .
, , DI/IoC, . , , , , , . , :
- 100%, , , .
- - , ( ) .
- , «» -; -, , , , , , // .