In my application that uses Typhoon library, I've created an AppAssembly that is being initialized in SceneDelegate like this:
self.appAssembly = [[AppAssembly new] activated];
my appAssembly looks like this
- (Person *)me;
- (Dog *)dog;
- (Cookie *)cookie;
- (DogInteractionVC *)dogVC;
- (HowManyCookiesVC *)howManyCookiesVC;
From SceneDelegate I want to transit to dogVC,
Then, from the dogVC, I want to transit to howManyCookiesVC
Calling the instance of dogVC from SceneDelegate is quite easy as I do have an access to it:
self.viewController = [self.appAssembly dogVC];
I do not understand how to pass the very same appAssembly instance to a dogVC and then to howManyCookiesVC. When I try to create an instance of AppAssembly in the dogVC, I come across the issue that I believe is called circular dependency.
There is a guide on GitHub about injecting Assembly itself. So I created a property appAssembly in a dogVC of type TyphoonComponentFactory. Here is how my initializing method inside my appAssembly for a dogVC looks like:
- (DogInteractionVC *)dogVC {
return [TyphoonDefinition withClass:[DogInteractionVC class]
configuration:^(TyphoonDefinition *definition) {
[definition useInitializer:#selector(initWithPerson:)
parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:[self me]];
}];
[definition injectProperty:#selector(appAssembly) with:self];
}];
}
I think the part injectProperty:#selector(appAssembly) is wrong, but I spent a long time understanding that, and I am afraid that I cannot go any further than this without some help from the community. Any help is appreciated. Thank you.
Side note:
Dear community, I am very close to being blocked from posting, as my last posts have not been well received. I believe that question has everything that it needs. If I am wrong, please let me know before putting your thumbs down so I can understand my mistakes. Thank you.
Dependency Injection:
Typhoon helps to apply the dependency injection pattern - an object oriented software approach whereby:
The key actors and their interactions with other core software components in a system a declared at the composition root.
In this way:
We can de-duplicate configuration of shared objects.
We can have the benefits of singletons without overly tight coupling.
Using Dependency Injection in a Mobile App:
When we use dependency injection in a mobile app, we start at the app delegate to launch a view controller.
The first controller will depend on some singleton services to do its job.
We may then wish to transition from one view controller to another. We can load an 'object graph' consisting of the view controller and it dependencies.
When the next controller is presented, we can release the current one.
Factory Pattern:
To transition from one controller to another we can use Typhoon as a factory for emitting built instances. The factory pattern allows us to:
Obtain an instance (ie a view controller) with a mix of runtime and static dependencies.
So to transition from one view controller to another we can inject Typhoon assembly to be used as a factory to obtain the next view controller. To inject the assembly as a factory, docs are here.
Scopes:
Depending on navigation style, controllers will typically retained in memory as long as used and then released. Meanwhile services or other shared infrastructure will be shared.
The default scope is TyphoonScopeObjectGraph
To create a shared class use definition.scope = TyphoonScopeSingleton as documented here.
Pilgrim:
Typhoon is, at least in my opinion, the best and most flexible DI library for objective-C. Meanwhile, if you use Swift you might like to try simpler and better: pilgrim.ph
Related
I'm trying to find how I can use dependency injection to inject a ConnectionString or a custom AppSetting object so far i end up in the startup using
services.Configure<IConnectionStrings>(Configuration.GetSection("MyConnection"));
example layer
Web MVC application
Business Logic (class library)
Repository (class library)
DAL (class library)
Model (class library)
where web see only Business logic and so on, on model is available for all.
In the DAL project I have an object that takes care of connecting and running queries against my database (CDbTools object).
Now, how can I inject directly into CDbTools without going from controller down to DAL.
Thank you.
Dependency injection definitely takes a little getting used to, and you won't be creating objects quite the way you're used to. What you want to do is first is modify your CDbTools to take the injected strings.
public CDbTools(IConnectionStrings strings)
{
_connectionString = strings
}
The next step will be to actually inject the CDbTools into the classes that need it as well. First, register it in the startup.
services.AddScoped<CDbTools>();
You'll need to follow this up the chain. Don't think of it as passing the objects from the top level down - that will mess up your separation of concerns. Each layer has the lower layer injected in. This won't just get you the injection of your string you are looking for. It will let you mock things easier, swap layers easier, and a slew of other benefits.
I believe you should add this to your ConfigureServices method:
services.Configure<CustomSettings>(settings =>
{
Configuration.GetSection("CustomSettings").Bind(settings);
});
Where services is your IServiceCollection object and CustomSettings is your custom configuration class that you want to inject. That custom object should map to your settings fields.
Hope this helps!
I am currently creating my first Swift / Mac application and I have the problem of sharing a model (in the MVC sense) between several controllers.
In C# for example one would first create a model, then a number of view models, and then plug that model into them like this:
var gameEngine = new MyGameEngine()
var vm1 = new ViewModelCockpit(gameEngine);
var vm2 = new ViewModelOptionsDialog(gameEngine);
However, in XCode it seems that my controllers I am supposed to place into the .xib, which are, in turn, automatically instantiated.
What is given Swift's language features and XCode / Objective-C existing standards the best and most professional way have a number of heavyweight models that can be shared and accessed from several controllers? (Heavyweight in the sense that they take some time, memory or complex logic / dependencies) to load and might not easily be put into the .xib themselves.
Potential answers could be: global variables, some magic / static properties, ... Ideally the solution should feel solid in a software engineering sense and take Swift's language features into account.
Depending on how complex your data model is, here are some things to consider:
For complex data models, consider using Core Data
Create a singleton DataController class that gives you access to your models from any controller in your app. In Swift it could be done like this: Using a dispatch_once singleton model in Swift
You only use XIBs/Storyboards for the UI, never for your models.
I like to create the model(s) first, then pass them into each view's initialiser code, very similar to what you describe in C#. It's also similar to how you would do this in JavaScript (for example, in Backbone JS).
let gameEngine = MyGameEngine()
let vm1 = ViewModelCockpit(nibName: "ViewModelCockpit", bundle: NSBundle.mainBundle(), gameEngine: gameEngine)
let vm2 = ViewModelOptionsDialog(nibName: "ViewModelOptionsDialog", bundle: NSBundle.mainBundle(), gameEngine: gameEngine)
class ViewModelCockpit: NSViewController {
var myGameEngineModel: GameEngineModel
init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!, myGameEngineModel: GameEngineModel) {
self.myGameEngineModel = myGameEngineModel
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
Note — you have to call the super.init() of the parent class, and if you forget, Xcode very nicely reminds you! I use Xcode's autocompletion to provide me with the usual init function and its exact args.
If I compare Typhoon with one of the common IOC container spring in java i could not find two important freatures in the documentation.
How to annotate #autowired?
How to annotate #Scope? Especially distinglish between SCOPE_SINGLETON and SCOPE_PROTOTYPE.
More about spring here:
http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/html/beans.html#beans-standard-annotations
Typhoon supports the prototype and singleton scopes along with two other scopes designed specifically for mobile and desktop applications.
In a server-side application, the server may be supporting any of the application's use-cases at a given time. Therefore it makes sense for those components to have the singleton scope. In a mobile application, while there are background services its more common to service one use case at a time. And there are memory, CPU and batter constraints.
Therefore the default scope with Typhoon is TyphoonScopeObjectGraph, which means that references to other components while resolving eg a top-level controller will be shared. In this way an object graph can be loaded up and then disposed of when done.
There's also the following:
TyphoonScopeSingleton
TyphoonScopePrototype
TyphoonScopeWeakSingleton
Auto-wiring macros vs native style assembly:
Unfortunately, Objective-C has only limited run-time support for "annotations" using macros. So the option was to use either a compile-time pre-processor, which has some drawbacks, or to work around the limitations and force it in using a quirky style. We decided that its best (for now) to use Macros only for simple convention-over-configuration cases.
For more control we strongly recommend using the native style of assembly. This allows the following:
Modularize an application's configuration, so that the architecture tells a story.
IDE code-completion and refactoring works without any additional plugins.
Components can be resolved at runtime using the assembly interface, using Objective-C's AOP-like dynamism.
To set the scope using the native style:
- (id)rootController
{
return [TyphoonDefinition withClass:[RootViewController class]
configuration:^(TyphoonDefinition* definition)
{
definition.scope = TyphoonScopeSingleton;
}];
}
Let's say I have a few controllers. Each controller can at some point create new objects which will need to be stored on the server. For example I can have a RecipeCreationViewController which manages a form. When this form is submitted, a new Recipe object is created and needs to be saved on the server.
What's the best way to design the classes to minimize complexity and coupling while keeping the code as clean and readable as possible?
Singleton
Normally I would create a singleton NetworkAdapter that each controller can access directly in order to save objects.
Example:
[[[NetworkAdapter] sharedAdapter] saveObject:myRecipe];
But I've realized that having classes call singletons on their own makes for coupled code which is hard to debug since the access to the singleton is hidden in the implementation and not obvious from the interface.
Direct Reference
The alternative is to have each controller hold a reference to the NetworkAdapter and have this be passed in by the class that creates the controller.
For example:
[self.networkAdapter saveObject:myRecipe];
Delegation
The other approach that came to mind is delegation. The NetworkAdapter can implement a "RemoteStorageDelegate" protocol and each controller can have a remoteStorageDelegate which it can call methods like saveObject: on. The advantage being that the controllers don't know about the details of a NetworkAdapter, only that the object that implements the protocol knows how to save objects.
For example:
[self.remoteStorageDelegate saveObject:myRecipe];
Direct in Model
Yet another approach would be to have the model handle saving to the network directly. I'm not sure if this is a good idea though.
For example:
[myRecipe save];
What do you think of these? Are there any other patterns that make more sense for this?
I would also stick with Dependency Injection in your case. If you want to read about that you will easily find good articles in the web, e.g. on Wikipedia. There are also links to DI frameworks in Objective C.
Basically, you can use DI if you have two or more components, which must interact but shouldn't know each other directly in code. I'll elaborate your example a bit, but in C#/Java style because I don't know Objective C syntax. Let's say you have
class NetworkAdapter implements NetworkAdapterInterface {
void save(object o) { ... }
}
with the interface
interface NetworkAdapterInterface {
void save(object o);
}
Now you want to call that adapter in a controller like
class Controller {
NetworkAdapterInterface networkAdapter;
Controller() {
}
void setAdapter(NetworkAdapterInterface adapter) {
this.networkAdapter = adapter;
}
void work() {
this.networkAdapter.save(new object());
}
}
Calling the Setter is where now the magic of DI can happen (called Setter Injection; there is also e.g. Constructor Injection). That means that you haven't a single code line where you call the Setter yourself, but let it do the DI framework. Very loose coupled!
Now how does it work? Typically with a common DI framework you can define the actual mappings between components in a central code place or in a XML file. Image you have
<DI>
<component="NetworkAdapterInterface" class="NetworkAdapter" lifecycle="singleton" />
</DI>
This could tell the DI framework to automatically inject a NetworkAdapter in every Setter for NetworkAdapterInterface it finds in your code. In order to do this, it will create the proper object for you first. If it builds a new object for every injection, or only one object for all injections (Singleton), or e.g. one object per Unit of Work (if you use such a pattern), can be configured for each type.
As a sidenote: If you are unit testing your code, you can also use the DI framework to define completely other bindings, suitable for your test szenario. Easy way to inject some mocks!
I have a class that acts as a manager and does some work.
A servlet that starts up when the application server starts up instantiates this manager.
I need to add another class that will do other work, and needs to coordinate with the manager.
I was thinking about adding the class to the manager as an instance variable.
Should I have the manager instantiate the new class (like in the constructor), or have the servlet instantiate the new class and call manager.setNewClass() after the manager has been instantiated?
Well, as a gross-over-generalization, you should instantiate it in the servlet and pass it into the manager (either via a constructor parameter, or via setNewClass())... Inject the dependencies rather than hard-code them.
However, depending on your exact use-case, even that might not be the right answer. You might be better off with a Builder for constructing the manager class. That way, the builder manages the construction of the entire manager (including any dependencies) rather than hard-coding it into the servlet. This would move the dependency out of the servlet and into the builder (which you can better deal with in tests and other code).
The short answer is that there's no silver bullet. Without knowing the hard relationships between all of the classes, and the roles and responsibilities, it's hard to say the best method. But instantiating in a constructor is almost never a good idea and you should inject the dependency in some form or another (but from where is up for debate)...
This reminds me of the FFF pattern.
It does not matter where you create the instance. Just create wherever it fits you best, and if you need it somewhere else, just apply some basic refactoring.
If you really need decoupling try using some tool like Guice, but only if you really need it.
You should do the latter -- it decouples the manager from its delegate. To do the decoupling correctly, you should create an interface that defines the behavior the manager expects, and then provide an implementation via inversion of control/dependency injection. This will allow you to test the manager and its worker class (I called it a delegate, but it might not be) in isolation.
EDIT -- this answer assumes java because you mentioned servlet.
You have your manager class, in it you expect an interface
class Manager {
Worker worker;
Manager(Worker worker) {
this.worker = workder
}
}
Worker is an interface. It defines behavour but not implementation
interface Worker {
public void doesSomething(); //method definition but no implementation
}
you now need to create an implementation
class WorkerImpl implements Worker {
// must define a doesSomething() implementation
}
The manager just knows it gets some Worker. You can provide any class that implements the interface. This is decoupling -- the Manager is not bound to any particular implementation, it is bound only to the behavour of a worker.