6 ms·
Go is the most readable language I’ve used in terms of understanding other peoples complex code bases, and I’ve been doing this a long time and have used a lot
by jshen 5y ago
Go is the most readable language I’ve used in terms of understanding other peoples complex code bases, and I’ve been doing this a long time and have used a lot of languages.
Edit: It’s also one of the most approachable languages.
- valenterry 5y agoWhy don't you list the languages that you have used? Otherwise there isn't really any new information. For example for, having done Java, Scala, Python, Groovy, Haskell, Typescript and a couple others, Go reads extremely horrible. It feels as bad as enterprisey Java to me.
- jshen 5y agoI’ve used all those languages. It’s far easier to make sense of a non trivial go code base I’ve never seen before than any of those.
- valenterry 5y agoIt's far easier for you. It definitely isn't for me or in general. Thank you for answering the list of languages though. Makes me wonder what the concrete points are for, since I really have a different opinion. Maybe our minds just work very different; :)
- jshen 5y agoJust ran into a great example today. Was using typescript/javascript to hit an api that has a limit of 5 requests per second. One of these fails saying that it's making more than 5 requests per second, the other doesn't, is it obvious why? It took me several hours to figure it out, wouldn't have had this problem in go. choices.forEach(async (ce) => { let ce = choices[index] Deno.sleepSync(220); let cf = await getChoice(ce); // this makes the API call Deno.sleepSync(220); }); for (index = 0; index < choices.length; index++) { Deno.sleepSync(220); let cf = await getChoice(ce); // this makes the API call Deno.sleepSync(220); }
- valenterry 5y agoGood example, because that's exactly what I don't want to see when I read code. This should really be: streamOf(choices) .mapAsync(ce => getChoice(ce)) .throttle(5, 1.second) This is such a common use-case, it should really be in the streaming-library of choice. It's also a good example of how more abstract code is often better and has less edge-cases. In this example, of you have 4 choices, then these can send all at once without delay. This will be much faster compared to the code you posted, which will wait after each request, even though the rate-limit is not applied. Apart from that, I don't think the second example is complete, where does ce come from here? And also, I don't know Deno, but calling "sleepSync" already looks like a bad idea to me, no matter where it's used - especially since calling a sync operation within an async doesn't make much sense.
- lucacasonato 5y agoYeah, this should not be calling `Deno.sleepSync`... this should be an `await new Promise(resolve => setTimeout(resolve, 220));`.
- deleted 5y ago[deleted]
- jshen 5y agoThat's kind of my point, it's less obvious how to do basic things in js/ts than golang. What's the vanilla way in ts/js to do the equivalent of this golang code where getChoice makes an HTTP call and can't make more than 5 per second? for _, v := range choices { getChoice(v) time.Sleep(200) } Also, why doesn't Deno.sleepSync work as I expect here?
- deleted 5y ago[deleted]
- jshen 5y agoI messed up my copy/paste, the 'let ce' line in the first example should be in the second example. Regarding your example, where is this throttle method implemented in javascript? And, your code is not easier to reason about for me than the synchronous golang code. It's not clear how throttle is affecting the function call that happens before it. Compare to this. for _, v := range choices { getChoice(v) time.Sleep(200) }
- jshen 5y agoI would probably require a book length post to truly answer this, but here's the best short version I can do. I think it comes down to a few things. 1. Some languages on your list are very flexible, and that allows them to be written in a very readable form with great discipline. People tend to not have great discipline thought, for various reasons: their bosses are pushing them to go faster and cut corners, they aren't experienced enough yet, etc. I'd say that python and typescript/javascript fall into this category. 2. I think inheritance is the devil, and a more functional style is better (by functional I mean first class functions, passing parameters, etc not purely typed). Java/Groovy fall into this category, they overuse inheritance and things like dependency injection with xml or annotations rather than far easier to read function calls with parameters. 3. Then there is haskell :) Haskell requires a phd in rocket science to be proficient, and most people have other things they want to do with their life. You also can't hire a team of 1000 rocket scientists so most companies can't go this route. Edit: One other thing I'll add about typescript/javascipt because it's a bit of an oddball. There really isn't a typescript/javascript style because most devs end up writing javascript. The java people try to write java in it, the python people python, etc. This alone makes it hard to jump into a random JS/TS codebase and figure out what's going on. Regarding Go, it takes away a lot of flexibility, which makes the code longer generally, but it makes it much more consistent across code bases. It's lack of inheritance prevents the devil from showing up, and it's largely a simple function call with parameter passing style all the way through the code base. Structural typing is also a godsend. Edit 2: Also, package management in python is a complete train wreck.
- mariusor 5y agoFrom the list of languages you mentioned I understand that you probably enjoy ways to express algorithms in an elegant and (maybe) terse way. Maybe that's easier for you to understand. However all that abstraction is very far removed from what the compiler or the interpreter actually execute on the CPU. For me an easy to understand program is one where the way memory is structured and the way execution modifies said memory is easy to follow. That's why Go, despite being very verbose in some cases, it's easier to reason about, than codebases doing similar things in higher level programming languages.
- eru 5y agoGo is ok-ish, if you use small programs and solve exactly the same problems the language designers had in mind in exactly the same ways the language designers had in mind. The constant repetition and near-but-not-quite copy-paste boilerplate everywhere makes it hard to spot the crux of what's actually going on.
- fsdjkflsjfsoij 5y agoI've used all of those and more and spent a decade deep in the purely functional Scala/Haskell camp. Diving into a moderate or large Go code base is always far easier for me even though I've used Go much less than the others. Before I even knew Go I would often look at various algorithms in Go just because it was so easy to understand exactly what was happening.
- valenterry 5y agoFor algorithms, this might indeed be different. Not only are algorithms usually small and very focussed snippets, the emphasis is on performance and hence mutability, language primitives and shortcuts are common. I can definitely see that languages like python or go beat pure functional languages in that regard. For business logic and glue code (which in my field is the vast amount of code) I think it is the opposite though.
- jshen 5y agoGo is easier to read for complex code bases.
- koffiezet 5y agoI agree with the parent though, Go code is super-readable and accessible. I've coded actual useful stuff in Java, C, C++, Pascal, Python, PHP, Pascal, Basic, (Jenkins) Groovy, Typescript, Javascript - and am probably forgetting some. I also dabbled around in Rust and a bunch of other languages, but I wouldn't call that experience, although when it comes down to the initial accessibility and impressions, in this context, that is relevant I think. Go was hands down the most readable and accessible of the bunch, which probably has some roots in having a C/C++ background, and it being a pretty simple language. Dev-env wise, it used to be a mess with the GOPATH etc, but that has mostly been resolved. And once past that, it was easily the language I picked up the quickest. It took me 2 or 3 days to actually write something useful. I've jumped head-first into codebases of large projects without even thinking about it, which I would have been very hesitant about if they had been written in another language. I've had to do that plenty for C++ and Java projects, but that always took some convincing of myself, and was never a pleasant experience.
- Intermernet 5y agoThe readability of Go is intrinsically linked to the error handling in Go. If the spec started accepting "clever" rules to do with auto-magic return / assignment of error values instead of explicit handling, then the cognitive load of code review increases. If every error path is explicit, then the review becomes simple and self-explanatory (at least when it comes to error handling).
- valenterry 5y agoBy that logic, assembly would be the most simple and self-explanatory language. I'm not sure if these two attributes are sufficient to determine how readable/productive a language is in the large.
- Zababa 5y agoI'm not sure error handling in Go is really explicit. Go checks that you assign an error and usually handle it, but it doesn't check that you handle all values of the error. If a function suddenly returns a new error value, the compiler won't help you here. This is like in language with unchecked exceptions, you have to read everything carefully.
- 3a2d29 5y agoSurely Python gets that honor over Go. As much as I like Go, Rust, C, over Python, I would never say the reason is readability.
- eru 5y agoPython is quite readable for short snippets. It can be quite a mess for larger systems. That combination of trade-offs makes it a great language to solve interview style problems in on a white board. You can alleviate those larger scale problems in Python a bit with good IDE support, embracing type annotations, and going with a style that prefers immutability over action-at-a-distance.
- pawelmurias 5y agoThis change is intended to be used to avoid using interface{} with generics which aren't used by existing code