Live data from Hacker News

How I write HTTP services in Go after 13 years

grafana.com

201–210 of 259 posts

Re: How I write HTTP services in Go after 13 years

#201
post #158
post #19

I really like Mat Ryer's work, and I've applied most of the ideas in the 2018 version of this article to all of my Go projects since then. The one weak spot for me is this aspect: > NewServer is a big constructor that takes in all dependencies as arguments... In test cases that don’t need all of the dependencies, I pass in nil as a signal that it won’t be used. This has always felt wrong to me, but I've never been ab…

You can use Dependency Injection to solve this issue but in my view the added complexity is not really worth it.

Is this a Go thing? In C# land this is trivial.

Re: How I write HTTP services in Go after 13 years

#202

Earlier quoted context omitted.

Except Username is not exactly the same as string, and that's important. Username is a subset of string. If they were equivalent, we wouldn't need to parse/validate. The often misinterpreted part of DRY is conflating "these are the same words, so they are the same", with "these are the same concept, so they are the same". A Username and a String are conceptually different.

DRY is just "Do not repeat yourself". And a LOT of devs take that literally. It's not "Do not repeat concepts" (which is what it SHOULD be but DRC isn't a fun acronym). Unfortunately "This is the same character string" is all a DRY purist needs to start messing up the code base. I honestly believe that "DRY" is an anti-pattern because of how often I see this exact behavior trotted out or espoused. It's a cargo cult t…

In my experience (~20 years) with software development I developed the belief that people will go through the path of applying patterns, techniques, architectures, good practices, first as dogma, then to rejection, ending in acceptance of the knowledge that almost all of software development patterns/best practices are mostly good heuristics, which require experience to apply correctly and know when to break or bend the rules.

DRY applied as a dogma will eventually fail, because it's not a verified mathematical proof of infallible code, it's just a practice that gives good results inside its constraints, people just don't learn the constraints until it explodes in their faces a few times.

Like any wisdom, it's hard it will be received and understood without the rite of passage of experience.

Re: How I write HTTP services in Go after 13 years

#203

Earlier quoted context omitted.

C++ constructors actually make the guarantee, but it comes with other pains

Lots of languages handle it just fine and don’t need the mess of C++ ctors. GP is pointing out that go specifically makes it an issue.

What language do you have in mind?

Re: How I write HTTP services in Go after 13 years

#204
post #200

Earlier quoted context omitted.

> you can't just look at the documentation of the type Sure you can. Option func is a constructor for option type, and constructors are auto-included above methods in the docs. PLS completion works for them as well.

The options for the thing being constructed are all separate types from the thing being constructed; the options aren’t a facet of the definition of the type they mutate.

I'm saying:

- main constructor is easily available from the main type's docs,

- option type is easily available from the main constructor's docs,

- all option funcs are easily available from the option type's docs (because in fact these option funcs are constructors for the option type).

Excerpt from grpc godoc index:

    type Server

    func NewServer(opt ...ServerOption) *Server

    ...
    ...

    type ServerOption

    func ChainStreamInterceptor(interceptors ...StreamServerInterceptor) ServerOption
    func ChainUnaryInterceptor(interceptors ...UnaryServerInterceptor) ServerOption
    func ConnectionTimeout(d time.Duration) ServerOption
    func Creds(c credentials.TransportCredentials) ServerOption
    etc...
One more hop compared to a flat argument list, that's true. But if you only commonly use maybe 0-5 arguments out of 30-50 available, it does not look like a bad deal.

Re: How I write HTTP services in Go after 13 years

#205

Earlier quoted context omitted.

Except Username is not exactly the same as string, and that's important. Username is a subset of string. If they were equivalent, we wouldn't need to parse/validate. The often misinterpreted part of DRY is conflating "these are the same words, so they are the same", with "these are the same concept, so they are the same". A Username and a String are conceptually different.

DRY is just "Do not repeat yourself". And a LOT of devs take that literally. It's not "Do not repeat concepts" (which is what it SHOULD be but DRC isn't a fun acronym). Unfortunately "This is the same character string" is all a DRY purist needs to start messing up the code base. I honestly believe that "DRY" is an anti-pattern because of how often I see this exact behavior trotted out or espoused. It's a cargo cult t…

DRY vs premature optimisation is the landscape most long term devs find themselves in. You can say that FP, OO and a bunch of other paradigms affect this, but eventually you need to repeat yourself. The key is to determine when this happens without spending too much time determining when this happens.

Re: How I write HTTP services in Go after 13 years

#206
post #23

I've recently been playing with ogen: https://github.com/ogen-go/ogen Write openapi definition, it'll do routing, definition of structs, validation of JSON schemas, etc. All I need to do is implement the service. Validating an integer range for a querystring parameter is just too boring. And too easy to mistype when writing it manually. Anyways, so far only been playing, so haven't found the bad parts yet.

I've started doing the same but with oapigen; github.com/deepmap/oapi-codegen

I thougt it would be boring writing the spec, but it was not nearly as bad as I thought. Also, a spec is needed, so might as well write it up front.

Re: How I write HTTP services in Go after 13 years

#207

What is the value making main.go as small as possible? Whose dreams come true in this scenario?

I assume you mean main() and not main.go.

main() is the only place where you can't return an error. In order to keep as much of the code as idiomatic as possible you just call something like run() where you can do so.

In addition there is the testing aspect. You can't invoke main() from your tests.

Re: How I write HTTP services in Go after 13 years

#208
post #127

Earlier quoted context omitted.

>All the advice in the article is still helpful, but it takes the "how do I make sure X is initialized when Y needs it" part completely out of the equation and reduces it from an N*M problem to an N problem, ie I only have to worry about how to initialize individual pieces, not about how to synchronize initialization between them. I gotta say, I hate these dependency injection frameworks. In a well designed system th…

If you have ever topologically sorted 100 components connected in a complex graph by hand or found the right spot to insert the 101st, you'd quickly appreciate more help than a compiler check.

I’m not against DI, but I don’t find your argument convincing: having dependencies modelled directly with the simplest language constructs (variables and arguments) and validated by the compiler makes “debugging” a ton simpler than dealing with DI errors, even in a good DI framework. Having an error just means I wrote invalid code: even a junior can easily figure it out.

DI still has other advantages, but that’s not one

Re: How I write HTTP services in Go after 13 years

#209
post #23

I've recently been playing with ogen: https://github.com/ogen-go/ogen Write openapi definition, it'll do routing, definition of structs, validation of JSON schemas, etc. All I need to do is implement the service. Validating an integer range for a querystring parameter is just too boring. And too easy to mistype when writing it manually. Anyways, so far only been playing, so haven't found the bad parts yet.

The problem with this approach is writing openapi by hand from scratch is incredibly tedious process. Writing Protobufs, capnproto or any such similar idl feels much more productive

it lacks flexibility but i really enjoy grpc-gateway for 99% of my work

https://github.com/grpc-ecosystem/grpc-gateway

Re: How I write HTTP services in Go after 13 years

#210
post #127

Earlier quoted context omitted.

If you have ever topologically sorted 100 components connected in a complex graph by hand or found the right spot to insert the 101st, you'd quickly appreciate more help than a compiler check.

I’m sure there’s a place for them. But when micro-services are so common, it seems like people use them (Spring) because everyone else does, not because they actually provide needed value.

Spring is an overly complicated mess. I use DI when it makes things simpler, I don't see how Spring would ever do that.
Post reply on HN