4 ms·
> I worked at an employer who heavily used golang ... they ended up reinventing the wheel on so many different things, including DI and an entire application fr
by sagichmal 5y ago
> I worked at an employer who heavily used golang ... they ended up reinventing the wheel on so many different things, including DI and an entire application framework.
Sounds like they were trying to force the language to be something it's not. DI frameworks (I think what you mean) are basically incoherent in Go, dependency injection is naturally modeled with interfaces. In fact any inversion-of-control style "framework" is a mismatch to the language, it (intentionally) lacks the features that frameworks rely on to deliver benefits that outweigh their costs.
> The way interfaces are handled in golang makes it very annoying to try to find out which types implement said interface.
The desire to do this reflects a misunderstanding of interfaces.
- closeparen 5y agoTake a look at the major DI frameworks for Go, Wire [0] and FX [1]. They just plumb the gaps between methods that return types and methods that want them. Although technically they work for concrete types, 99% of the time it's going to be an interface, so that you can substitute a mock for testing. Prior to DI frameworks we used global variables, often initialized in a package's init() method. >The desire to do this reflects a misunderstanding of interfaces. Generally you have a few layers: gRPC/HTTP/Kafka handler, business logic, and database or external service access. Layers are unit tested individually against mocks of the layers below. Because you're going to inject a mock, you can't depend on a concrete type, so you depend on an interface. Often when you're developing you want to know what the concrete implementation of a lower layer does, so it's useful to have "go-to-definition" see through the interface declaration to its implementations. I think the implicit satisfaction of interfaces is very cool and I wish I had it in every language. I wouldn't give it up just to simplify the IDE's job. But the IDE having this functionality does matter. [0] https://github.com/google/wire https://github.com/google/wire [1] https://github.com/uber-go/fx https://github.com/uber-go/fx
- sagichmal 5y ago> Take a look at the major DI frameworks for Go, Wire [0] and FX [1] I'm well aware of them. (There are several more, too, which see at least as much use as these two, unfortunately.) They also reflect a misunderstanding of the language. Wire less so than FX. (I'm also aware Wire is written by Googlers, no need to point that out.) > Prior to DI frameworks we used global variables, often initialized in a package's init() method. I don't understand how these things are related. DI frameworks aren't necessary for Go-idiomatic dependency injection, and global variables were never an appropriate way to manage dependencies. > Generally you have a few layers: gRPC/HTTP/Kafka handler, business logic, and database or external service access. Yes! > Layers are unit tested individually against mocks of the layers below. Yes! > Because you're going to inject a mock, you can't depend on a concrete type, so you depend on an interface. Yes! > Often when you're developing you want to know what the concrete implementation of a lower layer does, so it's useful to have "go-to-definition" see through the interface declaration to its implementations. ...no? There are basically two situations where you use an interface in this way. One, most often, in an application where the "production" code uses one implementation, which you know a priori and therefore have no need to go spelunking. Or, two, in a library where you by definition cannot know what implementation your users will provide to you. In the first case, your mock would model the implementation, which I guess is trivial. In the second case, your mock would reflect your expectations of the interface's implementations, explicitly without knowledge of any implementation.
- gher-shyu3i 5y ago> which you know a priori and therefore have no need to go spelunking. Except when you're working on a codebase that's new to you, and you're trying to navigate it to make a change somewhere, so you don't have a priori knowledge about what implements which interface.
- deleted 5y ago[deleted]
- gher-shyu3i 5y ago> Sounds like they were trying to force the language to be something it's not They're getting around the lack of features in the language. Most languages that I know of have mature DI solutions, and those are needed for writing any non-trivial app. Also, one of said frameworks I was referring to generates mocks for your app and wraps errors so you automatically get stack traces in errors that are being passed around. Something already solved in Java and C# and practically any language with exceptions.
- sagichmal 5y ago> Most languages that I know of have mature DI solutions, and those are needed for writing any non-trivial app. Patently false. > Also, one of said frameworks I was referring to generates mocks for your app and wraps errors so you automatically get stack traces in errors that are being passed around. Something already solved in Java and C# and practically any language with exceptions. You're speaking as if generating mocks and adding stack traces to errors are... features? They're not! Generating mocks almost totally defeats the purpose of using them, and stack traces have no business being attached to errors in the general case. Sometimes I truly don't understand the context that my peers are working in. Totally incoherent...
- gher-shyu3i 5y ago> You're speaking as if generating mocks and adding stack traces to errors are... features They're working around a weakness in the language. Stack traces in exceptions are definitely a feature. golang doesn't offer it out of the box, which is why the abomination of a framework I was telling you about had to be written. Similar things had to be done to work around the lack of generics, or the lack of composability of goroutines, or even in normal functions because of lack of composability of error handling. > Sometimes I truly don't understand the context that my peers are working in. Totally incoherent... Exactly what I think when I see people writing large projects in golang, and all the messes they have to go through to work around its limitations.
- sagichmal 5y ago