Hacker News new | ask | show | jobs
by chmike 3436 days ago
I don't see any "strength" in the classical object oriented programming model as found in C++ or Java. Actually, in modern programming composition is considered superior to inheritance.

The interface concept of Go makes programming with composition much more flexible and powerful than with the class model. The author skips this Go specific and original interface typing. This provides a multiple inheritance equivalent without all the complications on C++ and that most OO oriented languages forbid because of that complication.

Go is a very original language in this aspect as well as with concurrency. Understanding and mastering these properties goes beyond simple syntax analysis.

To me the most remarkable property of Go is its simplicity. As I explained to a friend who is a strong advocate of D, the difference with other programming language is the same as dealing with a spoken language of 1000 words instead of 10,000 words. It's true that the language with 10,000 words is more expressive and richer. But the effort required to learn, read and write a language of 1000 words is much lower than a with a language of 10000 words. I'm beyond 50 years old, and too me this makes a huge difference. The best way to express it is that with Go programming is fun again. I hope that Go will preserve this simplicity. At the beginning Java was simple too. They later killed it to the point I don't want to deal with Java code anymore.

5 comments

OOP is primarily about polymorphism (subtyping) and encapsulation, code reuse by means of inheritance is just a nice to have, so that comparison doesn't make sense.

You can compare OOP with parametric polymorphism, you can compare it with type-classes. Heck, OOP isn't necessarily about subtyping and we could be talking about row polymorphism (e.g. OCaml) which has some really nice properties.

> This provides a multiple inheritance equivalent without all the complications on C++ and that most OO oriented languages forbid because of that complication.

Except that it doesn't solve the fundamental problems with OOP, because it's still essentially OOP with subtyping ... and lots of marketing. So coming from Go you can be excused for thinking that the last 30 years of research have been for nothing.

> Except that it doesn't solve the fundamental problems with OOP, because it's still essentially OOP with subtyping

I'm not sure what fundamental problems you're speaking of, but what's nice about Go viz-a-vis C++ is that classes are fundamentally open. Personally, I think it's a win. By the way, I'm a C++ dev and I love C++ too. I just think Go has really interesting ideas.

By "classes are open" you mean that you can add methods to classes at will by just implementing a func with the right receiver?

In that case they're not truly open: Go does not allow you to declare methods on receivers from other packages, which means you can't extend anything which wasn't written by you. Which makes open classes almost useless.

`Go programming is fun again` I found this expression really difficult to accept it :) Ruby, Python are languages that are quite fun for me.

Also, `Go is a very original language in this aspect as well as with concurrency` CSP is quite old also.

Dlang, is quite a nice and easy to start language, If I will compare d vs go, I will say that you can see that golang has a lot of money and people behind. And, after I wrote more than a simple library, I tend to be tired of some parts of the language decision, and is not about interface, is just the small stuff. But again, I tend to write code that is more OOP :)

Please excuse me if my reply offend you, that is just my personal opinion after work with golang few years ago

> Go is a very original language in this aspect as well as with concurrency

Actually it isn't.

Using object Composition/Aggregation is a very old, and composition as the recommended paradigm dates back at least to COM (that's just my memory, it's probably older). Granted, delegation in COM aggregates was based on conventional interface and not structural typing, and it was implemented using ugly C macros, but dynamic languages made it easier and far more flexible. Kotlin even made it part of the language: https://kotlinlang.org/docs/reference/delegation.html

What Go has, despite all the hype, is not real composition with delegation though, but a crippled form of inheritance. With proper composition, your child objects are named, and you can choose which interfaces you want to delegate to which object. This doesn't just give you better control over which functionality you wish to expose, but also avoids conflict when two member objects implement the same interface. In Go you essentially get the same nasty diamond problem of multiple inheritance, with none of the benefits. Sure, you can disambiguate your method calls, but you could do the same in C++ and Python.

As for Go's approach for concurrency obviously isn't new. The CSP model was implemented by Rob Pike in at least 3 different languages previous to Go (Newsqueak, Alef and Limbo) and theory behinds it dates to research by Tony Hoare in the late 1970s.

I won't argue with you that Go is simple, but it's not revolutionary. As for the fun, I think that really depends on the individual. I know many people who think Go is fun, but for others, like me, it's about as fun as fingernails on chalkboard. There seem to be a strong correlation between people who like functional programming (especially the ML camp, but also the LISP camp).

For me coding in Go is plain drudgery: error handling boilerplate, noisy imperative looping (and in general very low SNR) and almost no ways to create abstractions. Yeah, you can make very useful and down to earth software in this language and it's currently satisfying much of my microservices needs at work. But it isn't what I would call fun.

> With proper composition, your child objects are named, and you can choose which interfaces you want to delegate to which object. This doesn't just give you better control over which functionality you wish to expose, but also avoids conflict when two member objects implement the same interface.

Oh but you can avoid that, it's part of the language, see this link:

https://golang.org/doc/effective_go.html#embedding

Typically, you can have something like this:

    type lockedReader struct {
        io.Reader
        sync.Mutex
    }

    lr := lockerReader{someReader, sync.Mutex{}}
    lr.Lock()
    lr.Read(...)
    lr.Unlock()

By default, methods will be delegated to the first field that has the method. If you want something else, you are free to override this default behavior.
No they're not. io.Reader and sync.Mutex do not embed the same type and do not have conflicting methods with the same name.

This is how a diamond looks like:

  type Base struct {
    Foo int32
  }

  type Child1 struct {
    Base
  }

  type Child2 struct {
    Base
  }

  type Diamond struct {
    Child1
    Child2
  }

  func (c *Child1) DoSomething() {
    fmt.Println(c.Foo)
  }

  func (c *Child2) DoSomething() {
    fmt.Println(c.Foo)
  }

  func main() {
    c := Diamond { }
    c.Foo = 42       // Doesn't Compile
    c.Child1.Foo = 10
    c.Child2.Foo = 20
    c.DoSomething()  // Doesn't Compile
  }
"[I]t's about as fun as fingernails on chalkboard."

Nailed it.

"The best way to express it is that with Go programming is fun again."

I beg to disagree in the strongest possible terms. I found programming with Go to be the opposite of fun. It's a highly opinionated language which gives people poor libraries, poor tooling, and the worst of many possible worlds. It's as if someone who couldn't see past C wanted to be slightly Erlangish.

No thank you, I will go back to Common Lisp and Haskell any day of the week from this abomination of a language. I've been exploring Clojure (on JVM, CLR and JS) as a practical alternative to CL lately.

> I don't see any "strength" in the classical object oriented programming model as found in C++ or Java. Actually, in modern programming composition is considered superior to inheritance.

I work in C++ and still use inheritance (although I generally prefer composition). One advantage over composition is that it's less typing. For example, if I'm using public inheritance to express a is-a relationship between a base and derived class, all of the public methods of the base are available without having to implement a method in the derived class that just forwards the call to the base class.

My understanding is that Go provides for this by a mechanism called embedding. You can place an object i:Inner in class c:Outer and then Outer acquires all of Inner's public interface.

I think it's a nice idea. In general, Go seems to provide the language mechanism without the "moral" aspect. In other words, it saves you typing without forcing you to accept the OO paradigm (Liskov substituion etc.).

It's always felt like something you should be able to do in C++. That is, tell it to apply interface X to class Y. If the interface and class have matching function signatures, the mapping should be automatic.