Monthly Archives: December 2015

On Go

Some time ago noticed somebody was building #golang complaints list. On Monday noticed this tweet by @golangweekly. Now decided to address top five complaints, taken from How to complain about Go. So here are those top five:

  1. error handling / no exceptions
  2. no generics
  3. stuck in 70’s
  4. no OOP
  5. too opinionated

Below they are addressed in the numbered sections, one complaint per section.

1. error handling / no exceptions

Majority of programmers are lazy. Especially programmers of business logic. Commodity programmers constitute 90-95% of all programmers base. The rest 5-10% are master programmers. Usually commodity programmers write simple business logic, translating requirements into the machine program, nothing mission critical, usually not challenging, and they are getting lazy. Some commodity programmers become very lazy. It is normal for them to code only positive path and totally ignore the negative. That is not good, in any programming language. Just some languages do tolerate the laziness, and allow to avoid explicit coding of the errors.

Go does not tolerate laziness. If you wrote “if”, please write “else”. Within “else” write retry logic, or switch to default parameters, or try to recover, or stop explicitly. If something can fail, then check for success or failure before moving forward. In go you still could skip the negative path, but you are enforced to code the positive one.

Errors are part of the code. Because of binary nature of the information, errors are part of the flow. So it’s better to program both sides, good & bad, light & dark. It’s absolutely good that go nurtures to code errors as organic pieces of your entire program. Isn’t “if err != nil” annoying? Yes, it is. It is part of technology, you just do it to use the technology, you adapt to the technology. Skipping errors, or obscuring errors is bigger evil than having some idiomatic annoyance.

Exceptions failed [in other programming languages]. Exceptions were invented to handle really exceptional situations. Majority of C++ coders did not ever read “Design and Evolution of C++” to understand why language features were introduced for solving real problems with C++ language. So exceptions failed in C++ during its best times. Java and .NET coders went further from exceptions as really exceptional situations, and exceptions became error codes and events. Having exceptions as events is the worst case, because they were not designed for that purpose. The laziness of commodity programmers reached pinnacle with catch(…){} and catch (Exception e){} and except: and so on. That sucks.

As go is not a programming language for all purposes, it was designed to rewrite old C++ programs, and to do new system programming, there is no need to listen to those complains by commodity programmers. It is important to not nurture laziness. It it good to enforce checking for errors, and coding of both “if” and “else”. There is no other way to go, the machine will not create the missing logic for negative path for you. That code must be done by the programmer.

2. no generics

How generics appeared in other programming languages? Let’s take C++ again. Before generics, coders used preprocessor directives to tweak and glue the words, generate the program code, so that same algorithm/flow could work with different types. That glueing was done only by families of the types, e.g. glueing for all numeric types (small integers, signed integers, unsigned integers, long integers, …, same for floats etc.) There is common sense in that, because numeric types all together is a cluster vs. other clusters of types. But how it unfolded? You could parameterize everything by everything, even declaring type on the left and passing it as parameter on the right: class MainWnd : public CWindowImpl<MainWnd>

The pinnacle of generic design and generic programming could be considered typelists. Here is the source code typelist.h allowing deep nesting of templates. AFAIR initial implementation allowed 50 levels of nesting. The wisdom emerged, typelists’ author Andrei Alexandrescu slams generic programming nowadays.

So it’s OK that generic paradigm was fashionable, promising in the past. It’s also OK that it did not solve the problems. It’s better to apply commonality and variability analysis during your abstraction exercises and use interfaces for the coding of commonality. Go goes that way, which is good. Go lacks clustering by type families, it’s not so bad, just think again which type do you really need and use only that type. It is not a problem of go, it is your problem [laziness] during program design.

3. stuck in 70s

Java was released in 1995, far after 70s. And we have idiomatic (or idiotic?) public static void main. Is it improvement since 70s? Or furthermore, each program is a class. OMG, my single script is a class? My simple dumb print is a class? Was that escape from 70s? I prefer to stay with old good ANSI C simplicity and clarity, rather than consuming such escape from “being stuck”.

For Java lovers… Java is ideal for code generation. If Java is done by machines, it is perfect. Usually it took place. Enterprise suites with visual BPM do generate Java code. Business analysts drag’n’drop, modeling the real life process, with all tiny details of types mapping, events, conditions, data transformations, transactions etc. And the suite makes the Java code, and runs in on middleware (usually ESB). For machines all that formality and strictness with public static void main is OK. But not for the human.

Why we got so many Java programmers then? Why machines did not produce all Java code? Two reasons. First: not many solutions were designed in BPM, or at least by making some domain specific language (DSL) and design solution with it. So coders took wrong tools and produced imperfect solutions. Two: not everything is possible in WYSIWYG tools. Some manual polishing is needed, and humans filled the gap left by machines. As machines generated Java code, humans had to complement with same Java, to fill in the blanks. Now some Java legacy spread to Android…

Ok, back to go. Go has been designed to mainly overcome C++ problems. For modern system programming. What is modern system programming? It’s Docker for example, not to mention internal Google stuff. C++ was based on C, and C is rooted since 70s. So everything OK with similarity. I do not agree that we stuck, and I do not agree that 70s were bad at all. We had Concorde, introduced in 1976. We were accelerating. While today there is a feel of deceleration. Go dropped modern overengineering pseudo features, and it’s not to go into the past, it’s to go into the future.

4. no OOP

This is most pleasant complain. Commodity programmers usually don’t know OOD and OOP. Hundreds of times I’ve asked the same question on interviews, and hundred times they failed. The question was simple, dual. First: which programming design paradigms you know? Usually OOP was mentioned. Second: what is OOP, main principles? Almost everybody answered “encapsulation, inheritance and polymorphism”. After that the interview finished shortly. Few answered “abstraction” and then those three others.

So, abstraction. Abstraction is the foundation to any programming paradigm, especially to OOD/OOP. How you abstract the real world into the machine world, that could be emulated and run by the machine. Master programmers know that sometimes it’s better to abstract into function, or families of functions; sometimes into data; sometimes into compilation modules; files; namespaces; structures. It is context dependent.

What we got with OOP in the programming languages, which are loved by complainers? Abstraction into classes is prevailing, though other abstraction mechanisms are supported. And with abstraction into the classes we have one God aka Object. It means that entire abstraction of the real life case that we want to emulate and run on the machine is purely hierarchical? That’s not relevant mapping. Because the real world in not hierarchical.

There are hierarchies, at some abstraction levels. But if you look one level up, or one level down, your hirerarchy will be gone. You will see the mesh, grid, web. Then step again one level, and you will spot hierarchy again. Go further, and you will get the mesh. Think of the orders of magnitude in both directions, from this to bigger, and from this to smaller. It’s all about abstraction levels. In the software solution, it’s normal that multiple abstraction levels present, corresponding to the reality, but it’s not normal that only one method is used to deal with them all. OOD is OK only for the context where you deal with true realistic hierarchy. Outside of it, OOD is not the best choice.

Regarding abstraction, go language is absolutely normal. You are not imprisoned into the Object pseudo hierarchy. You could abstract into multiple relevant language tools, depending on the context. I don’t even want to move to secondary goodies (encapsulation & Co, they are OK there too). It’s important that the primary one – abstraction – has been fixed.

For technology creation go is good. Just don’t code business logic in go. For biz logic please design (or select) a DSL/DSEL, and build the logic at higher abstraction level, 3.5/4GL or visually or hybrid. Good book how to think wider “Multi-Paradigm Design for C++”, not tightly bound to C++, very useful for other programming tools.

5. too opinionated

So what? Is it bad? Opinion is a skeleton of design, philosophy of lifestyle. If somebody (Rob Pike?) invented the tool/technology to solve C++ problems, then it is cool. If you don’t like some idioms, like ok idiom for the map, then think about every technology PROs and CONs. First space ship could fly into the space, but there was no restroom in it. The technology could not provide it. So if you needed to fly more than pee, you selected the technology and flied. If you needed to pee, you went with another technology and did not fly. It’s so common sense.

I suggest to many of you to read very thin useful book “Practice of Programming”. As soon as you understand that different tools were designed to solve different problems, and multiple tools are used to solve bigger problems, you will give up with religious fanatism and stop averaging the tools. Each tool must remain as specific and laser focused on certain problem as possible. Just don’t be lazy, master many tools, physically and mentally. Consider future evolution of the tools, like the restroom in the space ship. And stop blaming go, use it when you need it, not when you want it. That’s my opinion.

Advertisements