Get the free guide with the foundation behind all career strategies we use to help iOS developers boost their income and work with remarkable people... www.essentialdeveloper.com/how-to-boost-your-ios-developer-income
Hey Thx for the nice explaination . I have one question regarding to global non mutable functions or variables at 11:50 So if i would have an extension on Image for example and want to access directly an image from my assets it would be ok to call that extension from one module? Isn’t this as well a dependency to the main that we should not have? Or did i get it wrong? I mean, everything that is global, leads to a strong dependency to that variable whatever where its belonging to. Best regards Björn
Hi! The assets should live in the same module where you define and use the static assets references. This way, there's no cross-module dependency. Otherwise, if the assets live in the main module, it'd be best to inject them to the other modules as to decouple other modules from "main".
Hello Hai! You can create a RootCoordinator to help you compose your application as long as it lives in the main application target and is only used in the Composition Root (no other module should reference the concrete RootCoordinator directly). Remember that the Composition Root isn’t a class: “The Composition Root isn’t a method or a class, it’s a concept. It can be part of the Main method, or it can span multiple classes, as long as they all reside in a single module.”-Dependency Injection: Principles, Practices and Patterns by Mark Seemann, Steven van Deursen Finally, using a DI Container is optional. ✅
Do I create in composition root the resources, objects, needed in the last screen of my navigation stack i.e Do I need to create object of network module in composition while it will be needed after user navigates from screen A through B, C, D and finally F where he would need this network module object.
Hi! We recommend you to instantiate/compose components in the Composition Root. Otherwise, all screens might end up with unnecessary dependencies. For example, if Screen F needs dependency X, other Screens (A/B/C/D...) would need to either instantiate or hold X to be able to pass it to F. (And X might have its own dependencies...)
Hi guys, nice content! we work with micro features. each of then has a public factory thats only exposes a UIViewController (make() -> UIViewController). Make sense create an internal composition root inside a microfeature? I ask this because you talk about composition root in app target
Hi! Only applications have a Composition Root. You can provide some facilities like factories from the microfeature module to help clients. But it ideally shouldn't prevent apps from composing the features in different ways. From the book 'Dependency Injection Principles, Practices, and Patterns by Mark Seemann and Steven van Deursen': "...a Composition Root is specific to the application. Composition Roots aren’t reused. You shouldn’t attempt to compose classes in any of the other modules, because that approach limits your options."
@@EssentialDeveloper but in this case I have turn mvvm components public in each module Only to compose then in application? Maybe my mistake was use the wrong name, maybe I must just call factory instead composition root
If the modules are composed only through a factory in the feature module, it can limit its composability. For example, it can only be composed in the way the factory provides - and this will prevent many benefits of dependency injection, such as Interception. That's why the recommendation is to compose in the main app module to avoid limiting your options.
Hi guys! Thank you so much for explaining this essential topic with so much details. I'm trying to implement the example given by Mike: load a list of books and show them on screen inside a table. I structured the UI as a tab controller with a tab (Relationship "view controller") for each different category or genre of books ("fiction", "food", "history"...). To fetch the books from remote API, I'm using a service or provider which I believe I should inject to each controller that needs to use it. I'm not sure how to inject this service dependency: should I inject it to the tab controller (parent) and make it available to each of it's tabs (children) somehow, or should I inject it to the tabs (children)? If I inject it into the parent then I won't be able to reuse any of it's children viewcontroller in isolation (nor will be able to test those view controllers in isolation either) because the will need the parent to get this dependency, am I right? Thanks a lot!
Hi Francisco! It depends on what you're trying to achieve. If you want to decouple the parent from its children's dependencies (recommended), then you need to inject the child components into the parent. This way, the parent won't need to create its children - whoever creates the child components will inject all dependencies at creation time (so the parent won't depend on the dependencies of the child components!).
Hi, guys! I have a question about DI-container and ServiceLocators. Situation: MyModule depends explicitly on Service1 and Service2. And probably I will add more services to the module. Than I remembered about ServiceLocator and decided to pass ServiceLocator to my module (as a protocol or not, does not matter for now) for give a responsibility to MyModule to invoke any service it needs. But I can see that this is a bad approach because it leads to implicit dependancies on Service1-2-3-X inside MyModule. Which makes MyModule less solid, less testable etc. Is my opinion right or I am missing something? If yes, what is the purpose of ServiceLocator at all? Thanks in advance!
Hi Anton, That's right. Service Locator works for injecting/obtaining services (dependencies), but it's considered an anti-pattern as it has known negative effects (e.g., implicit dependencies that will be evaluated at runtime) while better solutions exist (e.g., Constructor Injection). From "Dependency Injection Principles, Practices, and Patterns" by Mark Seemann and Steven van Deursen: "Service Locator is a dangerous pattern because it almost works. You can locate Dependencies from consuming classes, and you can replace those Dependencies with different implementations - even with Test Doubles from unit tests[...] The main problem with Service Locator is that it impacts the reusability of the classes consuming it. This manifests itself in two ways: - The class drags along the Service Locator as a redundant Dependency. - The class makes it non-obvious what its Dependencies are. You must redistribute not only your module but also the Locator Dependency, which only exists for mechanical reasons. If the Locator class is defined in a different module, new applications (reuse) must accept that module too[...] The use of generics may trick you into thinking that a Service Locator is strongly typed. But it is weakly typed, because you can request any type. Being able to compile code invoking the GetService method gives you no guarantee that it won't throw exceptions left and right at runtime. When unit testing, you have the additional problem that a Test Double registered in one test case will lead to the Interdependent Tests code smell, because it remains in memory when the next test case is executed. It's therefore necessary to perform Fixture Teardown after every test by invoking Locator.Reset(). This is something that you must manually remember to do, and it's easy to forget." Service Locator can be convenient at first, but we recommend you to avoid this anti-pattern as it doesn't scale well and might make your codebase rigid.
Get the free guide with the foundation behind all career strategies we use to help iOS developers boost their income and work with remarkable people... www.essentialdeveloper.com/how-to-boost-your-ios-developer-income
Hey
Thx for the nice explaination .
I have one question regarding to global non mutable functions or variables at 11:50
So if i would have an extension on Image for example and want to access directly an image from my assets it would be ok to call that extension from one module? Isn’t this as well a dependency to the main that we should not have? Or did i get it wrong? I mean, everything that is global, leads to a strong dependency to that variable whatever where its belonging to.
Best regards
Björn
Hi! The assets should live in the same module where you define and use the static assets references. This way, there's no cross-module dependency. Otherwise, if the assets live in the main module, it'd be best to inject them to the other modules as to decouple other modules from "main".
What do you think about using Coordinator as composition root. Is is necessary to use Dependency Container if I use Coordinator. Thank you!
Hello Hai!
You can create a RootCoordinator to help you compose your application as long as it lives in the main application target and is only used in the Composition Root (no other module should reference the concrete RootCoordinator directly).
Remember that the Composition Root isn’t a class:
“The Composition Root isn’t a method or a class, it’s a concept. It can be part of the Main method, or it can span multiple classes, as long as they all reside in a single module.”-Dependency Injection: Principles, Practices and Patterns by Mark Seemann, Steven van Deursen
Finally, using a DI Container is optional. ✅
Do I create in composition root the resources, objects, needed in the last screen of my navigation stack i.e Do I need to create object of network module in composition while it will be needed after user navigates from screen A through B, C, D and finally F where he would need this network module object.
Hi! We recommend you to instantiate/compose components in the Composition Root. Otherwise, all screens might end up with unnecessary dependencies. For example, if Screen F needs dependency X, other Screens (A/B/C/D...) would need to either instantiate or hold X to be able to pass it to F. (And X might have its own dependencies...)
Hi guys, nice content! we work with micro features. each of then has a public factory thats only exposes a UIViewController (make() -> UIViewController).
Make sense create an internal composition root inside a microfeature?
I ask this because you talk about composition root in app target
Hi! Only applications have a Composition Root. You can provide some facilities like factories from the microfeature module to help clients. But it ideally shouldn't prevent apps from composing the features in different ways. From the book 'Dependency Injection Principles, Practices, and Patterns by Mark Seemann and Steven van Deursen': "...a Composition Root is specific to the application. Composition Roots aren’t reused. You shouldn’t attempt to compose classes in any of the other modules, because that approach limits your options."
@@EssentialDeveloper but in this case I have turn mvvm components public in each module Only to compose then in application? Maybe my mistake was use the wrong name, maybe I must just call factory instead composition root
If the modules are composed only through a factory in the feature module, it can limit its composability. For example, it can only be composed in the way the factory provides - and this will prevent many benefits of dependency injection, such as Interception. That's why the recommendation is to compose in the main app module to avoid limiting your options.
Hi guys! Thank you so much for explaining this essential topic with so much details. I'm trying to implement the example given by Mike: load a list of books and show them on screen inside a table.
I structured the UI as a tab controller with a tab (Relationship "view controller") for each different category or genre of books ("fiction", "food", "history"...). To fetch the books from remote API, I'm using a service or provider which I believe I should inject to each controller that needs to use it. I'm not sure how to inject this service dependency: should I inject it to the tab controller (parent) and make it available to each of it's tabs (children) somehow, or should I inject it to the tabs (children)? If I inject it into the parent then I won't be able to reuse any of it's children viewcontroller in isolation (nor will be able to test those view controllers in isolation either) because the will need the parent to get this dependency, am I right?
Thanks a lot!
Hi Francisco! It depends on what you're trying to achieve. If you want to decouple the parent from its children's dependencies (recommended), then you need to inject the child components into the parent. This way, the parent won't need to create its children - whoever creates the child components will inject all dependencies at creation time (so the parent won't depend on the dependencies of the child components!).
Hi, guys!
I have a question about DI-container and ServiceLocators.
Situation:
MyModule depends explicitly on Service1 and Service2. And probably I will add more services to the module. Than I remembered about ServiceLocator and decided to pass ServiceLocator to my module (as a protocol or not, does not matter for now) for give a responsibility to MyModule to invoke any service it needs.
But I can see that this is a bad approach because it leads to implicit dependancies on Service1-2-3-X inside MyModule. Which makes MyModule less solid, less testable etc.
Is my opinion right or I am missing something?
If yes, what is the purpose of ServiceLocator at all?
Thanks in advance!
Hi Anton,
That's right. Service Locator works for injecting/obtaining services (dependencies), but it's considered an anti-pattern as it has known negative effects (e.g., implicit dependencies that will be evaluated at runtime) while better solutions exist (e.g., Constructor Injection).
From "Dependency Injection Principles, Practices, and Patterns" by Mark Seemann and Steven van Deursen:
"Service Locator is a dangerous pattern because it almost works. You can locate Dependencies from consuming classes, and you can replace those Dependencies with different implementations - even with Test Doubles from unit tests[...]
The main problem with Service Locator is that it impacts the reusability of the classes consuming it. This manifests itself in two ways:
- The class drags along the Service Locator as a redundant Dependency.
- The class makes it non-obvious what its Dependencies are.
You must redistribute not only your module but also the Locator Dependency, which only exists for mechanical reasons. If the Locator class is defined in a different module, new applications (reuse) must accept that module too[...]
The use of generics may trick you into thinking that a Service Locator is strongly typed. But it is weakly typed, because you can request any type. Being able to compile code invoking the GetService method gives you no guarantee that it won't throw exceptions left and right at runtime.
When unit testing, you have the additional problem that a Test Double registered in one test case will lead to the Interdependent Tests code smell, because it remains in memory when the next test case is executed. It's therefore necessary to perform Fixture Teardown after every test by invoking Locator.Reset(). This is something that you must manually remember to do, and it's easy to forget."
Service Locator can be convenient at first, but we recommend you to avoid this anti-pattern as it doesn't scale well and might make your codebase rigid.
@@EssentialDeveloper Thank you for full answer!