The Node
might be getting passed down to a view for presentation to the user, and the view in turn just happens to store the Node
in a local property. The view might allow the user to mutate some properties on the Node
, like expanding it to show the children or editing the name
field. Those edits need to propagate back up to some source-of-truth in the application, which in this case might be a data model or document holding a Tree
of Nodes
.
If I take my trivial example and bring it into a "real world" application, then I routinely find myself with views that have properties referencing some shared state.
Forum friendly examples are always tough, but maybe this will help a bit:
Thinking in AppKit/UIKit as SwiftUI is quite different.
final class Model {
var tree: Tree {
didSet {
// Notify ListView and maybe DetailView...
}
}
}
final class ListView {
var presentedTree: Tree?
}
final class DetailView{
var presentedNode: Node?
}
final class SummaryView {
var presentedTree: Tree?
var presentedNode: Node?
}
In this example, a mutation of the tree
in the Model
will trigger a CoW because ListView
and SummaryView
each have a reference to it. A mutation of any property in the DetailView
needs to propagate back to the Model
and then down to the other views.
So either the Model
or the Tree
needs some API that takes a Node
, or Node.ID
and can mutate the tree to reflect the desired changes. IMHO, that API is challenging to build because it's not clear how it should defined. And if Tree
is something a lot more complex, with deeply nested properties, then it can be challenging to "find" the instance of the property to mutate.
Now, there's a strong argument to be made that perhaps the Views
should only have access to the Model
. Perhaps that's the solution, but the Model
is likely to be a reference type so now all we've really done is hide the value type behind a reference type.
Perhaps a Tree
example is a bit too simplistic to express myself. Consider perhaps a Document
type that represents a rather complex type with many levels of nested properties and sub-types.
I would find it strange to pass around a Document
to every view that needs to display some subset of the document. If the Document
had layers and a I had a view for showing Layers
, then I'd expect to just give said view an Array of layers, not the entire Document
.
But any mutations of those layers, like their ordering or visibility, need to get back to whatever component is holding a reference to the "main" Document
itself. Document
have an API for updateLayers()
or maybe there some more functional approach like updateLayers(document, layers) -> Document
.
If I understand you correctly, then you're suggesting that the Tree
itself should be passed around instead of a Node
? That would certainly allow any view to mutate the Tree
, but now you have multiple references to it everywhere.