Today I don’t use them, unless I need it retrospectively. Which I find is rare.
This is not a knock on interfaces as a language feature. Just inserting a random anecdote about pragmatism..
Today I don’t use them, unless I need it retrospectively. Which I find is rare.
This is not a knock on interfaces as a language feature. Just inserting a random anecdote about pragmatism..
We've tried both approaches, declaring the interface in one package and importing it where used but also declaring it directly colocated with the consumer.
I've found the first approach worked better when we had to add or modify the interface methods
Of course this doesn’t apply when using interfaces for polymorphic return types in a library, but that is a distinct use case for interfaces to address.
Perhaps some of this is just taste, but this is the way I’ve found interfaces in Go to be most useful.
I'm working on a Golang project where we've not yet introduced those kind of tests and, although it can be quicker to code initially, it's slower overall. The project relies heavily on other Open Source systems so the Golang code isn't even that complex.
I can't imagine doing something hard and keeping it working over time without being to isolate dependencies to enable testing and keep the structure clear overall.
But like with everything in life, there is no right solution. Just different tradeoffs. If interfaces best align with the trades you are willing to make, go for it.
If you do this consistently, then you have much of the side effecting code residing next to each other per process/input handler etc.
It's not always feasible or the right thing. But it's a good default way of structuring code and makes testing much more straight forward. And it makes more clear "at a glance" what happens because you can reason more locally about the side effecting parts.
> It also means you are less depedent on the concrete implementation of the API and don't leak types and behaviour from systems you don't control into your codebase
You are always dependent on that. Whether you hide it down the stack or lift it up, you still need to put your data into a specific shape, do the same essential checks etc.
I've never seen Go code that does anything else. That's not to say it doesn't exist, but it's seemingly not the norm amongst Go developers (probably exactly for the reasons you describe). That doesn't address what the parent is talking about, though. You have the exact same problem spoken of no matter where in the stack you put it.
If the software's logic is too complex and fiddly to lend itself to straightforward end-to-end testing (i.e. enterprise software), I just wouldn't write it in Go. I'd choose a higher level language like Python or Java where mocking (and other kinds of dynamism) are straightforward and require no boilerplate.