Reflections on Beauty and Code
I think that sooner or later, every developer thinks in his head that the code needs to be written in a certain way. Why is this author’s framework so easy to use, and immersion in it is so fast? Why does this piece of code seem awful to me? At this moment, an important round in the development of the developer as a professional takes place. He not only begins to think about how to implement a specific task, but also how to arrangeyour decision. Thoughts about a certain structuring of the code and its beautiful design begin to arise in my head. Someone begins to create for themselves a certain empirical set of rules for the design of the code, someone comes to the aid of literature or the advice of more experienced comrades. In any of these scenarios, the code begins to be seen not just as an unconditional solution to the problem. There are thoughts that some of the code is made ugly , but here it turned out cool and elegant . But who defines these beauty criteria in relation to the code and what is laid in them? Is everything clear about code etiquette and beauty?
Disclaimer:This article aims to share thoughts that arose in the process of trying to comprehend the concept of beautiful code. These thoughts do not claim to be the ultimate truth. I only hope that these thoughts, reflections and arguments will probably help someone to look at the process of writing code from a slightly different perspective. Further, not a single formal rule of the form "Write the code this way, and you will be happy." A large volume of literature from much more respected authors has already been written on this topic.
All interested in discussions on the topic of what code beauty is, what it can be expressed in, why all well-known practices are not able to close this question once and for all, I ask for cat.
I think there are a huge number of books that can complement this list. But the story is not about the need to apply this or that approach. Not about how this or that book is good or bad. In the course of reflection, we can conclude that even using all the good practices described in these books does not guarantee you a beautiful code. And that all this can be both to the detriment and for the good. It turns out that if there is no definite "formula for success", then perhaps it is worth starting at least with a sketch of thoughts about what exactly you want to achieve, trying to write beautiful code. We know what code is, but none of us can say what beautiful code is.
No matter how anyone wants to separate programming into a separate independent discipline, it comes down to engineering. Accordingly, general thoughts and ideas in the field of engineering are valid both for the automotive industry and construction, as well as for programming. All this is about the application of scientific knowledge to the creation of something practical, to some extent material (if we are talking about software development, purely philosophical disputes about materiality may arise). From a practical point of view, the simpler the system (design, idea) - the more convenient, easier to work with and maintain it, and the more beautiful it seems.
There are many more similar examples from human life and nature that will be united by a common thought: often a simple solution is the most beautiful. It is at the moment when I find out how simple this or that object seems to be so necessary in life, the thought that it is made beautifully creeps into my head . While we are not talking about aesthetics, exclusively about the “engine compartment” device.
I once stumbled upon the book Kevlin Henney - 97 Things Every Programmer Should Know: Collective Wisdom from the Experts. This book is 97 small chapters written by different people and related only to the fact that they are all about programming. A kind of worldly wisdom from people with extensive programming experience. Immediately make a reservation that such a detailed description is by no means an advertisement. But I can’t mention this book, because one of its chapters calls for thinking that beautiful code is simple code . In general, it is called “Beauty is in Simplicity” (Beauty lies in simplicity). The author begins the chapter with a quote from Plato that all beautiful things are simple:
So, we come to the very question of the beauty of the code. In order to understand as objectively as possible whether beauty is a synonym for simplicity in our question, we should start with a basic concept. Turn to wikipedia for a definition:
I think many will agree that, in addition to practical value, the code (more precisely, the result of its work and the creation process) is creative. The closest creative analogy to software development is the creation of a literary work. These branches of creativity, undoubtedly, have a lot in common. For simplicity, the program code can be compared to a book. Both are simulacrum of thoughts. The only difference is that, roughly speaking, the result of the code is some kind of result on the device’s screen, and the result of reading the book ishallucinationsvisuals, associations and impressions that arise in our minds. When writing books, a large number of rules are taken into account that allow you to correctly format the text. This moment is similar to the rules of a programming language and the compiler / translator / interpreter workflow. The original text of the book undergoes rigorous iterative editing before appearing before the eyes of the reader. But the content is more important. On the other hand, few people can master the most interesting and fascinating book to the end or understand correctly if thoughts are not correctly (read: beautifully) framed in a coherent text.
In the expression of thoughts on paper, it is undoubtedly worth focusing on the rules of the language, as well as on the structure and simplicity of expression. Impressions and thoughts that will be transmitted to the reader, and what images appear in his head, directly depend on this. Everything is a bit more complicated with the code. The end user of our software does not care how beautifully it is written, and what kind of experience the developer gets from working with this code. The end user is only interested in the quality of the released product, how it works, how convenient it is to use it.
Unlike literature, code quality is a characteristic that is important to the developer or team that works on it. It does not have to be developers. The entire team (for example, project managers, bosses and investors) may suffer from an abundance of bugs during development. However, in the case of specialists from other areas, the beauty of the code concerns them only indirectly. First of all, developers become victims of ugly code. Why is it so important to them? Most of the time when developing a product we spend on parsing the code, navigating in it, in search of a place where you need to write or fix the necessary lines.
Everything would be much simpler if one person were involved in the development of a particular product. All source code would be consistent and comprehensible to him. But so that this very software can be developed in real time, rather than decades, a team of several developers is often involved in the development of one software. It makes its own adjustments. For example, the concept of beauty (in particular, the beauty of the code) each developer can have his own. But since the work goes on in teams, standards are set to set up the team to think
more or less the same. This allows us to make it so that when reading the code, the developer can not always understand ^ whether he or someone else wrote the code and who exactly, and gives a sense of community, team integrity. We say “Code of our application”, and not “my piece of code” or “my script”. Roughly speaking, we are trying to get a general idea about the beauty of a group of people connected by one software and most often, nothing more. It turns out that there is subjectivity in the concept of code beauty, but we try to minimize it within the team. But is it possible to make the concept of code beauty completely objective? What are we resorting to in an attempt to achieve objective beauty and how much does it work? To come to the answer to these questions, it is worth considering that little in common that absolutely all people have. Namely: the brain and how it processes information.
On the Internet, you can find countless articles on how the brain works in recognizing information. For example, you can refer to this article.
Our brain processes a huge amount of information and in order to optimize its activity, it uses templates. These patterns are formed in the course of our lives. A good example is the reading process. The more literature a person has read in one language, the higher his reading speed. The more books you read, the more words you read and the more often you come across them. Visual recognition of frequently occurring words is many times faster than reading new terminology (especially this applies to an unfamiliar subject area). The more books one author has read, the faster he will be able to read other works by that author. This is true because each author has a limited vocabulary and writing style.
If you look deeper, then we learn to read from the fact that we are learning the alphabet. More precisely, we learn to recognize written letters, and only then we take up the recognition of words. Another interesting fact is related to the recognition of letters - the speed of recognition of letters by the brain also depends on the font, if we are talking about printed text, or handwriting for handwritten texts. Moreover, when it comes to handwritten texts, the situation can go to the point of absurdity - the handwriting can be so bad that we simply can’t make out what is written (hello to the doctors). The process of teaching a child to read is most likely the life phenomenon that inspired people to come up with neural networks. Those who are interested in this topic can look at materials about how text is recognized using neural network algorithms.
When we read the words, then only at the initial stages we pay attention to all the letters. And they teach us to read accordingly - first by letter, then by syllables and only then by words. There is an interesting study, the thesis of which can answer for itself:
From these facts, it turns out that a good code should consist of templates so that we are comfortable working with it. Such a template can serve as a general style of code in the development team. If the indentation in the code is different for each source file or line in it, then navigating in it will be quite difficult. One more template can be a common tip - program in terms of a subject area (code in terms of domain). This is true because some words may have different meanings depending on the context (a great example is the word “bow” or “castle”).
After thinking about templates, I thought about which code would work the hardest. The thought of obfuscating the code flashed through my head. After all, this is done solely to complicate other programmers understanding of the internal workings of your system. In addition, the obfuscated code most clearly shows the importance of visual perception of the code.
As methods of obfuscation, you can bring this set:
It turns out that beautiful code should be created from simple redundant repetitions . There is even a well-known acronym DRY on this subject - Don’t repeat yourself. However, is this always true if you look at the world wider?
A great example is music. She cannot get around without repetition. It is worth mentioning that there are exceptions to this statement. The simplest example of such an exception is virtuoso solos. They are remembered by fans, despite the fact that they often do not contain repetitions. But in general, the rule works. If you look at the music that is gaining more and more momentum - Rap / Hip-hop - you can most clearly see this. The minus structure almost completely consists of simple short repeating fragments, which far from always characterizes its beauty. As a degenerate example, we can recall the metronome - no one will argue that its uniform and monotonous ticking is an excellent musical composition. Can an increase in the number of repetitions in music be considered its optimization or improvement? You can look at classical music first, full of unexpected moves, unique parts and a small number of repetitions. The current trend is almost independent of the genre, the works have become shorter. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. For this reason, there are many more connoisseurs of popular music than connoisseurs of classics. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. For this reason, there are many more connoisseurs of popular music than connoisseurs of classics. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. That is why there are many more connoisseurs of classic music connoisseurs of popular music.
Another example of this phenomenon of constant repetition and simplification is the game industry. The genre of casual games, flowing smoothly into the genre of hyper-casual, is gaining more and more popularity. These are games aimed at repeating a simple chain of quick actions, strictly limited by a short period of time. While complex variative games and low-repeating games, for example, the genre of strategies, are going through
hard times now.
If there is an example of the inoperability of the simple non-redundant pattern approach, should this approach always work for code?
From the moment of immersion in the profession, complex and intricate, at first glance, principles and approaches are circling around us. Senior specialists, under whose wing we study, talk about various approaches, patterns and books that are worth reading in order to succeed in the field of OOP. I think the most frequently heard words are design patterns and SOLID . By no means does it immediately become clear to everyone why all this is necessary. But the general point is to write beautiful and correct code. And how does this help us, and is it always? All magical patterns and abbreviations are aimed at teaching us to think about programming with the same patterns as when reading and analyzing plain text.
From the very beginning, developers have been taught patterns. Let's try to figure out why. Any design pattern is aimed at making the entity as compact as possible and simple. She did not do what she should not and did what was required of her in the most concise way. All this is not only about making the solution architecturally sustainable, but also about making the solution easy to understand. From project to project, you use approximately the same set of patterns. Frequent repetition of these patterns speeds up the design process and the processing of existing code in the brain, reducing the time it takes to search for a particular piece of code.
By itself, software development for the sake of software development is of no interest to anyone, except for educational purposes, which can be left out of the box. Software development always has some kind of business goal. It is worth noting here that when it comes to business goals, it is not always about money. Perhaps the goal is to earn a reputation, help someone, or just show off to family / friends (“Look, I wrote a game!”) And so on. For the most part, it is a business goal that is fundamental to the choice of application architecture. First, the requirements are analyzed, based on which it can be concluded whether the software will be supported, what will be the development cycle. All these factors are superimposed with information about resources - a team or their own knowledge. All these factors are explicit or implicit (if you are just starting your journey in software development, you don’t have to think about architecture, but you’ll definitely start soon) affect what approaches and patterns you will use during development. Based on the selected architecture, approaches and patterns, a software code base appears.
Before the conversation turned to design patterns, the beauty of the code could be seen in abstract terms. That is, it was possible to hypothetically imagine some source file taken out of context. Guided solely by the visual component of the code, not paying attention to its semantics, we can conclude whether the code is beautiful or not. It is when at one fine moment the abstract source becomes part of the code base (part of something larger, part software), new variables begin to be introduced into the equation of beauty of the code.
Suppose a new developer comes to a project who has never seen the code for this project. First of all, he needs to enter the project, in other words, to study the code base. During the study, the developer will form his opinion about the project, more precisely about what it consists of. And at this moment, the developer may have the following thoughts - “This solution is ugly”, or vice versa “Wow! What an elegant (beautiful) solution ... ". In this case, beauty refers to architecture, which is expressed by means of code. That is, the concept of semantic beauty can also interfere with the concept of code beauty - as far as the decision is correctly architectural. Is the approach or pattern selected correctly and is it sustained.
This is exactly the place where everything becomes most complicated:
In the last two cases, it will be much easier for you to make a conclusion and express your thoughts about the code and its beauty.
It turns out that just for this we are all forced to learn design patterns - so that we all speak the same language, in a standardized way. In addition, a pattern is what our brain likes to work with.
However, we got to the point where everything may not be as simple as it seems. A source file can combine the implementation of several patterns. We omit the question of the correctness of such a solution, it very much depends on the situation and can be both the right and the wrong decision. Diluting the implementation of one template with the implementation of another can complicate the perception of the code, making it ugly in our eyes. An improperly implemented pattern exacerbates the situation. It may seem to you until the very end that you understand the code, since it is subordinate to the pattern, and then it turns out that all this time you perceived it incorrectly. At this moment, a beautiful code loses all its charm and becomes not so beautiful, but rather with a sweetheart. In this case, the lack of a pattern could look prettier, than an incorrectly implemented pattern. Another aspect concerns incorrect approaches or anti-patterns. In essence, an anti-pattern is a pattern that should not be used. Nevertheless, this is a pattern that in a certain way gives readability and comprehensibility, that is, simplicity and beauty to the code. It turns out that the use of patterns in the project code is a double-edged sword.
Speaking about the beautiful design of the API, most often it comes to either some kind of service or a library (or framework). The service most often seems to be something external to the code, so in our context it is better to consider the library. The choice of this or that kind of API will affect not only the structure of the library code, but also the appearance of client code using the library. Offhand I can bring 2 styles.
The classic style is that we frame the library into one specific entity (class) and all the methods that are in this class perform a specific action, returning a specific result that does not depend on the state of the main entity of the library. Most of the various plugins are made in the classical style, so there should be no problem understanding this style.
The second style is fluid interfaces . This approach consists in the fact that at the output of the library we get the same object that triggered the action, only now configured a little differently. An example is the implementation of LINQ in C #. In it, chain actions are performed on the same collection (IEnumerable). At each step of the request, we somehow modify the collection until we get the desired result. Another example from C # is a dependency injection container called Zenject .
In it, dependency binders are written in a fluid style:
In it you can often see such designs:
In most cases, the appropriate style can be chosen based on the current situation. But no one bothers to rewrite the library API from one style to another without changing functionality, and then it becomes a matter of taste or beauty. In general, fluid interfaces are not as common as the classic style, but depending on a large number of factors, they can make the code more beautiful or uglier. It is also impossible to derive a universal formula here.
We have already come to the conclusion that for beauty, we need templates, without them anywhere. Patterns should be recognizable, simple and short. With design patterns, everything turned out to be ambiguous. But in addition to architectural patterns, constructions of the language you are writing also come to the rescue. The same design pattern implemented in one language can look beautiful and ugly depending on specific language tools.
Common for most, if not all programming languages, then for most, a language tool that does not affect the semantics of the code, but affects its beauty is commenting. Adding a good comment in the right place can improve the look and feel of the code. But it's worth writing a comment in isolation from the general style (for example, c-like languages allow you to describe comments in three different ways), as it immediately spoils the overall picture and visually distracts from the perception of the code itself.
As a victim, let's look at some of the tools that C # provides us. One of the simplest tools in this language is the var keyword . It avoids explicitly indicating the type of a variable when it is declared, using var for any type or interface.
On the one hand, this tool helps to remove almost all type names in method bodies. On the other hand, it makes you think about what type this or that variable belongs to. The vast majority of developers who condole with C # consider using var a good practice. That is, this language tool can be considered more useful than harmful in terms of the beauty of the code.
Directive #region #endregionallows you to specify blocks of code that can be collapsed in the IDE. It is one of the most controversial tools. In some teams, the use of this directive is strictly forbidden, in others it is advised on a mandatory basis. One argument for not using this directive is that it dilutes the code with semantically useless inserts that prevent you from concentrating on the code itself. As an argument “for”, one can cite a practice where class methods are grouped by region in such a way that you can easily and without editing the code see its internal implementation, or an external API, or an implementation of a pattern (which can often look template and it is removed to the region so that the eyes do not callus). Summing up, we can say that the tool is more than controversial.
The final tool to consider for sure is lambda expressions and anonymous methods. In general terms, we can say that both tools are designed to describe the method as compactly as possible, often without explicitly declaring it. For these purposes, we can come to the rescue with such features as lowering the signature, types of input and output parameters, forcing the compiler to display all this explicitly for us. The tool, which many tend to consider an integral part of the language, however, has the most controversial position in terms of the beauty of the code. For example, LINQ is hard to imagine without lambda expressions; they are compact and concise. But if you abuse their use, all the code in the class can easily be turned into an unreadable mess.
Such language tools as extension methods (extension methods), foreach vs for, anonymous methods, ternary operator, chaining of constructors and others remain outside the scope of the analysis. All of them are also united by the controversial use in certain parts of the code. From this we can conclude that there is no perfect syntactic sugar, which makes the code undeniably more beautiful.
As an additional material on the topic of syntactic sugar, I can not miss the young programming language - Swift. For the most part, it does not offer unique language constructs. However, its ability to omit the ";" at the end of the line of code, I was most ripped apart by my current notion of the process of writing code. I know that in the usual reading of this feature, it is not perceived as something out of the ordinary. But during the combat development in this language, at first it was rather difficult to rebuild. Do not write ";" at the end of a line of code is the recommended practice in this language. It would seem that this is a real trifle, but you can also draw a parallel with it outside the programming context. This parallel lies in the punctuation rules of most languages of the world. We are used to putting dots at the end of a sentence, over the years forming a pattern for recognizing complete thoughts in a text. Perhaps in a simple opportunity to omit ";" a hidden rule is hidden in the code, which can be expressed as follows: write only one code deadline on one line of the source code file. And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operator And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operator And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operatorguard .
If it is about ";" at the end of a line of code, it's hard not to mention the Python language. This language is replete with all kinds of syntactic sugar. A considerable part of this sugar is controversial, even, if I may say so, clearly not necessary, only complicating the reading of the code. However, all this is ambiguous in the context of the fact that the threshold for entering the language is extremely low. It seems that the developers of the language have made every effort to ensure that you can write code in Python, paying as little attention to the syntax as possible. Another of the features of this language, I would note the absence of explicit allocation of code blocks (the brackets "{}" are not used). Instead of explicitly highlighting Python lives indented. On the one hand, this is better perceived visually, because the text has fewer meaningless service characters. On the other hand, you have to pay attention to the indentation, which in most languages is clearly not necessary. This language could not do without breaks of C-patterns. Instead of a try-catch statement, we have try-except. By name, the operator looks logical, but it’s difficult to rebuild.
As the last controversial example of a language tool that is found in many languages, I will give generalized classes and methods (Generics). Generalizations per se are designed to save us from having to duplicate heavily boilerplate code. That is, at least in terms of getting rid of code duplication in different places, generalizations serve as a tool to make the code more beautiful. But the very concept of a type parameterized by another type is perceived rather difficult. Each time, bumping into generalization in code, one has to spend more time on understanding semantics than on understanding semantics of non-generalized code.
Given the points indicated above, it can be argued that syntactic sugar is also a controversial tool that can make the code more and less beautiful.
The whole subjectivity of the approach to writing code and the concept of its beauty can be confusing. This problem is especially acute in a situation when a new developer comes to a well-coordinated team. Often, a novice has no choice but to mimic the code already written and adjust in the course to the existing style. This is what most people do not like when they come to a new job. All your patterns of perception, neural chains, reflexes that have formed over the years of experience, begin to do harm instead of past benefits. Fortunately, at least in this area it is possible to introduce a few general practices, free from subjectivity.
Moreover, we have been thought and taken care of for this for a long time. Modern IDEs have gone far from conventional text editors and can greatly facilitate the task of maintaining a code style. Syntax highlighting is perhaps the oldest tool in the IDE's inventory. Despite its simplicity and familiarity, the idea in it is the same - to form a certain template that helps to write code. The simplest example is underlining a certain word in the code in red on error. In addition, many dubious places that you should pay attention to are marked in yellow. All this together is a template that has been formed in our head since childhood since using a traffic light.
In terms of code beauty, modern IDEs are also trying to help as they can. For example, you can take a fairly young IDE from JetBrains - Rider. Here, simplification of logical conditions, and help in choosing a variable name, spell checking in comments and variable names, automatic alignment and much more come to the rescue.
As for naming variables, aligning the code, inserting tabs instead of spaces and spaces in the merged code - this is all the main point that helps to design the text as code in a style that suits you. And the IDE will make most of these edits in the background for you. It turns out that you just need to teach her what you want, and subsequently it will become an indispensable assistant for you, which will save you a lot of time. The details of teaching your IDE your style are not relevant to the subject of this article. But if you think about this concept as a whole, the process turns out to be very similar to the process of introducing a new developer into the team. An indispensable tool for this is a code style agreement document. The only difference is that the developer will receive it in the form of a document,
Thus, the undeniable step towards a beautiful code is its standardization. A lot of it companies around the world neglect writing a document that standardizes the style of code. It happens that a catastrophe takes on terrifying proportions - the number of projects being simultaneously developed in the company is equal to the number of coding styles used within the company. In such circumstances, the transition of a developer from one project to another becomes even more non-trivial. If nobody monitors the standardization of the code base, then the code tends to turn into a bulk code, and adaptation on a new project feels like moving to another company, causing more stress than it could. Along with the increase in stress during the transition to a new project, the adaptation period also increases.
Such problems can be avoided by having in stock just a document with a code style convention. This document can also be considered a development tool. Having such a document and a modern IDE in your arsenal, you can greatly simplify your life by automating the code style at the IDE level. This will reduce the threshold for the developer to join the team and reduce the number of complaints to the developer during the code-review. The idea of automating and using development tools to the maximum is far from new, it can be found in many sources, including the legendary book "Programmer-pragmatist."
To summarize: development tools have an exceptionally positive effect on the beauty of the code. Moreover, the factor of subjectivity does not affect the usefulness of these tools.
We have already familiarized ourselves with the good software part. But are all the technical solutions aimed at making the code more beautiful? It so happens that when a product is almost ready for release, it turns out that it does not correspond to the technical characteristics of a particular device, which is so important for us to support. This problem is especially acute in the field of game software development. Someone may have reasonably reasonable objections that you can immediately write optimal software and do optimization during development, achieving the most optimal solution. To such objections can be cited a counter-argument:
The debate about whether this statement is true or not does not concern the beauty of the code and is beyond the scope of current reasoning.
But optimization can adversely affect the beauty of the code. This does not always happen, but there are some practices that can most likely be expressed in far from the most readable code. Examples of such optimizations:
These optimizations are quite difficult to implement, but are necessary in the development of high performance computing and in a number of other situations. But, for example, excessive use of multi-threaded interaction tends to greatly complicate the code. We get a situation where the beauty of the code can be sacrificed for technical optimization.
We decided that regardless of the subjectivity of the concept of the beauty of code, there are practices that help maintain it - a document on the style of code and a properly configured IDE. This bundle can really make life easier, but it cannot guarantee a 100% result. The reason for this is the human factor. The developer may be familiar with the code style document, have a properly configured IDE, and yet ignore all the rules and warnings of the IDE. There may be at least 2 reasons for this:
It doesn’t matter what reason prompted the developer to write an ugly code and fill it into a common code base. At the same time, as soon as such an amendment enters the release, it is likely that it will remain in such an ugly form. It would seem that what could go wrong if we all understand that this happens only in exceptional situations and that this cannot be done? The essence of the problem is that this is the precedent that has taken place. This means that it is very likely that after some time, when everyone forgets the context of the situation that has taken place, some developer will stumble upon this ugly piece of code during the work. Then wrong thoughts may creep into his head that if this is already in the project, then adding one more portion will not get any worse. The recipe for disaster is simple - repeat the last action n times,
Such an effect is very well described in Broken Window Theory . You can deal with broken windows quite simply - we just need a security guard who will monitor the code. Regarding programming, such a solution fits well with the concept of code-review. I can not name a single bad side effect of the practice of conducting regular code-reviews. The only thing that leading people can touch is the waste of a significant amount of time on conducting a code-review and correcting comments on it. It can be difficult for such people to explain what technical debt is and where it comes from. But in the context of the beauty of code, code-review is a purely positive practice.
In addition to the person who conducts the code-review on the project (or several people), you can also contact the developers of the language or the programming guru for advice. Of course, you should not rely on the fact that you can write a letter or call directly by this very guru. But for most programming languages, there are official or generally accepted
code style standards written by reputable people. Examples:
Following generally accepted code style standards is good practice to help keep your code beautiful. Although subjectivity is also present in generally accepted standards, it is not possible to conclude that code written by common standards will be beautiful.
All considered thoughts on the beauty of the code lead exclusively to its subjectivity, even in terms of its simplicity. Simplicity, in turn, stems from how easy it is to understand the code and how compact it is (or vice versa). All the described tools, the choice between this or that approach form a handwriting, giving recognition and support from other developers. At the same time, it turns out that the concept of beauty in code still lends itself to some, albeit very weak, standardization. In general terms, we can assume that the patterning is more correlated with the beauty of the code, although variations are possible here.
Reaching a consensus among all the developers of the world may never succeed. But it’s worthwhile to approach the conclusion of the concept of code beauty. Perhaps, thinking about why you prefer to write one way or another, you will begin to write more readable code and express your thoughts in the code more clearly. Or, such an understanding will help you take the choice in the direction of a certain of the existing styles.
Disclaimer:This article aims to share thoughts that arose in the process of trying to comprehend the concept of beautiful code. These thoughts do not claim to be the ultimate truth. I only hope that these thoughts, reflections and arguments will probably help someone to look at the process of writing code from a slightly different perspective. Further, not a single formal rule of the form "Write the code this way, and you will be happy." A large volume of literature from much more respected authors has already been written on this topic.
All interested in discussions on the topic of what code beauty is, what it can be expressed in, why all well-known practices are not able to close this question once and for all, I ask for cat.
Good and bad practices
"... and asked the baby: - What is good and what is bad?" - Mayakovsky V.V.And we often wonder how to properly format our code. In order to answer this question, a large amount of professional literature has already been written in the world. Take, for example, the most popular works on this subject, which are most widely heard:
- Clean Code - Robert C. Martin
- Perfect Code. Master Class - Steve McConnell
- Receptions of Object Oriented Programming. Design Patterns - Gang of Four
- The pragmatic programmer. The journey from apprentice to master - Andrew Hunt, David Thomas
I think there are a huge number of books that can complement this list. But the story is not about the need to apply this or that approach. Not about how this or that book is good or bad. In the course of reflection, we can conclude that even using all the good practices described in these books does not guarantee you a beautiful code. And that all this can be both to the detriment and for the good. It turns out that if there is no definite "formula for success", then perhaps it is worth starting at least with a sketch of thoughts about what exactly you want to achieve, trying to write beautiful code. We know what code is, but none of us can say what beautiful code is.
Prerequisites for thoughts
No matter how anyone wants to separate programming into a separate independent discipline, it comes down to engineering. Accordingly, general thoughts and ideas in the field of engineering are valid both for the automotive industry and construction, as well as for programming. All this is about the application of scientific knowledge to the creation of something practical, to some extent material (if we are talking about software development, purely philosophical disputes about materiality may arise). From a practical point of view, the simpler the system (design, idea) - the more convenient, easier to work with and maintain it, and the more beautiful it seems.
An explanation of this thought is an example from the automotive industry.
Возьмем пример из автомобилестроения. На данный момент мы имеем большой выбор автомобилей различной ценовой категории и характеристик, а также внутреннего устройства агрегатов. Давайте отбросим в сторону все мысли об экономической составляющей (стоимости, PR, маркетинга и прочего), и попробуем оценить текущую ситуацию на рынке автомобилей с точки зрения надежности. Сузив область рассуждений — ограничимся оценкой силового агрегата. Это касается, к примеру, двигателей автомобилей. На данный момент люди изобрели уже множество различных типов двигателей, каждый из которых хорош в своей области. В принципах их работы лежат простые мысли о расположении поршней, цилиндров, их количестве и объеме. Все это в той или иной степени сказывается лишь на 2 показателях — надежности и мощности. Текущие реалии таковы, что самым надежным решением является использование большого атмосферного агрегата. Турбированные двигатели имеют меньший размер по сравнению с атмосферными решениями, однако подразумевают использование отдельного узла для подачи воздуха (турбины), что усложняет систему в целом. Кроме того, так как сам по себе двигатель меньшего размера, в компании с турбиной он может выдавать столько же или даже больше мощности, чем атмосферный двигатель размером в 2 или 3 раза больше. Это достигается за счет того, что двигатель, выдавая большую мощность, работает на пределе возможностей. В то же время, большой атмосферный двигатель выдает примерно ту же мощность, но проще в устройстве и гораздо более ресурсный. То есть более простое решение является в тоже время наиболее прагматичным.
Explanation of this thought by an example from nature
Еще один простой пример можно взять из природы. С момента своего появления на планете пчелы строят ульи. Ульи считаются самыми совершенными постройками насекомых. Все дело в том, каким образом пчелы строят соты. Для строительства сот используется минимум материала — воска, который выложен самым оптимальным образом — в форме шестигранников. Тут мы снова можем наблюдать триумф простоты. Вместо того, чтобы использовать более крепкие материалы или более сложные конструкции (которые наверняка потребуют каких-то вспомогательных колонн, опор и так далее), используется простой материал и простая, но самая совершенная форма в достижении наиболее прагматичного и изящного решения. Свидетельств тому, что такое решение является красивым, целое множество. Взять, к примеру, 3D-печать. Любой человек, мало-мальски интересующийся 3D принтерами, знает, что принтеры печатают модели, внутри которых сотовая структура, которую мы подсмотрели у пчел.
Explanation of this idea by an example from mathematics
В этом примере простота может быть не столь очевидна. Многие люди, в основном, не технического склада ума, считают математику сложной и по большей части бесполезной. Основная идея, давшая основу всей математике — мысль о том, что все жизненные ситуации можно смоделировать. При этом стоит учесть, что зачастую полученная модель гораздо проще и менее детальна, чем реальный жизненный процесс. Простейший пример — допустим, у пастуха есть стадо овец. Но день выдался тяжелый, и он уснул на работе, а проснувшись, подумал, что нужно убедиться в том, что все овцы на месте. В этот момент на помощь ему может прийти самый древний математический аппарат — цифры. Сами по себе, цифры не значат ничего. В абстрактной цифре, в отрыве от реальности смысла не больше, чем в попытке одеть штаны через голову. Но касаемо ситуации определения количества объектов им нет равных.
Приведу более сложный пример. В моей университетской программе был крайне полезный предмет, который назывался «Комбинаторные алгоритмы». Большая часть этого курса была посвящена изучению теории графов и различных алгоритмов на графах. Разговоры о теории графов уже были ранее на других предметах, но исключительно поверхностно. То есть все мои одногруппники уже представляли, что это такое, и с чем это есть. Кто-то даже делал лабораторные работы по реализации какого-либо алгоритма на графах. Но именно на одной из пар по комбинаторным алгоритмам преподаватель неожиданно спросил: «А кто может сказать, зачем вообще нужны эти графы?». Как ни странно, ответить не смог никто из группы, повисло гробовое молчание. Ответ был очевиден и прост — графы нужны для моделирования. Сами по себе графы никому не нужны, как и умение реализовать обход в ширину или глубину. Но, в применении ко многим жизненным ситуациям, бывает крайне удобно отказаться от кучи ненужных деталей и оставить только абстрактную суть.
Приведу более сложный пример. В моей университетской программе был крайне полезный предмет, который назывался «Комбинаторные алгоритмы». Большая часть этого курса была посвящена изучению теории графов и различных алгоритмов на графах. Разговоры о теории графов уже были ранее на других предметах, но исключительно поверхностно. То есть все мои одногруппники уже представляли, что это такое, и с чем это есть. Кто-то даже делал лабораторные работы по реализации какого-либо алгоритма на графах. Но именно на одной из пар по комбинаторным алгоритмам преподаватель неожиданно спросил: «А кто может сказать, зачем вообще нужны эти графы?». Как ни странно, ответить не смог никто из группы, повисло гробовое молчание. Ответ был очевиден и прост — графы нужны для моделирования. Сами по себе графы никому не нужны, как и умение реализовать обход в ширину или глубину. Но, в применении ко многим жизненным ситуациям, бывает крайне удобно отказаться от кучи ненужных деталей и оставить только абстрактную суть.
There are many more similar examples from human life and nature that will be united by a common thought: often a simple solution is the most beautiful. It is at the moment when I find out how simple this or that object seems to be so necessary in life, the thought that it is made beautifully creeps into my head . While we are not talking about aesthetics, exclusively about the “engine compartment” device.
I once stumbled upon the book Kevlin Henney - 97 Things Every Programmer Should Know: Collective Wisdom from the Experts. This book is 97 small chapters written by different people and related only to the fact that they are all about programming. A kind of worldly wisdom from people with extensive programming experience. Immediately make a reservation that such a detailed description is by no means an advertisement. But I can’t mention this book, because one of its chapters calls for thinking that beautiful code is simple code . In general, it is called “Beauty is in Simplicity” (Beauty lies in simplicity). The author begins the chapter with a quote from Plato that all beautiful things are simple:
Beauty of style and harmony and grace and good rhythm depend on simplicity - PlatoIt was this aphorism that further sparked my interest in the field of beautiful code and the applicability of the concept of a “beautiful solution” to code, and as a result, the equivalence of a beautiful code to simple.
What is beauty?
So, we come to the very question of the beauty of the code. In order to understand as objectively as possible whether beauty is a synonym for simplicity in our question, we should start with a basic concept. Turn to wikipedia for a definition:
Beauty is an aesthetic category denoting perfection, a harmonious combination of aspects of an object, in which the latter evokes aesthetic pleasure in the observer.Speaking of code, we cannot reason exclusively from an aesthetic point of view. A beautiful (perfect, good) code combines both aesthetics and semantics. The semantics of the code should also fall into the category of “beautiful solutions”.
I think many will agree that, in addition to practical value, the code (more precisely, the result of its work and the creation process) is creative. The closest creative analogy to software development is the creation of a literary work. These branches of creativity, undoubtedly, have a lot in common. For simplicity, the program code can be compared to a book. Both are simulacrum of thoughts. The only difference is that, roughly speaking, the result of the code is some kind of result on the device’s screen, and the result of reading the book is
Why is beautiful code important?
In the expression of thoughts on paper, it is undoubtedly worth focusing on the rules of the language, as well as on the structure and simplicity of expression. Impressions and thoughts that will be transmitted to the reader, and what images appear in his head, directly depend on this. Everything is a bit more complicated with the code. The end user of our software does not care how beautifully it is written, and what kind of experience the developer gets from working with this code. The end user is only interested in the quality of the released product, how it works, how convenient it is to use it.
Unlike literature, code quality is a characteristic that is important to the developer or team that works on it. It does not have to be developers. The entire team (for example, project managers, bosses and investors) may suffer from an abundance of bugs during development. However, in the case of specialists from other areas, the beauty of the code concerns them only indirectly. First of all, developers become victims of ugly code. Why is it so important to them? Most of the time when developing a product we spend on parsing the code, navigating in it, in search of a place where you need to write or fix the necessary lines.
Everything would be much simpler if one person were involved in the development of a particular product. All source code would be consistent and comprehensible to him. But so that this very software can be developed in real time, rather than decades, a team of several developers is often involved in the development of one software. It makes its own adjustments. For example, the concept of beauty (in particular, the beauty of the code) each developer can have his own. But since the work goes on in teams, standards are set to set up the team to think
more or less the same. This allows us to make it so that when reading the code, the developer can not always understand ^ whether he or someone else wrote the code and who exactly, and gives a sense of community, team integrity. We say “Code of our application”, and not “my piece of code” or “my script”. Roughly speaking, we are trying to get a general idea about the beauty of a group of people connected by one software and most often, nothing more. It turns out that there is subjectivity in the concept of code beauty, but we try to minimize it within the team. But is it possible to make the concept of code beauty completely objective? What are we resorting to in an attempt to achieve objective beauty and how much does it work? To come to the answer to these questions, it is worth considering that little in common that absolutely all people have. Namely: the brain and how it processes information.
What is the brain doing the best?
On the Internet, you can find countless articles on how the brain works in recognizing information. For example, you can refer to this article.
Our brain processes a huge amount of information and in order to optimize its activity, it uses templates. These patterns are formed in the course of our lives. A good example is the reading process. The more literature a person has read in one language, the higher his reading speed. The more books you read, the more words you read and the more often you come across them. Visual recognition of frequently occurring words is many times faster than reading new terminology (especially this applies to an unfamiliar subject area). The more books one author has read, the faster he will be able to read other works by that author. This is true because each author has a limited vocabulary and writing style.
If you look deeper, then we learn to read from the fact that we are learning the alphabet. More precisely, we learn to recognize written letters, and only then we take up the recognition of words. Another interesting fact is related to the recognition of letters - the speed of recognition of letters by the brain also depends on the font, if we are talking about printed text, or handwriting for handwritten texts. Moreover, when it comes to handwritten texts, the situation can go to the point of absurdity - the handwriting can be so bad that we simply can’t make out what is written (hello to the doctors). The process of teaching a child to read is most likely the life phenomenon that inspired people to come up with neural networks. Those who are interested in this topic can look at materials about how text is recognized using neural network algorithms.
When we read the words, then only at the initial stages we pay attention to all the letters. And they teach us to read accordingly - first by letter, then by syllables and only then by words. There is an interesting study, the thesis of which can answer for itself:
According to the rzelulattas, the ilseovadny odongo of the anligisok unviertiseta has no work, in cocoons the pumpkins in the solva are dehydrated in cocoons. Galvone, chopping and slapping bkvuy blyu on msete. In the past, the bkuvs can be sealed in a completely bosom, all-torn text reads without a brem. Pichriony Egoto, it’s because we don’t make every single pumpkin separately, but it’s all solid.And this is another proof that the brain works with patterns. All the new information that we receive from the brain is also trying to drive through existing templates, resorting to 3 basic principles:
- deletion - we delete from memory unused unique (least template) information
- distortion - refers to exaggeration or understatement of something. For example, in our everyday life the words “never”, “always”, “nothing”, “all”, “all” are often used. If you think about it, then every use of such a word is a lie or a distortion of facts.
- generalization - all new information is trying to be reduced by the brain to something with which it has already worked. On analogies, it’s easier to remember and remember.
From these facts, it turns out that a good code should consist of templates so that we are comfortable working with it. Such a template can serve as a general style of code in the development team. If the indentation in the code is different for each source file or line in it, then navigating in it will be quite difficult. One more template can be a common tip - program in terms of a subject area (code in terms of domain). This is true because some words may have different meanings depending on the context (a great example is the word “bow” or “castle”).
From the contrary
After thinking about templates, I thought about which code would work the hardest. The thought of obfuscating the code flashed through my head. After all, this is done solely to complicate other programmers understanding of the internal workings of your system. In addition, the obfuscated code most clearly shows the importance of visual perception of the code.
As methods of obfuscation, you can bring this set:
- Long and meaningless names of variables, classes, methods and functions. Not only is long words harder to read, but you have never seen such combinations of letters and numbers in your life.
- Spaces, indents and line breaks are completely removed. In this case, we are apparently just a mishmash of letters, numbers and symbols. In the worst case, it can be a whole screen without a single free space. Then you have to parse this text character by character, which will take a breakthrough of time. In addition, at the end of the day of working with such a code, you will feel exhausted and tired. Someone will say that his brain exploded.
- It is possible that calls to some methods or functions will be replaced by their source code. A little weird moment. In fact, these are disfigured huge patterns, but with the condition of their meaningless repetition. Makes text extremely redundant. As long as you recognize the huge pattern, thoughts about the previous context have already left your brain.
It turns out that beautiful code should be created from simple redundant repetitions . There is even a well-known acronym DRY on this subject - Don’t repeat yourself. However, is this always true if you look at the world wider?
A great example is music. She cannot get around without repetition. It is worth mentioning that there are exceptions to this statement. The simplest example of such an exception is virtuoso solos. They are remembered by fans, despite the fact that they often do not contain repetitions. But in general, the rule works. If you look at the music that is gaining more and more momentum - Rap / Hip-hop - you can most clearly see this. The minus structure almost completely consists of simple short repeating fragments, which far from always characterizes its beauty. As a degenerate example, we can recall the metronome - no one will argue that its uniform and monotonous ticking is an excellent musical composition. Can an increase in the number of repetitions in music be considered its optimization or improvement? You can look at classical music first, full of unexpected moves, unique parts and a small number of repetitions. The current trend is almost independent of the genre, the works have become shorter. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. For this reason, there are many more connoisseurs of popular music than connoisseurs of classics. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. For this reason, there are many more connoisseurs of popular music than connoisseurs of classics. They are now called songs and they are completely stereotyped in terms of structure - there is an introduction, a refrain, a simple keynote. We take these components in various variations and combinations and get a more or less universal formula. Such works are easier to "go" to the audience. That is why there are many more connoisseurs of classic music connoisseurs of popular music.
Another example of this phenomenon of constant repetition and simplification is the game industry. The genre of casual games, flowing smoothly into the genre of hyper-casual, is gaining more and more popularity. These are games aimed at repeating a simple chain of quick actions, strictly limited by a short period of time. While complex variative games and low-repeating games, for example, the genre of strategies, are going through
hard times now.
If there is an example of the inoperability of the simple non-redundant pattern approach, should this approach always work for code?
How to achieve simple OOP code and what can help with this?
From the moment of immersion in the profession, complex and intricate, at first glance, principles and approaches are circling around us. Senior specialists, under whose wing we study, talk about various approaches, patterns and books that are worth reading in order to succeed in the field of OOP. I think the most frequently heard words are design patterns and SOLID . By no means does it immediately become clear to everyone why all this is necessary. But the general point is to write beautiful and correct code. And how does this help us, and is it always? All magical patterns and abbreviations are aimed at teaching us to think about programming with the same patterns as when reading and analyzing plain text.
Are design patterns always good?
From the very beginning, developers have been taught patterns. Let's try to figure out why. Any design pattern is aimed at making the entity as compact as possible and simple. She did not do what she should not and did what was required of her in the most concise way. All this is not only about making the solution architecturally sustainable, but also about making the solution easy to understand. From project to project, you use approximately the same set of patterns. Frequent repetition of these patterns speeds up the design process and the processing of existing code in the brain, reducing the time it takes to search for a particular piece of code.
By itself, software development for the sake of software development is of no interest to anyone, except for educational purposes, which can be left out of the box. Software development always has some kind of business goal. It is worth noting here that when it comes to business goals, it is not always about money. Perhaps the goal is to earn a reputation, help someone, or just show off to family / friends (“Look, I wrote a game!”) And so on. For the most part, it is a business goal that is fundamental to the choice of application architecture. First, the requirements are analyzed, based on which it can be concluded whether the software will be supported, what will be the development cycle. All these factors are superimposed with information about resources - a team or their own knowledge. All these factors are explicit or implicit (if you are just starting your journey in software development, you don’t have to think about architecture, but you’ll definitely start soon) affect what approaches and patterns you will use during development. Based on the selected architecture, approaches and patterns, a software code base appears.
Before the conversation turned to design patterns, the beauty of the code could be seen in abstract terms. That is, it was possible to hypothetically imagine some source file taken out of context. Guided solely by the visual component of the code, not paying attention to its semantics, we can conclude whether the code is beautiful or not. It is when at one fine moment the abstract source becomes part of the code base (part of something larger, part software), new variables begin to be introduced into the equation of beauty of the code.
Suppose a new developer comes to a project who has never seen the code for this project. First of all, he needs to enter the project, in other words, to study the code base. During the study, the developer will form his opinion about the project, more precisely about what it consists of. And at this moment, the developer may have the following thoughts - “This solution is ugly”, or vice versa “Wow! What an elegant (beautiful) solution ... ". In this case, beauty refers to architecture, which is expressed by means of code. That is, the concept of semantic beauty can also interfere with the concept of code beauty - as far as the decision is correctly architectural. Is the approach or pattern selected correctly and is it sustained.
This is exactly the place where everything becomes most complicated:
- If you are not familiar with this or that approach, then its idea may not be obvious, incomprehensible and perceived in a negative context or positive. Such a case is the most unpredictable.
- You may be familiar with the approach and perceive it negatively, for example, anti-patterns.
- You may be familiar with the approach and take it positively.
In the last two cases, it will be much easier for you to make a conclusion and express your thoughts about the code and its beauty.
It turns out that just for this we are all forced to learn design patterns - so that we all speak the same language, in a standardized way. In addition, a pattern is what our brain likes to work with.
However, we got to the point where everything may not be as simple as it seems. A source file can combine the implementation of several patterns. We omit the question of the correctness of such a solution, it very much depends on the situation and can be both the right and the wrong decision. Diluting the implementation of one template with the implementation of another can complicate the perception of the code, making it ugly in our eyes. An improperly implemented pattern exacerbates the situation. It may seem to you until the very end that you understand the code, since it is subordinate to the pattern, and then it turns out that all this time you perceived it incorrectly. At this moment, a beautiful code loses all its charm and becomes not so beautiful, but rather with a sweetheart. In this case, the lack of a pattern could look prettier, than an incorrectly implemented pattern. Another aspect concerns incorrect approaches or anti-patterns. In essence, an anti-pattern is a pattern that should not be used. Nevertheless, this is a pattern that in a certain way gives readability and comprehensibility, that is, simplicity and beauty to the code. It turns out that the use of patterns in the project code is a double-edged sword.
API Writing Style
Speaking about the beautiful design of the API, most often it comes to either some kind of service or a library (or framework). The service most often seems to be something external to the code, so in our context it is better to consider the library. The choice of this or that kind of API will affect not only the structure of the library code, but also the appearance of client code using the library. Offhand I can bring 2 styles.
The classic style is that we frame the library into one specific entity (class) and all the methods that are in this class perform a specific action, returning a specific result that does not depend on the state of the main entity of the library. Most of the various plugins are made in the classical style, so there should be no problem understanding this style.
The second style is fluid interfaces . This approach consists in the fact that at the output of the library we get the same object that triggered the action, only now configured a little differently. An example is the implementation of LINQ in C #. In it, chain actions are performed on the same collection (IEnumerable). At each step of the request, we somehow modify the collection until we get the desired result. Another example from C # is a dependency injection container called Zenject .
In it, dependency binders are written in a fluid style:
Container.Bind<Foo>().AsSingle().NonLazy().FromInstance(FooInstance");
A very famous example of a fluid interface from Swift is the popular Alamofire framework . In it you can often see such designs:
Alamofire.request(
.GET, "http:foo.com", parameters: ["include_docs": "true"],encoding: .URL).validate().responseJSON { (response) -> Voidin... }
In most cases, the appropriate style can be chosen based on the current situation. But no one bothers to rewrite the library API from one style to another without changing functionality, and then it becomes a matter of taste or beauty. In general, fluid interfaces are not as common as the classic style, but depending on a large number of factors, they can make the code more beautiful or uglier. It is also impossible to derive a universal formula here.
Language beauty products
We have already come to the conclusion that for beauty, we need templates, without them anywhere. Patterns should be recognizable, simple and short. With design patterns, everything turned out to be ambiguous. But in addition to architectural patterns, constructions of the language you are writing also come to the rescue. The same design pattern implemented in one language can look beautiful and ugly depending on specific language tools.
Common for most, if not all programming languages, then for most, a language tool that does not affect the semantics of the code, but affects its beauty is commenting. Adding a good comment in the right place can improve the look and feel of the code. But it's worth writing a comment in isolation from the general style (for example, c-like languages allow you to describe comments in three different ways), as it immediately spoils the overall picture and visually distracts from the perception of the code itself.
As a victim, let's look at some of the tools that C # provides us. One of the simplest tools in this language is the var keyword . It avoids explicitly indicating the type of a variable when it is declared, using var for any type or interface.
On the one hand, this tool helps to remove almost all type names in method bodies. On the other hand, it makes you think about what type this or that variable belongs to. The vast majority of developers who condole with C # consider using var a good practice. That is, this language tool can be considered more useful than harmful in terms of the beauty of the code.
Directive #region #endregionallows you to specify blocks of code that can be collapsed in the IDE. It is one of the most controversial tools. In some teams, the use of this directive is strictly forbidden, in others it is advised on a mandatory basis. One argument for not using this directive is that it dilutes the code with semantically useless inserts that prevent you from concentrating on the code itself. As an argument “for”, one can cite a practice where class methods are grouped by region in such a way that you can easily and without editing the code see its internal implementation, or an external API, or an implementation of a pattern (which can often look template and it is removed to the region so that the eyes do not callus). Summing up, we can say that the tool is more than controversial.
The final tool to consider for sure is lambda expressions and anonymous methods. In general terms, we can say that both tools are designed to describe the method as compactly as possible, often without explicitly declaring it. For these purposes, we can come to the rescue with such features as lowering the signature, types of input and output parameters, forcing the compiler to display all this explicitly for us. The tool, which many tend to consider an integral part of the language, however, has the most controversial position in terms of the beauty of the code. For example, LINQ is hard to imagine without lambda expressions; they are compact and concise. But if you abuse their use, all the code in the class can easily be turned into an unreadable mess.
Such language tools as extension methods (extension methods), foreach vs for, anonymous methods, ternary operator, chaining of constructors and others remain outside the scope of the analysis. All of them are also united by the controversial use in certain parts of the code. From this we can conclude that there is no perfect syntactic sugar, which makes the code undeniably more beautiful.
As an additional material on the topic of syntactic sugar, I can not miss the young programming language - Swift. For the most part, it does not offer unique language constructs. However, its ability to omit the ";" at the end of the line of code, I was most ripped apart by my current notion of the process of writing code. I know that in the usual reading of this feature, it is not perceived as something out of the ordinary. But during the combat development in this language, at first it was rather difficult to rebuild. Do not write ";" at the end of a line of code is the recommended practice in this language. It would seem that this is a real trifle, but you can also draw a parallel with it outside the programming context. This parallel lies in the punctuation rules of most languages of the world. We are used to putting dots at the end of a sentence, over the years forming a pattern for recognizing complete thoughts in a text. Perhaps in a simple opportunity to omit ";" a hidden rule is hidden in the code, which can be expressed as follows: write only one code deadline on one line of the source code file. And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operator And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operator And this recommendation is expressed ultimately in the form of practice not to put ";" at the end of the line, not giving the opportunity to add something else to this line. However, Swift also has successful syntax innovations, for example, the operatorguard .
If it is about ";" at the end of a line of code, it's hard not to mention the Python language. This language is replete with all kinds of syntactic sugar. A considerable part of this sugar is controversial, even, if I may say so, clearly not necessary, only complicating the reading of the code. However, all this is ambiguous in the context of the fact that the threshold for entering the language is extremely low. It seems that the developers of the language have made every effort to ensure that you can write code in Python, paying as little attention to the syntax as possible. Another of the features of this language, I would note the absence of explicit allocation of code blocks (the brackets "{}" are not used). Instead of explicitly highlighting Python lives indented. On the one hand, this is better perceived visually, because the text has fewer meaningless service characters. On the other hand, you have to pay attention to the indentation, which in most languages is clearly not necessary. This language could not do without breaks of C-patterns. Instead of a try-catch statement, we have try-except. By name, the operator looks logical, but it’s difficult to rebuild.
As the last controversial example of a language tool that is found in many languages, I will give generalized classes and methods (Generics). Generalizations per se are designed to save us from having to duplicate heavily boilerplate code. That is, at least in terms of getting rid of code duplication in different places, generalizations serve as a tool to make the code more beautiful. But the very concept of a type parameterized by another type is perceived rather difficult. Each time, bumping into generalization in code, one has to spend more time on understanding semantics than on understanding semantics of non-generalized code.
Given the points indicated above, it can be argued that syntactic sugar is also a controversial tool that can make the code more and less beautiful.
The software side that can help us
The whole subjectivity of the approach to writing code and the concept of its beauty can be confusing. This problem is especially acute in a situation when a new developer comes to a well-coordinated team. Often, a novice has no choice but to mimic the code already written and adjust in the course to the existing style. This is what most people do not like when they come to a new job. All your patterns of perception, neural chains, reflexes that have formed over the years of experience, begin to do harm instead of past benefits. Fortunately, at least in this area it is possible to introduce a few general practices, free from subjectivity.
Moreover, we have been thought and taken care of for this for a long time. Modern IDEs have gone far from conventional text editors and can greatly facilitate the task of maintaining a code style. Syntax highlighting is perhaps the oldest tool in the IDE's inventory. Despite its simplicity and familiarity, the idea in it is the same - to form a certain template that helps to write code. The simplest example is underlining a certain word in the code in red on error. In addition, many dubious places that you should pay attention to are marked in yellow. All this together is a template that has been formed in our head since childhood since using a traffic light.
In terms of code beauty, modern IDEs are also trying to help as they can. For example, you can take a fairly young IDE from JetBrains - Rider. Here, simplification of logical conditions, and help in choosing a variable name, spell checking in comments and variable names, automatic alignment and much more come to the rescue.
As for naming variables, aligning the code, inserting tabs instead of spaces and spaces in the merged code - this is all the main point that helps to design the text as code in a style that suits you. And the IDE will make most of these edits in the background for you. It turns out that you just need to teach her what you want, and subsequently it will become an indispensable assistant for you, which will save you a lot of time. The details of teaching your IDE your style are not relevant to the subject of this article. But if you think about this concept as a whole, the process turns out to be very similar to the process of introducing a new developer into the team. An indispensable tool for this is a code style agreement document. The only difference is that the developer will receive it in the form of a document,
Thus, the undeniable step towards a beautiful code is its standardization. A lot of it companies around the world neglect writing a document that standardizes the style of code. It happens that a catastrophe takes on terrifying proportions - the number of projects being simultaneously developed in the company is equal to the number of coding styles used within the company. In such circumstances, the transition of a developer from one project to another becomes even more non-trivial. If nobody monitors the standardization of the code base, then the code tends to turn into a bulk code, and adaptation on a new project feels like moving to another company, causing more stress than it could. Along with the increase in stress during the transition to a new project, the adaptation period also increases.
Such problems can be avoided by having in stock just a document with a code style convention. This document can also be considered a development tool. Having such a document and a modern IDE in your arsenal, you can greatly simplify your life by automating the code style at the IDE level. This will reduce the threshold for the developer to join the team and reduce the number of complaints to the developer during the code-review. The idea of automating and using development tools to the maximum is far from new, it can be found in many sources, including the legendary book "Programmer-pragmatist."
To summarize: development tools have an exceptionally positive effect on the beauty of the code. Moreover, the factor of subjectivity does not affect the usefulness of these tools.
A software side that can ruin everything.
We have already familiarized ourselves with the good software part. But are all the technical solutions aimed at making the code more beautiful? It so happens that when a product is almost ready for release, it turns out that it does not correspond to the technical characteristics of a particular device, which is so important for us to support. This problem is especially acute in the field of game software development. Someone may have reasonably reasonable objections that you can immediately write optimal software and do optimization during development, achieving the most optimal solution. To such objections can be cited a counter-argument:
Premature optimization is the root of all evil. -Donald Knut
The debate about whether this statement is true or not does not concern the beauty of the code and is beyond the scope of current reasoning.
But optimization can adversely affect the beauty of the code. This does not always happen, but there are some practices that can most likely be expressed in far from the most readable code. Examples of such optimizations:
- Alignment of data / variables in memory
- Using Data Oriented Design (DOD)
- implementation of asynchronous or multithreaded actions
These optimizations are quite difficult to implement, but are necessary in the development of high performance computing and in a number of other situations. But, for example, excessive use of multi-threaded interaction tends to greatly complicate the code. We get a situation where the beauty of the code can be sacrificed for technical optimization.
Who can I contact for advice?
We decided that regardless of the subjectivity of the concept of the beauty of code, there are practices that help maintain it - a document on the style of code and a properly configured IDE. This bundle can really make life easier, but it cannot guarantee a 100% result. The reason for this is the human factor. The developer may be familiar with the code style document, have a properly configured IDE, and yet ignore all the rules and warnings of the IDE. There may be at least 2 reasons for this:
- Unscrupulous developer. Maybe the developer is not used to the new style for him and writes in his usual manner. Or maybe he just does not consider maintaining a common style an important point, one that is worth paying attention to.
- A certain combination of circumstances. Most of us know or have tried Agile and practice sprints with a fixed deadline and a set of tasks. In life, there are situations when a request came “from above” about the need to implement an important feature right here and yesterday that was not included in the current sprint. No company can guarantee that this will not happen. When implementing such features, things very often happen, such as a “decision on the knee” and “hotfix”. Often such things are done for the sake of speed and there is simply no time to monitor the beauty of such an edit.
It doesn’t matter what reason prompted the developer to write an ugly code and fill it into a common code base. At the same time, as soon as such an amendment enters the release, it is likely that it will remain in such an ugly form. It would seem that what could go wrong if we all understand that this happens only in exceptional situations and that this cannot be done? The essence of the problem is that this is the precedent that has taken place. This means that it is very likely that after some time, when everyone forgets the context of the situation that has taken place, some developer will stumble upon this ugly piece of code during the work. Then wrong thoughts may creep into his head that if this is already in the project, then adding one more portion will not get any worse. The recipe for disaster is simple - repeat the last action n times,
Such an effect is very well described in Broken Window Theory . You can deal with broken windows quite simply - we just need a security guard who will monitor the code. Regarding programming, such a solution fits well with the concept of code-review. I can not name a single bad side effect of the practice of conducting regular code-reviews. The only thing that leading people can touch is the waste of a significant amount of time on conducting a code-review and correcting comments on it. It can be difficult for such people to explain what technical debt is and where it comes from. But in the context of the beauty of code, code-review is a purely positive practice.
In addition to the person who conducts the code-review on the project (or several people), you can also contact the developers of the language or the programming guru for advice. Of course, you should not rely on the fact that you can write a letter or call directly by this very guru. But for most programming languages, there are official or generally accepted
code style standards written by reputable people. Examples:
- Python - PEP8
- C # - StyleCop
- Swift - The Official raywenderlich.com Swift Style Guide
- Objective-C - The official raywenderlich.com Objective-C style guide
Following generally accepted code style standards is good practice to help keep your code beautiful. Although subjectivity is also present in generally accepted standards, it is not possible to conclude that code written by common standards will be beautiful.
Conclusion without conclusion
All considered thoughts on the beauty of the code lead exclusively to its subjectivity, even in terms of its simplicity. Simplicity, in turn, stems from how easy it is to understand the code and how compact it is (or vice versa). All the described tools, the choice between this or that approach form a handwriting, giving recognition and support from other developers. At the same time, it turns out that the concept of beauty in code still lends itself to some, albeit very weak, standardization. In general terms, we can assume that the patterning is more correlated with the beauty of the code, although variations are possible here.
Reaching a consensus among all the developers of the world may never succeed. But it’s worthwhile to approach the conclusion of the concept of code beauty. Perhaps, thinking about why you prefer to write one way or another, you will begin to write more readable code and express your thoughts in the code more clearly. Or, such an understanding will help you take the choice in the direction of a certain of the existing styles.