I've been following the discussions around SE-0395: Observability as well as the counter-points raised by @gwendal.roue here, and some new ideas related to the topic formed in my mind that I want to share and hear feedback on.
Based on Gwendal's post I believe that my experience grappling with the implementation of "Observation" patterns is more limited than his. The ideas I propose here are not meant to address the full problem space, rather to attempt to describe a possible design for a specific subsection of it.
As far as my experience with the topic, I did recently implement (somewhat hastily hack together) this Swift package which provides
MainActorValueSource<Value>, a main-actor-isolated generic single value holder that can be composed with other (compositions of) sources and then observed. It uses a SwiftUI-like approach for dependency tracking so as to provide what I believe is what Gwendal describes as "Value Observation":
To be clear, the implementation in that package is not directly related to what I describe below.
I'm going to try to lay out my ideas clearly and concisely. I don't know if the things I'm thinking of actually fit together as a coherently implementable approach - it's more of a brainstorm:
I imagine defining a huge, deeply nested struct. When I say "huge struct" I don't mean that the top level has a lot of properties. I'm imagining the struct encoded as a JSON object, which can still be huge even if the top level has only one key.
I imagine using the new move-only features to create exactly one instance of this huge struct. That instance "has an identity" by virtue of being move-only (a concept which I started a thread about here).
I imagine that access to that huge struct instance could be restricted to a specific concurrency context. (e.g., one's
ViewModelwould be restricted to the
If this huge struct is indeed a view model, then I imagine having a beautifully direct method (probably using key paths) of connecting one of its far-away leaves to a small sub-component of my UI, and have that UI component observe changes to that specific part of the huge
ViewModelstruct and update itself accordingly.
More generally, I imagine being able to conveniently observe any key path on this giant struct. (I realize that the definition of "conveniently observe" is hotly debated - I don't think that's what I'm addressing here, in that whatever the resolution is there would presumably be compatible with what I'm describing here).
To summarize so far, I think the core of what I'm proposing is the ability to observe arbitrary key paths on move-only structs, using whatever observation API we deem best in general (although maybe the results of those debates are fundamentally incompatible with this design for whatever reason - the whole thing is too abstract for me to feel very certain about it).
If I've correctly understood the discussions surrounding invariants and the problems wanting to be addressed, I think that this approach may offer an elegant solution, which is that you statically enforce your invariants using structs and then you just have to widen the scope of your observed key path enough to encompass the enforcement. For example:
// Instead of:
I'm not 100% sure that my point about invariants is an appropriate or relevant addition to the discussions I saw going on in Gwendal's thread, but I think that what I'm getting at is at least somewhat clear.
- Lastly, I'll give a shout-out to BSON, the existence of which some of @taylorswift's posts only recently brought to my attention, because I'm imagining observing a change in a distant leaf of my huge move-only struct and then leveraging BSON's architecture (if I've understood it correctly) to efficiently persist that change to the BSON file that contains the whole encoded struct without needing to encode and persist the entire struct on every change.
Would love to hear your thoughts (and corrections - I am sure that many of the things I said are correctable).