-
Notifications
You must be signed in to change notification settings - Fork 261
Add a sqlx datastore implementation #69
Comments
My proposal for how to organize database access is shown in this blog post, in particular the section on using an interface. The idea is simple. First, create an interface that describes what the backend should do:
now we can create a concrete struct, like
and implement all the datastore methods using the Placing all the database methods behind a database has several advantages:
This pattern is easy to implement, maintain and extend and should be considered for dependencies in general, but especially when importing code that is hard to test or might be replaced later on. Here's an example from A bunch of implementations of the Backend: |
Playing a little with the code, here's how an initial refactoring could look like: current code:
refactored
new adapter packagedatabase implementation lives here instead
|
One last thought here: this can get pretty ugly:
To keep the interface relatively small, we can add some useful filters.
Here
|
@zwass @marpaia mind reviewing my comments above and giving me some feedback? I'd like to tackle this in three steps:
|
It looks like you hit on one of my concerns with your "one last thought". I think that using filters like you describe could be helpful, but how will we decide which filters to implement? Just implement them as needed? I am also wondering about creating mocks to conform to the interface. I notice there are a couple of packages for Golang that help with this (https://github.com/golang/mock, https://github.com/stretchr/testify#mock-package). Do you have experience with them? It seems likely that we would want to implement the methods on an as-needed basis, and it would be convenient if the mocks were easy to update alongside. Lastly, I'm not sure about the nesting of |
My example of embedding UserStore inside Datastore is just for code cleanliness. It just means that Datastore is an UserStore. Having smaller interface definitions also helps when you're mocking something. When you're mocking user interactions, you only need to implement that subset of methods. I tend to avoid big testing packages like testify, in favor of relying on stdlib. Embedding an interface into a struct can also help with quickly mocking just a subset of that interface: https://play.golang.org/p/qhQwgq0CYs Regarding filters: I think we implement them as the need comes up. |
Thanks for the reminder on embedding. I'm not quite used to all this Go syntax yet but I understand what you're doing now. One thing I really don't understand is why Go lets you compile code with only a partially implemented interface (that then segfaults at runtime if you try to call unimplemented functions), but that is convenient for our purposes here. Overall, yes I am into this idea. |
@murphybytes We should probably close this now? |
Following the patterns laid out here, lets move to sqlx isolated behind a subpackage.
The text was updated successfully, but these errors were encountered: