News for hackers. Stuff that matters.
Re:Monolith First (2015) by ngngngng on Friday February 19, 2021 @04:05AM (#26191055)
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.

Re:Monolith First (2015) by rollulus on Friday February 19, 2021 @04:41AM (#26191261)
Exactly 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?

Re:Monolith First (2015) by domano on Friday February 19, 2021 @04:19AM (#26191140)
I 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)

Re:Monolith First (2015) by b-pixel on Friday February 19, 2021 @07:32AM (#26192427)
This is the way. Interfaces for modularity and leveraging nested packages within the monolith to keep code decoupled and organized.
Re:Monolith First (2015) by pjmlp on Friday February 19, 2021 @04:06AM (#26191069)
Yep, that is the right approach, modular code.
Re:Monolith First (2015) by cowsandmilk on Friday February 19, 2021 @10:50AM (#26194381)
My 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.
Re:Monolith First (2015) by technics256 on Friday February 19, 2021 @08:29AM (#26192911)
As someone who is new to Go and learning actively, do you have an example of how this would look?
Re:Monolith First (2015) by ngngngng on Friday February 19, 2021 @01:25PM (#26196192)
Sure. First you'll need to familiarize yourself with interfaces in go. This link explains them well.

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

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.

Re:Monolith First (2015) by jjnoakes on Friday February 19, 2021 @03:24PM (#26197605)
There'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.