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<SRV>::ServiceInstance<X> would disable any usage of Depend<SRV> 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
This commit is contained in:
parent
5516700523
commit
786f051132
3 changed files with 65 additions and 9 deletions
|
|
@ -116,7 +116,6 @@ class DependInject;
|
|||
template<class SRV>
|
||||
class Depend
|
||||
{
|
||||
public:
|
||||
using Factory = std::function<SRV*()>;
|
||||
|
||||
static SRV* instance;
|
||||
|
|
@ -125,6 +124,7 @@ class Depend
|
|||
static InstanceHolder<SRV> singleton;
|
||||
|
||||
friend class DependInject<SRV>;
|
||||
public:
|
||||
|
||||
SRV&
|
||||
operator() ()
|
||||
|
|
@ -209,6 +209,7 @@ class DependInject
|
|||
"but another instance has already been dependency-injected."
|
||||
, error::LUMIERA_ERROR_LIFECYCLE);
|
||||
Depend<SRV>::instance = &newInstance;
|
||||
Depend<SRV>::factory = Depend<SRV>::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<Dum>::ServiceInstance<SubDummy>{} );
|
||||
SHOW_EXPR( checksum );
|
||||
|
||||
|
|
|
|||
|
|
@ -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//&nbsp; 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.
|
||||
&rarr; [[implementing defaults|DefaultsImplementation]]</pre>
|
||||
</div>
|
||||
<div title="DependencyFactory" creator="Ichthyostega" modifier="Ichthyostega" created="201803110155" modified="201803180023" tags="def Concepts draft" changecount="9">
|
||||
<div title="DependencyFactory" creator="Ichthyostega" modifier="Ichthyostega" created="201803110155" modified="201803181619" tags="def Concepts draft" changecount="10">
|
||||
<pre>//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
|
||||
</pre>
|
||||
</div>
|
||||
<div title="DesignDecisions" modifier="Ichthyostega" created="200801062209" modified="201505310104" tags="decision design discuss Concepts" changecount="5">
|
||||
|
|
|
|||
|
|
@ -26792,6 +26792,7 @@
|
|||
<node CREATED="1521208242178" ID="ID_539882602" MODIFIED="1521208246821" TEXT="erforderliche Mechanismen">
|
||||
<node CREATED="1521208254376" ID="ID_1933406851" MODIFIED="1521208256603" TEXT="Singleton">
|
||||
<node CREATED="1521208339124" ID="ID_287433738" MODIFIED="1521209063045" TEXT="Closure über konkreten Ctor"/>
|
||||
<node CREATED="1521208339124" ID="ID_826329078" MODIFIED="1521387972747" TEXT="(optional)Closure mit speziellen Argumenten"/>
|
||||
<node COLOR="#338800" CREATED="1521209708336" ID="ID_1667188609" MODIFIED="1521332921903" TEXT="Storage für UnterBla-Instanz bereitstellen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -26806,7 +26807,9 @@
|
|||
</node>
|
||||
</node>
|
||||
<node CREATED="1521208257336" ID="ID_1129640741" MODIFIED="1521208261323" TEXT="ServiceInstance">
|
||||
<node CREATED="1521208859989" ID="ID_549061661" MODIFIED="1521208874756" TEXT="Lazy-Init-Factory deaktivieren"/>
|
||||
<node COLOR="#338800" CREATED="1521208859989" ID="ID_549061661" MODIFIED="1521387920055" TEXT="Lazy-Init-Factory deaktivieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1521208793630" ID="ID_1357481546" MODIFIED="1521335430941" TEXT="Service-Zugang in Depend<Bla> injizieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -26833,6 +26836,7 @@
|
|||
<node COLOR="#338800" CREATED="1521208724943" ID="ID_1527628667" MODIFIED="1521335442003" TEXT="smart-ptr-artiger Zugriff auf die Service-Impl">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1521208339124" ID="ID_1092066450" MODIFIED="1521387948246" TEXT="(optional)Closure über konkreten Ctor"/>
|
||||
</node>
|
||||
<node CREATED="1521208261887" ID="ID_384054163" MODIFIED="1521208264827" TEXT="Local">
|
||||
<node CREATED="1521209044203" ID="ID_1994153994" MODIFIED="1521209058181" TEXT="Closure über konkreten Ctor"/>
|
||||
|
|
@ -27093,14 +27097,63 @@
|
|||
<node COLOR="#338800" CREATED="1521253803963" ID="ID_100415207" MODIFIED="1521332991888" TEXT="Installation wenn Factory bereits genutzt wurde">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1521253831776" ID="ID_1332033733" MODIFIED="1521303545433" TEXT="Zugriff auf Service bevor er hochgefahren wurde">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1521253858692" ID="ID_442301762" MODIFIED="1521253866011" TEXT="tückisch">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node COLOR="#338800" CREATED="1521253831776" ID="ID_1332033733" MODIFIED="1521387909137" TEXT="Zugriff auf Service bevor er hochgefahren wurde">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1521253858692" ID="ID_442301762" MODIFIED="1521385565612" TEXT="tückisch">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1521253867787" ID="ID_662728746" MODIFIED="1521253891037" TEXT="beachte Lifecycle-Handle existiert noch nicht">
|
||||
<node CREATED="1521253867787" ID="ID_662728746" MODIFIED="1521385616988" TEXT="Lifecycle-Handle existiert erst viel später">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1521385652999" ID="ID_1974848336" MODIFIED="1521385657839" TEXT="statischer Schutz">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1521385660206" ID="ID_200575604" MODIFIED="1521385685919" TEXT="fragil">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
<node CREATED="1521385687874" ID="ID_1561975152" MODIFIED="1521386168998" TEXT="C++ kennt keine statische Klassen-Initialisierung">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1521385709463" ID="ID_713439022" MODIFIED="1521385757820" TEXT="workaround">
|
||||
<node CREATED="1521385721637" ID="ID_1822970415" MODIFIED="1521386025178" TEXT="Initialisieren eines statischen member">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1521385768359" ID="ID_1123247553" MODIFIED="1521385776914" TEXT="ist unzuverlässig">
|
||||
<node CREATED="1521385782861" ID="ID_1190214158" MODIFIED="1521385787152" TEXT="erfordert non-const member"/>
|
||||
<node CREATED="1521385787980" ID="ID_81600101" MODIFIED="1521385794375" TEXT="wird vom Compiler wegoptimiert"/>
|
||||
<node CREATED="1521385795059" ID="ID_1426898485" MODIFIED="1521386008204" TEXT="sofern er Wirkungslosigkeit nachweisen kann...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Und das hängt nur von den Umständen ab.
|
||||
</p>
|
||||
<p>
|
||||
In einem einfachen statisch gelinkten Executable entfernt gcc die gesamte Variable sogar ohne Optimierung.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
In Zukunft könnten Compiler/Linker noch "schlauer" werden...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1521386182598" ID="ID_1671815821" MODIFIED="1521386187993" TEXT="ist undurchsichtig">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1521386206627" ID="ID_1928841192" MODIFIED="1521386214661" TEXT="erzeugt eh bloß eine Fehlermeldung"/>
|
||||
<node CREATED="1521386219297" ID="ID_1181038545" MODIFIED="1521386233755" TEXT="...was auch noch beim Hochfahren des Service passieren kann"/>
|
||||
</node>
|
||||
<node CREATED="1521386241406" ID="ID_1481722887" MODIFIED="1521386259129" TEXT="es ist ein Architektur-Problem">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1521253986491" ID="ID_546204807" MODIFIED="1521254005609" TEXT="Singleton wenn Interfaceklasse abstrakt ist">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue