Add Resin. Move to package manager file layout.#7
Open
danieleggert wants to merge 4 commits into
Open
Conversation
Currently “Incremental” provides “incremental programming helpers” for updating and observing state changes. As we’ve used this, we have written wrappers and helpers to integrate this into an iOS app. We’ve named this wrapper library “Resin”. This provides a way to manage application state. More detailed info is in the (updated) readme.md file. Co-authored-by: Sommer Panage <panage@apple.com> Co-authored-by: Teddy Wyly <twyly@apple.com> Co-authored-by: Julien Grimault <juelz@apple.com> Co-authored-by: Robb Böhnke <robb@robb.is> Co-authored-by: Daniel Eggert <deggert@apple.com>
Owner
|
This looks really cool, but I'm wondering if it should be a separate repository. I'll have to play around with it a bit. Ideally, I'd like to keep Incremental very small. Do you have a sample app that uses all (or at least some) of this? |
|
Would it be possible to see an example app using this great concept? |
This updates `Resin` where we move away from the `Environment` parameter in `Store` and `Middleware`. We found that in practice, it is easier to deal with injecting the required dependencies at the `Parcel` level. Each Middleware/Reducer that has dependencies can get them passed in when the parcel is constructed. Co-authored-by: Sommer Panage <panage@apple.com> Co-authored-by: Teddy Wyly <twyly@apple.com> Co-authored-by: Julien Grimault <juelz@apple.com> Co-authored-by: Robb Böhnke <robb@robb.is> Co-authored-by: Daniel Eggert <deggert@apple.com>
Co-authored-by: Sommer Panage <panage@apple.com> Co-authored-by: Teddy Wyly <twyly@apple.com> Co-authored-by: Julien Grimault <juelz@apple.com> Co-authored-by: Robb Böhnke <robb@robb.is> Co-authored-by: Daniel Eggert <deggert@apple.com>
# Conflicts: # .gitignore # Package.swift # Sources/Incremental/IncrementalArray.swift # Sources/Incremental/Info.plist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Currently “Incremental” provides “incremental programming helpers” for updating and observing state changes.
As we’ve used this, we have written wrappers and helpers to integrate this into an iOS app. We’ve named this wrapper library “Resin”. This provides a way to manage application state. More detailed info is in the (updated)
readme.mdfile.Here’s a copy of the “Resin” part of the updated
readme.md:Resin
Resin uses Incremental and additionally provides a framework way to manage application state.
An app using Resin would typically have a single, shared struct that contains the entire application state. Different parts of the app would then focus this state to only operate on their subset of the state. This helps keep the concerns of different modules isolated from each other.
As a trivial example, consider
where the app has two components (see Parcel below), one of which would operates on a state of the type
Foo, and the other one onBar.Actions
Resin enforces that changes to this global state can only be done through an
Action.An
Actionhas value semantics. And it can trigger two things: aReducercan use an action to udpate the app state; and aMiddlewarecan handle anActionto trigger side effects.A note of caution: It is important to stress, that the channel to submit actions is not intended to be used as an event stream, and should absolutely not be misused as such. An
Actionis supposed to be a way for one part of he app to tell another to do something. This is not a way to notify about events of changes.NSNotificationand observing the app state are better vehicles for that.Store
The app has a (root) store that holds onto the
AppState. It only exposes theAppStatethrough an (Incremental)I<AppState>such that various parts of the app can observe change of the state and react upon those changes.MiddlewareandReducers can be registered with the store and anyActionthat gets dispatched will then be send to those. TheReducers are the only ones that are given an opportunity to update the state. Their handler gets aninout AppStateto operate on.As different parts of the app operate on subsets of the all encompasing
AppState, each part can operate on aStorethat’s tied to the root store, but only operates on its subset (as noted above). TheMiddlewareandReducers can then also operate on such a store’s subset, which transparently ties into the root store.Navigation
tbd
Parcel
Each part (usually a Swift module) of an app has a combination of
Reducers,Middleware, andNavigationRoutes to implement its features. All of these needs to be registered with the store. In order to facilitate that, aParcelcan wrap a combination of all of these. The parcel can then be registered with the store, which in turn will register all of itsReducers,Middleware, andNavigationRoutes.The benefit of this, is that the app itself only needs to register the
Parcels that it uses, and doesn’t have to know whichReducers,Middleware, andNavigationRoutes it needs. This makes updating code within a specific part / domain of an app easier. If, e.g. a newMiddlewareis added, it just needs to be added to itsParcel, and will then automatically be registered with the app.Additionally, a module that has a parcel, does not have to expose its
Reducers, etc. aspublic. They only need to be added to the module’sParcel. This reduces the API surface of a module.