3 ms·
These examples seem to exemplify java's tendency towards design astronautics and the getter-and-setter-for-every-field pattern more than demonstrate the problem
by infogulch 12y ago
These examples seem to exemplify java's tendency towards design astronautics and the getter-and-setter-for-every-field pattern more than demonstrate the problem we're discussing here; I would find it very strange to see a `GetName() string` method on a go interface.
Even so, this problem could still have been fixed by just renaming the method to be more descriptive because they were still designing it. The only time this would be a problem in Go is if you had two unfortunately and oddly named methods in two libraries where you can't control either.
Edit: And to take it a step further, I would say that since interfaces are Go's only resource for representing generic behavior, go developers are more mindful of the methods they add to interfaces, in both number and descriptiveness.
- pcwalton 12y ago> I would find it very strange to see a `GetName() string` method on a go interface. How else do you write a function that can take multiple types of structs, all of which have a Name field, and select that field? (Other than reflection.) I mean, there are a bunch of Go packages that have types with a method named precisely that: https://www.google.com/search?q=golang+"getname" https://www.google.com/search?q=golang+"getname" > Even so, this problem could still have been fixed by just renaming the method to be more descriptive because they were still designing it. The only time this would be a problem in Go is if you had two unfortunately and oddly named methods in two libraries where you can't control either. Like in the Android case mentioned above? The Android system frameworks required a getString() method, while the MVVM library the commenter was using required an incompatible getString() method. Neither could be changed without a lot of headache.
- infogulch 12y agoFunny, the first link in your google search is slides for a presentation called "Go for Javaneros". The presentation takes a java program, finds a problem with it and fixes the problem in both java and Go. Go's solution starts with a `Name() string` method, but then he drops the method completely in favor of a public Name field instead. Other links in that google search are clear examples of a naive java-to-go translation with half a dozen `GetX() X` methods. > How else do you write a function that can take multiple types of structs, all of which have a Name field, and select that field? That presentation that you linked to says to use struct embedding aka composition. And if you don't want to do that then I'd say you're "probably" framing the problem wrong, but we really need a more concrete example to discuss this further otherwise we'll just be talking past each other.
- tptacek 12y agoThis by the way is a theme with Golang: Golang's answer to insufficiency in its ability to model problems is virtually always a pragmatic reframing of the problem without all the modeling. You can see this through the lens of i.e. Peter Norvig writing a Sudoku solver vs. that object modeling guy, or you can look at it through the lens of "the language should capture problems as safely and completely as possible". You can take either perspective too far. When Pike suggests implementing generics with "go generate", I feel like he's taking it too far. Here, I think maybe we're too far the other direction.
- pcwalton 12y ago> Here, I think maybe we're too far the other direction. We have at least three examples of this being an actual problem in practice that could not be worked around. Two in Java, and one in Golang itself. I don't know how you can come to the conclusion you did. In particular, "struct composition" does not solve the problem any more than inheritance would in Java. This comes up in cases in which the structs in question have separate declarations and you don't want to force all of your method's callers to inherit from your class/embed your struct just to call your function.
- tptacek 12y agoI think the objection is that you rule out workarounds that involve rethinking decisions about what should be a struct, what should be an interface, and what things should be named.
- pcwalton 12y agoSorry, if your position is "Golang doesn't use getters to abstract over structure fields", that's just not true. Here are some examples: - https://golang.org/pkg/database/sql/driver/#Rows https://golang.org/pkg/database/sql/driver/#Rows -- Columns is a getter - https://golang.org/pkg/database/sql/driver/#Stmt https://golang.org/pkg/database/sql/driver/#Stmt -- NumInput is a getter - https://golang.org/pkg/image/#Image https://golang.org/pkg/image/#Image -- ColorModel and Bounds are getters - https://golang.org/pkg/reflect/#Type https://golang.org/pkg/reflect/#Type -- Align, FieldAlign, NumMethod, Name, PkgPath, Size, Kind, Bits, ChanDir, IsVariadic, Elem, Key, Len, NumField, NumIn, NumOut are all getters And so on. The reflect package could, for example, have the Type-returning methods return a struct using structure embedding to handle most of those fields. But they didn't write the API that way, because it would be annoying to do so. So they used interfaces with getters instead. This isn't Java "astronaut" design—it's just how you program in a language with interfaces. Look at the implementation of PkgPath() for example: https://golang.org/src/reflect/type.go#L446 https://golang.org/src/reflect/type.go#L446 There's only one implementation of PkgPath(), and it does nothing but address a struct field. The functions could expose uncommonType directly, but they didn't. That's because getters are a common design pattern in Go.