Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Proposal For Use Of Interfaces
Context
Greetings,
Our development team utilizes the
gocb
package for our platform. When we use external packages such as this, we tend to wrap them in an abstraction that makes our application code easier to understand. Take the snippet below, for example; we are creating our own wrapper package calledstore
. The application only has to understand how thestore
package works, and doesn't need to know that behind the scenes it usesgocb
. This makes it very easy to understand the application code since we are the ones defining those methods.application
wrapper
Testing
We do not make wrappers solely for comprehensibility, but also for testing. Any code that uses the
store
package will be easy to write unit tests for because theStore
type is aninterface
. In our unit tests, we can implement our ownmockStore
type that implements theStore
interface.The issue we are facing is not that we can't write tests at the application level, which consumes the
store
package, but rather that we cannot test thestore
package itself without creating a true connection to aCouchbase
instance or cluster. We want to be able to run our unit tests in a CI pipeline where we are not able to connect toCouchbase
.The best way that we know how to address this is for the types in
gocb
to beinterfaces
instead ofstructs
so that we can manipulate the functionality of the public methods directly in our unit tests. Let's look at the following examples:Structs
We can see that with the
structs
approach, we are unable to test every code path. In order to test the cases where the document does and doesn't exist, we have to write additional code in the unit tests to write and remove the expected document fromCouchbase
. And we still are unable to test the case where an error has occurred because we cannot forceCouchbase
to return an error.store.go
store_test.go
Interfaces
We can see that with the
interfaces
approach, it is easy to create our own mock version of acollection
. Another change to note is that the*gocb.ExistsResult
type has been changed from astruct pointer
to aninterface
in thegocb
package. By using aninterface
,gocb.ExistsResult
, we can create our own types which implement thatinterface
in our unit tests, allowing us to test every code path in our wrapper as well as run these unit tests in a pipeline without the need for a connection to aCouchbase
instance.store.go
store_test.go
What We Are Asking
We are asking the maintainers for this package if they are open to changing the public
structs
ingocb
tointerfaces
for the reasons listed above. The most obvious reason for why the answer would beno
is that this would ultimately be a breaking change, and everyone else that uses this package would have to modify their code to work with theinterfaces
instead. Our goal here is really to test our wrapper in an automated fashion as mentioned before, without the need for aCouchbase
instance. If the maintainers for this package have any solutions outside of the one that we have proposed, I am all ears. The alternative, if no other solution is provided and the maintainers are against the changes we have proposed, is for us to maintain our own fork ofgocb
and make the changes ourselves. We are not entirely against this, but it would be another layer of maintainence since we will need to periodically sync with upstream branch, which could include conflicts.Additional Details
The changes that were raised in this Pull Request were the bare minimum amount of changes that were required to get the code snippets from above to work. This Pull Request is not a request to merge these changes, but rather to demonstrate the effort that it took to make our code sample work.