Mittwoch, 28. Februar 2018

PantherDI - Part 8: Progress-Update

This blogpost does not come with a released version. Instead I just want to give an update about the progress I made and where I still want to go before the release.

PRISM integration


The first and big change was the PRISM integration library which I decided to create as a separate repository that uses PantherDI as NuGet-Package.
While implementing this, I noticed that I needed to register some types only when the user of PantherDI hadn't already registered implementations for them.
The container (or container builder) does not have any support for this and I didn't want to give the PRISM integration library any control over PantherDI that a normal developer wouldn't have.
Thus I started my first approach of registering a type as a fallback (meaning it'll only be used if no type is already registered).
The idea was to create a container which only contains the fallback types and add this to the original container in a way that it's only used if the original container can't find anything.
Thus I started working on the general topic of adding containers to new containers and came up with three ways this could be done:

  • Adding a container as a resolver
  • Adding the providers of a container as factories
  • Creating child containers (which can access their parents content but not otherwise)

Nested Containers

Adding a container as resolver

This part was rather easy at first:
To add a container as resolver, I made it implement IResolver and implemented the Resolve method to simply call on the knowledge base and its resolvers to do the job.
I then refactored this, so a container needs to explicitely converted to a resolver using the AsResolver method.

Adding the providers of a container as factories

To do this I needed to create some code that creates a catalog from a container by iterating through all its resolvers and converting their content to registrations.
Since there are two resolver types that directly contain registrations and two types that contain more resolvers, I made this a depth-first-search through all resolvers.
For now only the knowledge base and the unconverted registrations in a RegistrationConverter can be converted. All resolvers implementing IEnumerable<IResolver> will be recursively processed.

Creating child containers

To create a child container in runtime I plan to make the interface IContainerBuilder resolvable.
When resolved, the container builder will build children of the container that resolved it.
That means that the new container has full access to the content of its parent, but the parent container is unable to resolve the content of its child.

This is added because normally the content of a container is immutable once it's been created.
If a container is disposed however, it will also dispose all of its children.

All singletons created will be part of the container that created them.
So child containers can not (yet) be used to indicate lifetime scopes.
Lifetime scoping is a feature planned for the future however.

Fallback registrations

However this does not solve the original problem of registering types as fallbacks for when no other registration exists.
I'm pondering two options right now - and will most likely add both:


  • Adding optional priorities to catalogs, registrations and factories
    Only the providers with the highest priority will be used, others will be ignored. A priority on a node deeper in the registration tree overrides the value it inherits from its parents. No priority means highest priority.
  • Making it possible to specify fallback catalogs.
    This would be implemented by making the ContainerBuilder store a second List<Catalogs>.
    The factories from the second list will only be considered for a contract if there isn't yet factory present for it.


Then the PRISM integration library could be completed and a simple sample project created. The sample will grow and show how-tos for using PantherDI with PRISM.

Donnerstag, 4. Januar 2018

PantherDI - Part 7: Generated Code

In this blogpost I will describe implementation of features that were left because they needed code generation. Between christmas and new years I sometimes felt the urge to continue working on PantherDI and thus read up on code generation using T4-Text-Templates and implemented these features.

Resolving any Func<..., T>

Goal of resolution of Func-Types is that all of them can be resolved, no matter how many parameters the function has. Note that when I use "parameters" in this post, I don't talk about the type parameters of Func<...>, but the parameters of the function itself or in other words the type parameters except for the last one (which is the result type of the function). Since there is no meta-type which matches all of them, there needs to be code for all possible number of parameters. This code is mainly copy and paste plus adding a new entry into some lists for each added parameter. Thus I decided to solve that problem using code generation and learning about T4-Text-Templates.
First of all I refactored the Func1Resolver, so the main logic resides in a new static method of a new class. This method takes the parameters of the function as an array and uses them to create the actual provider. The algorithm for creating the provider is the same as it was for the Func1Provider:
  • Get all providers for the return type that fulfil the given contracts. Take into account that one contract might need to be replaced with the return type
  • Filter out providers that don't depend on the parameters of the function
  • Wrap each provider to returns a function that when called
    • adds the function parameters to the dictionary of resolved types that were passed to the wrapped provider
    • call the wrapped provider with the new dictionary
    • return its result
Next I created the text template which calls the new base function. While doing so I moved getting all providers for the return type into each generated Func#Provider, because replacing the Func<...>-Type in the list of expected contracts with the return type of the function can only be done when the Func<...>-Type is known.

Registering any Func<..., T> as factory

Registering custom factories was not implemented at all before because the only way to create a factory was using a MethodInfo or ConstructorInfo. But enabling to register any function as factory is a major part in any dependency framework in my opinion, so this was a rather important step to me. Thus this change is actually two changes in one:
  • Enabling the user to create a factory from any Func<..., T>
  • Enabling the user to register any IFactory

Create a factory from any Func<..., T>

This calls for a new factory type, the DelegateFactory. But since I don't want to create the whole DelegateFactory using text-templates, I split it up into two partial classes. One contains the actual functionality of the DelegateFactory (which means the implementation of IFactory) and a base constructor taking a Func<object[], object> (the implementation of the Execute-function). The other contains generated static creation methods that each take a different Func<..., T>, convert it to an Func<object[], object> by simply mapping the entries of the array to the formal parameters of the input function.

Registering any factory to a ContainerBuilder

To register any factory to a ContainerBuilder two new methods have been added:
WithFactory(IFactory, params object[]) expects the actual return type of the factory for creating a registration for that type and the factory itself. Optionally a list of additional contracts that only the result of this factory fulfils can be added. It just registers the factory with default settings.
RegisterFactory(IFactory) expects the same parameters but returns a type on which the settings for the registration can be changed. This way the factory can be registered as a factory for a singleton for example.
In addition to that a class with extension methods for the ContainerBuilder is generated that allows to directly register a Func<..., T> as factory to the ContainerBuilder.


Code

The code after implementing this blogpost can be found on GitHub under the Tag v1.3.0: Link

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.

Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.

Processing
Often means converting a Factory into a Provider by resolving all its dependencies that can be resolved.


Samstag, 23. Dezember 2017

PantherDI - Part 6: Metadata, Factories

Metadata


Apart from the metadata that PantherDI will hold internally, in this blogpost I will implement functionality which allows custom metadata to be registered for a type.
This metadata can then be used to further determine which resolved item will be instantiated for example when creating a dynamic plugin system.

Internal storage

Custom metadata are stored in a key-value store for each type where the key is a string and the value is an object supplied by the registration. It will not be possible to supply different metadata for each registered factory, the metadata will be attached to the registered type (=the registration) itself. Also it will be possible to request metadata which is not registered for a given type or to have metadata registered which is not be retrieved.
In other words: Registering and retrieving metadata is completely optional.

Registration by reflection

Metadata can be either registered manually (by adding it to the IRegistration) or - if reflection is used - registered with the means of attributes. Since the manual registration is rather trivial, I will mainly go over the registration via attributes as there are three ways to add metadata to a type: Attributing the type, marking a static property or field as metadata and metadata inheritance.
Both ways can be mixed, however a key must be unique for a type. PantherDI will throw an exception when a key is present more than once for the metadata of a single type. The only case where the presence of a metadata attribute with an already known key is when the key is added via metadata inheritance.

Attributing the type

The attribute Metadata can be used on a registered type to add an entry to the metadata of its registration. This attribute expects the key as well as the value of the entry. You can add as many of these attributes to a type. It is also possible to create your own attribute that inherits from the MetadataAttribute so the key, which is a magic string does not need to be supplied manually.

Attributing a static property or field

If the MetadataAttribute is added to a static property or field, the value of this property or field is read at the time of resolving the metadata (more on that later). While this allows the metadata to be changed during the lifetime of the container, it is advised to set the metadata statically and never change it afterwards.

When supplying metadata through a field or property, the key of the MetadataAttribute can be ommitted. This will cause PantherDI to use the name of the property or field as key for the entry. However if a key is supplied in the attribute, it is used instead of the property or field name.

Metadata supplied as fields or properties will always override metadata supplied on the type itself.

Inheriting metadata

Metadata on a type will also be set on types it inherits from. These inherited entries can be overriden on the derived type.
Thus the normal inheritance mechanism can't be used: PantherDI needs to know which entry comes from which type, so overriding is done correctly.

Retrieval

To retrieve the metadata of a type, Lazy<T, TMetadata> needs to be resolved. PantherDI will create a new instance of TMetadata and fill all its public, non readoly properties with the metadata.
The rules for doing so are as follows:

  • If the property is decorated with a MetadataAttribute, the key from it will be used to retrieve the entry. This is why the MetadataAttribute can be instantiated without value. However if a value is supplied, it will be ignored.
  • If the attribute is missing, the name of the property is used as a key
  • If the metadata of the type contains an entry which is not reflected in a property of TMetadata, it is simply ignored.
  • If a property of TMetadata can't be matched to an entry in the metadata, its setter will never be called.

This allows the consumer of metadata to easily specify which entries are of interest.

Creating your own MetadataAttribute types

If you create a type that inherits from MetadataAttribute, PantherDI will also use it to gather metadata or mark properties to be filled with metadata. That way you can create your own attribute and use that instead of the key.

Missing registration of instances via properties and fields

During implementation of registration of instances I forgot to implement registration via static properties and fields. Now that metadata can be registered in a similar way, I will fix that bug, using the same mechanisms to detect these an assembly is scanned. 
The field or property needs to be decorated with the ContractAttribute and just like decorating a type, the set of ContractAttributes will determine the fulfilled contracts of the registered instance.
If a contract attribute is present without a contract, the name of the property and its type will be used.
Instances registered in that manner can not have any metadata (for PantherDI would be unable to distinguish whether you want the property or field to be the value of a metadata entry or whether the metadata should be annotating the property or field).

To enable registration of instances with their own contracts, factories now can have a set of fulfilled contracts too. These contracts are only fulfilled when the respective factory is used to create the instance.

FactoryAttribute for registration of static methods as factories

Instead of just using the constructors, PantherDI supports registration of static methods as factories. If a static method is annotated with the FactoryAttribute, it will be considered a factory for the return type. ContractAttributes can be used to further annotate the method and add contracts that will only be considered as fulfilled when the factory is used.



Code

The code after implementing this blogpost can be found on GitHub under the Tag v1.2.0: Link

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.

Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.

Processing
Often means converting a Factory into a Provider by resolving all its dependencies that can be resolved.

Samstag, 16. Dezember 2017

PantherDI - Part 5: Instance registration, Late processing, IgnoreAttribute

License and readme

First up a rather smaller change: The project now features a license file and a readme.
I chose the creative commons Attribution 4.0 international license, because it empowers others to build upon my work and use it in commercial projects too.

Instance registration

One of the features still missing is the ability to hand an instance of an object to the container and have it return the instance whenever a request matches its registration. The basis for the implementation is rather simple for it is just a factory that declares no dependencies and returns the given instance.

In the ContainerBuilder however there will be two new methods: WithInstance and RegisterInstance.
While WithInstance simply registers the instance and returns the ContainerBuilder, providing chainability, RegisterInstance returns an object which allows to modify the registration.

Late processing

The major philosophy of PantherDI is to put the time consuming stuff up front which stems from the philosophy found in medical projects. This ensures that it is always well known when the work will be done and that user interaction can't create a package of workload while the application runs and maybe even while time critical processes are executed.
Usually during normal application development this is not a requirement and thus this default behavior which leads to a slower application startup actually counteracts what the developer wants to achieve.
Thus I want to implement a way to revert that behavior and process registrations only when a type is requested that the registration handles. This removes processing time from the application startup (or container creation) and spreads it out over resolution requests. If a registration is never requested, it won't be processed at all.

The implementation of late processing is rather simple. First of all the container no longer holds the knowledge base. Instead it "only" holds a cache, which contains the result of resolutions for a specific request. If the cache already contains a result for the request, it will be used.
During normal operation the KB will be handed to the container as first resolver. As it was before, only if it does not contain a solution for the given request, the other resolvers are actually triggered. But instead of adding their results to the KB, they will also just be added to the cache. This will only be a slight change when using the default configuration, but when late processing should be used, the first resolver won't be a pre-filled KB, but a resolver that first processes any registrations that fulfil the first requested contract and then query the KB. This is the same behavior as it was in the ContainerBuilder when requesting to process a specific contract.

As you can see, separating the ContainerBuilder from the logic that does the actual processing was already a step towards implementing this feature: The change will be that the RegistrationConverter will be put into a resolver.

IgnoreAttribute

The IgnoreAttribute is meant to tell PantherDI to not process items via reflection it would otherwise process. Its detailed semantic changes depending where it is placed:

  • Used on a type, the Container won't contain this type even though it implements an interface or inherits from an abstract class marked as contract.
  • Used on a constructor, it will not be used as a factory for that type
  • Used on a parameter of a constructor, the parameter won't be resolved, even if it could, rendering the type only resolvable by Func<TIn, TOut> when using this constructor.
    This enables to create constructors for view-models that take the corresponding model, even when in non-strict mode and thus the model could be resolved.
While implementing ignoring a constructor parameter, I noticed a bug in the GenericResolver base class: The filter condition for when the GenericResolver was used always chose to use the resolver when the requested type was not a generic at all. system tests were added and the condition now does not use the GenericResolver when either the requested type is not a generic or the generic type definition does not match the implemented GenericResolver.

Code

The code after implementing this blogpost can be found on GitHub under the Tag v1.1.0: Link

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.


Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.


Processing
Often means converting a Factory into a Provider by resolving all its dependencies that can be resolved.


Mittwoch, 13. Dezember 2017

PantherDI - Part 4: The first release

Okay, so here it is. The blogpost with which the first released version of PantherDI will be published.
But still this does not mean that PantherDI is finished. The roadmap can be viewed in the GitHub-Issues by filtering by the "New Feature"-Tag.

Switching to DotNetStandard

The easiest part in this blogpost will be the switch to DotNetStandard. A colleague actually triggered me trying it after having had issues with KittyDI and the test project. Well, what can I say? I simply created a new Project in the solution, targeted DotNetStandard 1.0, copied all files to it and changed the reference in the test project. Basically the only changes I needed to to was switching between TypeInfo and Type in several places and replacing a.IsInstanceOfType(b) by b.IsAssignableFrom(a). 
After that all the projects compiled again and the tests ran green.

DirectoryCatalog

This one actually got lost while adding the reflection stuff.
The DirectoryCatalog simply scans a directory for assemblies, tries to load them and if it succeeds will create an AssemblyCatalog for each found assembly. The DirectoryCatalog itself will return the merged result of these AssemblyCatalogs. Since loading an assembly from a file is not supported in DotNetStandard (yet?), the DirectoryCatalog will be part of an extension that targets the regular .NET-Framework.

Fluent Syntax for ContainerBuilder

This is mainly convenience for the developer using the library. The goal is to give the developer an opportunity to do all registrations that PantherDI offers by calling methods on the ContainerBuilder.
Also the code that converts registrations to the knowledge base is moved out of the ContainerBuilder itself.

The ContainerBuilder now knows three ways to add something to the configuration which will then produce the DI-container:

  • Using a version of the Add-Method
    This enables the use of the collection initializer syntax too.
  • Using one of the With*-Methods
    These return the ContainerBuilder itself, so they can be chained.
  • Using one of the Register*-Methods
    These return a different object, which enables to change the registration using a fluent interface.

Since the collection initializer syntax is only available, when an object implements ICollection, the ContainerBuilder will enumerate over all catalogs, registrations and resolvers that it contains when enumerating its contents.

In addition a helper class for RegisterType has been introduced that enables configuring how the type should behave. By default it will neither use reflection to determine which contracts the type providdes nor use the constructors of the type as factories. This behavior can be changed however.

Also the With*-Methods contain convenience-methods, so the setup can be more concise when using the encouraged configuration. For example the method WithGenericResolvers will add all resolvers for generics that ship with PantherDI. If all but one should be used, the method WithoutResolver<T> can be used to remove the resolver again.

Adding CI/CD

Now it's getting real: I'm going to add the repository to Appveyor which will add Continous Integration to the project. Also I want to configure it that upon pushing a tag it will build a release, package it with NuGet and publish that in the Appveyour-NuGet-Stream that you get with registering a project. This means PantherDI is technically ready to be used.

During implementation of the CI/CD using AppVeyor, I decided to change how or specifically when a new release will be created: AppVeyor is set up to build each PullRequest in GitHub and upon merging them, push the resulting packages to NuGet. This means that for each PullRequest the version number in the AppVeyor-configuration needs to be updated.
Since AppVeyor is unable to change the version of a dependency, the required version of PantherDI needs to be updated in the PantherDI.DNF-Package whenever the major version of PantherDI is changed. Version numbering should be according to "Semantic Versioning" (www.semver.org)

Roadmap

This does neither conclude the development of PantherDI, nor this series of blogposts. Instead all features I want to see in PantherDI are reflected in the issues on GitHub.

Code

The code after implementing this blogpost can be found on GitHub under the Tag v1.0.0: Link

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.


Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.


Freitag, 24. November 2017

PantherDI - Part 3: Singletons, Generics and Reflection

Singletons

A typical scenario for dependency injection that I saw is that most dependencies that get injected are only instantiated once. Thus PantherDI must offer a way to mark a registration as singleton, so only one instance will be created and then this instance will be returned on subsequent resolutions.
This is achieved by appending a flag to the resolution, which PantherDI can read. However, it also means that this flag needs to be transported down to the created providers.

Now I can think of two ways to implement that in the container. The first would be similar to how they were implemented in KittyDI: If it's a singleton, the provider will hold onto the first instance it creates and return this on subsequent calls without calling the providers for its dependencies. The other option would be for the container to hold on to the singletons it created and not even call the provider anymore, but instead use that singleton-cache.

Since I plan on each container disposing the singletons it created (but not the ones its parent container created) I'll opt for the second approach. So a container will hold the singleton-cache. For singletons the container will wrap the original provider into a SingletonProvider which will only call the original provider if the singleton-cache does not hold an instance. That way the container can quickly access all generated singletons during disposal.

This disposable behavior is also included in the changes made during this post.

Generics

I aim to make PantherDI handle certain generics differently when there is nothing actually registered for them. This will be done by using additional resolvers. The following generics are planned:
  • IEnumerable<T>
    Returns instances of all registered type that fulfill the given contracts and can be casted to the type T
  • Lazy<T>
    Doesn't instantiate the dependency immediately
  • Lazy<T, TMetadata>
    Also contains metadata that has been provided during registration
    This will be part of a different blog post
  • Func<T>
    Returns a function that, when executed, will create a new instance of the registered type.
    Except of course for singletons - there it will always return the same instance.
  • Func<T1,..., TOut>
    Like Func<T> only that it can be used to resolve types with dependencies unresolvable by the container.
    This can be used as factory-function for sub-viewmodels by simply adding the model to the constructors parameters and resolving Func<TModel, TViewModel>
    For now only the one-parameter version will be implemented
Also those generics should be nest-able, so when resolving an IEnumerable<Lazy<T,TMetaData>>, you should get an enumeration of not yet instantiated types that fulfill the given contracts and can be casted to the type T, including the registered metadata. This is a good thing when lazy loading plugins for example.

Implementation notes

  • Due to the same troubles as mentioned in the previous post, it was not possible to use Set operations and GroupBy to implement the EnumerableResolver, even though there is an IEqualityComparer for dependencies and one for sets that forces ISet<T>.SetEquals to be used - their Equals-Method is not used however although their GetHashCode returns the same value for both instances. Instead a workaround is employed. Again I ask for help on why this doesn't work and how to make it work with LINQ and Set-Operations.
  • Upon implementing the resolver for Lazy<T>, I extracted a helper class which does the pre-check and instantiates an inner resolver with the same type parameters as the generic that is to be resolved. So to create a resolver for MyType<T1,T2>, I just have to create a MyTypeResolver<T1,T2> and a proxy which inherits from GenericResolver and registers typeof(MyType<,>) and typeof(MyTypeResolver<,>) to the generic resolver.

Reflection

The topic of reflection falls apart into two areas: Automagic registration via reflection and using that to enable a non-strict behavior of a container. Automagic registration means the container will use reflection to determine what is registered and which contracts it has, the non-strict behavior enables types to be resolved without registering them at all, just like it was possible in KittyDI.

Registration

In order to perform registration via reflection, each element which is used to create a catalog, as well as the catalog itself will get versions that use reflection to set themselves up. To do so, a set of attributes will be added.

ConstructorFactory

The ConstructorFactory represents the constructor of a type and will create the type by invoking its constructor. It can be created by passing it the ConstructorInfo that Reflection will return. Each constructor parameter will be treated as a dependency. The contracts each dependency requires will be read from the ContractAttribute, if present. If no ContractAttribute is present, or if a ContractAttribute has no contract set, the type of the constructor parameter is used as contract.

TypeRegistration

The TypeRegistration registers a single type. It will contain a factory for each constructor of the type unless the constructor is decorated with the IgnoreAttribute. The fulfilled contracts will be
  • read from the ContractAttributes decorating the type itself. If one of these attributes is given without a contract, the type itself is used as contract.
  • read from the ContractAttributes on all implemented interfaces an up the type hierarchy
  • if no ContractAttribute is found at all, the type itself will be used as only contract
If the SingletonAttribute is present on the registered type, it will be registered as a singleton.

TypeCatalog

The TypeCatalog is a fast way to add TypeRegistrations to the container. As it implements methods to add types quickly which will generate a TypeRegistration for each added type.

AssemblyCatalog

The AssemblyCatalog scans a whole assembly and adds a TypeRegistration for each type which is decorated with a ContractAttribute, implements an interface decorated with a ContractAttribute or inherits from a type decorated with a ContractAttribute.

MergedCatalog

Not really related to reflection, the MergedCatalog will contain all registrations of all the catalogs it contains. If two contained catalogs contain the same registered type, the registration will be merged. This means the new registration will contain the union of the fulfilled contracts and the factories. It will be registered as a singleton as soon as one of the catalogs registers the type as singleton.

Non-Strict behavior

Non-Strict behavior will be achieved by the ReflectionResolver which will try to resolve any Dependency. It will do so by iterating over all required type contracts (and the expected type) to find a type which can be instantiated and fulfills all given contracts. To do so it will use the TypeRegistration to scan each type.
If a type is found, the algorithm to recursively resolve the dependencies of that TypeRegistration's factories is called from the container construction. Only this time it uses the function handed to the resolver for recursive resolution.
For this the function has been made static and returns the found Providers that it created. Adding to the knowledge base while container construction will be done in the calling function.

Code

The code after implementing this blogpost can be found on GitHub under the Tag Blogpost3: Link

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.


Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.

Mittwoch, 8. November 2017

PantherDI - Part 2: Constructing a container

Basic principle

The basic idea of container construction is that there is a data structure storing the unprocessed registrations which the construction algorithm will take out of the data structure, process and then add the generated providers to the knowledge base.
Processing the unprocessed registrations would basically work as follows:
  1. Get the next entry and remove it from the unprocessed registrations
  2. Resolve its dependencies
  3. For all possible combinations of resolved dependencies create a provider and add it to the knowledge base.

Dependency resolution during container construction

Requirements to the "unprocessed items" data structure

To ensure that the knowledge base contains all registrations needed for dependency resolution of the factory to convert, the algorithm needs to first process all unprocessed registrations for each of the dependencies' contracts first. This means that the data structure to store the unprocessed registrations needs a way of retrieving all registrations that fulfill a contract.

The chosen solution for the data sctructure which stores the unprocessed registrations is to use a dictionary that maps a fulfilled contract to all registrations fulfilling it. This does mean that removal is a bit costly as removing a registration means removing it from all dictionary entries. However the main scenario is that each type only fulfils one contract (which is the expected return type), so this overhead will only come into play in complex configurations.

Resolving the dependencies of the factory

In order to turn a factory into a provider, the construction algorithm needs to resolve its dependencies. For this it has a list of strategies which it will execute and use the concatenated results.
Each of these strategies will be called "Resolver".
While the default resolver is rather trivial, resolvers will also be used to handle certain "automagic" generics like IEnumerable, Lazy and Func. For now the most important part is that a resolver takes the a dependency as well as a function to resolve a dependency (which will run the list of resolvers again) and returns an enumeration of providers for the given dependency.

Accessing the knowlegde base

In its implementation it will store all providers in a dictionary that maps a single contract to an enumeration of the providers that fulfil it. The rest of the constraints will be checked by the resolver.
For encapsulation the knowledge base is a resolver in itself which will only rely on its contents.

Additional Remarks on the chosen implementation

Container

  • The container contains an internal resolution function which is passed to the registered resolvers. This will become interesting in the next blog post when we add implicit handling of certain generics.
  • The container already handles types not resolved by the knowledge base by adding their resolutions to the knowledge base. This is actually work done for the next blog post.

ContainerBuilder

  • While processing the registrations, the container builder will pull a registration from its to-do-list, remove it from that list and then process this single entry until the to-do-list is empty
  • While processing a factory, the builder will encounter dependencies of the factory. Before it tries to resolve those using the registered resolvers, it processes all registrations that fulfill the first contract of the dependency.
    Why only the first contract? Because all registrations that fulfill the other contracts but not the first can't be considered as dependencies, so all dependencies must be in the knowledge base as soon as the first contract has been processed.
  • After resolving all dependencies of a factory, each possible combination of providers for each dependency is converted into a provider, so if there is a partial resolution (=provider with dependencies) for a dependency, there also will be a partial resolution for the currently processed factory.
  • Unlike the container, the ContainerBuilder does not yet handle resolutions done by resolvers other than the knowledge base differently. This is due to the fact that it doesn't support adding custom resolvers yet (unlike the container).

Dependency

  • The dependency has a custom equality comparer. Still I need to manually invoke it to find an entry in a Dictionary<IDependency, T> or ISet<IDependency>. I would be happy if someone looked into that, so I could use the methods provided by the builtin dictionary and set structures.

ManualRegistration

  • For now the only way to register a type is by creating a ManualRegistration. However this series of blog posts will also handle the desired ways to create a catalog. These will mainly be via a builder with a fluent interface and via reflection.

Code

The code can be found on GitHub:

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI. 
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.


Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Resolver
An algorithm that utilizes the knowledge base to return all providers for a given dependency.
It may create new providers from the ones given in the knowledge base, depending on its purpose.

Samstag, 28. Oktober 2017

PantherDI - Part I: Interfaces

After developing KittDI with a rather naive approach (not thinking much prior, doing refactorings as I went) I decided to start another, more heavyweight library for dependency injection.


The first thing I want to talk about is the Interface of the library. To do this I am going to assume a usual workflow:

  1. Setting up the configuration for the new container
  2. Creating the container using that configuration
  3. Resolving what you need.

Container setup

Basically the setup of a container is a set of registrations. Upon construction, the container will use these to construct resolution strategies for the registered types. 


But what is a registration?
At first a registration is done for a specific type, so the data structure used for registrations needs to provide the type that is registered.
Next the registered type usually fulfils contracts, so for each registration we need to supply which contracts are fulfilled.
Then for each registered type there must be at least one way to create an instance of that type, so the registration needs an enumeration of factories for that type.
Each of these factories can have parameters (as in parameters of a function) which would be treated as dependencies of the registered type, when constructed using that factory.
Each dependency needs an expected type and a list of contracts that need to be fulfilled in order to satisfy the dependency. In the most cases the contract will be the expected type which both are the type of some interface, but any object can serve as contract.
Thus a dependency of a factory is modeled as a separate entity.
Also the factory has an execute-method which takes the resolved dependencies in the order given by the dependency list as an array of objects.

Container creation

To create a container it should be supplied with a catalog that contains the setup for the container. The algorithm that creates the container from a given catalog is the heart of PantherDI and will thus be within its own class for testability. It will create, what I will call the "knowledge base (KB)" of the container in future references. The KB contains an entry for each contract that can be fulfilled within the container. Each of these entries provides all ways to fulfill the given contract. A way to fulfill the contract is called a provider and just like the factories it too can have parameters, but when a provider in the KB does have parameters this means that during container creation this parameter was not resolvable using the catalog. This means that the KB basically contains a version of the factories which already know how to resolve the dependencies that actually can be resolved. Apart from that it it also contains the actual returned type, a full list of contracts fulfilled by this provider and additional metadata used by the container or set via registration.
The KB thus is a dictionary that maps contracts to a enumeration of providers. 

Resolving a registered type

To resolve a registration, the container needs an enumeration which contains at least one contract and a return type. A provider matches the request if it provides all the requested contracts and its actual type can be assigned to the requested return type. Since the typical call will be the return type being the contract, a parameterless call is allowed, causing the return type to be used as contract.

Test first (somewhat)

With that in mind the interfaces can already be created and with the interfaces already there, we can write tests for the behavior. But while I won't work test driven (meaning always implement the minimal solution to satisfy a test), I will write these tests up front and then use them to check if my implementation actually does what it should.
The following behavior should be covered by the tests (for now):

  • When no type is registered, trying to resolve by type or contract fails
  • When a type is registered, it can be resolved by its type and the registered contract type.
    The registered factory is called for each resolution
  • The registered type can also be used as contract
  • When a factory declares a dependency, the factory of that dependency is also called.
  • When multiple factories are registered that fulfil the contract requested, an exception is thrown
  • When there is a circular dependency, an exception is thrown
In order to write the tests without instantiating mocks for each interface, a first implementation of each interface is given, where all properties can be read and written, but without any internal logic.

Glossary

This chapter contains a cumulative list of terms that are used within this project.

Container
The central element of PantherDI.
It offers a way to retrieve instances of objects with all their transitive dependencies resolved.

Registration
Information about a single type, enabling a container to create it, resolve its dependencies and use it as dependency.

Contract
Any object that serves as the promise that a registration can be used as dependency. A registration can be retrieved only by contract, so the consumer does not need to know its actual type.

Factory
Basically the object representation of a function which will create an instance of a registered type.

Dependency (of a Factory or Provider, see below)
A single dependency of a factory is the object representation of one a function parameter. It includes meta-information, for example the contracts the instance passed needs to fulfil.


Provider
Created from a factory by resolving all the dependencies that can be resolved using the given registrations.

Knowledge Base (KB)
The knowledge base contains all providers that can be used by the container.

Code

The state of the code after this blogpost was written can be found under the tag "Blogpost1" in the GitHub-Repository: https://github.com/MarkusPalcer/PantherDI/tree/Blogpost1

Sonntag, 24. September 2017

KittyDI or "How I wrote my own dependency injection container"

Since KittyDI is rather well developed (I mainly just miss the NuGet packaging and publishing stuff and can't find the motivtion to actually do the PRISM-Integration), this blogpost will be more of a retrospective than a developers diary. I still file it as such, because it is planned as the first part in a series about me creating two DI-Container implementations.
But first things first:

How it all began

In the beginning there was... a project at Zühlke. my employer. While I can't disclose much of the project, I can say that we worked on a complicated enterprise application using Autofac and PRISM. At one point we used Autofac to populate a list with ViewModels for the items to be displayed. I thought that to be a rather nice approach as we only had to resolve a function that takes the model as an argument and returns the viewmodel. Autofac then takes care of selecting a constructor where it can resolve all dependencies but the model with types registered to the container and put the model in as last missing dependency.
This all worked pretty well, but it took a long time for the list of viewmodels to fill (with about 100 items in the list of models). So I wondered aloud why it takes so long to create 100 instances of a type and a coworker replied "Well that's obvious. Autofac needs to go through all the strategies of creating the viewmodel for each of the 100 instances."
My first thought was "Really? Can't it just re-use the strategy it used the last time?" Of course I dismissed that thought as being too naive and instead considered implementing my own dependency injection container just to learn the pitfalls of doing so. I just never got around doing that.
In my current project we're using the lightweight Java dependency injection container "Feather" to create an Android project. Inspired by the simple idea that Feather implements (which was basically the same idea I had back then) I decided to finally start that. So yes, KittyDI is inspired by Feather, but no I never used their code as an actual example.
Why I chose KittyDI as name? Because I viewed this DI container as an experiment. A first, naive, maybe even childish try to implement a DI container and to mature by doing so. The relation to felines should be obvious while reading this blog. If it isn't, check the archives.

The goal

My main goal of course was to learn, maybe to fail and see why, to see where the complexety lies and to see if writing a DI container really is as hard as I thought and as people made me think it was. (Spoiler: It isn't.)

For dependency injection my goals were to offer a mixture of the features MEF, AutoFac and feather offer. This means:

  • Being able to resolve a type which is not yet known by the container 
  • Telling the container which type to resolve when an interface is requested 
  • Registering types as singletons 
  • Resolving all registered implementations of an Interface 
  • Resolving a factory for a type 
  • Resolving a factory that takes parameters 
  • Putting containers inside each other 
  • Creating and resolving containers 
  • Automatic disposal of container contents on container disposal 
  • Resolving generics
  • And of course remembering how a type got resolved last time
Of these features I only scrapped resolving all registered implementations of an Interface. 

The work

I implemented KittyDI in an incremental way. 
The first functionality that got added was simple resolving of an unknown type. The approach was to check the constructors of the requested type and selecting the one that fits. There was the first decision: how do I choose which constructor to use. I decided for a simple approach that doesn't force the user to add an attribute to the constructor of each type he wants to resolve (like MEF does). Instead I decided that KittyDI always uses a parameterless constructor if it is there. If there is no parameterless constructor but only a single constructor with parameters, it is used and the parameters are in turn resolved. Only if there is no parameterless constructor and instead multiple constructors taking parameters, the attribute is needed to tell KittyDI which one to use. This does two things at once: it enables the user to simply resolve types without the danger of missing the attribute and getting cryptic exceptions and it makes it possible to use types defined in libraries that don't know about KittyDI. This was a major flaw I personally saw in MEF. After KittyDI decided how to resolve a type, it wraps that in a function and stores it in a dictionary so it doesn't have to search for the right constructor again. 
In order to prevent endless resolution loops KittyDI hands the resolution stack (meaning the types of all factories currently in the call stack) to an internal factory and if a factory is called where it's type is already on the stack we are in a resolution loop and throw an exception notifying the caller of the circular dependency. 

The next step was rather simple. After refactoring out the functionality which creates the factory for a type if it's not yet in the dictionary, I added the possibility to resolve that exact factory by providing a special function for that. In fact normal resolution turned into "resolve the factory and then execute it". Spoiler: I removed that function after I added generic resolving and turned resolution of a factory into a generic resolved. 

Singletons are handled by KittyDI either by setting an optional boolean parameter to true when registering the type of by adding an attribute to the type. If the type should be a singleton, it's factory is wrapped by one that on first call executed the inner factory and then just returns the result of that call on subsequent calls. 

The next rather important point was the ability to tell KittyDI which type to use to resolve an interface. This was also pretty naïvely implemented: First the function which ensures that the factory for a given type had been resolved is called for the implementing type and then it is put into the dictionary of known factories as factory for the"contract type". This way it is not just possible to do that for interfaces but for all types provided the implementing type actually inherits from our implements the contract. 

Next up was generic resolution. This means that I created a list of "generic resolvers" which intercept requests and instead of searching for constructors on the generic type perform their own logic. This is now used to resolve factories but it was also used to resolve IEnumerable<T> - something that I removed after I also added a generic resolver for Lazy<T>. I wanted nesting of generics to be allowed and IEnumerable proved troublesome here with the architecture KittyDI evolved into. This I scraped resolution of enumerables and moved that to PantherDI where I aim to give the architecture a bit more thought instead of letting it evolve. 

Now adding the possibility to resolve a factory which takes parameters was rather easy. I just needed to register a generic resolver which all have full access to the container and trigger resolution with the tires given in the parameters already set. The change I had to make was to add another parameter to my internal factories which is a dictionary of all types provided by the caller. While doing so, I decided to move all the information passed into an internal factory into an object instead of having to change the signature of functions all over KittyDI each time I added something. 

To prepare for more complex scenarios, the container supports adding whole containers. This enables the concept of scoping. Each step that is taken to resolve a type (checking the dictionary of known resolutions, checking if a generic type can be resolved and registering the type as new type) will search the DI-Containers that have been added to the container on which the original request was made. Only if the step did not yield any result when performed on the whole tree of containers, then the next step will be started.

Creating child containers then was rather easy. The child container is an empty container which searches its parent before failing each step. After creation, Types can be registered to the child, but they won't be known to the parent.
At the same time resolving a container (resolving the types "DependencyContainer" and "IDependencyContainer") yields a new child on each resolution.
This enables services or view models to register types only to the child and then resolve a helper that uses those.

Last but not least the container supports disposal. If it is disposed, it will dispose all instances of singletons that it has created as well as all child containers too.

Conclusion

As I already said writing a DI container is not that hard. But my main takeaway is - and I think that is a general rule in software development - that you should think beforehand about how you want to achieve your goal unless you want your code to become more and more messy and complicated to read over time.
Even though the PRISM integration isn't done, I see KittyDI as done and the experiment a success (KittyDI can be used in projects) and have many ideas - also on what to think about beforehand - for the mature version "PantherDI" (by now the source of the name should be obvious to the reader).

Further links

Freitag, 22. Januar 2016

Über Politik...

Ich habe eben ein längliches Kommentar zu einem Facebook-Post geschrieben, bei dem ich dachte, das könnte ich hier auch mal veröffentlichen.

Der Post, auf den ich mich beziehe, ist hier zu finden.

Und das ist meine Reaktion darauf:

Es ist wahr, dass Frau Merkel einen Job hat, der sehr fordernd ist - körperlich wie geistig. Gerade in der Politik gibt es so oft sehr komplexe Zusammenhänge, die einem erst auffallen, wenn man sich näher damit befasst. Daher ist es häufig auch nicht einfach, eine Entscheidung zu treffen, vor allem vor dem Druck der unweigerlich auf einem aufgrund der Tragweite einer jeden Entscheidung auf einem lastet.
Sie bekommt für diesen Job ein Gehalt, welches relativ zu meinem sehr hoch ist. Ob dies zu ihrer Arbeitsbelastung passt, kann und will ich nicht beurteilen.
Ich weiß jedoch dass ich mir diesen Job und die Verantwortung nicht zutrauen würde, von daher ist die Bundeskanzlerin ein Beruf, vor dem ich Respekt habe.

Ob die Entscheidungen, die unsere Regierung getroffen hat, richtig oder falsch waren, lässt sich teilweise auch nur schwer sagen. Ich weiß, dass ich aus meinem aktuellen Wissensstand heraus anders entschieden hätte, jedoch würde ich nicht behaupten, dass dadurch alles besser(tm) geworden wäre.

Ich finde nicht, dass Frau Merkel einen schlechten Job macht, wenn man bedenkt, dass sie bei dem, was Sie entscheidet auch vor allem die Interessen ihrer Partei vertreten muss - denn das ist ihr Job als Kanzlerkandidatin, sobald sie gewählt wurde. Da sie auch nicht allwissend und unfehlbar ist, hat sie nicht die alleinige Macht in Deutschland. Dafür hat sie eine Horde von Ministern, die mit ihr zusammen unsere Regierung bilden.

Doch auch die Minister sind einer Partei zugehörig und vertreten deren jeweilige Interessen.
Dass diese nicht mit dem Programm der jeweiligen Parteien übereinstimmen, ist absolut nichts neues und ich verstehe niemanden, der sich darüber wundert. Jedoch kann man diese Interessen sehr gut daran sehen, wie die Minister einer Partei abstimmen und welche Haltung sie in Interviews vertreten.
Wenn einem nicht passt, was eine Partei macht, sollte man sie nicht wählen, sondern eine andere Partei suchen, in der man seine Interessen findet. Findet man eine solche nicht, liegt es einem offen, eine eigene Partei zu gründen - jedoch ist es viel weniger anstrengend und durchaus befriedigender, sich auf Facebook über die Parteien und Politiker zu beschweren. ( Tipp: sich über sie lustig zu machen klappt auch und hält den Blutdruck niedriger)

Wer meint, er würde den Parteien zeigen, wie sehr er sie satt hat, indem er nicht wählen geht, spielt genau denen in die Arme, die er eigentlich Strafen will: Wenn die Wahlbeteiligung niedrig ist, zählt einfach jede ( also auch meine ) Stimme mehr und man unterwirft sich dem Urteil derer, die noch wählen gehen. Ich persönlich finde es sogar feige, da man sich nicht der Verantwortung stellt, dass man an der Urne die falsche Entscheidung getroffen haben kann.
Zu was eine immer niedriger werdende Wahlbeteiligung führen kann, kann man derzeit in Polen beobachten. Lasst euch das eine Warnung sein.

Meiner persönlichen Meinung nach, macht Frau Merkel einen guten Job, ihre Partei jedoch nicht.

Und um mal aus einem sehr schlauen Buch zu zitieren: "Es ist nicht der Job des Präsidenten [...] Macht auszuüben, sondern die Aufmerksamkeit von ihr ab zu lenken.
Schaut mal weniger auf Frau Merkel als Person, sondern mehr auf die gesamte Regierung.
Schaut mal, welche Partei Entscheidungen wirklich tut (Tipp: es wird auch im Parlament gewählt ) und überlegt nächstes Mal gut, wen ihr wählen wollt.

Mittwoch, 12. August 2015

Bei dem ist wohl eine Sicherung durchgebrannt

Diese Metapher hört man häufig, wenn Menschen extremes Verhalten zeigen. Im Grunde ist sie aber denkbar ungeeignet. Den Grund möchte ich hier einmal erläutern. Dazu möchte ich mir zunächst einmal die Bedeutung einer Sicherung in der Elektrotechnik anschauen.

Eine Sicherung, die durchbrennt, wurde bzw. wird meist aus einem Stück Draht gebaut, welcher sich bei zu starkem Stromdurchfluss erhitzt, bis er zu schmelzen beginnt und damit die Verbindung zwischen den beiden Kontakten der Sicherung elektrisch voneinander trennt. Daher nennt man eine solche Sicherung auch "Schmelzsicherung".
Schmelzsicherungen werden verbaut, wenn Bauteile vor zu großen Strömen geschützt werden sollen. 

Spontan fallen mir zwei Fälle ein, in denen dies passiert:
Den typischen Fall, den man im Haushalt findet, ist der Schutz vor einem Kurzschluss. Im Falle eines Kurzschlusses fließt in kurzer Zeit ein großer Strom, der unter anderem die Leitungen in der Wand eines Hauses zum schmoren bringen und einen Brand auslösen könnte. Daher wird in der Hausverteilung eine Sicherung verbaut, die zwar einen sehr hohen Strom aushält, aber rechtzeitig durchbrennt, dass die Kabel im Haus sicher sind. Da die Hitzeentwicklung des Kabels umso stärker ist, je dünner das Kabel ist, findet man hinter dieser initialen Schmelzsicherung magnetische Modelle, die schon bei geringeren Strömen auslösen und hinter denen entsprechend dünnere Kabel verlegt wurden. Der Vorteil der magnetische. Sicherungen ist, dass man sie wieder einschalten kann, während eine Schmelzsicherung ausgetauscht werden muss. Daher findet man in den meisten Verteilerkästen einer Wohnung nur magnetische Sicherungen mit Schalter.

Der zweite Fall, auf den ich mich im weiteren auch konzentrieren möchte, da er der Metapher eher entspricht, ist die Absicherung eines Gerätes vor einer Überlastung. Ich bediene mich hier Dem Bild eines HiFi-Verstärkers. Dieser verbraucht umso mehr Strom, je lauter man ihn aufdreht. Jedoch sind die Bauteile nur bis zu bestimmten Strömen ausgelegt und würden beschädigt werden, wenn zu viel Strom fließt. 

Normalerweise verhindert eine Begrenzung des Lautstärkereglers, dass die Ströme, die in dem Verstärker fließen über den Toleranzen der Bauteile liegen. Jedoch ist nie ausgeschlossen, dass es zu einem Fall kommt, in dem diese Toleranzen überschritten werden. Daher ist in einem Verstärker eine Schmelzsicherung verbaut, die dann durchbrennt, wenn zuviel Strom durch die Bauteile fließt. Dies sorgt dafür, dass dieser für die Bauteile gefährliche Strom nur sehr kurz fließt und die Bauteile möglichst intakt bleiben. Wenn eine solche Sicherung durchgebrannt ist, muss man sie austauschen, um das Gerät wieder benutzen zu können.

Nun möchte ich zurück auf die Metapher kommen und sie rückwärts anwenden, um zu zeigen, dass sie unpassend ist.
Wenn bei einer Person eine Sicherung durchbrennt, dann heißt das, dass sie sich in irgendeiner Art und Weise extrem verhält. Beim Verstärker, bei dem die Stromaufnahme mit der Lautstärke zunimmt würde das heißen, dass er extrem laut, lauter als normal möglich bzw. vorgesehen, verstärken würde. Und zwar immer dann, wenn seine Sicherung durchgebrannt ist. Jedoch ist das Gegenteil der Fall: Wenn die Sicherung des Verstärkers durchgebrannt ist, so wird er keine Töne mehr von sich geben. Eine Person, bei der eine Sicherung durchgebrannt ist, müsste demnach plötzlich nichts mehr tun, um sich davor zu schützen, etwas extremes zu tun.

Weiterhin ist dieser Extremzustand beim Menschen nur von begrenzter Dauer, auch ohne Einwirkung von außen. Jemand, der sich aufregt, regt sich mit der Zeit von alleine wieder ab.
Das heißt, die durchgebrannte Sicherung würde sich nach einer Weile (nämlich wenn die Extremsituation überwunden ist) wieder selbst reparieren. Wie schon erwähnt, muss eine Schmelzsicherung ausgetauscht werden. Einzig magnetische Modelle erlauben es, dass man die Sicherung wieder in den Urzustand versetzt und bisher habe ich noch keine gesehen, die das automatisch tut. Woher sollte sie auch wissen, wann der richtige Zeitpunkt gekommen ist.

Die Metapher ist also in zweierlei Hinsicht falsch: zum einen entspricht das Verhalten der Person eher  dem Fall, dass eine Sicherung hätte durchbrennen sollen, dies aber nicht getan hat, zum anderen besitzen Menschen in der Regel die Fähigkeit von alleine wieder in einen als "normal" empfundenen Zustand zurück zu kehren (wenn auch nur äußerlich).
Daher wäre es eigentlich richtiger zu sagen: Bei dem ist keine Sicherung durchgebrannt.

Dieser Beitrag wurde ihnen gesponsert von RandomThoughts Corp. und MobileInternet Inc.

Dienstag, 25. November 2014

Die Tribute von Panem und wir - wie nah sind wir den Leuten aus der Hauptstadt?

Ich muss zugeben, ich habe etwas gemacht, was ich normal als Fehler betrachte:
Nachdem ich das Hörbuch "The Hunger Games" gehört habe, habe ich mir gestern Abend den Film angesehen (die Auswirkungen davon schlagen sich immernoch in Müdigkeit nieder heute Morgen).
Normalerweise sehe ich das als ungute Idee an, da man sofort anfängt die "Fehler" im Film gegenüber dem Buch zu erkennen und damit den Film schlechter bewertet als wenn man sich ein wenig vom Buch gelöst hat vorher. Immerhin ist der Film die Interpretation eines Schauspielers der Interpretation eines Regisseurs der Interpretations eines Drehbuchautors einer Buchvorlage.

Interessant fand ich, dass der Film aber einen ganz anderen Fokus hat, wie die Bücher. Während die Bücher sich stark auf die Emotionen und Gedanken von Catnis (->Hörbücher, verzeiht eventuelle falsche Schreibweisen) vor, während und nach der Spiele, konzentrierten, konzentriert sich der Film auf einen anderen Aspekt. Das erste Buch zeichnet dabei eine Welt in der die Ohnmacht des einzelnen und auch der gesamten Bewohner der Distrikte im Vordergrund steht. Eine Welt in der die Armut stark hervorgehoben wird. Das Buch enthält keine Perspektivenwechsel, man erfährt immer nur das, was Catnis auch gerade erfährt bzw. was sie bereits weiß.

Im Film jedoch wird die Perspektive oft zu einer anderen Gruppe gewechselt: Zu den Spielmachern. Diese kommen im Buch lediglich in Sätzen vor wie "Ich kann mir vorstellen, die Spielmacher..." im Film sieht man jedoch direkt, was deren wirklichen Beweggründe für Dinge sind und teilweise auch stärker, wie sie auf die Spiele einfluss nehmen. Dies wird dadurch meiner Meinung nach in dem Film eher hervorgehoben und zeigt die Geschichte in einem ganz anderen Licht, denn es zeigt nicht die extreme Machtausübung der Hauptstadt gegenüber den Distrikten, sondern die Perversion ihrer Fernsehkultur. Wenn ich die Parallelen zum Kolosseum in Rom mal streiche, bleibt im Endeffekt übrigt, dass tragische Schicksale von Personen forciert und inszeniert werden für die Belustigung oder Zerstreuung des Volkes.

Was mich dabei so stark bewegt hat ist, dass man dies nicht nur in Panem findet, sondern auch in unserer Zeit. Die offensichtlichste Parallele wird man zu Big Brother und den damals entstandenen Derivaten (z.B. Solitude) ziehen können, was eine Sendung ist, in der die Teilnehmer 24/7 Kameraüberwacht sind und sich der Willkür der Spielmacher, verzeihung: Produzenten, unterwerfen. Noch schlimmer in diese Richtung gehen die ganzen Reality-Soaps, welche seit Jahren den Eindruck erwecken, die Darsteller seien lediglich von einer Kameracrew begleitet worden, obwohl die ganze Scheiße von den Machern inszeniert wird. Nicht immer kommen dabei wirklich Drehbücher und Schauspieler zum Einsatz, jedoch werden die Personen ähnlich wie in The Hunger Games so manipuliert, dass sie eine möglichst tragische Darbietung bieten. Wer dazu mehr erfahren möchte, kann mal durch das Archiv von Fernsehkritik.tv blättern.

Alles in Allem finde ich die Verfilmung von "The Hunger Games" gelungen, auch wenn sie einen ganz anderen Aspekt dieser Welt in den Vordergrund stellt, als es die Bücher tun und aus Sicht des Buches einiges an Fanfiction enthalten. Wir sollten diesen Film jedoch als Anlass sehen, unsere Fernsehgewohnheiten zu überdenken und zu überlegen, ob wir wirklich so enden möchten, wie die Leute aus Hauptstadt, bzw. inwieweit wir bereits so geworden sind.

Ich werde jetzt das zweite Hörbuch fertig hören und dann den zweiten Film sehen. Eventuell folgt daraus noch einmal ein Post, aber versprechen möchte ich nichts.
Wer die Hörbücher haben will: Zum Zeitpunkt an dem ich das Schreibe läuft das entsprechende HumbleBundle noch 13h, wer also schnell ist, kann für 15$ nicht nur alle drei Teile von The Hunger Games (auf englisch), sondern noch einen Pack andere Bücher bekommen: https://www.humblebundle.com/books

Montag, 3. November 2014

Wider die GDL vom Teufel gestift'

Ich hab grad so 'nen Hals:
Die #GDL hat schon wieder Streiks angekündigt. Diesmal sind sie sich aber zu fein, zu verraten, _wann_ sie streiken.
Der Kampf für mehr Lohn und bessere Arbeitsbedingungen ist ja ganz löblich, nur auf wessen Rücken wird der denn ausgetragen?
Eigentlich sollen die Streiks ja den Arbeitgeber treffen, der durch die Arbeitsniederlegung Umsatzeinbußen hat. Hat die Bahn mit Sicherheit und das auch nicht ganz unverdient bei dem Haufen, jedoch trifft es sie nicht am härtesten.
Am härtesten betroffen sind eindeutig die Fahrgäste, vor allem die, welche auf die Bahn angewiesen sind, um zur Arbeit zu kommen.
Gehen wir aber erstmal vom Normalfall aus, nämlich dass der Streik angekündigt wird. Hier wird immer so toll gesagt, dass man sich halt um Alternativen bemühen muss und daher Pech hat. Das kann ich im ersten Moment auch nachvollziehen, um ehrlich zu sein - das heißt, solange es wirklich Alternativen für die Strecke gibt, die mir ermöglichen zur Arbeit zu kommen (und das _bevor_ mein Arbeitsplatz schließt). Für viele Pendler sollte das aber der Fall sein, daher ist diese Regelung erstmal okay - wenn auch ziemlich ärgerlich.
Nun ist es jedoch so, dass zu bestimmten Zeiten auf bsetimmten Strecken (z.B. morgens S3 von Frankfurt nach Eschborn) die Züge schon extrem überfüllt sind, so dass ein betriebsbedinger Ausfall (z.B. ein Schaden am Zug) dazu führt, dass eine riesen Traube von Pendlern am Bahnhof steht. Wer jetzt darauf verweist, dass man ja mit Bus und Taxi weiterfahren kann, war eindeutig selbst noch nicht in der Situation, denn die wenigen Busse sind mit dem plötzlichen Ansturm von Pendlern total überfordert (es kann pro Bus jeweils nur ein Bruchteil der Pendler mitgenommen werden, die Menschentraube verkleinert sich scheinbar überhaupt nicht) und wenn man einen Taxidienst anruft, wird man eher ausgelacht, denn die Taxen sind quasi sofort ausgebucht. Die einzige Chance, die man noch hat ist, wenn man seine Firma das Taxi bestellen lässt, denn die werden scheinbar bevorzugt behandelt. Ein Ausfall eines Zuges auf der Strecke führt also in der Regel zu einem ziemlichen Chaos - Ausweichstrecken gibt es also effektiv nicht. Während eines Streiks sieht das ähnlich aus. Die Pendler, die glücklich genug sind, ein Auto ihr eigen zu nennen oder eine Fahrgemeinschaft bilden zu können, füllen in langen Staus die Autobahnzufahrten nach Eschborn, die Autolosen überfüllen die wenigen Busse, die als einzige Verbindung zwischen Frankfurt und Eschborn fahren. Ein Schelm, wer Böses in Zusammenhang mit dem Umstand vermutet, dass Eschborn Frankfurt viele große Firmen "weggenommen" hat, weil es steuerlich einfach günstiger ist. Okay, wir halten fest: Bei einem bekannten Streik kann ich mich darauf vorbereiten, dass es länger dauert, weil ich eine andere Strecke fahren muss, wobei es immernoch Glückssache ist, ob ich diese geplante Zeit einhalte, da es jeder, der nicht anders kann, auf diesem nicht für diese Massen ausgelegten Wege versuchen.
Ist der Streik nun unangekündigt, kann es mir passieren, dass ich gerade in der S-Bahn sitze, wenn diese stehen bleibt und meint "so, wir fahren nicht mehr weiter, wir streiken!". In dem Moment sitze ich zunächst einmal irgendwo im Untergrund von Frankfurt, habe kein Internet (denn zum einen gibt es faktisch keinen Netzausbau in den Frankfurter S-Bahn-Tunneln, zum anderen will jetzt verständlicherweise _jeder_ mit seinem Smartphone ins Internet) und kann mich also nicht darüber informieren, wie ich nun genau von _hier_ zu meinem Arbeitsplatz komme, ohne die Bahn zu benutzen. Natürlich könnte ich für jede Station durch die eine S-Bahn fährt einen Notfallweg mitnehmen, jedoch würde das bedeuten, dass ich ein kleines Heftchen Papier mit mir rumschleppen muss, da zwischen OF-Ost und Eschborn 7 Haltestellen liegen (sofern ich keine Vergessen habe) und die "Ersatzstrecke" natürlich nicht parallel zu dieser verläuft. So muss ich also für jede dieser 7 Haltestellen eine Ersatzroute parat haben. Gehen wir aber einfach mal davon aus, ich hätte diese Ersatzroute immer dabei (also merken könnte ich sie mir eindeutig nicht), so muss ich diese immernoch fahren und komme damit sicher nicht schneller ans Ziel. Um genau zu sein ist mein Weg zur Arbeit doppelt so lang, wenn ich gar nicht erst von der ersten Haltestelle weg komme (Warten auf den ersten Bus der korrekten Linie mal ausgenommen). Das ich nicht in der Lage war, mich auf den längeren Weg vorzubereiten - wir gehen schließlich von einem Streik aus, dessen Termin mir nicht bekannt war - bin ich also eine Stunde später als geplant an der Arbeit. Natürlich hat mein Arbeitgeber Verständnis dafür (ich bin ja nicht in einer schlechten Zeitfirma, wo man für sowas einen Grund in den Krümeln sucht, den Mitarbeiter zu kündigen) und ich bekomme erst einmal keine Probleme, dass ich "zu spät gekommen" bin. Um genau zu sein haben wir Gleitzeit, daher interessiert es meinen Arbeitgeber erstmal weniger, wenn ich mal eine Stunde später komme - mache ich manchmal auch einfach so, weil ich morgens keine Lust habe, so früh aufzustehen. Jedoch muss ich dennoch meine acht Stunden arbeiten, wenn ich nicht eine Stunde aus meinem Gleitzeitkonto abbauen will. Jedoch hatte ich gar keine Möglichkeit, pünktlich zur Arbeit zu erscheinen, vielmehr war eine andere Gewalt, die mich dazu zwang, später zur Arbeit zu erscheinen. Effektiv ist die GDL hier Schuld, denn die hat den Termin des Streiks gewählt und entschieden, ihn mir nicht mitzuteilen. Ach, da kommt mir eine Idee: Soll die GDL mir doch diese eine Stunde bezahlen - im Gegenzug unterschreibe ich sogar, dass ich an diesem Tag keine Überstunden mache und mir von der Firma die eine Stunde als unbezahlten Urlaub anrechnen lasse (damit niemand behaupten kann, ich würde für diese Stunde doppelt Geld kassieren).
Was ist aber nun, wenn ich einen Kundentermin habe (was theoretisch gesehen durch einen nicht gewonnenen Auftrag meiner Firma einen noch höheren Schaden einbringt, der meiner Meinung nach auch von der GDL zu begleichen ist)? Nun, wenn ich von dem Streik vorher weiß, kann ich auf anderem Wege zu dem Kunden fahren - auch wenn es dadurch länger dauert, mein Pech halt. Sehe ich erstmal ein - außer ich müsste um 9 Uhr abends los fahren, um mit Bus pünktlich beim Kunden zu sein (lassen wir mal das optische und olfaktorische Problem, was das mit sich bringt, ausser Acht). Andererseits kann ich mir natürlich auch ein Taxi nehmen - hier bin ich mir sicher, dass die Taxen nicht ausgebucht sind, wenn man sie frühzeitig ordert. Das ist ja möglich, da man den Termin des Streiks auch frühzeitig weiß. Jedoch ist ein Taxi nicht gerade das billigste Fortbewegungsmittel und somit entsteht mir hier durch den Streik ein finanzieller Schaden. Wieder eine Rechnung, die eigentlich im Postfach der GDL landen sollte.

Warum ich bisher so auf dem Geld herum reite? Weil das bei vielen (zugegebenermaßen aber nicht allen) Streiks eines der Hauptthemen ist, um die es geht: Die meiner Meinung nach extrem unterbezahlten Lokführer wollen ein Gehalt, welches ihrer geistigen und psychischen Beanspruchung gerecht wird. Geistig, da es einiges an Konzentration erfordert, den Fahrbetrieb zu überwachen und somit die Sicherheit der Passagiere herzustellen. Psychisch, da es eine extreme Belastung für einen Lokführer ist, wenn der Zug mal wieder einen Deppen überrollt, der meint, auf den Gleisen herumturnen zu müssen. Zwei kleine Ausschnitte aus dem Job, die ihn für mich schon extrem stressig machen würden. Zum Glück muss ich ihn ja nicht machen, denn es gibt ja Leute, die dafür Geld kriegen. Leider kann man das nicht als angemessene Bezahlung bezeichnen. Von daher ist es für mich verständlich, wenn die Lokführer für bessere Arbeitsbedingungen (z.B. auch längere Pausen) kämpfen und dabei streiken.
Mittlerweile habe ich jedoch das Gefühl, dass die aktuellen Streiks der Lokführer nichts mit besseren Arbeitsbedingungen zu tun haben. Also - nicht aus Sicht der Lokführer. _Die_ gehen auf die Straße, weil sie endich gescheit bezahlt werden wollen, gescheit Pause machen wollen, etc. Jedoch wird das Gefühl immer größer, dass diese Sehnsucht der Lokführer von der Gewerkschaft missbraucht wird, um ihre eigene Macht zu stärken. Das Ziel der Gewerkschaft sind also nicht die Lokführer, sondern ist die Gewerkschaft selbst, die den Streik als Instrument zur Festigung ihrer Macht verwendet. Dies ist jedoch lediglich ein Gefühl und kann durchaus falsch sein - das streite ich auch gar nicht ab, jedoch hat es die GDL meiner Meinung nach sträflich versäumt, darauf hinzuweisen, warum nun wieder gestreikt wird. Ich kann in dem heutigen Post auf deren Webseite (http://www.gdl.de/Aktuell-2014/AushangReport-1415030562) zumindest nicht erkennen, warum ich mit RMV/DB zu spät zur Arbeit kommen soll wenn ein mir gänzlich unbekanntes Unternehmen namens "RegioTram", welches dem Namen nach nicht für S-Bahnen, sondern für Straßenbahnen zuständig ist, nicht bereit ist, ein akzeptables Angebot zu machen. Die Tagesschau schreibt: 'Noch am Sonntagmorgen habe es "keinerlei Zweifel" an einer greifbar nahen Lösung gegeben. Am Abend sei dann nach einer Sitzung der GDL-Tarifkommission "die Rolle rückwärts" gekommen. "Eine gute Zukunftslösung ist erneut an reinen Machtfragen gescheitert", sagte Bahn-Personalvorstand Ulrich Weber.' (http://www.tagesschau.de/wirtschaft/lokfuehrer-gdl-103.html) Sollte dies Stimmungsmache der Bahn sein, so hat die GDL ein prächtiges Mittel, um sich dagegen zu wehren: Soziale Medien. Es wäre ein Leichtes gewesen, die Entscheidung zuerst auf Facebook, Twitter und im hauseigenen Blog zu veröffentlichen _und_ dabei zu beleuchten, _warum_ es zu dieser Entscheidung gekommen ist. "Die Bahn weigert sich immernoch unsere Forderung nach XYZ anzunehmen" wäre z.B. ein guter erklärender Tweet, den man noch während der Sitzung hätte verschicken können. So muss ich als Bahnkunde jedoch von reiner Willkür und "Machtfragen" ausgehen, was meine Wut gegenüber der GDL noch weiter schürt.
Wie wäre es denn mal mit einer Gegendemonstration bei dem Streik? Ich könnte mir das auch schon gut vorstellen - im Stil einer klassischen Demonstration. So Mittelalter-Klassisch. Jedoch mit Mistgabeln und Fackeln aus Pappe und Krepppapier. Wobei wenn es nachts ist kann man die Fackeln gern durch echte ersetzen, man will schließlich was sehen. Hätte was von 'nem Laternenumzug irgendwie...
Ja, am liebsten würde ich zu etwas aufrufen, was gesetzlich nicht vertretbar ist ... würde - Leute, lasst's. Geht lieber ordentlich demonstrieren, auch wenn ich den Entscheidern in der GDL sonstwas an den Hals wünsche.