Zettelkasten Forum


Writing project: ReSwift Recipes Collection

I've been mentioning here and there that I wanted to assemble a (book) outline or two since Christmas, but so far, no progress.

So to create more leverage through peer pressure, I'm going to share progress here.

The topic is an open source library I'm a co-maintainer of for a couple of years now. https://github.com/ReSwift/ReSwift

The general idea of the library may survive, but the library itself is likely about to become obsolete in 1--3 years because of technical changes. That's why I want to do something with this, anything really, before it can only go straight to the trash. (Aka the sub-conscious of the Zettelkasten through forgetting about it.)

The Outline

This is an old note from 2017 that grew and grew and was changed a couple times. It started as a buffer note, as @sfast called them, i.e. an assorted collection of quick tips that don't need much background/theory to grasp. Since then I've interleaved section headings and rewrite both the commentary in the outline and some notes themselves. (I have no version control that survived, so I can't reproduce the old content to show how miserable it looked for the first 2 years or so.)

Thankfully, I've switched to the [[wiki link]] link syntax when The Archive came into being, so the outline is easily traversed and I can also assemble a rough first draft from the outline.

Before I share details of the draft assembly, here's the outline:

# 201707111628 § ReSwift Recipes ebook Collection
#reswift

ReSwift Recipes

Inspiration:

- [[201810051443]] ReSwift questions and usage problems

## Unidirectional flow

Example:

- Multi-directional flow
    - text fields are bound to database fields, bind changes live as input and output
- Unidirectional flow
    - view state is derived from a "source of truth"

## General info

- [[201606161929]] ReSwift doesn't impose architectural constraints
- [[201610160957]] VIP architecture pattern. Simple component-based approach with presenter & event handler distinction.
- [[201801151617]] ReSwift self-dispatching actions

## State

### Create your state type

- [[201708071646]] Favor Immutable State. Reference types change under the hood.
    - [[201707071633]] App services inside ReSwift state postmortem -- didn't pay off
- [[202001061908]] Keep the app state flat for as long as you can.
    - See subscriptions/partitioning with substates later.
- [[201702231648]] Nelsons 5 types of Redux app substates. If your app evolves, clusters like these may emerge; but don't force it top-down from the beginning.
    - [[201702231700]] minNV app substates partitioned by type. This bit me later.

### Partition state into substate for subscriptions

- With a flat app state, you can pick-and-choose at the point of subscription.
- [[202001021834]] Use ReSwift substate protocols to hide implementation
    - [[202001041121]] Putting ReSwift substate protocol definitions into the state module doesn't help. You need the protocols to be defined in the glue layer.
- [[201912291336]] Subscribe to sub-states in ReSwift with parameter types. Partition the `AppState` when demanded.

### Namespacing state

- "Namespacing" refers to having the same (sub)state type, but used multiple times, e.g. for different contexts.
    - Example:  `UserProfile` state with user name, avatar, posts. When your app allows showing one user's profile, then go to another profile from the posts there, your app will need the context for both users.
- [[202202071342]] Namespacing in ReSwift states

### Transient and permanent states

- [[201701170838]] Modeling file write operations using ReSwift
- [[201706271428]] When to keep sorted collections in ReSwift state

## Change the state

### Creating actions

- [[201707031510]] Create ReSwift actions as much as you want
- [[201705202041]] Decouple ReSwift actions from Domain Services: use `Promise` to dispatch actions upon success of async Domain service calls.

### Naming actions

- [[201612031034]] ReSwift Action naming convention
- [[201610081158]] Naming ReSwift events

### Writing reducers

- [[201707031447]] Partitioning reducers in ReSwift
- [[201801041611]] Focus ReSwift reducers to one state change
    - [[201804300911]] Combine Reducers into one in ReSwift

## State subscriptions

### Writing subscribers

- [[201706271334]] Populate large NSTableViews with ReSwift
- [[201707102124]] Skip initial state subscription in ReSwift
- [[201708071705]] ReSwift reactive Store extension in RxSwift
- [[201903211729]] Assemble multiple subscriber states from app state in ReSwift
- [[201912291336]] Subscribe to sub-states in ReSwift with parameter types
- [[201707102124]] Skip initial state subscription in ReSwift
    - [[202001271748]] Prefer more expressive state over skipping first states in subscriptions.
- [[202004302003]] BlockSubscriber in ReSwift

### View updates

- [[202007111018]] Coalesce multiple state updates to trigger a single view update

## Perform network requests

- [[202003011022]] Naive but broken approach to handle HTTP requests in ReSwift:  make reducers as small as possible and handle request responses in yor app, not in the reducer.

### Writing middlewares

The most basic, side-effect free middleware you may want to keep as a template:

\```swift
let passthroughMiddleware: Middleware<AppState> = { dispatch, getState in
    return { next in
        return { action in
            next(action)
        }
    }
}
\```

- Use Middleware's dispatch to produce results.
    - [[201708231440]] Why does ReSwift Middleware have dispatch
- [[201709071916]] Use Middleware in ReSwift to wrap any I/O
    - [[202106020937]] If you don't need I/O or if all the info is part of your state, prefer reducers.
- [[201709221647]] Comparing ReSwift Middleware to action filters: Middleware can trigger its own cascade of events, delay and cancel action dispatching.

- [[202001062001]] Use of ReSwift Thunks: scales better, and you can define them outside of the state module.

### Perform side-effects for actions

- [[201709281039]] Injecting side-effects as middleware from the app target

### Server synchronization

- [[201610081152]] Adding server sync to ReSwift
    - [[201610081154]] Handling server sync errors with ReSwift

## Bypass limitations

- [[201906171023]] Affect the order of subscription callbacks in ReSwift.

## Put your state into an isolated module

- [[201707081409]] How to write shared ReSwift core as a framework
- [[201707031519]] Add empty public initializers to public structs

## Testing

- [[201710120814]] ReSwift testing via action recording

## App architecture inspiration

- [[201811011831]] Modular app with feature modules and a ReSwift state layer

## ReSwift Alternatives

- [SwiftRex](https://github.com/SwiftRex/SwiftRex) supports 3 reactive libraries to create store subscriptions (Combine, RxSwift, RactiveSwift)

Author at Zettelkasten.de • https://christiantietze.de/

Comments

  • edited March 2022

    Recovered tasks "for later" -- which is now

    Must have been around ~4 years ago when I started collecting tasks in OmniFocus for this topic.

    Whenever something relevant to the project popped up on the web and was too long to read and process immediately, I'd file a task for later, when I wanted to work on the project.

    It's 2--3 years now that I use Emacs and .org files to organize my projects. Some time last year I imported OmniFocus tasks into my .org files, too, before ditching the Intel Mac.

    So before I actually do anything, you can find in the expandable Spoiler section an almost assorted list of tasks.

    On top, there're a couple links to read, then a TODO for the concatenation of the outline I shared above into a single document. Afterwards, imported tasks from OmniFocus.

    Even though I don't remember anything from that list, it's good to know that there's some preparation. Might turn out to be absolutely useless preparation, but it's a good feeling to have this.

    * PROJECT ReSwift Recipes Book                                         :book:
    
    [[zettel:201707111628 § ReSwift Recipes ebook Collection]]
    
    Read:
    - 2018-05-01 The Complete Redux Book
    
    Read up on:
    - http://jamesknelson.com/5-types-react-application-state/
    - https://medium.com/@lizdenhup/understanding-unidirectional-data-flow-in-react-3e3524c09d8e
    - https://flaviocopes.com/react-unidirectional-data-flow/
    - https://github.com/ReSwift/ReSwift/issues/431#event-2851583516
    - https://duckduckgo.com/?q=what+is+unidirectional+flow&t=ffab&ia=web
    ** TODO concatenate everything from the Zettel into a single page
    
    [[zettel:201707111628 § ReSwift Recipes ebook Collection]]
    ** (imported OmniFocus tasks)
     - verzettel where to place helper/service objects
         https://github.com/ReSwift/ReSwift/issues/273
    *** https://github.com/svdo/ReRxSwift
    *** https://github.com/kzaher/RxFeedback
    *** reswift router samples
    **** short lived nav state
    https://github.com/ReSwift/ReSwift/issues/257
    **** Ben-G's sample project
    **** Viscaweb drawings
    *** add variants to multiple reducer partition
    https://github.com/ReSwift/ReSwift/issues/241
    *** what to do with ReSwiftInit (and nillable initial state)
    Why the state is optional and if this could be avoided, I don't know, really :) I try to get rid of the optionality as soon as possible.
    
    I didn't find a good use case for hooking up something to the ReSwiftInit event either. It's implicit when state is nil at first. I guess one could do some side-effects like setup of daemons or whatever in a middleware that only reacts on ReSwiftInit passing through.
    
    https://github.com/ReSwift/ReSwift/issues/216
    *** testing dispatching actions
    https://github.com/ReSwift/ReSwift/issues/194
    *** should i use struct over class in states?
    https://github.com/ReSwift/ReSwift/issues/236
    *** complex subscriber dependencies
    https://github.com/ReSwift/ReSwift/issues/219
    *** subscriber function implementation matters when you write subscribe() closure
    https://github.com/ReSwift/ReSwift/issues/199
    *** saving state to database
    https://github.com/ReSwift/ReSwift/issues/110
    https://github.com/ReSwift/ReSwift/issues/117
    *** handle async side effects with enqueue/dequeue pattern or a value cache
    https://github.com/ReSwift/ReSwift/issues/136
    
    real issue was state change was expected for alert but async state updates triggered it lots of times
    *** rx reswift combo viable?
    https://github.com/ReSwift/ReSwift/issues/78
    *** reswift recorder quickies?
    

    I'll survey these and delete what doesn't make sense.

    I don't want to research a lot for this project. The material is not yet dated, but also not fresh enough to warrant further delay.

    Author at Zettelkasten.de • https://christiantietze.de/

  • I hope this doesn't come across as mean-spirited, but do you really want to do this? Every time you mention it, it doesn't seem like you give it much importance or value. Is it meaningful to you, or is it more that you are worried about the sunk cost of all this information? Would you be happier putting your time into other projects?

    Obviously you don't need to justify it to me or anyone else, but I'm giving you a nudge to reduce or abandon the project if that is what you are subconsciously looking for.

  • @boxcariii said:
    I hope this doesn't come across as mean-spirited, but do you really want to do this?

    Exactly what I was thinking. It sounds like your sub conscious is telling you to let it go already. I second what @boxcariii said.

    It is probably suffice to just have one document with things you absolutely want to say on the subject stuffed into the git archive.

  • @boxcariii and @Perikles -- you are totally right. At the moment, my "definition of done" would be this:

    • discard what doesn't add value to any of the other projects (including my actual code bases for e.g. The Archive!) from the short research list, complete the rest; no re-filing for "later"
    • put the writing onto my website in a section around this topic

    So: no print book edition. That's way too much work for something that's not worth the effort any longer.

    @Perikles you're right that stuffing this into a git repo and archiving it on GitHub for posterity would be the least amount of effort. (Might also use GitBook as a front-end to make the test more readable than .md files in git.) -- I'll fall back to that if I find that assembling the web page gets on my nerves too much :)

    What I am looking for is having an excuse to go through the motions of publishing something like this. Tweaking the tools, and preparing for future (software and writing) projects.

    It's not all bad. :) On top of this being a low priority thing in general, I wouldn't want to do this during my main work time to not put serious effort into this instead of e.g. The Archive. The opportunity cost are too high to put real effort into this outline.

    Author at Zettelkasten.de • https://christiantietze.de/

Sign In or Register to comment.