Skip to content

Commit ed99c88

Browse files
authored
Merge pull request #8307 from woocommerce/issue/2221-docs-depedency-injection
Document Service locator and Dependency Injection
2 parents 9555ed6 + df1bca3 commit ed99c88

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

docs/architecture-overview.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,22 @@ It is important to note that at the moment there is not a global unified archite
348348

349349
That being said, there are some high-level abstractions that are starting to pop up.
350350

351-
### Global Dependencies
351+
### Global Dependencies and the Service Locator pattern
352352

353353
Global dependencies are provided by an implementation of the Service Locator pattern. In WooCommerce, a [`ServiceLocator`](../WooCommerce/Classes/ServiceLocator/ServiceLocator.swift) is just a set of static getters to the high-level global abstractions (i.e. stats, stores manager) and set of setters that allow overriding the actual implementation of those abstractions for better testability.
354+
355+
The Service Locator acts as a central point of access to the different services: When a component needs a service it no longer has to instantiate the class itself, it gets it through `ServiceLocator` instead.
356+
357+
Despite its convenience, its usage comes with some downsides:
358+
359+
- Harder testability
360+
- Hides class dependencies, which could cause runtime errors rather than catching these at compile time
361+
- There are objects that are loaded once in the app’s lifetime but may change later. These need to rely on something else when updating data. A typical case is the store `siteID` when switching sites, or logging out. These should almost always be injected and retained instead.
362+
363+
While we shouldn't avoid using the `ServiceLocator` on demand, dependencies should preferably be declared at the top of each class and injected via the constructor, this provides certain benefits:
364+
365+
- Makes dependencies explicit rather than hidden. Making the communication between different objects clear
366+
- We want to be able to inject a certain level of abstraction and have decoupled code, so we can provide different implementations details without breaking the system, for example using a common protocol.
367+
- Dependencies will exist along the object's lifecycle
368+
- It guarantees that all necessary dependencies are available to our components at compile time
369+
- For dependencies that don't change, injecting them into the constructor enforces type safety ands avoid inconsistent behavior later at runtime

0 commit comments

Comments
 (0)