-
|
I'm trying to follow the recently posted episode 348's approach with task loading, but I'm not sure how to define what my repos should return for this observation. Consider the following example of a SOLID app architecture where models are vended through repositories; @Table
struct Player {
let id: String
let name: String
let score: Int
}
protocol PlayerRepository {
func all() throws -> [Player]
func increaseScore(of player: Player) throws
func observable() -> ?
}and the following view & view model: struct PlayersView: View {
@State
var model: Model
var body: some View {
Form {
ForEach(model.player) { player in
HStack {
Text(player.name)
Spacer()
Text("Score: \(player.score)")
Button {
model.userDidTapPlayerScoreButton(for: player)
} label: {
Text("Add point")
}
}
}
}
.task {
try await model.task()
}
}
}
extension PlayersView {
@Observable
final class Model {
let repo: any PlayerRepository
@ObservationIgnored @FetchAll
var players: [Player]
init(repo: any PlayerRepository) {
self.repo = repo
}
func userDidTapPlayerScoreButton(for player: Player) {
withErrorReporting {
try repo.increaseScore(of: player)
}
}
func task() async {
withErrorReporting {
try await $players.load(repo.observable).task
}
}
}
}In a concrete implementation of such a repository, I could then return this for struct MainPlayerRepository: PlayerRepository {
...
func observable() -> ? {
Player.all.order { $0.score.desc() }
}
}But I'm not sure what type I should return, in a generic way. Is there a Or more generally, is there a better way to work with SOLID here? My main goal is to not depend on the DB in my app/UI layer... |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
|
Hi @MrSkwiggs, if you are wanting the type of query that can be loaded into func observable() -> any Statement<Player>However, I'm not really sure what your abstraction is buying you. First, you still have to use And second, what would another conformance of So, I would take a hard look at whether or not this abstraction is really worth the effort, |
Beta Was this translation helpful? Give feedback.
Hi @MrSkwiggs, if you are wanting the type of query that can be loaded into
@FetchAll, then you can useStatement:However, I'm not really sure what your abstraction is buying you. First, you still have to use
@FetchAllin the model, and so you're not really insulating yourself from the APIs of the library. And that is just something that you will have to live with because there is no way to abstract away that tool.And second, what would another conformance of
PlayerRepositoryeven look like? Typically these kinds of protocols are to make code more testable so that you can provide test-friendly implementations in tests. But in the case of SQLite…