TL;DR
Stop posting about “Patterns in Go” that are nothing more than verbose Java boilerplate ported to Go syntax and do not even use proper Go idioms.
People keep posting “Patterns in Go - XXXXX” articles.
- They are not even Object Oriented Patterns, but people keep posting them as they are.
- Those “patterns” are not written in idiomatic for Go.
- And even if they were, as it is very easy to discover, Go is not an Object Oriented language; or is it?
What is Object Oriented then?
The language decisions that were made when the Go syntax was created were a direct reaction to the the wasteful verbose boilerplate of C++ (and ironically inheritance of the same things in Java, but worse, at least all the additional boilerplate is in a single file now ).
Object Oriented programming is actually not about the Objects it is about message passing.
I regret the word 'object'. It gets many people to focus on the lesser idea. The real issue is messaging. Messaging is the abstraction of the communication mechanism. It's what allows different parts of a system to interact without knowing anything about each other. That's the power of objects, and it's what makes them so useful.
— Alan Kay in an interview with Peter Seibel for Dr. Dobb's Journal in 1997.
So why are C++ and Java called “Object Oriented”?
I made up the term 'object-oriented', and I can tell you I didn't have C++ in mind
— Alan Kay, OOPSLA '97
If C++ is not what you should think about when hearing “Object Oriented” then neither is Java. Especially since Java does not have “message passing”.
Java and C++ make you think that the new ideas are like the old ones. Java is the most distressing thing to hit computing since MS-DOS. — Alan Kay in an interview with Peter Seibel for Dr. Dobb's Journal in 1997.
Guess what does? Go. Specifically goroutines, and they were inspired by Erlang processes.
Does that make Go “Object Oriented” by the definition of the creator of the term. Not by itself, but it does make it considerably more “Object Oriented” than C++ or Java. Especially whey they disavow both languages as meeting their original conceptual criteria.
Way more, if you consider other statements he made on the definition later. Lets look for more evidence to support my argument.
So what should C++ and Java be called? Well that is enough for another article or more, but anything else would be a way better term, given what the inventor of the term says.
I personally think “Class Type Oriented” would be semantically more appropriate considering Alan Kay focuses on the term “class” even less than “object” and C++ and Java are all about classes and type systems first and foremost and objects are just a side effect of instantiating classes to them.
So what does Alan Kay think defines an “Object Oriented” language in his own words?
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
— Alan Kay from an email to Stefan Ram on 2003-07-23
How would you do that in Go?
Make every struct field non-exported (starts with a lowercase letter in its name), this translates to package private
you Java wonks, and have nothing but exported functions that work with the hidden data. Make every function take an Interface
and return nothing but struct
that implements an exported Interface
.
To spell it out:
-
only messaging: Export only functions and
Interface
which is just a collection offunction
signatures that are public, so you are effectively passing functions or collection of functions to functions, thus messaging. -
local retention and protection and hiding of state-process: non-exported
struct
fields meets all these criteria outside the package level, package == local. -
extreme late-binding of all things: this one is one that is tricky from a practical stand point.
Alan Kay admits that difficulty is what motivates this requirement. “(I'm not against types, but I don't know of any type systems that aren't a complete pain, so I still like dynamic typing.)” - from an email to Stefan Ram on 2003-07-23
The original design of the Go language to allow inference of
Interface
implementation via “duck typing” was to eliminate a lot of the pain, mostly boilerplate, associated with static typing.Go is a static type safe language; it does not do exclusively late-binding, much less extremely. For non-trivial sized code bases, you find out very quickly, whatever you are gaining with extremely late-binding, you lose much more by not having compile time checks. In Go there are ways to do late binding, but you have to use
interface{}
or with genericsany
in all those places which makes you question your choices in life very quickly. duck typing and now generics is a decent compromise between the two extremes.
So what languages are “Object Oriented” as per clarifying statements by the originator of the term?
The one that I am most familiar with because I have written real world production applications with is Erlang. I learned it because it was created for real world scenarios that needed 9 “nines” uptime. I learned it because thing I needed to create, it needed similar uptime. I am sure that other Functional languages will be mentioned in the comments, but it is the only one I have first hand experience with in a deployed commercial production environment.
*Why am I not an Erlang main now? *
It is not that practical a language to work in for things that do not demand the features that make it unique. Very few projects demand the extreme uptime and massive concurrency that Erlang provides, but there are costs to consider. Another article worth of costs at least.
As a former Java main, it is embarrassing …
What you are pushing is not even “Object Oriented” it is a perversion of it to the point that it is not even recognizable.
It is especially embarrassing when your implementation does not even begin to use Go idioms and ignores go specific things that were implemented specifically to do the thing you think you are being “informative” about and showing your competence, when you are just exposing the opposite and promoting misinformation to the most vulnerable, those that know less then you. Providing LLM with even more misinformation at the same time.
Please stop pushing “Object Oriented Pattern Implementations” on Go like you are informing the ignorant and unwashed masses that have been using Go for the past 10+ years and saving them from themselves. It is embarrassing, I say that as a former Java main myself. And you wonder why Java programmers get a bad rap?
What triggered the compulsion to post this article.
Let us take the most beloved Gang of Four Pattern of all time. Especially to the Java faithful. The one most people have their first epiphany with when introduced to “Patterns Of Reusable Design”; probably because it is the easiest to comprehend and abuse. Singleton.
Just to make sure my point is not misinterpreted this is not about Singleton,
My point is about the articles that are nothing more than terrible ideas in Java ported to Go syntax. They are still Java examples.
For this example:
Let us ignore the fact that it was a terrible anti-pattern when it was first documented, because it is by definition global state and the #1 goto Java pattern. “Singleton Considered Harmful” has been a thing for decades. See what I did there; goto, singleton
Let us also ignore the fact that in the JVM you can not even implement Single correctly because by design the JVM can not guarantee that one and only one instance of a class is ever created. Here is a hint to the all the self professed Java experts that are about to write a comment about how I am wrong; Multiple Classloaders.
If you see someone post “Patterns in Go - Singleton” first look at the implementation they post; if you do not see sync.Once()
anywhere in the code, then let them have it in the comments!
That is what you should call them out on, their promotion of misinformation. The hubris in posting a “teaching” article about something they barely know the basics on. That is a malicious disservice to those that know even less than they do.
The rest of the internet has already proven all the other points, that is why I prefaced this with “Let us ignore …” caveats.
I tried to research everything in this article for factual accuracy, but I am sure the internet will tell me what their opinion about it is. If there are any factual inaccuracies, and you want to point them out in the comments, provide the source and I will correct them. Otherwise, do not waste everyone else’s time. If it is important enough to correct, it is important enough to site sources like I did for the quotes and technical specs.
Top comments (35)
Great article. As a Java/Kotlin developer, I would say that I don't give a F*. The takeaway for me from this article is that we should learn why a language was designed the way it was and stop porting patterns without understanding what the compiler/interpreter will do with them.
Very well stated TL;DR,
Sadly, reading comprehension is a lost art and even something as clearly stated and short as your comment, someone will comment saying you said the exact opposite of what you did.
It happened a lot when you get people with an "Enterprise" software background looking at a new to then language or platform.
I feel similarly when I see IoC shoe horned into JS/TS. It generally isn't needed and only adds indirection and complexity for no good. It's usually best to stay simple and become familiar with a language and ecosystem before trying to shove patterns that may be familiar, but may also be a very poor fit for a different language.
I discovered decades ago that you can write COBOL style in almost any language. Had no idea at the time that VB could even do what I saw in a couple apps written by COBOL mainframe developers. And it wasn't good, even if it worked.
Most developers will get stuck in particular approaches and thought patterns and carry them ahead forever without considering the fit for purpose aspects.
Even the gang of four patterns aren't meant to be used all the time. Just because you can use a given pattern doesn't mean you always should. And if it makes the whole system more complex instead of less complex, then reconsider it. Some this are more complex... The use of patterns and abstractions should reduce the complexity of the whole, not increase it.
The problem is the gospel of Uncle Bob adherents is "Clean Code" == "lots of abstraction and layers because "Clean Code" is the goal, software that works is just a side effect.
They only hear/read the first half of anything he said or wrote and assumed it was confirmation bias on what they already thought about how to do things.
"Hexagonal" whatever flavor of the week; is just more Consultant theory crafting to sell courses, certifications and consulting hours to tell you how you are "doing it wrong" but never actually doing anything themselves.
Yeah, I am jaded and cynical, I was part of that thresher in the dot.com boom/bust and aftermath.
I completely agree. I just have been in the area 6 years but I have seen a lot of systems the ones that follows the Gospel as the bible are the ones that you have to touch like 5 and 6 files just for one feature spread across interfaces for the sake of it, abstractions and reimplementing things "to not depend on something" that probably won't change in 3/5 years.
Programming that way takes years to complete things and probably they never see the light of production. Because they are focused too much in code/structure perfection not in building solutions to the customers.
but "consultants"/"experts from out of town" make lots of bank on projects like that! And people like you and I make even more bank rush charge multipliers + other peoples code multipliers + making them do what you need vs what you asked for multipliers ) to get them over the line after they are years behind schedule and over budget.
Me thinking Java is OO and hearing it’s less OO than it is. This opens up to a new understanding. Thanks for the heads up😂.
any thing you thing I should write about on this subject, please suggest them. :-)
Based on the article, you suggested Go is
more OO although, it doesn’t support the traditional OO, like classes. Do correct me if I’m wrong. I’d love to hear your views probably in another article on how Go is inherently more OO. You did point out a few interesting points but I’d like to hear more. I believe understanding the design pattern of these languages could help make us better users of it
there is no such thing as "traditional OO", what you think is "OO" is not "Object Oriented", never has been. That should be extremely clear from the quotes and citations in my article, not a suggestion, it is a fact. Go supports the principles that Alan Kay puts forth as what "Object Oriented" means, he invented the term. I am working on an example repo that shows an implemenation of the things he says an "Object Oriented" language should support. Hint: he never mentions "classes".
Would love that. I hope to see it very soon
What is common understanding of OO from the PoV of C++, Java and C# devs is quite a bit off from the original meaning.
Most of the purity gets muddied in practice anyway. You should look for inspiration from many approaches. It doesn't mean it's always a good fit for a language or platform though.
Exactly, Alan did argue same. I think that’s what this article was all about
Whether you agree with this article or not please report the scumbag that stole my work and posted it as his own on medium.com. Stealing others work is complete scumbaggery, especially someone's work that blew up just to get traffic for your own lazy self!
medium.com/@dmitrijkumancev571/go-...
here is the link to report copyright violations
help.medium.com/hc/en-us/requests/...
Go is for prototype driven development and data driven design 😎 pure OOP or pure FP never has become the practical solution.
Having a procedural and concurrent programming mentality was heavier than OOP and FP aspects in Go. I guess the definition of light OOP and definition of light FP kinda has slided into small subsets like polymorphism and closures. Go ticks these boxes with light checkmarks but it is more heavy checkmark on its procedural and concurrent mantra
no, Go is not "for prototype driven development" what ever that made up term is supposed to mean in the context of OO. JavaScript is called "prototype inheritance" before it got "classes" and Go is not JavaScript.
Go only supports composition.
And given your confusion on "for prototype driven development" you would have to define what you thing "pure OOP" or "pure FP" means, because given Alan Kay's statements and his functional language background, and all the languages he says can support what he means by "Object Oriented" are all Functional languages are almost synonyms. Also not sure why you think a language with first class functions is "procedural ... mentality", especially give than the "concurrent programming mentality" in Go is a direct inspiration from Erlang, which is about as "pure FP", in your terms as you can get for a non-academic commercially successful language.
prototype driven development means you add as you go, it is not related to JS/TS objects or the design pattern prototype.
Go doesn't only support composition, it supports polymorphism/encapsulation/abstraction, one of the creators of Go; Robert Griesemer insisted on this feature because he was mainly inspired from Smalltalk and Pascal. Just because we don't have inheritance doesn't mean it is not OOP, it will always have its own lightweight OOP and lightweight FP side.
All functional languages are not same, Go doesn't have monads, algebraic data types and pattern matching and so forth. Pure FP means Haskell/OCaml/Miranda. Pure OOP means Java/Smalltalk/Simula
Go is not the direct inspiration from erlang. Erlang has a nice scheduling for its internal processes but it doesn't have concurrency primitives + you need to have VM everywhere in order for it to work with target OS. Only Elixir is direct inspiration from Erlang.
Concurrent programming for Go has been added by Rob Pike and the others with all the concurrency primitives that actually made the difference from language called Limbo which was used in Inferno OS in bell labs. Go doesn't use actor model and doesn't require yet another VM.
The existence of channels sets Go apart from actor model-style concurrent languages like Erlang, where messages are addressed directly to actors (corresponding to goroutines). The actor style can be simulated in Go by maintaining a one-to-one correspondence between goroutines and channels, but the language allows multiple goroutines to share a channel or a single goroutine to send and receive on multiple channels
Just because it has added first-class functions doesn't make it purely functional, but it is still functional, just like OOP, it doesn't have objects/inheritance but it has method receivers/polymorphism/data composition etc... they decided to take small likeable sets of features.
Go is procedural(C)/functional(APL)/OOP(smalltalk)/concurrent(limbo) programming language, there is no such thing as one because the founders come from diverse languages, It is multi-paradigm. It is all on the wiki btw, just in case you wanna read;
en.wikipedia.org/wiki/Go_(programm....
From my observation, I love the procedural(C) and the concurrent(Limbo) features with heavy check mark. Because it is not like I am programming in only OOP language or in only FP language. This is one of the reasons why it has less keywords in it as well. But you can call it however you love.
go on and and tell me how Rob Pike did not really mean what he said about goroutines being inspired by
"In the Go blog post "Go Concurrency Patterns: Pipelines and cancellation", Rob Pike, one of the Go language designers, wrote:
"The Go scheduler is inspired by the Erlang scheduler. Erlang processes are lightweight, concurrent threads that can communicate with each other using message passing. Gooroutines are similar to Erlang processes in many ways. They are lightweight, concurrent threads that can communicate with each other using channels. Gooroutines are also managed by the scheduler, which ensures that they are scheduled fairly and that they do not consume too much resources."
Pike also mentioned Erlang in a talk he gave at the 2012 GoCon conference. In the talk, he said:
"We were inspired by Erlang in a number of ways. Erlang has a very good model for concurrency, and it has a very good model for fault tolerance. We took some of the ideas from Erlang and applied them to Go."
So, there is clear evidence that the Go developers were inspired by Erlang when they designed goroutines and the fail fast error handling model that everyone from Java and Python hates.
"
Go follows fall fast approaches only in context of goroutines. In rest cases, it's a heavy explicit error handling.
fail fast has nothing to do with "heavy explicit" anything, it has to do with just failing as soon as the error happens. Erlang does it implicitly, Go explicitly.
The idiom is
if err != nil { panic("") }
and nottry/catch/final
as a direct reaction to the FAIL LATER thattry/catch
introduces and the extremely LOW COUPLING ( which is even worse ) that it causes,scattering error handling logic across unrelated functions and files.the "fast" part in "fail fast" has nothing to do with HOW to handle the failure, but WHEN, immediately. No passing the buck,that is why Java main hate it, they just want to do
try/catch/throw
and ignore it because that is the lazy thing to do and makes it someone elses problemSorry, I didn't get a notification on your response.
Fall fast approach has a lot of concerns and limitations. In Erlang, if some thread fails on processing a piece of data, its upper level should make a decision what to do with the piece of data. Or it rerun the thread with the same data (for example, sending to a remote service that temporary unavailable) or do something other. And handling of similar cases may have his own such complicated logics, so it become difficult to call it "fast fail". The idiom with panic in Go looks so-so for me because it doesn't provide any information about fail reason to upper level. Of course, if you strictly follow SRP, the panic itself may provide this info. But this make your Go code to look like Erlang: a lot of short functions. I like this style.
Personally, I have no much issues with try/catch approach. It's a good way to promote the error to an abstraction layer that can handle it the best. Of course, programmer have to understand well an application architecture for it. But usually people doesn't care to document it properly.
also one of the misconceptions you have is the definition of "OOP" is not tightly attached to Alan Kay's quotes from 1997. It has been 26 years. The messaging term Alan Kay means is "structured" programming, not "functional" programming.
Data = struct, data can be the owner of the function(OOP) or be owned by a function(Procedural/OOP/FP). Thus erlang has no features from OOP. You can't call distributed message passing as OOP.
"What if "data" is a really bad idea?" -- Alan Kay July 2016
news.ycombinator.com/item?id=11945722
"I wanted to get rid of data." -- Alan Kay
userpage.fu-berlin.de/~ram/pub/pub...
but gone and tell me how Kay really meant that the focus is the data and "data == struct" ...
"The real issue is messaging. Messaging is the abstraction of the communication mechanism." — Alan Kay in an interview with Peter Seibel for Dr. Dobb's Journal in 1997
but go on and tell me how Erlang which is 100% message passing "has no features from OOP".
all your comment does is shows everyone reading it you either did not read my article, with all the quotes and their sources or you did and are just a troll.
dude HE INVENTED THE TERM, he gets to say what it means.
by definition his opinions are not just "tightly attached" they ARE the definition.
you need to seriously read up on what Dunning/Kruger Syndrome is and get some help before embarassing yourself in public further.
good article, made me laugh a lot and think a bit.
What a great article. I like the way you jump Java-go-erlang-go. The Right Tool For The Job™ right. Very insightful and well-written. Thank you.
I'm sorry the world is frustrating. Should we leave you all alone?
I think humans don't share the same brains, so some brains act differently, which makes some of those harder to understand. But then again, there's freedom, so why bother what others are thinking? All that negative energy is wasted because with that energy you could have written your next epiphany.
Because someone has to maintain the software people write. And introducing excess complexity early on makes software systems that are inherently more difficult to maintain.
I'm literally dealing with this right now and having to hold my nose until MVP launches before refactoring becomes an option.
Some people actually care about the software that create add the people that have to work with it after them.
"Jacks Total Lack of Self Awareness" ...
the OO ecosystem is also full of crazy mentality, ex.: as much library/framework you have as dependencies in your project is better, most of the people even never had a curiosity to check their impact on code performance in any stage, only for the sake of use it... sounds like computers does not matter anymore, only the aesthetics of the code, since it has indirection, lot of interfaces, full of
return new EmptyObject();
and libraries the code will look beautiful, perfect and if it will perform well doesn't matter, just allocate 4 machines with 8vcpu with 32gb of ram each that my code will perform well along side a redis cache. =DI'm totally disagree. OOP is about Application Architecture/Design. It became a great common language between architects and developers that opens to developers a door to formal architecting processes.
And the Golang interface concept is taken exactly there.
Okay, Let's suppose, Golang is great by its own. It doesn't use experience of previous tenths years of computing and computer science and all researches, conventions and approaches isn't for Golang. Then there would be a good point to suggest own design patterns, terms and approaches. But I don't see that anybody suggest anything like that. Renaming of common conceptions isn't "an own design patterns".
I see Golang adepts are trying to declare a their own great way, that it's mostly consists of denying some common rules, approaches and common sense.
A good example of the compilation fault on "declared but not used". It makes senseless headache at a development stage, forces using third party tools for handling it comfortably and so on.
But it has pretty unclear motivation that actually get up to childish "we don't want to fix it".
Here there was mentioned Erlang. It's really great programming language that allows to write extremely reliable code. But why it isn't a mainstream language? Exactly because its designing concepts are really totally different from most of other programming languages. Golang in opposite has grown up from common languages. It's one of points that have made Golang so popular, powerful, and easy to learn. And for me this kinda cancel culture for common approaches and Golang roots looks abnormal.
wow, how to project your own bias on to my article which is Titled "Go is Not Java",not "Go reinvents the last 30 years of CS".
interface
in Go is one of those "direct reactions" and is the EXACT OPPOSITE asInterface
in Java/C++/C#/"OOP". Go back and read up on the whatinterface
is in Go and why it was created, not just blog posts telling you how to write Java in Go and misusinginterface
and composition to do "Inheritance`.you completely missed the point, the designers of Go state unequivocally that Go is a reaction to C++/Java/OOP. Their goal was to remove all the mistakes and keep what actually works. Both can be true at the same time. But yeah, telling people to stop doing the stuff in Go that the designers intentionally left out or did a different way, is "bad". Appeal to Popularity is a logical fallacy.
No such thing as "AI" or "Cancel Culture". Both are marketing terms that were intentionally conflated with things to misrepresent them to willfully ignorance listeners/readers.
Sorry, I don't have any bias specifically on your article. it's not a first article "Go is not something. Stop using Go as that something" that I read before.
Reread your TL;DR. You insist there that [any] Programming Patterns is a Java boilerplate. My point is that it's definitely not. It's common conceptions that useful to know for everyone (I mean programmers of course) and understand how implement it properly in a certain programming language, including Golang.
Rest of my graphomaniac excursions is about where this "Go is not..." coming from and why.
another remark:
I had came to OO programming (not Patterns) from procedural languages (C, Fortran, pascal, PL/I), and was extremely confused trying to use OOP in real practice. Everybody believed that OOP should be used totally, and it's cool to build up great universal class hierarchy, and after that starts implementing it. Especially we had a great example of OOP implemention as TurboVision UI.
Nobody explains us at that time that a tool should be used only if it makes your code more clear, easy to understand and modify. I got it only after patterns of gang-of-four. I turned to the patterns when I hadn't known how to implement better one or another things. And now in Golang, a bunch of classic patterns like fabrics, adapter, decorator are called "Golang idioms" .
It's okay. I know it and it makes most of my previous experience applicable in Go.
The only problem is that It confuses newbies. They start thinking about OO patterns as it is something wrong and shouldn't be learned. It mitigates their professional growth significantly.
Would you happen to have suggestions on learning the correct idiomatic way of writing Go code as one is learning to become comfortable with Go?
Some comments have been hidden by the post's author - find out more