Lecture
i
to cycle I bring to your attention the advice of masters of antiquity, following which will create additional jobs for JavaScript developers.
The code that you write will be so complicated to support that JavaScript developers who come after you, even the simplest change will take years of paid labor!
Moreover, carefully following these rules, you will also save your workplace, since everyone will be afraid of your code and run away from it ...
... However, everything has its own measure. The code should not look complicated in support - any fool would write like that. The code must be one. Otherwise, it will be noticed, and the code will be rewritten from scratch. You can't let that happen. These tips take into account this possibility. Long live zen.
The article is a free translation of How To Write Unmaintainable Code with additions for JavaScript.
To prevent another programmer from fixing your code, you need to understand the path of his thoughts.
Imagine, in front of him - your big script. And he needs to fix it. He has neither the time nor the desire to read it in its entirety, and even more so to thoroughly disassemble it. He would like to quickly find the right place, make a change and get out of the way without any side effects.
He views your code as if through a tube of toilet paper. This does not give him an overall picture, he is looking for the small fragment that he needs to change. At the very least, he hopes that this fragment will be small.
What he will try to rely on in this search is the conventions adopted in programming, the names of variables, the names of functions and methods ...
How to complicate the task? You can break the agreement everywhere - it will prevent him, but this may be noticed, and the code will be rewritten. What would a ninja do in your place?
…Right! Follow the “in general” agreements, but sometimes break them. Thoroughly scattered around the code, breaches of the agreements on the one hand do not make the code clearly bad at first glance, but on the other, they have exactly the same, and even better, effect than an obvious failure to follow them!
For example, jQuery has a wrap method that wraps one element around another:
1 | var img = $( '<img/>' ); |
2 | var div = $( '<div/>' ); |
3 |
4 | img.wrap(div); // обернуть img в div |
Result code above:
< div > |
< img /> |
</ div > |
( div
turned around img
)
And now, when everyone relaxed and enjoyed this wonderful method ...
... It's time for the ninja to strike!
What do you think will happen if you add the line to the code above:
5 | div.append( '<span/>' ); |
Perhaps you think that <span/>
will be added to the end of the div
, immediately after img
?
And no! And no! ..
This is hard to imagine, but calling img.wrap(div)
inside clones a div
. And wraps around img
not the div
itself, but its evil clone.
The original div
remains empty. After append
is applied to it append
two div'а
: one wrapped around the span
, and in the other only img
.
Variable div | Clone div created by wrap (no variable assigned) | ||||||
---|---|---|---|---|---|---|---|
|
|
The convention in this case is that most of the jQuery methods do not clone the elements. And the call wrap
- clones.
The code of his true ninja wrote!
Write “as shorter,” not as clearer. “Less letters” is a good reason for breaking any agreements.
Your faithful assistant is the language features used in a non-obvious way.
Notice the question mark operator '?'
, eg:
// код из jQuery |
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; |
The developer, who met this line and tried to understand what is still i
, will most likely come to you for clarification. Feel free to tell him that in short it is always better. Dedicate him in the way of the ninja. Do not forget to hand the Tao Te Ching.
A significant part of the science of creating unsupported code is the art of choosing names.
Name the variables briefly: a
, b
or c
.
In this case, no one will be able to find it using the Text Search function.
Moreover, even finding - no one can "decipher" it and guess what it means.
i
to cycle In those places where single-letter variables are generally accepted, for example, in a loop counter - in any case do not use the standard names i
, j
, k
. Anywhere, just not here!
Stop looking at something more exotic. For example, x
or y
.
The effectiveness of this approach is especially noticeable if the body of the cycle takes one or two pages.
In this case, it should be noted that the variable is a loop counter, without scrolling up, it is impossible.
If you have to use long, understandable variable names - what to do .. But even here there is room for creativity!
Name the variables “tracing paper” from the Russian language or somehow “improve” the English word.
In one place write var ssilka
, in another var ssylka
, in the third var link
, in the fourth - var lnk
... It really works great and is very creative!
The number of errors with the support of such a code increases many times.
When choosing a name, try to use the most abstract word, for example obj
, data
, value
, item
, elem
, etc.
data
. Use this name wherever possible. In the end, each variable contains data , right? But what if the data
name is already taken? Try value
, it is no less universal. After all, each variable contains a value .
Busy and this? There is another option.
obj
, num
, arr
... How much will it complicate the development? Oddly enough, much!
It would seem that the name of the variable contains information, says that the variable has a number, an object or an array ... On the other hand, when the uninitiated will parse this code - he is surprised to find that there is no information!
After all, just the type is easy to understand by running the debugger and looking at what's inside. But what is the meaning of this variable? What array / object / number is stored in it? Without a long meditation on the code is not enough!
item1, item2, elem5, data1
.. Only a truly attentive programmer is worthy of understanding your code. But how to check whether the reader is worthy?
One way is to use similar variable names, such as data
and date
. To read such code fluently is almost impossible. But to notice a typo and fix it ... Mmmmm ... We are here for a long time, time to drink some tea.
Use abbreviations to make the code shorter. For example, ie
(Inner Element), mc
(Money Counter) and others. If you find yourself confused about them yourself - suffer heroically, but do not rewrite the code. You knew what you were going for.
In order not to be bored - use similar names to designate identical actions .
For example, if a method shows something on the screen, start its name with display..
(say, displayElement
), and elsewhere declare a similar method as show..
( showFrame
).
As if to hint that there is a subtle difference between the display methods in these methods, although in fact it does not exist.
If possible, negotiate with members of your team. If Vasya uses display..
in her classes, then Valera is sure to render..
, and Peter - paint..
... Conversely, if there are two functions with important differences - use the same word to describe them! For example, with print...
you can start the print method on the printPage
printer, as well as the method of adding text to the printText
page.
And now, let the reading code think: “Where does the message printMessage
?”. Special chic - add an element of surprise. Let printMessage
not output where everything is, but into a new window.
Do not give in to the requirements to write a glossary of terms for the project. If he already has one, don’t follow him, but rather swallow him and say that this is how it was!
Let the programmer reading your code search in vain for differences in helloUser
and welcomeVisitor
and try to understand when to use what. You know that in fact there are no differences, but you can search for them very long.
To designate a visitor in one place, use user
, and in another visitor
, in the third - just u
. Choose one name or another, depending on the function and mood.
This will immediately embody the two key principles of ninja design - hiding information and the substitution of concepts !
If possible, reuse variable, function, and property names. Just write new values in them. Add a new name only if absolutely necessary.
In the function, try to manage only those variables that were passed as parameters.
This will not only make it difficult to identify what is now in a variable, but also make it almost impossible to find a place where a specific value has been assigned.
The goal is to make debugging as difficult as possible and to force the programmer reading the code line by line to analyze the code and take note of the changes of variables for each branch of execution.
An advanced version of this approach is to quietly (!) Replace a variable with something similar, for example:
1 | function ninjaFunction(elem) { |
2 | // 20 строк кода, работающего с elem |
3 |
4 | elem = elem.cloneNode( true ); |
5 |
6 | // еще 20 строк кода, работающего с elem |
7 | } |
A programmer who wishes to add actions with elem
to the second part of the function will be surprised. Only during debugging, having looked at all the code, he was surprised to find that he was dealing with a clone!
Regular meetings with this technique in practice say: it is impossible to defend oneself. Effective even against experienced ninjas.
Add underscores _
and __
to variable names. It is desirable that their meaning be known only to you, and better - without any obvious reason at all.
This will achieve two goals. First, the code will become longer and less readable, and secondly, another programmer will long look for meaning in underscores. It will work especially well and bring confusion to his thoughts if in some parts of the project there are underscores and in some parts not.
In the process of developing code, you will most likely get confused and mix styles: add names with underscores where there are usually no underscores, and vice versa. This is normal and fully consistent with the third goal - to increase the number of errors when making corrections.
Let everyone see what wonderful entities you are operating on! The names superElement
, megaFrame
and niceItem
with a favorable position of the stars can lead to enlightenment of the reader.
Indeed, on the one hand, something is written: super..
, mega..
, nice..
On the other, it does not carry any specifics. The reader may decide to search for this deep meaning and slow down for an hour or two paid working time.
Why not use the same variables inside and outside the function? It is simple and does not require to invent new names.
1 | var user = authenticateUser(); |
2 |
3 | function render() { |
4 | var user = ... |
5 | ... |
6 | ... |
7 | ... // <-- программист захочет внести исправления сюда, и.. |
8 | ... |
9 | } |
The programmer who has come to the middle of the render
method will most likely not notice that the user
variable is “not the same” and uses it ... The trap is slammed! Hello, debugger.
Do not limit the actions of the function to what is written in its name. Be wider.
For example, the function validateEmail(email)
may, in addition to checking e-mail for correctness, display an error message and ask to re-enter the e-mail.
Select at least a couple of additional actions besides the main purpose of the function. The main thing is that they should not be obvious from the name of the function. A true ninja developer will make them unobvious from the code too.
Combining several related actions into one function will protect your code from being reused.
Imagine that another developer only needs to check the address, and not to display the message. Your validateEmail(email)
function, which does both, is not suitable for it. The employer will be forced to pay the creation of a new one.
There are functions whose name suggests that they do not change anything. For example, isReady
, checkPermission
, findTags
.. In treatises this is called “no side effects”.
A truly beautiful technique is to do something useful in such functions, along with the verification process. What exactly is completely unimportant.
The surprise and daze that your colleague will have when he sees that the function with the name in is..
, check..
or find...
changes something - will undoubtedly expand its reasonable limits!
Another variation of this approach is to return a non-standard value.
After all, it is..
well known that is..
and check..
usually return true/false
. Demonstrate original thinking. Let the call checkPermission
return not the result true/false
, but an object with the results of the check! And what is useful.
Those who try to write an if (checkPermission(..))
check will be surprised by the result. Answer them: "you must read the documentation!". And send this article.
All the tips above came from the real code ... And including from developers with more experience.
Perhaps even more than yours, so do not judge rashly
Comments
To leave a comment
Scripting client side JavaScript, jqvery, BackBone
Terms: Scripting client side JavaScript, jqvery, BackBone