Complicating C ++ is inevitable. And not only C ++

I have long wanted to write a similar text, but my hands did not reach. But after the summer meeting of the C ++ Standardization Committee that ended and the howling that the complexity of the language increased even more, I had to find the time and fix my own thoughts on this subject.

There will be a lot of text, so those who are not sorry for their time, I invite you to look under the cat.

Programming language is a technological product, but not so simple

Some time ago I had the opportunity to read an interesting book, The Innovator’s Dilemma . There, with examples of high-tech products, it is shown how new products emerge that first lose to the decisions that currently dominate the market, and then radically change the state of the market.

One of the most striking examples: digital photography, which was completely absent in the 1990s, but only 20 years later led to the collapse of such a monster of the 20th century as Kodak (which, incidentally, was the first to make a prototype of a digital camera).


Another example close to developers: the evolution of hard drives. From the hefty monsters of the mainframe and mini-computer era, to the small 3.5 "and 2.5" inch models, and then to the M.2 format SSDs and wired directly to the eMMC board.


The same thing with floppy disks, which first reached 3.5 ", and then disappeared as a class under the pressure of USB flash drives.


Another example from our professional field is the development of personal computers. Which initially were not able to compete with the "real" computers of the mid-late 1970s. And then they just destroyed the mini-computers as a class. Then they led to the emergence of modern servers, somewhat reminiscent of the then mini-computers. And now PCs themselves are disappearing from mass consumption under the influence of laptops, tablets and smartphones.


The authors of the book declare that events in all such cases develop according to the same scenario:

Programming languages ​​as technological products

At first glance, similar analogies can be seen in the way programming languages ​​came to the mainstream. And perhaps the most striking examples here are the Java and Go languages.

The Java language came about as a result of an attempt to create “proper C ++”. But the resulting language would hardly be needed by anyone, because he was very miserable and, more importantly, slow and gluttonous. On the desktop, even considering the rapid growth in PC power at that time, Java had no chance.

However, Java entered the “market” from a completely different perspective, through a niche in which no one could really work then: via the Internet and browser applets (everything was a bit more complicated and there was still a market for JavaCard and STK applets, but we won’t leave in the wilds). The Internet was a very hot topic, and then there was simply nothing to do dynamic sites / pages (JavaScript appeared after the announcement of Java). And, since there was nothing to use besides Java, Java began to be used. Well, then, as it developed and overcome childhood diseases, Java went into other areas, displacing other technologies from there. Although in the same desktop she could not bite off a significant piece of the pie herself.

The Go language could hardly interest anyone in traditional niches where C, C ++, Java, C #, Python, Ruby, etc. already lived. But the development of products for the Internet has spawned another niche - RESTful services. For development of which Java was an overkill, C ++ is too complicated and dangerous, Python / Ruby and other dynamics are too slow. And now one of the most miserable in the expressive terms of languages ​​developed in the 21st century becomes almost a silver bullet for this applied niche. From where, perhaps, it will spread somewhere else over time (which I personally will not be surprised at, given the general level of qualifications of the young generation of developers).

So one gets the feeling that programming should be the same with languages ​​as with other technological products: the emergence of new languages ​​will either lead to an almost complete disappearance or to oust previous languages ​​into separate marginal niches. At the same time, old languages, in the process of their development within the framework of the competitive environment, are becoming more powerful and expressive for cheaper solutions to their typical tasks. As a result, old languages ​​are becoming more and more voluminous and complex. And less attractive for use outside those niches that they have already occupied.

Therefore, it seems that the life cycle of a technological product described in the Innovator’s Dilemma should also extend to programming languages.

But not everything is so simple with programming languages

In the scheme of penetration of new technological products into the market described in the Innovator’s Dilemma, one of the most important reasons for users to switch from old mainstream products to new ones is either simply a significant reduction in the cost of ownership or the acquisition of previously available opportunities + a decrease in the cost of ownership.

For example, the development of PCs and the growth of their power makes owning a PC fleet cheaper than owning one or more mini-computers. As a result, three-inch floppy disks are cheaper per unit of capacity than 5.25 "(taking into account greater reliability and other factors). As a result, digital photography is cheaper per frame than film. And so on.

But two more important indicators are associated with the transition from one product to another - this is the cost / complexity of the transition itself, as well as the speed with which you can switch to a new product. These indicators can be estimated in money. And if the benefit of the transition to a new product is present, then the transition is carried out. Perhaps not fast, but carried out.

And here it turns out that the cost of switching from one programming language to another is much higher than in the case of switching from a mini-computer to a PC, from 8 "floppy disks to 5.25" or from HDD to SSD. Since changing a programming language is usually a complete rewrite of a software product. Often from scratch.

And what does rewriting mean? Salary of a new team of programmers, which will need to repeat the functionality already available in the product. And even if the new PL allows you to halve the size of the team, it will still mean significant costs. For if $ 10M was spent on developing the old version of the product, then rewriting will require a minimum of $ 5M.

But, more importantly, this is that the rewritten product will not appear right away, at once. Need time. A lot of time. Again, assuming that the new language allows you to write working code twice as fast, then rewriting a product whose development of an old version took 5 years will require only 2.5 years.

It turns out that right now you need to start investing a lot of money in order to get a copy of something that has been working for a long time and is bringing money now.

And one more side of this coin must be mentioned: if a software product is operated in changing conditions, then the product will inevitably be finalized or processed to meet modern needs. At the same time, the business does not have the opportunity to wait a year and a half, until a new version of the product appears on a new PL, new functionality, as a rule, is needed in the foreseeable future. Often, yesterday.

Therefore, when rewriting, expenses increase: you need to write a new version at the same time and develop the old one.

In my opinion, this is precisely what explains why new languages ​​are "fired", primarily in the development of new applications for a new application niche. But crowding out old languages ​​from previously occupied areas is already much slower. Fortran and Cobol can probably be considered the most striking examples. Not only is the software written on them still in operation, they continue to write new code in these languages. And these languages ​​themselves are evolving.

And it seems to me that one of the worst dreams of owners of software products in Cobol is to rewrite the product in Java or C #;)

And another important factor: the development of IT itself

Another point that I would like to draw attention to is the fact that IT exists not so long ago and the history of the evolution of high-level languages ​​is even shorter. The first part of this story is unlikely to provide us with solid support for our discussion of how some languages ​​replace others. The 1950s and 1960s were years of experimentation. Moreover, the years when the computer market itself was segmented and a significant part of the software was written for specific computers and OS, without any special requirements for portability. The number of existing software developers, as well as the range of areas in which computers are widely used, can not be compared with the current state of affairs.

IMHO, fundamentally things changed in the 1970s, and since the 1980s we have seen the emergence of nuclear weapons that are already based on both the practical experience of past years and the results of theoretical studies. As for me, it is precisely the 1980s (and maybe the late 1970s) that are the beginning of the era of programming languages ​​aimed at manufacturing software on an industrial scale. For it is here that we see Modula-2, SmallTalk, Ada, C ++, Eiffel, object extensions of Pascal, Objective-C, Perl.

Therefore, I will continue to build on precisely what appeared in this era of industrial nuclear weapons.

By the way

Listing the languages ​​that appeared in the 1980s, I remembered about the PL developed by Niklaus Wirth: first Pascal, then Modula / Modula-2, then Oberon.

By the example of these languages, one can see how the experience of their author leads to the emergence of tools that take into account the shortcomings of previous attempts, as well as meet the new requirements of their time.

But these same languages ​​also show how important it is for users of YaP to stay within the framework of the once chosen language. The transition from Pascal to Modula-2 was. But by no means massive. And, despite the fact that Modula-2 was more or less actively used, it did not become as popular as the heirs of Pascal, especially Delphi. And there was no observable transition to Oberon at all, as far as I remember.

The popular programming language cannot just be replaced. And what of that?

So, the main message in my previous reasoning is that if a language has found more or less widespread use and with its help a lot of various software products that are in everyday use have been created, then this language cannot simply be completely replaced by other programming languages. Especially in a short time.

Successful programming languages ​​are doomed to continue to be used for years. And most likely to evolve.

And the evolution of a programming language implies the expansion of the language with new features. Which is inevitable, because progress does not stand still. People come up with more convenient ways to solve known problems. Faced with new tasks, which require additional expressive capabilities of programming languages. And, since the programming language is just a tool, people are moving towards improving their tool.

Which means that widely used programming languages ​​are simply doomed to become more and more voluminous and more complex, in the course of their development acquiring opportunities that were not even discussed at first.

In principle, Bjarn Straustrup spoke about this a long time ago. And even what I myself have been observing for almost thirty years confirms the words of Straustrup. Say, modern Java is already very different from Java 1.0 of 1995. The C # language demonstrates an even more impressive evolution from a successful clone of the first Java to perhaps the most expressive mainstream language suitable for use by Hindu programmers (regardless of their nationality).

But the most striking example for me is still the Go language. Which, already in the 21st century, they began to do by deliberately throwing out a bunch of things that have proven themselves well over decades of widespread use in different nuclear materials. And which thanks, including this, has become popular. But, nevertheless, life takes its toll and Go is forced to add something that the authors initially intentionally refused - tools for generalized programming (aka templates / generics) .

So popular programming languages ​​evolve towards expanding their capabilities. And that means complications. Since new features need to be added so as not to seriously break the already written code. For the epic story with Python of the second and third versions became a good example, which few dare to repeat.

Is it so bad?

The negative side of the ever-increasing complexity of programming languages ​​(especially a language such as C ++) seems to be obvious: the input threshold is too high. Too much time needs to be spent in learning the language in order to start issuing code of acceptable quality in an acceptable time frame. What makes development in a complex programming language both expensive and risky. What happens if one or more qualified developers leaves the project? How fast and easy will it be to find a replacement? Difficult questions.

On the other hand, since a programming language is the same tool for recording the intentions of a particular person, as, for example, mathematical expressions, it is appropriate to draw an analogy with mathematics.

At school, we begin to study mathematics starting with the simplest arithmetic operations. Then we move on to more complex things: fractions, degrees and roots. Then we go further, towards the logarithms. Then we take a little integral calculus. Similarly with geometry.

As a result, a graduate of a normal high school has a certain mathematical apparatus, which may well be redundant for a single person. I will not be mistaken if I assume that many after school never needed to calculate anything using logarithms or take integrals.

Nevertheless, the mathematical apparatus, which is mastered in high school, can not be compared with the fact that university students will then be given courses in higher mathematics. Especially if this is a student of a mathematical or physical faculty (and not only seriously download higher mathematics in many specialties).

But after all, it does not occur to anyone to blame mathematics for the fact that the deeper you plunge into it, the more difficult it is. Since if a person is faced with an area of ​​activity where he needs TFKP, there is nothing to be done, TFKP will have to be studied. However difficult it may be. Well and yes, it’s normal that not everyone succeeds.

Actually, the same thing with programming languages.

If you need to solve relatively simple problems, then you have a choice: either you use a simpler programming language, or you use a limited subset of a more complex language. But if you are faced with a difficult task (or specific conditions for its solution), then you may not have such a choice at all: the complexity of solving this problem in a "simple" language may be too large.

Speaking of tasks

From time to time I come across the assertion that almost all complex problems have already been solved (i.e., OSs have been developed, there are many DBMSs, middleware for every taste and color, etc., etc.), so in most only a simple and monotonous routine remains, to combat which complex tools are not needed.

It’s hard for me to agree with this point of view. But I can’t refute it confidently either. it’s just that physically I don’t have the opportunity to survey everything that happens outside my narrow professional niche. I myself seem to be doing not the simplest tasks. But at the same time, the goal of my efforts is to make it easier for other people to do their job. So, it seems, I myself strive to ensure that it becomes more than a simple and monotonous routine.

In addition, judging by the prevalence of languages ​​such as Go, Python, Ruby, and PHP, it can be assumed that the percentage of tasks that really require sophisticated tools is gradually decreasing. Moreover, due to the fact that more and more are being programmed in absolute numbers, it may turn out that there are still more and more complex tasks over the years. Even if a smaller percentage of software developers are working on their solution.

However, it is necessary to take into consideration also such a factor, which is constantly increasing over time, as an increase in the amount of work per programmer. Roughly speaking, if 25 years ago one developer could make a medium-complex form for a GUI application in one working day, now the same form needs to be riveted in two hours. And the rest of the time should be spent on other tasks that would have taken another week 25 years ago.

Therefore, it may well be that it seems like a routine around you is uncomplicated in appearance, but there are so many of them that its volume is itself difficult. And therefore, a complex tool that will automate the routine and / or reduce the number of errors in its implementation, may also be preferable to a more primitive tool, albeit easier to learn.

So, on the one hand, indeed, we can assume an increase in the number of tasks of small or medium complexity for which it makes no sense to use complex languages, such as C ++, Scala, or Haskell. But, on the other hand, complex tasks still do not disappear. Yes, and simple, but voluminous, the task may also require a tool higher than Go or pure C.

At the same time, we have at our disposal programming languages ​​for every taste and color. You can choose any. Therefore, as mentioned above, developers have a choice: you can take a simple tool to solve a simple task, you can take a more complicated tool, but limit yourself to only part of its capabilities. Therefore, if someone is confused by the complexity of modern C ++, then this is not a problem at all. Because, firstly, it makes no sense to use C ++ anytime, anywhere. And, secondly, no one forces us to use all the features of C ++ in a specific project at once, it is enough to limit ourselves to only what is really needed.


So what can be said in the end? A few things:

But the main thing, perhaps, is still different: the specificity of the programmer’s work is that you always have to learn something new and relearn in this profession. The brains have to be kept ready for the perception of something new. This distinguishes our profession from some other, more conservative professions (although it is unlikely to find a profession that would not be influenced by technological progress and the development of society). , - , , : , , -. ;)


All Articles