5 ms·
With this in mind, if I were to start a new project today (using Go, which is all I use anymore). I would segment my code inside of a monolith using interfaces.
by ngngngng 6y ago
With this in mind, if I were to start a new project today (using Go, which is all I use anymore). I would segment my code inside of a monolith using interfaces. This would incur a very slight initial cost in the organization of the codebase prior to building. As your usage goes up and the need to scale parts of it increases, you could swap these interfaces out little by little by reimplementing the interface to contact your new external microservice.
I've worked at several companies where microservices were necessary, and I can't believe how clunky they are to work with. I feel like in 2021 I should be able to write a monolith that is capable of horizontally scaling parts of itself.
- pjmlp 6y agoYep, that is the right approach, modular code.
- domano 6y agoI don't see a lot of cost associated with the duck typing-ish approach go takes with interfaces. Instead of passing an implementation directly (or even having it in the first place) you can develop with an interface from the get go. Makes for easier tests too. In my experience the cost is lower if you write code the way you described (and you don't need to plan ahead as much)
- rollulus 6y agoExactly with this vision I started beginning of 2020 our Go monolithic backend. Currently, one year later with a few people developing it, it's working very well. And thank god I resisted and pushed back against people who were advocating to split off parts into AWS lambdas, misguided by confusing "physical" separation for logic separation. And regarding the cost you mention, I don't think there is any. Yes, the components only know each other via their interfaces, not their concrete types. Yes, you need to define these interfaces. But that's in essence plain old school dependency injection. You'd do that anyway for testing, right?
- b-pixel 6y agoThis is the way. Interfaces for modularity and leveraging nested packages within the monolith to keep code decoupled and organized.
- technics256 6y agoAs someone who is new to Go and learning actively, do you have an example of how this would look?
- ngngngng 6y agoSure. First you'll need to familiarize yourself with interfaces in go. This link explains them well. https://gobyexample.com/interfaces https://gobyexample.com/interfaces So a struct satisfies an interface if it implements all of the methods of the interface. The example you see in the above link is a monolithic design. Everything only exists in one place and will be deployed together. So if the functions for circle were getting hit really hard and we wanted to split those out into their own microservice so that we could scale up and down based on traffic, it would look something like this. https://play.golang.org/p/WOp0RL-pVg3 https://play.golang.org/p/WOp0RL-pVg3 There we have externalCircle which satisfies the interface the same way circle did, but externalCircle makes http calls to an external service. That code won't run because it's missing a thing or two, but it shows the concept.
- jjnoakes 6y agoThere's of course some nuance here - for example the original interface was designed to never error, assuming calculation was local in a way. The new implementation of that interface that makes remove calls may now fail - and basically either has to log and return an arbitrary float, or panic, because the interface doesn't allow for propagating errors.
- cowsandmilk 6y agoMy experience is that micro services are a method to enforce modularity. You don’t have any choice other than talking over interfaces (assuming you don’t cheat by sharing a database). Keeping things modular in a monolith requires discipline that is enforced by reviewing everyone else’s code.