I’m starting to take a look at Swift Data, and the experience is really, really uncomfortable for me. The tutorials and explanations of how this framework works and how it integrates with SwiftUI really serve to remind me that the way I think about structuring my programs is just plain not how most other folks who write tutorials or frameworks think about structuring programs.
Okay, concrete example first, then I’ll talk about why I don’t like it. For this discussion, I take as my text the book, “SwiftData by Example” by Paul Hudson. By the time we get to page 22 (really, really early on) we have:
- Created a model type (which is a
classand not astruct) - Tagged the model with an annotation which gets compiled to decorate it with lots of swell database-y stuff
- Modified the main application view to give it a special context to use to manage the model object instances
- Added an instance variable to the main content view, to hold a list of model objects, and annotated it with
a macro that gets compiled to code that runs a query against the context to fetch those objects when the view is
loaded or refreshed
…and that last bit is the part that frustrates me. See, what we’re doing there is, we’re mixing together a couple of concerns. The view is principally concerned with taking data and laying it out for display to the user. It might at some point offer some affordances to let the user edit the data, but really the view is about interacting with the user. Display and respond to feedback.
But here we are, taking a different concern, that of managing model objects, their lifecycles, their storage and retrieval, and we’re sticking that into the view. Which, okay, I can make an argument for that: this view is concerned with these objects. It knows which ones it wants (filtering/selecting) and it knows when it wants them, so it’s perfectly positioned to request the data. But. Here’s the thing. I don’t exist for the view’s convenience. That is exactly the inverse of our relationship. And you know what? I guarantee that in three or four years, I will have worked on half a dozen other projects and will have forgotten all the logic and deep thinking about data access that went into the decision to write the query exactly that way. And you know where I’m going to go to look for how some model object is being persisted and queried? The view layer?! Are you kidding me?
There should be some nice, easily located place where all the queries live, so I know what I need to tweak when I change the application logic. Maybe I’m going to persist the data somewhere else, now. Maybe I’m going to add a new feature that manipulates the relationship between the existing model object and some new object. The future is vast and unknowable. I want to make the life of future me be just that little bit easier. Changing a button style? Absolutely, I’m going to survey all the view stuff. Changing a data model? I want a data access layer to scope my stupid searches in.
This kind of structure matters. But not to the functionality of the program. It matters because reducing cognitive load on the programmer means I can be smart about the important stuff because I’m not getting all tired just remembering to be smart about stuff that doesn’t freaking matter. Why are all the cool new things so shitty at making my life better? Why do all the people writing frameworks hate themselves?