7 ms·
One thing that the people saying "just use a struct for keyword arguments" are missing is that structs should signal intent, i.e. "this is a concrete concept in
by nauticacom 5y ago
One thing that the people saying "just use a struct for keyword arguments" are missing is that structs should signal intent, i.e. "this is a concrete concept in the system." A Repository, Commit, Message, Person, etc. struct are all concepts in the domain, whereas "the arguments for this particular function" is not. I think Go people are allergic to writing code that does anything other than functionally work.
- jasonhansel 5y agoIMHO, if the arguments to a function are just a bunch of heterogeneous values that cannot be sensibly grouped together, then that's usually a sign that the function needs to be refactored (e.g. because it's trying to do a bunch of unrelated things, or because it couples tasks together in an unnatural way).
- scndrycntct 5y ago> I think Go people are allergic to writing code that does anything other than functionally work. I think that's what Go was designed for, as a language. To be readable, usable. It's uncaring for your personal programming philosophies. I think that's why it's been successful.
- danudey 5y agoSpecifically, Go was designed to be effectively and safely writeable and readable by mediocre programmers.
- jhawk28 5y agoMediocre programmers can still write bad Go code. Their code is neither safe or readable.
- jrockway 5y agoDon't take the obvious flamebait. HN's favorite comment on any Go article is "it's designed for bad programmers", implying that if you like it, you're bad at programming. I'm good at programming and like Go, so that implication is clearly false.
- throwaway894345 5y agoI'm a Go enthusiast, but I think the charitable interpretation is that you don't have to expend lots of mental energy to read and write Go code. Even if you have a lot of mental capacity, you can put the excess toward interesting problems rather than reasoning about object lifetimes or hidden control flow or complex interactions between obscure features. If anyone uses "Go is designed for bad programmers" as an insult to Go programmers, they're only arguing against themselves (and lacking the cognitive faculties to notice).
- geoka9 5y agoSome of the best software developers I've seen are mediocre programmers :)
- nauticacom 5y agoI'd agree that it was one of their design goals, but I wouldn't go as far as to say that it makes the language "readable and usable." That depends on what your values are. Go's philosophy (which clearly flows from its creators being C-enthusiasts) is that the only thing that matters for reading, writing, and understanding a program is what it concretely does, i.e. what structures are created, where values are stored, how computations are performed etc. If that's also your philosophy, then of course it's going to jive with you. But plenty of people also have different philosophies. Maybe you think the main thing that's important in crafting programs is developing a rich domain vocabulary that expresses concepts and how they interact. Maybe you think that what's important is formal proof of both logical and concrete correctness. In those cases, Go's rigorous opposition to abstraction (coming from its philosophy that what's important is concrete operations) will probably irritate and slow you down. I couldn't say exactly why it got popular. I'd guess that some significant segment of programmers also share its philosophy, but I have no evidence to back that up. Certainly any reasonably uncontroversial language with a large suite of libraries backed by Google is bound to have some level of popularity.
- opmac 5y ago> I couldn't say exactly why it got popular. Probably because it has the backing of Google.
- ts4z 5y agoI disagree. Go provides a low-runtime way of writing programs, like C, without having to resort to managing memory and threads super carefully. No VM, no interpreter, fairly straightforward to imagine what the compiler is doing. You can do the same work in Java but you can't statically link the JVM. You can sort of do these in Python, but the compiler story is murky at best, and the language isn't as type safe.
- saghm 5y ago> No VM, no interpreter That's not quite accurate; there is a runtime, it just gets statically linked into the binary instead of needing to be externally installed
- SquishyPanda23 5y ago> To be readable, usable. Go doesn't particularly value readability or usability. For example, the short variable name convention makes it harder to read code you're unfamiliar with, and there are a number of noticeable usability shortcomings, some of which are mentioned in the article. I think Go's design goals were really to (1) reduce compilation time, which explains why Go has human programmers do work that compilers do in other languages, (2) be statically typed and compiled, so you can use it conveniently for microservices, and (3) have syntax somewhat similar to Python. I think of Go as the successor to Java. Go is to Python as Java was to C++. That, plus the integration with many libraries is why it's taken off in some niches.
- throwaway894345 5y agoHonestly the biggest selling point of Go to me was that it's simple and consistent. It enforces strong opinions that I may disagree with, but it means everyone does things generally the same way which is an important component in readability. With respect to short variable names, the convention is to only use them for very local scopes (e.g., using `i` as a loop index variable). In particular, I don't need to learn a new language or run a daemon just to compile code with a few dependencies and ship a static binary. Similarly, I don't need to configure CI pipelines just to publish packages or documentation. I don't need an IDE, I don't need to shop around for a test framework or an external web server process because they're built in. I don't have to think about what version of the runtime and/or dependencies are installed on my target system. Plus performance is good and the ecosystem is substantial. Personally from experience, I weight these kinds of concerns a lot higher than whatever bells and whistles are available inside of the language.
- LandR 5y agoI don't find go readable in the slightest, the syntactic bureaucracy is just too high. There is a forest full of code hiding a trees worth of business logic, always. Go is one of the least expressive languages I've ever used.
- preseinger 5y ago> the syntactic bureaucracy is too high. Huh? What do you consider syntactic bureaucracy? Go has like 25 keywords and no sigils -- the least "syntactically bureaucratic" language I'm aware of! > Go is one of the least expressive languages I've ever used. This is definitely true. Of course expressiveness is not strictly a virtue!
- nauticacom 5y ago> What do you consider syntactic bureaucracy? I would assume "amount of syntax required to express a given concept," with the use of the word "bureaucracy" implying that some concepts require too much syntax relative to their complexity (something that depends on your values). The classic example being mapping over a slice.
- preseinger 5y agoAh, so in this framing, syntax is another way of saying amount of code? Here's some Rust code pub fn read(&self) -> u64 { self.counts.values().fold(0, |acc, x| acc + x) } Here's some analogous Go code func (w *Whatever) Read() uint64 { var total uint64 for _, v := range w.values { total += v } return total } The former is certainly fewer characters than the latter. But to me it represents _more_ syntactic bureaucracy, not less. There are more sigils, more language concepts I need to understand, more _types of syntax_ to express the same thing. It's 20% of the SLoC, but parsing it requires more implicit knowledge, and takes no less time, versus parsing the latter. YMMV, of course. None of this is objective.
- nauticacom 5y ago
- CGamesPlay 5y agoWell, "Command to Create a Repository" could easily be a concept which contains all of the options necessary to create a Repository, which is a different concept. Now, there is a problem that all of the struct fields have to have sane zero values for this to work, but I think that is a problem which would naturally arise with keyword arguments as well.
- nauticacom 5y agoSure, if you're pushing things through a command bus or something. Otherwise you're just stretching it. If you wouldn't use it in a sentence to describe a use-case, I'd say that it's probably not a concept. Would it? Only if you allow default values, which is a separate discussion. And even then only if your only mechanism for default values doesn't let the definitions specify what, exactly, the default value is.
- preseinger 5y ago> Only if you allow default values, which is a separate discussion. Keyword args practically require default values, I think? In any case, while this feature (like every feature) definitely delivers value, it's the considered position of the Go authors that this feature, over time, has a net negative impact on program maintainability.
- preseinger 5y ago> structs should signal intent Isn't a collection of parameters to a function an intent?
- nauticacom 5y agoNot really? I suppose what I meant by that was that, if you make a struct, it should represent a concept that makes sense outside of the context of passing it to one function in particular; you're signalling that this collection of data represents a concept in your program
- throwaway894345 5y ago> it should represent a concept that makes sense outside of the context of passing it to one function in particular Why? What's the utility? Fewer characters?
- nauticacom 5y agoBecause concepts in programming languages mean things. A discrete, named entity (a struct) is a distinct concept from a way to increase readability of a function call (keyword arguments). Overloading them with the same language construct is compressing disparate concepts. It's the same thing when "Go has no set type" comes up and people say "map[T]struct{}!" You might implement a set using a map, but they're fundamentally different concepts
- preseinger 5y ago> A discrete, named entity (a struct) is a distinct concept from a way to increase readability of a function call (keyword arguments). If you take func NewServer(addr string, certKey, certCA []byte, ...) (*Server, error) and coalesce the input parameters into type ServerConfig struct { Addr string CertKey []byte CertCA []byte ... then that type is still a meaningful domain concept in your program. There is no minimum scope requirement for discrete, named entities, is there?
- throwaway894345 5y agoNot everyone is a Kingdom of Nouns purist. Even most OOP proponents that I've spoken with reject Kingdom of Nouns because it's pretty indefensible (in the worst case it leads to banana-gorilla-jungle problems[0] and in the best case it imposes arbitrary and unnatural restrictions on program design). Note also that "modern Java" and "modern C#" and "modern C++" and "modern Python" virtually all reject these kinds of designs and end up looking a lot more like Go with respect to their use of structs/classes. [0]: https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/ https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/
- nauticacom 5y agoEven if you're not doing OOP you're modeling your domain in one way or another. Whether those models are explicit and expressive or not, and how you define those qualities, is another question. In neither case are the arguments to a particular function typically a concept in your domain
- throwaway894345 5y ago> Even if you're not doing OOP you're modeling your domain in one way or another. Using structs to bundle function parameters doesn't preclude or inhibit using them for domain modeling.
- nauticacom 5y agoSure, but there's a purpose-built tool that doesn't overload an already existing concept, and it's called keyword arguments
- throwaway894345 5y ago> there's a purpose-built tool that doesn't overload an already existing concept I'm not sure which came first, but structs are a ~60 year old concept. That ship has sailed. Keyword arguments and structs are both named collections of values. Structs just happen to have broader uses. You can argue that we should use the more specialized one, but that's pretty silly--do we implement a general "add(a, b)" function or do we use more specialized add1(b), add2(b), add3(b) functions? Of course we use the more general tool even though a more specialized tool could exist.