4 ms·
IoC DI in Go is a massive antipattern and absolutely should not be done. Do NOT write Java/.NET style controllers in Go i.e. initializing an instance of a "cont
by roncesvalles 2y ago
IoC DI in Go is a massive antipattern and absolutely should not be done. Do NOT write Java/.NET style controllers in Go i.e. initializing an instance of a "controller" type with some instances of a "dependency" such as a store.
Just use the dependent package directly. Initialize the package once using init() or Init(). Rely on the built-in package dependency resolver system in Go, which will catch cyclic dependencies, call init() in topo order, and other such things.
Test using monkey-patching. Stop using interfaces just to be able to swap a real thing with a mock implementation. These are all symptoms of writing Java in Go.
- 3uler 2y agoAnd yet Uber wrote fx[1] to support DI in their golang services. It’s clearly a useful pattern when working on large services. [1]: https://github.com/uber-go/fx https://github.com/uber-go/fx
- roncesvalles 2y agoI disagree with the premise of that whole project. It shouldn't exist.
- 65a 2y agoI really cannot say Uber's use of Go is particularly idiomatic to me, having started writing Go more than a decade ago now. It just strikes me as overwrought, and I've worked on big services.
- Cthulhu_ 2y agoJust because a known company uses it doesn't mean it's authoritative; there's likewise functional programming libraries built by big companies, but FP should also be avoided in Go because it's not a functional language and not optimized for it.
- someothherguyy 2y agoSo, write python in go instead, gotcha.
- roncesvalles 2y agoThe idiomatic way to write Go is as naively as possible after you fully understand how it works. Otherwise it'll just feel like Java with shitty ergonomics. If you're ever writing Go and wish you had real classes instead of this deconstructed "mess" with struct types, methods, and interfaces, you're writing Go totally wrong.
- gf000 2y agoSounds like a no true Scotsman fallacy.
- unscaled 2y agoThat is certainly one way to write Go, but I wouldn't call it "idiomatic" when evil the Google Best Practices guide recommends against it[1][2]. I'll wager you'll probably find it in most other Go style guides. This is how the Go standard library itself works. While you can use http.Get() if you want to use the default HTTP client for simple apps, the library provides you the http.Client struct, where you can also override the Transport (RoundTripper interface) and Jar (CookieJar interfaces). The transport interface lets you further override the Dialer and Proxy function. [1] https://google.github.io/styleguide/go/best-practices#global-state https://google.github.io/styleguide/go/best-practices#global... [2] https://google.github.io/styleguide/go/best-practices#providing-a-default-instance https://google.github.io/styleguide/go/best-practices#provid...
- roncesvalles 2y agoThe example they've chosen is somewhat contrived in that the dependency is maintaining a collection of plugins. In such a case it makes sense to go with their approach. I'm not actually arguing against having multiple instances of some package's functionality; indeed such instances may be created and stored per controller. I'm more so arguing against IoC style Dependency Injection, i.e. central instantiation of the controller and its dependencies. My point is just, as far as possible, it's better to rely on init() and package import relationships. You can simply call dep.New() in any number of inits.
- stpedgwdgfhgdd 2y agoI don't get the part on package. Often you want to use structs. (Instance vs static) How would you construct an instance in a test that needs mock implementations?
- roncesvalles 2y agoSuch an instance would just be a variable somewhere that would be initialized in some init() call when the program starts. Every user of that instance will use it directly (as opposed to storing a reference to it locally DI style).
- gf000 2y agoSo global mutable state? How wonderfully modern!
- akoboldfrying 2y ago> Test using monkey-patching. TIL Go has monkey-patching. But since it has monkey-patching, how is it statically typed? Or does Go monkey-patching amount to creating an instance of a defined-on-the-fly subclass? The latter would be interesting, because Java lets you do this too -- conveniently "new up" an instance of a subclass that you define inline of a given class or interface (this used to be the easiest way to define callbacks, before lambdas came along), so this testing strategy is available to Java too, but seems not to be preferred. Separate question: IIUC, monkey-patching is convenient if your test code directly needs to create a TestX instead of a real X, but what if you need the test double "deeper down" -- that is, you need an X that creates a Y that creates a TestZ instead of a real Z?
- tpm 2y agoJava doesn't really enable monkey-patching in the style of Javascript, Perl etc. AFAIK, or am I missing something? That you can create anonymous subclasses during runtime is different to e.g. editing methods of existing objects/classes during runtime.
- fweimer 2y agoJVMTI allows method patching: https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#RedefineClasses https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.h... The capabilities are somewhat limited, and an enhancement JEP was withdrawn: https://openjdk.org/jeps/159 https://openjdk.org/jeps/159 On the other other, there is a movement to remove such late binding/rebinding features from the Java platform. However, I think JVMTI is expected to remain supported if the agents are loaded ahead of time. Only on-demand loading of agents will be removed from OpenJDK.
- gf000 2y agoI wouldn't say that there is a movement to remove such late binding features -- the "movement's" primary goal is simply to properly encapsulate and mark any such part of the code (e.g. make it explicit in the module that that should be supported). That way AOT compilation becomes possible/efficient and dependencies can't hack into other packages in an unmaintainable way without explicit permission from the user, so that updating the JVM and dependencies will be even more streamlined.
- the_gipsy 2y ago> Test using monkey-patching. Can you elaborate? What library do you use?
- captain_coffee 2y agoHard disagree to literally every thing that you have said in your reply above.