⬆️ ⬇️

Are you afraid to open the editor?

At some point I began to notice that I was writing better quality: optimal, logical and readable code, but I was writing it slowly. At least, much slower than 15 years ago. Yes, you can’t look at the old code without tears: everything can be done more optimally and, at least, more readable. But the code was written quickly.



The problem is in control. I became tougher and deeper to control the code and ... began to spend on this control too many resources.



The basic principle is simple. If 10-20% of cases are subject to control, then it is necessary to spend on control ... 0% of resources. Bugs and rewriting will still be. But it is better to separate coding and debugging and forget about error coding at all.



')

A bit of theory and analogies



The outstanding psychologist Lev Semyonovich Vygotsky showed that human actions are iterative. And consist of his actions, control over this action and the correction of errors.



For example. When a child reaches out for a toy - this happens in several iterations:

For adults, an example is mouse movement. When we “poke” into a link, then with the first quick movement we move the cursor into the link area, evaluate the position of the cursor and bring it to the end. Either with an extra quick jerk, or a little less quickly and more smoothly than at the beginning of the movement. It turns out so quickly and habitually, that the movement seems fused.



The mastering of automatism is disabling control. Or translate it into more optimal, subconscious forms.

  1. The control on the reference points - an example with a mouse. We do not control the movement of the cursor at all; we control it at one control point next to the target. We do it very quickly and on the machine, so the movement looks solid.
  2. Subconscious control. If there is a standard reaction to the stimulus, then a subconscious response is quickly accumulated. When we miss the link, we do not stop and do not begin to analyze "who is to blame and what to do?". The subconscious has enough information to calculate the final phase of movement in the background (and immediately send for execution).
  3. Interrupt control When the movement is “full of automatism”, then the control is turned on if something goes wrong. For example, zaglyuchil mouse driver or computer hung. The calculation of the trajectory has become complicated. In this case, we turn on the speech apparatus to "drain" emotions and bring the mouse in several conscious iterations. Since the driver is rarely buggy (and the wheels with debris wound around them are almost history), control is rarely needed.
And most importantly, we do not even think that we can miss the link. (Do not remind me about mobile browsers).



Issue price



In the "Aquarium" of Suvorov-Rezun mentions the difference in the training of special forces and circus artists.



“I am already literate and I understand that a person can walk over the telegraph wire over the bottomless abyss. It's all about psychological hardening. A person must be sure that nothing bad will happen, and then everything will be fine. Circus artists spend years on elementary things. They are wrong. They have no scientific approach. They base their training on physical exercises, without paying enough attention to psychology. They train a lot, but they don’t like death, they fear it ... ”





The author exaggerates. But the meaning is clear - special forces refuse control (I can't fall), and circus ones develop control to perfection (I can fall, but at almost any moment they can correct the situation, therefore I have to control almost any moment)



The technology of retaining equilibrium is simple (even if not on a wire, where there are specific movements, but, say, on a narrow board). It is necessary to go with a constant speed clearly putting legs. A small error in the formulation of the leg or the deviation of the body is not terrible. It is terrible to fix it. An attempt to restore the allegedly lost equilibrium leads to a resonance, each new attempt to sway even more. The higher the board, the higher the cost of the error, and the earlier the control is turned on. And with him deadly "work on the bugs."



So we need two things. Do not respond to small deviations. The forward movement will smooth them. And to be able to clearly, without entering into a resonance, to correct big mistakes.



Special Forces men do not walk over the precipice every day, rather in special cases (at least without insurance). Therefore, it is enough to teach them not to be afraid of mistakes at height and, therefore, of the height itself. The lack of work on the bugs (or a limited option - counteracting wind gusts) will result in death too rarely (a trained person is rarely fatally mistaken, plus there is insurance). And you should not spend years on the development of "counter-reflections" in every possible case.



For the circus, this paradigm is literally fatal. They too often walk on the wire, often without insurance, and not only walk. They dance, juggle, jump, which increases the likelihood of an emergency situation. If control and work on mistakes are not gained, then one not very beautiful day in the circus children will cry, and the artist will not see it.



How to write code knowing all this?



With the theoretical part is complete. Let's not relax, to practice.



The main thing from which we must proceed is that in our code there are fewer errors than we think . At least we have to believe in it while we write the code. Ideally, assume that we can not be wrong in principle.



Say nonsense? And what is our reaction if the code is earned on the first attempt: WTF? !!! What am I doing wrong? !!!



With age experience, we are increasingly confident that we should be wrong. And we are waiting for this in advance. Write three lines? There may be (!) A mistake. Need to check. No error? It is somehow suspicious. Need to smoke and think.



Yes, we can, and we will be wrong, but it’s worth focusing on this only in the process of testing and debugging, where mother paranoia should reign. We should not foresee failures and lay on them. Doubts are the untimely redirection of resources for control.



Don't worry, just set aside some time for debugging. And if it turns out to be too much, then read with a clear conscience Habr.



Disclaimer



These recommendations are for experienced programmers.



If you are just starting your career, you can not neglect the control in any case.



The more carefully you control yourself, the faster automatism becomes. In fact, it is precisely for this purpose that control is needed ... for a more efficient development of automatism. At any stage of development.



Moreover, having met an incomprehensible idiom or behavior - do not be lazy to understand what it means and why. Take time to experiment to deal with behavior, to understand what is happening and when. When you get to the tasks, where your automatism will begin to give up and want to be checked at every step ... remember this article. Perhaps it will be useful.



So…



Work large iterations



Separate the writing, testing and debugging phases. Consider that you are not mistaken in the code. At least while writing it, you can not be wrong. At all.



Try to write as much code as possible without stopping, at least finish the functional block (Upd: but leave time to test / debug to finish today, before lunch (before any big break), do not delay it for a short time and do not delay it at all) . A stop for checking and debugging code is a context switch for which resources are spent and the rhythm is lost. Checking the code can and should be taken out in a separate phase before debugging. And start debugging from the top down. Start doing so, and you will be surprised how often the code can work immediately or immediately after correcting syntax errors. (Upd: I tried and was so surprised that I wrote this article).



Above all, do not stop for checks. It is not necessary to check the order of the function call arguments in the directory, if we roughly represent it. This can be done later (and perhaps never have to). (Upd: If you are using ASSERTs, and you cannot come up with a condition right away - put a label in the code and go on. If you are using a strict methodology, write _ASSERT (false) and forget about this place before reviewing / debugging.)



Do not stop to check a small piece of code. Even if they used an unfamiliar idiom or “freaking out a terrible construction”. Assume that the code works and go on.



If you need to use several blocks of the same type (and you are not sure that they are efficient) you should not check the first block, as we usually do. Just write what you think is right or move the block to a function. It is more profitable to fix a few blocks in the aftermath than losing pace and thought.



Upd: A large piece of code should not mean that the quality of the code should be sacrificed for no reason. Write comments first, then blocks, then code. Make this process familiar so that it does not cause any hitches.



Yes, sometimes it is worth sacrificing performance for the sake of conciseness and readability. More precisely, just do not bother with performance unnecessarily.



Yes, sometimes it is worthwhile to leave an ugly construction. If its alteration delays us, and we are ready to rush forward at full steam. In these cases, put tags in the comments. I use TODO and HACK. They help a lot before the final review (naturally, they should not be in alpha anymore, like the code they marked).



Check before debugging



Before running a large piece of code, "run over" it. First, you can check the spelling of idioms or function / method calls. At the very least, remember the places for which you need to go down in the directory. Secondly, obvious mistakes will immediately strike the eye, and they can be quickly and painlessly corrected without delay. Thirdly, this way we will once again review and better remember our decision, and immediately note the problem areas that need to be tested. Fourth, we still have to do it, why waste time?



However, if there is confidence that everything is written correctly, you need to immediately run the code for execution. As I mentioned, you will be amazed how often it works as planned on the first attempt. The more control - the more uncertainty and more likelihood to do wrong.



However, if something went wrong, then ...



Do not rush to debager



So, Houston, we have problems.



We stick a breakpoint or debug output in the code and for execution? Stop!



What will it give us? There are two options. First, we make sure that there is no error here and begin to check another place. Second, we are convinced that the error is here and happily climb to repair it. Great method. Allows you to "efficiently" spend working time with a clear conscience. We're not sitting on a habre - we are debugging.



In fact, when we chose a point for debugging, we did 60% of the work. We have chosen her for a reason (well, I hope so). Let's make the remaining 40%. Well, or at least 30%, and 10% is left to the probability of an epic file.



All we need is to take a step back. Back through the code. We expect problems in this place. Why exactly here? What could be wrong here? Often enough to look at the code to see it.



But for some reason we need to make sure that this code will not work. And this is unnecessary if it does not work. We recall Dr. House and immediately drag the patient to the operation without unnecessary analysis.



And if we didn’t find anything using the “gaze method”? Uh ... Are you still sure that the bench mark should be placed in this place?



If you need a point to diagnose problems, then at least use binary division effectively. Let's check right away if there is an error in the middle of the function block? We split the code in half and set the rapper.



No, we still want to dance from the beginning. Okay. But that's the problem. If the error is in the initial fragment, will we “dig deeper”? That is, to write some other debugging output that allows you to more clearly identify the error. Will we? So let's write it right away. Why run the program twice. It may not come to that, just thinking what kind of additional information we need, we often immediately understand where the plug is.



By the same logic, it makes sense to check several more reference points at once. 80% of errors is the absence of a signal (action, result), and not its distortion. Moreover, the distortion of the result is most likely its absence at the previous stage. Placing several reference points, we once again, by will-not by will, look through the program. And “magically” we find errors before launching debugger.



Do not be afraid to look up and look at the code above the expected place of failure, very often there is already a sign "I'm here!" I love, I wait! Your mistake".



Do not invent problems in advance





Well-known (perhaps the most famous) poker player Doyle Brunson, famous for a very aggressive game, said (I cannot vouch for the accuracy of the quotation), "When people ask me what I will do if the opponent raises my bet, I reply: he will raise first. But then I will think about it. "



Let us recall the “complex of a non-professional”, when a professional, knowing that the problem is not solved and why, refuses to even begin work. A novice, not having such knowledge, begins to do the work and ... does.



In fact, this is not so often and often not so. A professional knows that by writing 300 lines of code from, say, the required 400, he will face a problem. And he even knows with what. He does not begin to write code, but tries to immediately find a solution to a future problem. Finds a solution (if a pro is not STFW, then he is not a pro, right?), But it turns out that this solution is incomplete and it has flaws. Which can be corrected if you find a solution for this problem area ... And such a solution is found, only now ... there is a nuance ...



As you might guess, this is a direct path to depression. Habr, bash, jokes, news, LJ and even porn sites political debates. Depression of course retreat, but the work is worth it. What to do?



Jump. It is necessary to jump. That is, to write that part of the code in which there are no problems. When we get to the terrible problem that we, because of our experience, have noticed in advance ... It may turn out that it is solved in a simple way, it can be circumvented, or this functionality is no longer needed.



For example, often inventing problems associated with ergonomics. I want to make such a convenient control that "immediately here." Go to the forest. Some programmers are convinced that users should burn in hell. So let them immediately begin to suffer. From the awkward interface.



If everything else works like a clock, then your boss will burn in hell, who has not hired an interface specialist or an interface specialist who has not coped with this task.



Also in the forest are performance problems. I somehow caught myself trying to rewrite the cycle into 1000 iterations more optimally. It seems to be a good deal. But before that I parse the megabyte JSON file in memory. Who cares that I will reduce the time hash nesting to a level. The user is already waiting for a second. He will make the weather 20 milliseconds?



Yes, yes, the performance is also in the forest, and the forest is in the furnace To a reasonable limit, of course ... If we now have a thousand users, do not write an application that pulls a million. Of course, it’s bad to write an application only for a thousand users, but also to re-allocate more than an order of magnitude - to put it mildly, not optimally. With the growth of "clientele" will have to change the functionality and possibly the engine. And why extra control over the ideal code that will be rewritten?



Yes, if you can, immediately make an application with a large margin of performance, then you need to do just that. But if there is an opportunity to make an application only for three, two, or at least one and a half thousand (yes the hell with it, the current) thousand, then you still need to sit down and write just such an application. And then try to grind it with a file. Accelerating a ready-made application, with which it is clear how it works and why it works slowly easier than making a powerful engine from scratch. (If you do not believe me, you have not read the disclaimer).



Just sit down and write the code. Let not the perfect. I believe that you will bring it in the process.



Do not rush to search for a new shovel



I remember how python infuriated me after perl. It seems that the rider was forced to get on the tram. Yes, the tram is fast, and the rails are smooth and shiny, and the speeds are the same, but ... Where I used to consciously use defaults, python threw out the exception. Suddenly, I do not know that such an element in the hash may not be. Well this is a disaster!



I began to control, I began to get angry and lose time. Lose time and get angry. It seemed to me that the best solution is ruby ​​(remember the joke about the ducks?).



On the one hand, good. Understood even "on the fingers" with the rails. At the same time, I understood better how the barley Catalyst works. On the other hand, for three months I abandoned the project, which I am now writing back on python.



In fact, it is necessary to write “pythonic” on python, and not to try to apply the pearl barley paradigm: confusion in the sources - controlled confusion in the memory - output order.



Conclusion from the above welter difficult to do. But he is. Do not rush to change the development tool or library.



There are no perfect development tools. In the new shovel, the bayonet is bent at a more comfortable angle. But here's the pen, ... very unusual and tries to hit you know where.



The problem in choosing a tool is again the path to depression. There is no certainty that the new tool will do. And time to study it will have to spend. Do tests and stuff cones. Punched cones are a slide to smaller and smaller operations. And therefore the loss of inertia and speed.



Upd: It’s worth trying new tools when there’s plenty of time. Not when ideas or deadlines are tight. Or both. Search for new tools in such a situation - often it is to stand still. Sooner or later you will have a rollback when there are no ideas, and the work is all done, or not so important to do it. At least do it 14 hours a day. This is a good time to devote to the new.



And when there is a fire, before rushing between the tools, deal with the current, which you know well. It is likely you do not know him well enough. More than likely, digging deeper, you will understand exactly what you need. And you do not take the time to try out a bunch of new tools blindly. You either sit down and quickly file a spade with a file, or go to the market and buy exactly the spade you need.



Do not be afraid to throw out



I didn’t remember exactly the name of the psychologist I referred to at the beginning of the article. If I hadn’t found B.Yu. in my “Introduction to Psychology” mess Hippenreiter, then I would just delete this paragraph, so as not to postpone the publication. I cleaned up the draft of the article from the errors, but they remained a pack. I feel. I can not only understand where;)



But if you like the article - then the error factor is unimportant. And if you do not like it, then ... even more unimportant.



If you want to do something, do it right away. And publish immediately.



Do not be afraid of competitors. If you have not completed something, then competitors will most likely not finish it either. And exactly what you did not finish. They also need to hurry to move you from the market. And when they repeat your mistakes ... you will already come out with a new version on a new white horse ... with seven legs.



Polished velvet ribbon can be in the process. There are products of eppl. Where a considerable part of the price is technological aesthetics. But ... they simply donated something else. For example, the first Mac for the sake of completeness of the case was deprived of slots for expansion cards, which was one of the factors behind its loss of the IBM PC (at least in terms of sales).



Yes, Jobs ventured to abandon unnecessary. And he may have lost the battle, but focusing on the strong side - the design, eventually made Apple the current Apple.



Give up what you don’t pull or what’s stopping the exit right now. Do not be afraid to give users cut beta. They are much better than nepatannyh alpha.



Most elegant solutions are in the process of operation. The main thing to start it.



Send to ...



If someone says that your work is not needed, that it is done poorly, that now someone will come and do better ... In general, any non-constructive.



Send it to ...



Immediately. Without intelligence and trying to explain why you did just that. Well, if he is certainly not your boss. In this case ... I risked sending the boss a couple of times. And in the end I won, especially if the boss changed.



If you did something bad, this is just a reason to make the next job better. Or much better. The main thing is not to stop, not to look back and not to look down.



You did something. You got the experience. You have enjoyed the work done (at least to the end).



Upd. What is considered constructive criticism? This proposal is how to improve your work. Especially easy to implement and reasonable. These are links to similar projects from which you can learn new ideas. These are technologies (yes, those newest shovels) that will be useful if you have to make a qualitative leap, for example, in performance.



And non-constructive critics ... This system of control. Used in 10% occasion. And, therefore, not necessary.



Upd And once again summarize



If you follow all my bad advice, you should:

- write a large, functionally complete piece of code not paying attention to the possibility of errors and minimally using the documentation;

- before compiling, run through the code, outline possible improvements and test plan;

- do not use the debugger ... immediately after the error appears, but try to detect it / them logically;

- not to give in to excessive perfectionism;

- to divide coding, review and debugging;

- translate into operation immediately to achieve functional completeness (and stability, of course);

- to welcome constructive criticism and abruptly stop the non-constructive (forgive me, please, it seems I have overdone the latter in the comments);

- Do not doubt their own abilities.



And the most important thing



Do what you want and what follows and look back as seldom as possible. No need to check yourself once again.



Everything goes well.

Source: https://habr.com/ru/post/138754/



All Articles