Live data from Hacker News

Hyrum’s Law in Golang

abenezer.org

171–180 of 190 posts

Re: Hyrum’s Law in Golang

#171

Earlier quoted context omitted.

You actually should never return a specific error pointer because you can eventually break nil checks. I caused a production outage because interfaces are tuples of type and pointer and the literal nil turns to [nil, nil] when getting passed to a comparator whereas your struct return value will be [nil, *Type]

It's really hard to reconcile behavior like this with people's seemingly unshakeable love for golang's error handling.

People who rave about Go's error handling, in my experience, are people who haven't used rust or haskell, and instead have experience with javascript, python, and/or C.

https://paulgraham.com/avg.html

Re: Hyrum’s Law in Golang

#172
post #74

Hyrum's Law is one of those observations that's certainly useful, but be careful not to fixate on it and draw the wrong conclusions. Consider that even the total runtime of a function is an observable property, which means that optimizing a function to make it faster is a breaking change (what if suddenly one of your queues clears too fast and triggers a deadlock??), despite the fact that 99.99999999% of your users w…

That used to be a problem in the 1980s. Thus PCs came with a turbo button to slow them down, and 8 bit computers went the entire decade without upgrading their speed even though faster CPUs were available. These days nearly everything runs on more than one CPU and so nobody relies on function runtime (other than is if fast enough). Even in embedded they have been burned by their one CPU going out of production and so…

In the 8 bit computer era, we knew exactly how much time any given instruction took. Retrieving some precision clock (not available!) and computing the time delta between runs - as is trivially done today - would probably be more computing power than they had at the time. Every cycle counted. Not very surprising that it wasn't done at that era. Also, there wasn't a "winning" instruction set or compilers able to target different architectures, so there was far more at stake than just clock speeds. If they changed the processor, you lost all your software.

DOS didn't have any precision clocks either as far as I know (it seems that there's interrupt 1A but it only updates 18 times a second, which is an eternity). Apparently there's 8254 based timer code after a few PC generations.

Windows 95 came up with QueryPerformanceCounter() and that simplified life quite a bit.

Re: Hyrum’s Law in Golang

#173

Earlier quoted context omitted.

>My point is that a few years ago there was no exported and document constant. Then the feature didn't exist. Figuring out undocumented implementation details to "make it work" is asking for it to be broken in the future. So if you are unwilling or unable to support fixing it in the future then don't do that. If it is "the most basic expected stuff" then quite literally make the determination that it isn't ready for…

I am glad that your circumstances are such that you can just stop working on a project when the tooling it uses turns out to be inadequate, wait five years, and then come back when it improves. Unfortunately, many people can't really do that: when the ecosystem turns out to be somewhat inadequate in a project that's already been in use for couple of years, their options are either "just make it work one way or anothe…

> I am glad that your circumstances are such that you can just stop working on a project when the tooling it uses turns out to be inadequate, wait five years, and then come back when it improves.

Is it that terrible to just handle an error as an error, without having to know exactly what the error was? If you see some of the codebases which rely on the error, they are trying to be too clever and doing things like returning a 400 instead of 500 if that's the specific error message returned. Is that really necessary?

Unless the codebase can take corrective actions (and it could still attempt to do it regardless if that's the case), there's really no point trying to be cute. An error is returned, and that's that.

Re: Hyrum’s Law in Golang

#174

It's sort of Hyrum's Law but it's really just Go being Go. The error could've been an enum type that could be changed with only a string replace for consumers. Instead they are using strings as types, so now you have no idea how consumers might rely on it. They could check the middle 6 chars of the error and break if you change it. It's another terrible anachronistic design decision when better alternatives have been…

Yes, sadly, the comment is essentially incorrect. The strings were their official API in many cases.

Re: Hyrum’s Law in Golang

#175
post #16

Earlier quoted context omitted.

Unfortunately true. The Go maintainers might not agree with me on this, but I think in this case consumers have to learn the hard way. Go tries to always be backwards compatible, but I don't think that trying to be backwards compatible with incorrect usage is ever the right choice.

So the people who decided to make a stringly type error with `errors.New("http: request body too large")` and make you suffer, now can remove a stringly typed error and make you suffer even more? What would the lesson be? What would consumers learn?

[deleted]

Re: Hyrum’s Law in Golang

#176
post #116

Earlier quoted context omitted.

> Fixing the upstream would not have updated it on the millions of machines running it, It was a very different world back then. You couldn't even assume a dial-up connection. Nowadays, the software would have been automatically updated for 99% of the machines running it, whether they wanted that update or not.

Hah. Debian will happily keep shipping libraries years out of date. Then complain that you’re holding them back when they finally wake up and update sid to a bleeding edge release.

I feel like you have no idea on how debian works, but have read an article 25 years ago and are angry about that ever since.

The proof is this totally OT comment that doesn't even make any sense :)

Re: Hyrum’s Law in Golang

#177
post #86
post #30

Earlier quoted context omitted.

goto was only bad when used to save code and jump indiscriminately. To handle errors is no problem at all.

..as long as you don't make mistakes. I fixed enough goto bugs in Xorg when I was fixing Coverity-issues in Xorg that I can see the downsides of this easy way of error handling.

We're comparing to go here, not with a language with proper error handling.

Re: Hyrum’s Law in Golang

#178
IME, one of the places hyrums law shows up the most is in tests.

I've seen tests of various types (unit, integration end-to-end) break because they made assumptions about behaviors that weren't garanteed, and supposedly backwards compatible updates broke them. Here are some examples of things that have broken tests:

- an update resulted in a change in the order of elements in a Hashmap or set.

- a change in an error message (or other user-facing message), changed

- a change in how leap days are handled for datetime arithmetic

- change in the format of locale-specific datetimes

- the timezone offset for a given area

- removal of internal-only APIs that were accessed using reflection

- something performed faster, which revealed race conditions in the testing code

- changing the precise representation of some data format. To give a specific example, changing a single byte when gzip compressing a file, that has no impact on the compressed content.

Re: Hyrum’s Law in Golang

#179
post #74

Hyrum's Law is one of those observations that's certainly useful, but be careful not to fixate on it and draw the wrong conclusions. Consider that even the total runtime of a function is an observable property, which means that optimizing a function to make it faster is a breaking change (what if suddenly one of your queues clears too fast and triggers a deadlock??), despite the fact that 99.99999999% of your users w…

That used to be a problem in the 1980s. Thus PCs came with a turbo button to slow them down, and 8 bit computers went the entire decade without upgrading their speed even though faster CPUs were available. These days nearly everything runs on more than one CPU and so nobody relies on function runtime (other than is if fast enough). Even in embedded they have been burned by their one CPU going out of production and so…

> nobody relies on function runtime

Maybe not intentionally.

But there have been several times where I've seen bugs where two tasks are done concurrently, but task A always takes longer than task B, then someone makes A faster, and that exposes some race condition or deadlock that only occurs if A completes before B.

Re: Hyrum’s Law in Golang

#180

Earlier quoted context omitted.

In principle. In practice, most Go code, and even significant parts of the Go standard library, return arbitrary error strings. And error returning functions never return anything more specific than `error` (you could count the exceptions in the top 20 Go codebases on your fingers, most likely). Returning non-specific exceptions is virtually encouraged by the standard library (if you return an error struct, you run i…

You do not have to do more work to use errors.Is or errors.As. They work out of the box in most cases just fine. For example: package example var ErrValue = errors.New("stringly") type ErrType struct { Code int Message string } func (e ErrType) Error() string { return fmt.Sprintf("%s (%d)", e.Message, e.Code) } You can now use errors.Is with a target of ErrValue and errors.As with a target of *ErrType. No extra metho…

Your example is half right, I had misread the documentation of errors.As [0].

errors.As does work as you describe, but errors.Is doesn't: that only compares the error argument for equality, unless it implements Is() itself to do something different. So `var e error ErrType{Code: 1, Message: "Good"} = errors.Is(e, ErrType{})` will return false. But indeed Errors.As will work for this case and allow you to check if an error is an instance of ErrType.

[0] https://play.golang.com/p/qXj3SMiBE2K

Post reply on HN