Live data from Hacker News

The 4-chan Go programmer

dolthub.com

111–120 of 177 posts

Re: The 4-chan Go programmer

#111
post #7

As a scientist that ends up working closely with actual professional software engineers... lots of the stuff they do looks like this do me, and I can't for the life of me make sense of why you'd do it. I have seen a single line of code passed through 4 "interface functions" before it is called that call each other sequentially, and are of course in separate files in separate folders. It makes reading the code to figu…

Ugh, dealing with stuff like this right now for project config. Why can't I just use yaml files in the build to generate environment files based on region/app and then read those values in the code? Instead, it's that plus a few layers of interfaces grouping multiple levels of config items.

Re: The 4-chan Go programmer

#112

The "chan chan Value" or "chan struct{resp chan Value}" is actually a pattern I've used in a very specific situation. It's a situation where a message bus probably could have been used instead, but then you'd have a message bus to handle...

I used it too. It's useful to implement Promise-like semantics in Go.

Re: The 4-chan Go programmer

#113

Earlier quoted context omitted.

This is actually really bad practice and a very “over eager junior engineer” way of writing software. You’re not off base at all that it seems excessive and confusing. It’s the kind of thing that seems technically complex and maybe even “elegant” (in isolation, when you first write the “interesting” code) at first but becomes a technical nightmare when used in real software that has to grow around and with it. You’re…

I get your point, but a wait group or a mutex can be removed in favor of a clean usage of channels if the proper concerns are isolated at first. And I would personally much rather reason about channels than mutexes and wait groups. Wait groups and mutexes are just begging for deadlocks and race conditions, where a proper channel, used correctly, eliminates both of those by design.

> Wait groups and mutexes are just begging for deadlocks and race conditions, where a proper channel, used correctly, eliminates both of those by design.

By that same logic, if you just use wait groups and mutexes correctly, you should also not worry about deadlocks and race conditions. It's also quite trivial to introduce a deadlock with a channel.

Regardless, channels are basically a more expressive/flexible type than mutexes, waitgroups, and function calling, but in the same family as all of them. You can implement any of those rather trivially with a channel, but there are things you can do with a channel that are quite complex or impossible to implement using those. Such a flexible tool allows you to start doing things that are "easy" to implement yet poor design decisions. For example, instead of direct function calling you can now start passing data over channels, which "works" just as well except it incurs some scheduling overhead (not always a concern depending on how perf sensitive you are), makes debugging and interpreting stack traces more difficult (increasingly so as the logic on both sides of the channel increases over time), and allows the software to start evolving in an unintended way (specifically into an overly complex Actor model with tons of message-passing that is impossible to untangle, rather than a directed tree of direct function calling). Or you have a hard time understanding the state and properties of a piece of data throughout the program lifetime because it doesn't "belong" anywhere in particular.

---

Something I thought about recently: perhaps the biggest balancing act in software is between specificity and expressiveness. To solve a problem you might be able to find something that is perfectly tailored to your needs where you just click something or run something and your problem is solved, but it's highly likely that it will only solve that specific problem and not others ones. Alternatively, a lot of software (like Jira, SAP, many enterprise software) is highly configurable and expressive but requires a lot of effort to set up and may not be particularly good at solving your specific task. At its most extreme, you could technically call a computer containing only a brainfuck compiler and basic text editor as being able to solve any problem solvable by a computer, because it's a programmable turing machine.

This extends even into the weeds of programming, especially when you're working on software with other people or over long periods of time, where you might struggle to enforce or maintain your particular mental model for how the software should work. When faced with implementing something with an expressive approach vs a specific one, you want to be expressive enough to be able to modify the code later to do things you plan to do or think you have a high probability of doing, but you want to be specific enough that the purpose and function of something (be it a library, class, binary, or entire distributed software system) is clear - if it isn't clear, the people using it will struggle with it or avoid it, and the people working on it will start taking it in a direction you didn't intend.

Channels are the type of thing that are expressive enough to be broadly applicable, but are easily misinterpreted (you might be using them to implement parallelism, but your coworker Bob might think you're using them because you want to design your software under a message-passing actor model) and easily misused. They also make it very, very easy to "code yourself into a corner" by introducing inscrutable logical/data paths that can't be untangled. You might be able to use them safely in lieu of a mutex but it only takes one Bob to start taking them in the direction of unmaintainability. And sometimes you might be that Bob without knowing it. That's why I think it's best to avoid them unless your other options are even worse.

Re: The 4-chan Go programmer

#114

Earlier quoted context omitted.

I get your point, but a wait group or a mutex can be removed in favor of a clean usage of channels if the proper concerns are isolated at first. And I would personally much rather reason about channels than mutexes and wait groups. Wait groups and mutexes are just begging for deadlocks and race conditions, where a proper channel, used correctly, eliminates both of those by design.

> Wait groups and mutexes are just begging for deadlocks and race conditions, where a proper channel, used correctly, eliminates both of those by design. By that same logic, if you just use wait groups and mutexes correctly, you should also not worry about deadlocks and race conditions. It's also quite trivial to introduce a deadlock with a channel. Regardless, channels are basically a more expressive/flexible type t…

> By that same logic, if you just use wait groups and mutexes correctly, you should also not worry about deadlocks and race conditions.

I agree with most everything else you said - especially about software being a trade off between specificity and expressiveness - but I can’t agree with this.

The problem being that a mutex can hide things that a channel can’t. Channels will always give you what you expect, but that is not the case for mutexes or wait groups or error groups or whatever.

Honestly, the older I get, the more I understand that joke about “you must be this tall to write concurrent programs” and the mark is at the ceiling.

Re: The 4-chan Go programmer

#115
In LabVIEW code we sometimes do this as a means of receiving asynchronous response data; instead of dumping responses in a queue, the message you pass includes a callback event channel, which you can use to notify exactly the same caller that the operation is done, and what the results are. A little wasteful on memory, but since theyre single use and are closed upon responding, the ergonomics are worth it

Re: The 4-chan Go programmer

#116
post #7

As a scientist that ends up working closely with actual professional software engineers... lots of the stuff they do looks like this do me, and I can't for the life of me make sense of why you'd do it. I have seen a single line of code passed through 4 "interface functions" before it is called that call each other sequentially, and are of course in separate files in separate folders. It makes reading the code to figu…

Honestly it might not be you. Simplicity is very valued in good code. So if its hard to understand its probably not good code.

Re: The 4-chan Go programmer

#117

How is this related to 4chan or any other social media? It seems like a nonsense troll title designed to waste every reader's time.

Yeah, I have to agree with you here. 4chan does actually have a well-developed programming culture with their own memes. They came up with a quirky algorithm for sorting numbers using sleep (not practical but fun and very out of the box.) And they seem to really appreciate lisp like a lot of people here. There is sometimes good overlap between HN and 4chan. But that doesn't seem to be the case here.

Re: The 4-chan Go programmer

#119
post #45

Earlier quoted context omitted.

imagine allowing invalid values to exist

imagine enforcing invariants as part of the design of a software system

I’m just saying enforce invariants at construction time / type-designing instead of with the validity checks

Re: The 4-chan Go programmer

#120

How is this related to 4chan or any other social media? It seems like a nonsense troll title designed to waste every reader's time.

Yeah, I have to agree with you here. 4chan does actually have a well-developed programming culture with their own memes. They came up with a quirky algorithm for sorting numbers using sleep (not practical but fun and very out of the box.) And they seem to really appreciate lisp like a lot of people here. There is sometimes good overlap between HN and 4chan. But that doesn't seem to be the case here.

Thanks, we are on the same page.
Post reply on HN