Earlier quoted context omitted.
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 ChainStreamIn…
How I write HTTP services in Go after 13 years
211–220 of 259 posts
Re: How I write HTTP services in Go after 13 years
#212Earlier 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 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…
Especially in Go, where you don't have destructors to help with shutdown, having common structure in place to help tear down components has always been a net benefit for me.
Re: How I write HTTP services in Go after 13 years
#213Earlier 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.
Your dependency structure should just be a tree. It should be inserted literally right next to it's first use case. Your IDE will literally point it to you with red squigglys because the places where you've added a dependency will be missing a parameter. Go to the highest one and add it on the line above.
What do you do on shutdown? In languages with destructors, that can automatically give you a call order in reverse of the construction order, but in Go you end up manually ordering things or just not having panicless shutdowns.
Re: How I write HTTP services in Go after 13 years
#214> The Valid method takes a context (which is optional but has been useful for me in the past) and returns a map. If there is a problem with a field, its name is used as the key, and a human-readable explanation of the issue is set as the value. I used to do this, but ever since reading Lexi Lambda's "Parse, Don't Validate," [0] I've found validators to be much more error-prone than leveraging Go's built-in type check…
Crazy that actually using your type system leads to better code. Stop passing everything around as `string`. Parse them, and type them.
Types limit you from making some mistakes, but it also impacts your extensibility. Imagine an enum with 4 values and you want to add 1 because 10 level deep one of the services need new value. How does it usually go with strongly typed languages? You go and update all services until new value is properly propagated to lowest level who actually needs that value.
Now imagine doing same with strings, you can validate at the lowest level, upper levels just pass value as it is. If upper layers have conditionals based on value, they still can limit their logic to those values
Re: How I write HTTP services in Go after 13 years
#215Earlier quoted context omitted.
Any language without zero-values (or some equally destructive quality) can do "parse, don't validate". Go cannot. Rust is just an example.
Top of the hour again? Time for another Rust advertisement? The topic at hand is about preventing library users from doing things the library author didn't intended using the type system, not "what happens if a language has zero-values". Perhaps you are not able to comprehend this because you are hungry? You're not you when you are hungry. Grab a Snickers.
Maybe it's time for you to finally try rust? Or any other language without zero-values, since rust seems to irritate you in particular.
Re: How I write HTTP services in Go after 13 years
#216Only thing I agree on is putting all the paths in one file.
In most other programming languages I've done a lot of research how to make it nice and clean.
Was hoping this was it for Go because I'm cleaning up a big project.
But my very basic no nonsense current setup seems better to me than this in many ways.
If anybody has another example that is a lot better (and I don't mean complexer I don't have those ego issues), I am very interested.
But this I want to hide as best as I can from my dev team this is all wrong. It's clever in a lot of ways but it's wrong.
It does not have unit testing at all, all these tests would be duplicated in the end-to-end test.
I also like end-to-end tests better but why put them here, way better to put them in postman for example then you have the most up to date documentation always auto-generated.
Passing the config, man I had so many discussions with junior developers about this, don't do that you'll make things dependent on the config and cannot reuse them in other programs. But that was already mentioned a lot here.
There are also a lot of functions with like 10 arguments passed. If you have that many arguments just pass a stuct containing a lot of the arguments it's always super confusing when people make functions with 12 arguments. I'm always counting them an after 14 times counting I rewrite their function.
It's a matter of style so keep doing it this way if you like it, but it's not my style at all it makes no sense at all to me.
If anybody knows a better example please tell me.
Re: How I write HTTP services in Go after 13 years
#217Earlier quoted context omitted.
You inherit some code. Is that string a username or a phone number? Who knows. Someone accidentally swapped two parameter values. Now the phone number is a username and you’ve got a headache of trying to figure out what’s wrong. By having stronger types this won’t come up as a problem. You don’t have to rely on having the best programmers in the world that never make mistakes (tm) to be on your team and instead rely…
I agree on the one hand but empirically I don’t think I have seen a bug where the problem was the string for X ended up being used as Y. Probably because the variable/field names do enough heavy lifting. But if your language makes it easy to wrap I say why not. It might aid readability and maybe avoid a bug. I would probably type to the level of Url, Email, Name but not PersonProfileTwitterLink.
Re: How I write HTTP services in Go after 13 years
#218Re: How I write HTTP services in Go after 13 years
#219Earlier quoted context omitted.
Crazy that actually using your type system leads to better code. Stop passing everything around as `string`. Parse them, and type them.
things have different costs. Types limit you from making some mistakes, but it also impacts your extensibility. Imagine an enum with 4 values and you want to add 1 because 10 level deep one of the services need new value. How does it usually go with strongly typed languages? You go and update all services until new value is properly propagated to lowest level who actually needs that value. Now imagine doing same with…
Re: How I write HTTP services in Go after 13 years
#220Earlier quoted context omitted.
things have different costs. Types limit you from making some mistakes, but it also impacts your extensibility. Imagine an enum with 4 values and you want to add 1 because 10 level deep one of the services need new value. How does it usually go with strongly typed languages? You go and update all services until new value is properly propagated to lowest level who actually needs that value. Now imagine doing same with…
Why would you need to update code that isn't matching on the value? It just knows it has an X and passes it to a function that needs an X.