Monoculture in programming

Monoculture in programming is the use of one stack to solve all the problems that arise. It exists not only at the level of a specific person and his preferences, but also often occurs at the level of companies. In such companies, as a rule, everything is done using one technology.

Back in 2011, in Ulyanovsk, I started creating a branch of the company Undev, widely known in narrow circles, the same one that wrote software for broadcasting presidential elections, holding the Unified State Exam, and many other events. The company's main stack at that time was Ruby. As is known, there are very few Rubyists in the regions, and at that time in all of Ulyanovsk there were a dozen people whom everyone knew by name.

Our strategy was to take guys from other stacks and retrain them, as well as recruit green students. In essence, it was a training center in production. I was doing this for about 4 years, during which more than 70 developers were raised within Andev alone, not counting the activities aimed at developing the environment (during this time, several more branches of Ruby-oriented companies appeared in the city, and many began to use Ruby in addition to their main areas).

The original idea behind the development was that we use Ruby almost everywhere (and js, of course). After all, it gives so many possibilities:

  • It's easy to replace people and move them between projects

  • Quick entry into any project

  • Proven training schemes

  • Extensive Ruby expertise shared between all teams

In a sense, this is true. Indeed, for a business, the idea that it is easy to recoup losses and not be afraid that some part of the project cannot be supported due to the lack of specialists within the company seems very attractive. We worked successfully under this scheme for about two years, and then the system began to fail.

At that time, the company had many programmers who had seen practically nothing in their lives except Ruby. They were all trained internally. In addition, the complexity of the products themselves became higher, and Moscow began to trust us with increasingly complex parts of the services.

The problems started to appear as soon as it was necessary to write something outside the standard “rails” flow. Almost every library or independent module was written in the worst traditions of ruby:

  • Metaprogramming is the basic way of writing programs. Anything that can be generated programmatically is generated programmatically. Even if you are not familiar with this concept, imagine a program in which it is impossible to GREP function definitions.

  • Monkey patching as the main way to extend functionality

  • Active use of global state

I'm not even talking about the fact that the code itself often left much to be desired. In conversations, it turned out that many decisions were dictated solely by a limited outlook and a lack of understanding of programming principles. The guys couldn't differentiate them from the language itself. They considered any situation from the point of view of Ruby constructs. For example, despite the fact that Ruby is declared as a fully OOP language, those tasks that require the use of inclusion polymorphism (via dependency inversion) are solved through monkey patching and global state in classes (which themselves are global objects).

And this happened against the background of the fact that I was very actively developing an engineering culture. We used extreme programming practices to the fullest, wrote most of the code through tests, in each office we had monitors with a dashboard of integration servers. The guys read books, studied operating systems and actively shared knowledge with each other.

At that time, I met the well-known Lev Valkin, one of the most authoritative people in programming for me. A man who introduced tens of thousands of people to functional programming. At that time, he was working at the now defunct company Echo, and later at a branch of the company Machinezone. Although Lev has been living in the Valley for a long time, in those years he often visited his small homeland, just then we (Ulyanovsk IT specialists) launched the conferences nastachku.ru and ulcamp.ru.

> Currently we mainly use Python, Erlang, Haskell, C, C++, Docker, Vagrant, AWS, Git, Centos, Bash. But nothing prevents us from expanding or shortening this list. The main thing is to have the right tool for the task.

Every time we met, mono- and poly-cultures were the subject of discussion. I defended the point of view of the convenience of monoculture for business, Lev held the opposite idea that monoculture is harmful. And here are some examples:

Excerpt from the article on Lurka:

> Now, regarding functional programming languages. Of the ML family, OCaml is indeed the most practical. It has more users than other ML dialects, and, accordingly, many more libraries. The toolkit, although rather meager, is again richer. Yes, if we abstract from ML, then the same Haskell has even more users and libraries, but Haskell, according to Peyton-Jones himself, is not intended for production. Yes, it is used there, but Peyton-Jones positions and develops it as a research language. Well, what is much more important, as a language, Haskell is much more complex, the entry threshold is much higher. Both languages ​​are marginal enough to easily find developers for them, but the same Lev Valkin quite easily recruits simply smart people for his team, and there in a couple of weeks they begin to write quite well in OCaml.

An article on Lev's blog about how they came up with clojure: https://lionet.livejournal.com/125495.html

Then it became clear to me that the chosen training scheme for programmers at Andev was preparing not programmers, but Rails programmers. The problem of broadening horizons was aggravated by the fact that the level of automation and integration of tools in Rails is so high that it was extremely difficult for the guys to drag themselves somewhere else. Any task is solved with the phrase “install a gem”. Everything has been done before us, just find it and use it. I am not even talking about the fact that such developers can hardly understand the limits of applicability of a familiar tool and choose a more suitable solution for the task.

In 2013, I changed the course dramatically. Instead of teaching Rails, we started teaching the fundamentals of computer science. The main language during the training was Clojure. The main source of inspiration was SICP. Changes and a paradigm shift began within the company itself towards expanding the range of technologies and languages ​​used. I will immediately stipulate that this was not an expansion for the sake of expansion. Everything was justified from a business point of view, the main thing is that we lifted the taboo on this expansion. Languages ​​such as go, python appeared in the arsenal, and now, in restream (ex-undev) they write in everything in a row

The positive effect was almost immediate. A good understanding of the ideas and applicability of functional programming, an understanding of the importance of state management, abstractions, polymorphism and much more allowed me to get rid of the language and communicate at a higher level. The code became less dependent on language influence. It became easy and comfortable for the guys to switch between different languages. And it is clear that I have become a supporter of polyculture.

I think it is extremely important that a person who learns to program does not do it in the language in which he will (plans) write code for money. And it is no less important that the language should be completely different. If you wrote in C# at university, and write in Java at work, then little has changed for you. The transition from a dynamic to a static language (or vice versa) gives much more for general development, it is even better if this language is from a different paradigm.

In those years, I myself began actively writing in Erlang, Clojure, Python, and even a little OCaml with Haskell. Since then, TypeScript has been added to the mix.

Around 2017, I came to St. Petersburg as a consultant to Peter-Service, with whom I still cooperate. I was invited as a person who would help establish engineering practices and take a fresh look at the code and how development is carried out. I will honestly say that I myself have never worked on projects of such complexity: huge billing, more than 70 teams, thousands of people and a product that should work like clockwork. I was even a little afraid that my level would be insufficient for any changes. In general, it turned out that it was in vain.

Life has shown that everyone has the same problems. The company has a pronounced monoculture. Most of the teams I worked with write exclusively in one language, most often Java. Moreover, many guys either always wrote in Java, or have not seen anything else for a long time. When we began to deal with specific problems that guys encounter, it became clear that many of them have long been successfully solved in Rails in much more convenient ways. For some teams, using React instead of JSF would be an excellent solution. Moreover, JSF itself was chosen because “the architect knew it”, and no one would dare to try JS. There is no relevant expertise and no one is ready to take on this responsibility (it is understandable). Also, few people used the principles of automata-based programming, which led to difficult-to-maintain code (at least one team completely redesigned the architecture of one of the key services related to payments after we “dug” in the direction of automata).

The main problem with monoculture is that even if your ecosystem offers great solutions for everyday tasks, it cannot, even theoretically, offer the best solution for all emerging problems. Moreover, people tend to confuse the concepts of easy and simple. When in reality it turns out that the solution, although easy (familiar), is not simple at all.

In addition, the lack of experience working with different paradigms makes programmers very blinkered. Instead of seeing the essence of the problem, they immediately imagine a class diagram. This is especially evident during interviews. When, when talking about general concepts, a programmer can only reason in terms of the constructs of a specific language and when asked how he would do it if he had a different set of primitives, the person cannot give an answer. As Zadornov sadly joked, a specialist in the right ear does not understand anything in the left.

Putting it all together

  • Learn programming through several different languages ​​at once

  • Don't be a programmer, distinguish between essence and implementation

  • Keep your eyes peeled (following the right people and accounts on Twitter is enough).

  • If you've only written in static languages, be sure to learn a dynamic one.

  • If you've only written in dynamic languages, be sure to learn a static one.

  • Learn programming paradigms

  • Try to use at least two languages ​​in your daily practice (given the dominance of js, this is not so difficult)

  • If the previous point doesn't work, start a hobby project on a different stack from your work one.

Did you like the material? I write and shoot more:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *