When reading about Go, you will often hear the word “simplicity.” But different people interpret this word differently, especially in the context of software development, and many, often, do not even realize why it is generally used as a characteristic of the language. In this article we will try to approach conceptually the issue of “complexity” and “simplicity” in software development, and see why and why Go has put simplicity as the cornerstone of its design.

About complexity.
Simplicity is the opposite of complexity.')
The complexity of software development is a topic that has long troubled the minds of engineers and scientists, and one of the most conceptual approaches to the issue was designed by
Frederick Brooks , the famous book Mythical Man-Month, as a separate work -
“No Silver Bullet” Bullet ” ). This work was written in 1987, but the conceptual view on the topic makes it relevant after 30 years.
In particular, Brooks makes an important division of complexity into
“essential” (
essential ) and
“introduced” (or “accidental” -
accidental ).
Inherent complexity - this is the complexity that comes from the very area of the problem, from its nature. Say, if you need to implement the FTP protocol - no matter what language or toolkit you choose to do this, you still have a set of commands, actions, return codes and logic that you have to implement. There is no way to simplify the task before implementation in one line. The difficulty is given to you as given (in this case from the specification of the protocol), and you generally do not have a way to influence this component.
The complexity introduced is, on the contrary, the complexity that comes from the tools we use. This is the complexity that we create ourselves. We can influence and reduce it.
The history of the software development industry is reduced to the reduction of this particular,
accidental , complexity.
Why complexity is bad?
Everything should be made as simple as possible. But not easier.
Albert Einstein
The answer to the question is “good” or “bad”? - lies solely in the recognition or non-recognition of good and bad practices. There is no formal way to prove that, say, “global variables” is good or bad. Considering private examples, supporters of each of the parties will find you hundreds of convincing arguments both for and against. But having gathered, at least partially, the experience of many and many software developers working with a wide variety of programmers and languages, you will one way or another hear statements about “good practices” or “bad practices”.
It is only with the collective empirical experience of many thousands of engineers and programmers who put their thoughts on paper that an understanding comes that “complexity” is something that should be avoided as much as possible. The complexity leads to a whole avalanche of not immediately obvious effects, which are also often difficult to formally prove and which are measured by probabilities — a greater likelihood of errors, more time to understand the code, more time and effort needed to change the software design if necessary (refactoring), which , in turn, give rise to an incentive not to make these changes, which, in turn, lead to the fact that developers are beginning to look for workarounds and so on.
In the end, code is just a tool for solving problems, and as a result, the main criterion separating “good” from “bad” is productivity - the speed and quality of solving these very tasks. Complexity is a productivity killer, and that’s why the entire development industry is moving towards reducing complexity.
And here programming languages?
Complexity management is the quintessence of programming.
Brian kernigan
The choice of programming language is a very good, if not the best, example of the “introduced complexity” in the world of software development. Programming languages themselves are also tools for reducing development complexity. And each turn of their development one way or another solves one aspect of the complexity of software development, but in so doing introduces new elements of complexity.
The whole history of their development is the history of finding a simpler tool for the realities of that time. The theory of programming languages is the same developing science, as, for example, neurobiology, and there is no single canonical knowledge of what a programming language should be. This is a stochastic process, mixed with the laws of the market, successful solutions, a good backup in the form of a large company (almost all popular languages had a large company behind it) and a host of other factors.
And this process does not stand still, new concepts give rise to new problems and new levels of abstractions, the collective experience and understanding grows, at the same time, the hardware and software ecosystem is rapidly changing and changing, priorities are changing in terms of compromises and saving resources, and all this is tight based on the inertia of the human brain and educational systems. In other words - this is a very complicated colossus. Simple and one solution is not here and can not be.
But what can be argued for sure is that some languages introduce more complexity into the general pool of complexity, while others less. Some practices and patterns (“patterns are a bug report on your language”), which are imposed by languages, increase the total complexity of development, others decrease.
And we, as engineers, should strive ultimately to avoid this “introduced complexity”.
Difficulty in go
Go was born as a response to the increased “introduced” complexity of existing languages. At least, that domain which excited Google - development of system, network and server software. His main goal was initially to reduce this complexity at any cost. This was a top priority from the start.
A significant role was played here by the colossal practical experience of the authors of Go - Pike, Thompson and the company - people who were at the origins of Unix, the C language and UTF-8, and are now working on key Google products. One way or another, Go was to some extent a radical language that swung the pendulum of complexity in the other direction, trying to level the existing landscape of the software development world.
And this is exactly what is meant by the term “simplicity” in the context of Go. Reduced complexity. Reducing the time needed by an average programmer to understand an average project written by other people. Reduced risk of error. Reducing the time and cost of "good practices." Reducing the chances of writing code is bad and ugly. Reducing the time to learn the language. And so on and so forth.
Numbers
But enough words, let's really try to evaluate the complexity introduced by languages. In the comments to previous articles, the lack of "formal evidence" was the cause of violent controversy. I must say at once that I am aware of the complexity of this task. The real assessment lies in the plane of subjective practical experience and difficult-to-measure probabilities. There is no simple way to reduce everything to a single digit and say “the complexity of language A more than of language B”. Nevertheless, if you know any two or more languages well, you can easily decide for yourself which language is easier for you. Your brain somehow knows how to evaluate and decide which language is more difficult.
Therefore, in the absence of a better option, I will try to take a few techniques, and see what picture they draw. Each technique has serious shortcomings, but if their results are not very different, we can assume that this is something more than a random distribution.
At the same time, I will analyze languages that are sufficiently universal for solving a wide range of tasks, have a large enough community and information about them is available. Exotic like Brainfuck, we do not consider.
Method 1.
One of these simplest methods is counting the keywords (keywords) of a language. In fact, it will be more accurate to evaluate the concepts that a language introduces - but this is more difficult to count, and at the same time correlates with the number of keywords. The assessment will be very rough, but quite indicative and logical. Logical, because less knowledge equals less cognitive load on the brain.
Here is what we have:
The same, in the form of a graph:

Method 2
You can try to evaluate the grammar of the language, many of which are described using
Backus-Naur form . Grammar in this format (BNF / EBNF) is not available for all languages, but there are quite a few different grammars in the network that are composed semi-automatically. For example, I took a few grammars from here:
slps.imtqy.com/zoo/index.html . I will evaluate the number of rules as simple one-line players. For example, for Go it is very easy to extract ENBF rules directly from the official page with the language specification:
$ curl -s http://golang.org/ref/spec | grep pre.*ebnf | wc -l
. , , .
| |
---|
C | 65 |
Go | 58 |
Python | 83 |
Haskell | 78 |
JS (ECMAScript 5.1) | 128 |
Ruby ( 1.4) | 37 |
Java (JRE 1.9) | 216 |
C++ (2008) | 159 |
C# 4.0 | 314 |
Lua 5.1 | 25 |
PHP | 146 |
Rust | 115 |
Erlang | 219 |
Scala | 143 |
:
C curl -s
www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf | grep ": " | wc -l
Go curl -s
golang.org/ref/spec | grep pre.*ebnf | wc -l
Python manually copy text from
docs.python.org/2/reference/grammar.html, then “cat py.bnf | grep ": " | wc-l”
Haskell www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-17500010JS (ECMAScript 5.1) curl -s
www.ecma-international.org/ecma-262/5.1 | grep '.*::'| tr -d ' ' | sort -u | wc -l
Ruby ( 1.4) curl -s
docs.huihoo.com/ruby/ruby-man-1.4/yacc.html | grep ": " | wc -l
Java (JRE 1.9) curl -s
docs.oracle.com/javase/specs/jls/se8/html/jls-19.html | grep '' | wc -l
C++ (2008) curl -s
slps.imtqy.com/zoo/cpp/iso-n2723.bnf | egrep ":$" | wc -l
C# 4.0 curl -s
slps.imtqy.com/zoo/cs/csharp-msft-ls-4.0.bnf | egrep ":$" | wc -l
Lua 5.1 curl -s
wiki.luajit.org/Extended-BNF | grep "::=" | wc -l
PHP curl -s
slps.imtqy.com/zoo/php/cordy.bnf | egrep ":$" | wc -l
Rust curl -s
doc.rust-lang.org/grammar.html | grep "[a-z_]* :" | wc -l
Erlang curl -s
raw.githubusercontent.com/ignatov/intellij-erlang/master/grammars/erlang.bnf | grep "::=" | wc -l
Scala curl -s
www.scala-lang.org/files/archive/spec/2.11/13-syntax-summary.html | grep "::=" | wc -l
:

, , .
3.
— StackOverflow . , , RedMonk :
redmonk.com/sogrady/2015/01/14/language-rankings-1-15StackOverflow , , , , , , , , — — SODD, Stack-Overflow Driven Development. , — , (, , ). StackOverflow :
stackoverflow.com/tags?page=2&tab=popular, , , GitHub 2014, :
githut.info .
— StackOverflow Github. , .
:
| GitHub | SO | |
---|
Go | 22264 | 10272 | 0,46 |
Ruby | 132848 | 136920 | 1,03 |
Lua | 8123 | 8502 | 1,04 |
Rust | 4383 | 2478 | 1,76 |
C | 73075 | 184984 | 2,53 |
Haskell | 8789 | 22930 | 2,60 |
Python 2.7 | 164852 | 439994 | 2,66 |
JS | 323938 | 880188 | 2,71 |
Java | 222852 | 879064 | 3,94 |
C++ | 86505 | 377834 | 4,36 |
PHP | 138771 | 768018 | 5,53 |
C# | 56062 | 811952 | 14,48 |
Erlang | 2961 | 5571 | 1,88 |
Scala | 10853 | 38302 | 3,52 |
:

, , , , , . ( Go, , — Ruby, , ). - , — , .
, , , — “”, “” “” . Rust- — , Rust : ( 1.0 ), , , rust- — Stack Overflow. , , . , , .
. , :
) , ( )?
) , — ?
— — . Go, , . Go , — .
, Go , , , . — “ , ” — . , Go ( , )), “” Go — .
, , , . , , , . , . , Go “Go makes programming fun again”. Hello, World, , , , .
, . , Go — Go , .
No Silver Bullet —
faculty.salisbury.edu/~xswang/Research/Papers/SERelated/no-silver-bullet.pdfLess Is Exponentially More —
commandcenter.blogspot.com/2012/06/less-is-exponentially-more.htmlLess is more —
lambda-the-ultimate.org/node/4852