6 ms·
Go didn't try to be overly clever and abstract. That rubs quite a few people the wrong way, but it also means you are less likely to have to work with people w
by bborud 3y ago
Go didn't try to be overly clever and abstract. That rubs quite a few people the wrong way, but it also means you are less likely to have to work with people who try to be clever.
My first reaction when seeing Go is that it smelled of "old fart". It looked straightforward and unexciting. I'm an old fart. I like straightforward and unexciting. It tends to lead to code that I can still read 6 months from now.
I want to make stuff and not endure people boring me with this weeks clever language hack they came up with that expresses in one unreadable line what could have been expressed clearly in 3 lines.
- Veraticus 3y agoYeah this was my primary complaint with the inclusion of generics. People will try to be all clever and their code will wind up as an unreadable, unmaintainable disaster. It has definitely led to some cool stuff, but I prefer boring, verbose, and clear any day.
- pie_flavor 3y agoProblems are generic, such as having a tree collection. For solving generic problems, you can either use language generics, or reflection, or type erasure, or codegen. The latter three are about as far from 'boring and clear' as you can get. Still verbose, though, but I don't expect that's a benefit.
- Veraticus 3y agoI would say 95% of people who are trying to solve a complicated problem with reflection, type erasure, or codegen are solving the problem the wrong way. Obviously I'm glad these tools exist, and some problems can indeed only be solved with them. But I think people reach for them as a first solution and make bad code as a result. Go strongly encourages you not to reach for bad solutions, which is one of its bigger advantages, in my opinion.
- woooooo 3y agoCollections obviously need to be generic though. Slices and maps were generic from day 1 in go so it's not like this is controversial.
- Veraticus 3y agoFor sure — a lot of language features need to be generic. But most people aren’t coding language features, and giving them the ability to do so can lead to, well, CodeFactoryFactoryMakerGenericMethodHelpersFactory, rather than good, clear, usable code.
- maccard 3y agoI've spent a lot of time writing library-level C++, a reasonable amount of time writing application-level C++, and a reasonable amount of time writing both library and application-level golang. > But most people aren’t coding language features It's definitely a tough lever, but supporting generics for the people who are means that the people who aren't can write cleaner code. I think go got it right, eventually.
- pie_flavor 3y agoThere is no language feature for a tree map. Many problems require a tree map. Either inclusion of generics was a good thing, or it is worth sacrificing static typing or requiring codegen for these use cases. Repeat for numerous collections and APIs. Disallowing someone from using easy statically typed tree maps is not accomplishing any of the simplicity virtues people trumpet Go for having. While the much-warned-of castles of inappropriately applied generics have yet to be found in any codebase I've worked with in any language, including Rust.
- Veraticus 3y agoThis is a pretty arbitrary benchmark. I would guess, again, that 95% of programmers have never and will never need to create a tree map. Repeat for numerous collections and APIs that are totally irrelevant to most programmers' actual experience of programming. Go is optimized for use, not computer science edge cases. And as a result it is widely used, and some of the most complicated and widely-used open-source projects out there are built in it, even before it had generics. For example, Kubernetes. This is because of Go's simplicity, not in spite of it.
- bborud 3y agoSome problems benefit more from a solution using generics than others. Collection types, as you note, are a good example because you will have heavy re-use and the way you use generics is simple. It is worth a little bit of extra effort and it isn't going to demand much from the programmer using it. But in the hands of people who love to go bananas, generics can result in hellish code. My favorite example of a problem where generics is not useful is the OpenSAML implementation (Java). For all I know it may have been sanitized since I tried to make use of it about a decade ago, but that thing was, for lack of a better word, a pointless exercise in type system wankery. It was so bad it took us less time to implement what we needed from scratch than to figure out how to use the library correctly. (The code I wrote a decade ago has been in production, for a decade on a system that is used by ~150-200M users. Not just because it works, but because it can be maintained by people who aren't really that interested in spending weeks understanding it)
- lillywastaken 3y agoIs writing the same function n times more readable and more maintainable? Is it more maintainable to entirely circumvent the type system with interface{}?
- orwin 3y agoFirst time I used it, I called it 'C+-' after two weeks and a supervisord clone, but I really liked the language (except the module system). It was ~9 years ago, and other than that I only used it in coding interviews, as it's portable, simple, close enough to C that I'm not lost using it, yet simple enough that I don't introduce bugs carelessly every 30 loc. But it's a bit boring and I'll never use it for personal projects.
- bborud 3y agoYeah, the original GOPATH stuff was atrocious. Two questions: 1) how do you like the module system we have today? 2) can you expand on what you mean by boring, why it is important to you that a language not be boring, and give an example of a language that is not boring?
- valenterry 3y agoSince when has "clever" become something negative? If someone is clever, that's a good thing! I also try to be clever when I do things, be it repairing something, planning my workout routine or programming.
- sethammons 3y agoI've heard the drum against clever code for over a decade. This sums it up well: "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan
- valenterry 3y ago"If code is written as clevery as possible, it's surely written in a way that it's easy to debug it"... is what I would reply, but I get the gist. :-)
- Tainnor 3y agoIt's very unclear what people mean by "clever". For some people, a map or a fold is already "clever", while for others, this is just very straightforward code.
- dlisboa 3y agoMaintaining "clever" code is incredibly hard because the only "clever" person is the one that wrote it, everyone else is "dumb" to it. One can take hours debugging clever code. Obvious code won't wow anyone but will be immediately understandable, which is an advantage in a team setting.
- bborud 3y agoClever doesn't necessarily mean smart. Back in the day when GCC 2.9.5 was a widely used version of GCC we had a codebase that was full of "clever" hacks to trick the compiler to generate the assembler code we wanted. A few of these hacks were used in tight inner-loops that had a huge impact on performance. I can still remember the day someone removed what seemed to be a no-op in a piece of code, compiled it and pushed it to production - only to have everything grind to a halt and fall over because CPU use per request tripled. Sure, it was a "clever" way to get the compiler to output what you wanted it to output, and it was common knowledge among some of the programmers on the project what that no-op'ish line would do - but not all. The smart thing to do would have been to fix the compiler and upstream the fix (from our internal branch of the GCC toolchain). The "clever" solution was to just figure out a bunch of tricks to manipulate the compiler and call it a day. In the context of this thread, "clever" is mostly taken to mean "not as straight forward and understandable as it can be". Young me loved cleverness. Older me knows how frustrating it is when something isn't as straightforward as it could be. Either because I have to figure out how something someone else wrote works or because I have to explain what my code does to people who have gotten confused. When I write code other people can't understand I see that as a failure on my part. Because it is. Code isn't merely a mechanism to convey meaning to a compiler, it is a way to communicate with other human beings. Most of which aren't that interested in indulging my cleverness.
- Tainnor 3y agoI still don't know what people mean by "obvious" code. Yes, there are people who create a mess with abstraction. This happens in every language, in Java people create FactoryFactories, in Haskell people play type tetris, in Ruby, people abuse metaprogramming and in Go, I assume some people go overboard with code-gen. But that said, I suspect many people, when they say, "obvious code", they mean "I can easily understand what every line does". Which is a fine goal, but how does that help me with a project that has 100ks of lines of code? I can't read every single line, and even if I could, I can't keep them all in my head at once. And all the while, every one of these lines could be mutating some shared state or express some logic that I don't understand the reason for. We need ways of structuring large code bases. There are a ton of ways for doing so (including just writing really good and thorough documentation), but just writing "obvious" code doesn't cut it. Large, complex projects are not "obvious" by their very nature.
- Mawr 3y ago> Yes, there are people who create a mess with abstraction. This happens in every language, in Java people create FactoryFactories, in Haskell people play type tetris, in Ruby, people abuse metaprogramming and in Go, I assume some people go overboard with code-gen. It's possible in any language and yet some languages' codebases are consistently worse than others ;) If you create a culture of cleverness, implicitness and metaprogramming, that's what the programmers using your language will do. It's self-selection to an extent. "I've suffered long from the Ruby ecosystem's mentality of 'look at what I can do!' of self-serving pointless DSL's and frameworks and solemnly swore to myself to stay away from cute languages that encourage bored devs to get 'creative'." [1] "I worked at a Scala shop about 10 years ago. Everyone had their own preferred "dialect", kind of like C++, resulting in too much whining and complaining during code reviews. IMHO, the language is too complex." [2] > And all the while, every one of these lines could be mutating some shared state That's where the obvious code helps. Let's circle back. > I still don't know what people mean by "obvious" code. The Zen of Python is a nice primer: [3]. A beautiful display of taste right there. A few concrete examples: - "Explicit is better than implicit." Explicitly returning errors means we get to see every single point at which something could error out - explicit, as opposed to exceptions that could implicitly propagate from any line of code, with no way to tell. Preferring pure functions - a pure function is a black box with a clearly drawn boundary line of input->output. Trivial to reason about in isolation. No automatic type conversions. No global state - any part of the code could change it. No metaprogramming - you've learned Ruby but now some parts of the language have been changed to mean something completely different! "The syntax has so many ways of doing things that it can be bewildering. As with Macro-based languages, you are always a little uncertain about what your code is really doing underneath." [4] - "There should be one-- and preferably only one --obvious way to do it." Uniform code. Iterating through an array always looks the same, so if the code you're looking at does it differently, you'll pay attention. [1] https://news.ycombinator.com/item?id=13482459 https://news.ycombinator.com/item?id=13482459 [2] https://news.ycombinator.com/item?id=31219392 https://news.ycombinator.com/item?id=31219392 [3] https://peps.python.org/pep-0020/ https://peps.python.org/pep-0020/ [4] https://alarmingdevelopment.org/?p=562 https://alarmingdevelopment.org/?p=562