From 786f051132869c85adc2abdbff45fc8553964ab1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 18 Mar 2018 17:19:30 +0100 Subject: [PATCH] DI: problem of misconfiguration for service access This is a tricky problem an an immediate consequence of the dynamic configuration favoured by this design. We avoid a centralised configuration and thus there are no automatic rules to enforce consistency. It would thus be possible to start using a dependency in singleton style, but to switch to service style later, after the fact. An attempt was made to prevent such a mismatch by static initialisiation; basically the presence of any Depend::ServiceInstance would disable any usage of Depend in singleton style. However, such a mechanism was found to be fragile at best. It seems more apropriate just to fail when establishing a ServiceInstance on a dependency already actively in use (and to lock usage after destroying the ServiceInstance). This issue is considered rather an architectural one, which can not be solved by any mechanism at implementation level ever --- research/try.cpp | 5 ++-- wiki/renderengine.html | 4 ++- wiki/thinkPad.ichthyo.mm | 65 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/research/try.cpp b/research/try.cpp index 2d46eb391..fa426d9a0 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -116,7 +116,6 @@ class DependInject; template class Depend { - public: using Factory = std::function; static SRV* instance; @@ -125,6 +124,7 @@ class Depend static InstanceHolder singleton; friend class DependInject; + public: SRV& operator() () @@ -209,6 +209,7 @@ class DependInject "but another instance has already been dependency-injected." , error::LUMIERA_ERROR_LIFECYCLE); Depend::instance = &newInstance; + Depend::factory = Depend::disabledFactory; } static void @@ -362,7 +363,7 @@ main (int, char**) SHOW_EXPR( checksum ); } SHOW_EXPR( checksum ); - SHOW_EXPR( dep3().probe() ); + VERIFY_ERROR (LIFECYCLE, dep3().probe() ); VERIFY_ERROR (LIFECYCLE, DependInject::ServiceInstance{} ); SHOW_EXPR( checksum ); diff --git a/wiki/renderengine.html b/wiki/renderengine.html index a715012ea..04f6874d7 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1927,7 +1927,7 @@ As we don't have a Prolog interpreter on board yet, we utilize a mock store with {{{default(Obj)}}} is a predicate expressing that the object {{{Obj}}} can be considered the default setup under the given conditions. Using the //default// can be considered as a shortcut for actually finding an exact and unique solution. The latter would require to specify all sorts of detailed properties up to the point where only one single object can satisfy all conditions. On the other hand, leaving some properties unspecified would yield a set of solutions (and the user code issuing the query had to provide means for selecting one solution from this set). Just falling back on the //default// means that the user code actually doesn't care for any additional properties (as long as the properties he //does// care for are satisfied). Nothing is said specifically on //how//  this default gets configured; actually there can be rules //somewhere,// and, additionally, anything encountered once while asking for a default can be re-used as default under similar circumstances. → [[implementing defaults|DefaultsImplementation]] -
+
//Access point to dependencies by-name.//
 In the Lumiera code base, we refrain from building or using a full-blown Dependency Injection Container. A lot of FUD has been spread regarding Dependency Injection and Singletons, to the point that a majority of developers confuses and conflates the ~Inversion-of-Control principle (which is essential) with the use of a ~DI-Container. Today, you can not even mention the word "Singleton" without everyone yelling out "Evil! Evil!" -- while most of these people just feel comfortable living in the annotation hell.
 
@@ -1964,6 +1964,8 @@ Deliberately, we do not enforce global consistency statically (since that would
 :the generated object again acts as lifecycle handle and smart-ptr to access the {{{SubBlah}}} instance like {{{mock->doItSpecial()}}}
 :when this handle goes out of scope, the original configuration of the dependency factory is restored
 
+We consider the usage pattern of dependencies a question of architecture rather -- such can not be solved by any mechanism on implementation level.
+For this reason, DependencyFactory prevents reconfiguration after use, but does nothing exceeding such basic sanity checks
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 535ca26d5..01f511e97 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -26792,6 +26792,7 @@ + @@ -26806,7 +26807,9 @@ - + + + @@ -26833,6 +26836,7 @@ + @@ -27093,14 +27097,63 @@ - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + +

+ Und das hängt nur von den Umständen ab. +

+

+ In einem einfachen statisch gelinkten Executable entfernt gcc die gesamte Variable sogar ohne Optimierung. +

+

+ +

+

+ In Zukunft könnten Compiler/Linker noch "schlauer" werden... +

+ + +
+
+
+ + + +
+
+ + + + + + +