Replies: 1 comment 1 reply
-
Hi @beetee17, unfortunately I believe this approach is probably going to give you more pain than solutions. The dependencies library is not really meant to provide a particular feature's functionality, but rather meant to describe a global service that interacts with the outside world so that any feature can immediately get access. So I don't think it's going to help you much. The most general technique for flattening a tree of feature dependencies is to simply "delegate up to the parent". So, rather than B navigating to C directly (and hence B depends on C), you have B tell its parent, A, that it wants to navigate somewhere, and then A does the navigation to C. This means B can still navigate to C without actually depending on C, and then only A depends on B and C. In short, we've turned this dependency tree:
…into this one:
So things got a little flatter. That's the most general technique, and it can work for really any kind of navigation (sheets, popovers, drill downs, etc). But then further SwiftUI provides In that situation you have a enum Path {
case featureA(…)
case featureB(…)
case featureC(…)
…
}
var path: [Path] …and each of A, B, C, (…) do not depend on each other. Only the parent feature, the one that holds a |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi all, I'm currently working on a medium-sized project (~80k loc) that follows the modularisation approach of the isowords app. The project has grown to a few dozen modules, 1 for each feature or dependency. Slowly but surely, build times as well as the speed/reliability of SwiftUI Previews have degraded such that my ability to iterate quickly on features has decreased, and I have since been looking for ways to improve this and maximise my developer experience when working on the codebase.
The Problem
After some research, I believe that the problem with my set-up is that the dependency graph of my modules resemble a hierachical structure (with larger modules depending on smaller ones), and I would like to flatten the graph to become more horizontal. I believe the concepts behind what I'm trying to accomplish are well explained in this video (from 11:36).
Example: Initial Attempt
Disclaimer: I have never done something like this before, so please excuse my ignorance if the idea is completely off-the-mark! I would really love to learn from anyone who knows the solution.
The idea I have been toying with is to create protocols for each feature's Reducer, and rely on the Dependencies library for dependency injection of concrete Reducer implementations. Therefore, a module will be split into two, like so:
Example: Adding a parent feature
To make the example more practical, consider a parent feature that depends on the
Feature
we just created.Notes
Following this article on how to "Separate Interface and Implementation" in the swift-dependencies documentation,
TestDependencyKey
is used in the interface module, andDependencyKey
in the implementation module to provide the live value.The Issue
The biggest issue of the outlined approach is that
State
andAction
are not interfaces that can be extended (i.e. protocols). This means that aFeatureReducerImpl
is unable to layer on additional properties toState
, or cases toAction
that are only needed privately within that implementation, without also modifying itsFeatureAPI
module. This constraint feels a bit icky, and makes me wonder if I'm barking up the wrong tree here, though I'm unsure of the alternatives...At this juncture I'm facing many doubts, not only due to the aforementioned issue, but also questions such as "Is the Dependencies library the right tool for this?". I would really appreciate any feedback on my approach to separating interface and implementation of TCA features, and pointers on how it can be done properly.
Beta Was this translation helpful? Give feedback.
All reactions