I would generally say to stick to approach 1, as much as that stinks. Your observation about approach 2 especially compounds once you start to look at more complex operations that need to be optimized based on how the underlying DB works. Care still needs to be taken in approach 1 to avoid non-optimal operations, but at least you have the freedom to rework individual methods on your DatabaseProxy instead of all FirebaseProxy methods using your underlying CRUD operations.
One of the fastest ways I get people thinking about this is asking
How would you implement a listTimers or listTickets API with cursors?
Generally that’s complex enough to bring out pain points.
I would generally say to stick to approach 1, as much as that stinks. Your observation about approach 2 especially compounds once you start to look at more complex operations that need to be optimized based on how the underlying DB works. Care still needs to be taken in approach 1 to avoid non-optimal operations, but at least you have the freedom to rework individual methods on your DatabaseProxy instead of all FirebaseProxy methods using your underlying CRUD operations.
One of the fastest ways I get people thinking about this is asking
Generally that’s complex enough to bring out pain points.