📜 ⬆️ ⬇️

8 programming traps



This article contains those programming traps that I got into myself, continue to fall and maybe never stop, as well as those in which I found my comrades.

However, I believe that they can be avoided if you know which traps you can get in and how to get out of them. Perhaps this faith is another trap.

Brief introduction


Imagine that you fell into a hole. Let it be 3 meters deep. You will start to get out of it, climb, cling, I do not know what else you will think of, but most likely you will get out.
')
In programming, you can also fall into the trap. But if we take the pit as an analogy, then it will be 50 meters deep and covered with a heavy steel plate from above.

Do you think you will stay long in such a pit?

Most likely, until someone finds you there!

But this is not such a big problem; you can get out of each programming trap on your own and almost without any other efforts - you just need to know three things: what kind of trap are you, how did you get there and where is the “secret door” the exit.

There is one amazing thing about programming traps - almost every trap is a commitment to one of two opposing extremes, and getting out of a trap is skillfully balancing between them.

It can be said that avoiding traps is a narrow path, where problems are to the left and problems to the right are absurd to the right.

Okay, no one reads the introduction anyway, so let's go!


Trap # 1: Optimization




As Knut wrote, premature optimization is the root of all evil. Many people know this rule, some do not follow it, some make it absolute, but few know that late optimization is even worse!

Too much optimization attention


Often, this type of programmers is sinning like Olimpiadnik. Knowledge of efficient algorithms or the internal structure of the processor makes them think that the code should be as efficient as possible.

In practice, it takes too much time to optimize, the code becomes completely unsupported, non-extensible and error-proof.

Signs that you're trapped
• Attempt to immediately write fast / undemanding code to resources
• The desire to squeeze everything out of the code, to the detriment of other indicators
• Believing that O (n) instead of O (n ^ {2}) or replacing all multiplication operations with 2 by a bit shift will make a candy out of the program


Too little optimization attention


One of my still unfinished projects comes to an end. Trying to avoid the error of premature optimization, optimization was forgotten before the end - moved to the last (the last but one if absolutely be honest) stage.

Now, when more than half is already ready, I understood - trying to avoid one trap, I fell into the opposite!

Now, in order to improve performance to an acceptable level, you need not just to run the profiler a couple of times and fix a couple of isolated algorithms as functions, you need to rewrite at least a third of the code already written!

This trap is called - late optimization, if you do not anticipate the possibility of optimization in advance, be prepared for the fact that a significant part of your beautiful and clear code will have to be thrown out!

Signs that you're trapped
• Sincere belief that any optimization is premature
• Postpone optimization to the final part of the project
• Failure to provide some small architectural solutions for future optimization


Output

• Do not try to optimize the code immediately - create opportunities for future optimization.
• Do not delay optimization without a reason.
• Rule 20/80: waste your time on those 20% of the code that will give 80% of the result (yes, use the profiler)



Trap number 2: Abstraction




Abstraction in programming is probably the nicest thing. First there were binary codes, then processor command mnemonics, then imperative programming — state and operations (statements), then structural, procedural, modular, object-oriented, functional programming.

Imagine that you still need to use goto to organize a loop.

Imagine that you still need to produce the same functions, differing only in the type of data (instead of taking advantage of dynamic typing and patterns / generics).

Imagine that you can’t just pick up and resize a collection - you need to allocate a new memory, copy an old collection there, add a new item, free unused memory.

Excessive complexity


Again we start with the trap, where the attempt to abstract everything is brought to the point of absurdity.

To pile up 20 classes, use 12 different patterns, implement your DSL to parse another DSL, create a cross-platform framework for visualizing cyclic graphs to create the next Tetris - this is about “advocates of abstraction”.

Signs that you're trapped
• Writing a universal framework before implementing the main functionality, and 30% of the written code will be used on the strength of
• Believing that the best way out of any problem is to use any pattern.
• Writing the most generalized, receiving everything and issuing correct results for any input function values, instead of a specialized one, even if its functionality will never be used


Simplify to infinity


Signs of “advocates of abstraction” are more common among more experienced programmers. Ignoring abstractions - for beginners. The best again balance somewhere between these extremes.

Newbies often still do not know what abstractions are in programming in general and in the language they use in particular. Because of this, they often write inexpressive code - one that could be rewritten using built-in language tools or third-party libraries / frameworks making it shorter, clearer and, more often, more efficient.

Signs that you're trapped

For this item, it is quite difficult to find common features - it all depends on the language, the task and a lot of other factors, but still:
• Ignoring abstractions that could objectively improve the code (for example, iterators in C ++, monads in Haskell (I mean refusing to write your monad, where it makes sense), generators in Python, interfaces in Java, etc.)
• When switching to a new programming language - refusing to study its abstractions, in view of the fact that you lived well without them (again, for example, when switching from C to C ++, refusing to learn from iterators, when switching from an imperative language to Haskell - refusing from studying monads)
• Belief that the possibilities of the language that you do not use are actually superfluous (does not concern C ++ programmers; it’s a joke, of course, but as you know in every joke ...)


Output

• Do not use abstractions for the sake of abstractions.
• Use known / accessible abstractions where they belong and don’t use them where they don’t have a place
• Learn the abstractions that your programming language provides
• Before implementing any functionality, consider whether you really need it (YAGNI principle)
• Where it is possible to do without special losses without abstractions - do without them (KISS principle)



Trap # 3: Perfectionism




Perhaps the most popular trap among developers who know too much to just take and write code. On this topic, quite recently a wonderful small article on Habré appeared, you can find a link to it at the end of the article.

The pursuit of excellence


On this topic, everything was chewed up and to me, but I want to be consistent, so I will also analyze this trap in the bones.

Signs that you're trapped
• Belief that the main thing in the code is beauty, readability and maintainability
• Continuous refactoring and rewriting even acceptable code
• Find flaws in any code.
• Believing that it is possible to write the perfect code in a reasonable time.
• Increased attention to detail
• Attempts to achieve the highest possible result.
• Long thought over architecture of even the simplest parts of the project


The path of chaos


From the previous list it is clear that perfectionism is a dangerous trap, can it be abandoned altogether?

It is possible to completely ignore the purity of the code, refusal refactoring and turn off critical thinking and be better than absolute perfectionism (after all, a bad result is a result, and an absolute perfectionist only throws out the written code), but as with the other traps, balance is important here.

Therefore, a complete abandonment of your striving for perfection will drive you into a completely opposite trap.

Signs that you're trapped
• Belief that readability and extensibility of the code is not important
• Lack of critical thinking, especially in relation to your code
• Completion, even minimally acceptable result, or unacceptable at all
• Full refusal of refactoring
• Refusing to think about complex parts of the architecture
• Failure to rewrite project or part of it from scratch


Output


As always somewhere in the middle:
• Accept that the beauty of the code and the achievement of the result are important, sometimes the second is even more important
• Consider rewriting from scratch as a last resort, but accept the fact that it may be necessary
• Give yourself the maximum time you can spend on refactoring. It can be 20, 50, even 80% of the total working time, the main thing is never to exceed it, so as not to get stuck
• When you discover a flaw - think about how strong it is to spend time correcting it.
• Use the 20/80 rule - try first to do those 20% of work that will bring 80% of the result


I hope these tips will help habrovchanam to get out of the trap of perfectionism. All of them were understood in the bitter experience of the fight against this ailment and literally suffered through all the time that I do programming.


Trap number 4: Technologies and tools


image

Programming does not stand still and now you have a thousand and one tools and a library that, if they do not do all the work for you, they will certainly make it easier.

However, sometimes they are used either too often or too rarely. Let's start again with the first case.

Laziness


Of course, the use of already created libraries, frameworks and tools is only a reasonable manifestation of laziness, but sometimes even with good intentions this goes too far.

Connecting at the same time boost, Qt and the active use of STL when writing Hello World is not the best idea, but sometimes similar things happen and this is another trap.

Signs that you're trapped
• Library connection for 30+ megabytes, for the Mersen Vortex
• Belief that everything you need has already been written
• Failure that the bike might be better.
• Inability to write lines of code without autocompletion in the IDE
• Active use of tools, without understanding the principles of their work. For example, frequent use of tools for visual editing GUI (like Qt Creator, CodeGear Rad Studio, MS Visual Studio) and, at the same time, refusing to try to understand their device


Workaholism


Does this mean that I urge everyone to abandon the use of all tools and libraries, urge them to write bare code with their bikes in nano (or worse, on papyrus)?

By no means. On the contrary, as you will see, complete disregard for our programmer inheritance is an even worse vice. And probably the most dangerous trap for programmers.

Signs that you're trapped
• Regular writing of new and new bikes, without good reason for this
• Belief that the capacity of the language and the standard library should be enough for the whole
• Belief that autocompletion (not as in Sublime Text, but as in IDE) is for sclerotic
• Writing your library, albeit monstrous, but not even approaching the functionality of existing analogues
• Statements that debuggers and profilers are needed by those who do not understand how their own code works.


Output

• Get to know the tools available to you, but don't try to apply them anywhere
• Carefully weigh the pros and cons, before choosing between using a third-party library and writing a bicycle
• Try to improve your productivity using modern tools, at the same time do not depend on them
• Accept that in training / test projects you can make exceptions to these rules.



Trap number 5: Golden Hammer




Another item in our hit chart is a golden hammer.

Golden hammer is a bad habit. After any method has worked in solving several problems, trapped begins to use this method wherever possible!

There are several similar terms - panacea, magic pill, silver bullet, i.e. such a method, which always, in 100% of cases, performs any task. Another saying to this topic is to hammer nails with a microscope.

The golden hammer is a fairly common but completely different trap. Anyone can be a gold hammer, someone can fall in love with OOP and write classes for everybody, someone with design patterns and build a program from factories and singletons alone.

For someone, a golden hammer is a favorite programming language, for someone - a favorite paradigm, for someone - a development methodology.

The main thing that highlights the golden hammer - an attempt to use it always and everywhere.

Signs that you're trapped
• Using one programming language for all tasks
• Belief in the fact that one paradigm can solve all the problems of programming (most often they say so about OOP and AF)
• Use for all projects, regardless of the conditions of one development methodology, for example, thoughtless use of TDD in all projects
• The use of any tool provided by the language for most tasks, for example:
- Passing all arguments by constant link only
- The use of only one type of collections in the entire program, say arrays (vectors)
- Use of non-tricky objects everywhere
- Use in syntax-like languages ​​(for example, Java and C)
single indent style and entity naming method


Silver bullet does not exist


I am afraid that this trap is an exception to the rules and it is possible to avoid it without risking to get into another.

This exception to the pattern I noticed once again proves that the golden hammer does not exist - my method of describing the trap as a dual entity misfired, but I am not afraid to abandon its use.

This is the right way to get out of this trap.

Output

• If you know only one programming language - learn another one, or two (you can and more, but within reasonable limits)
• If you know several programming languages, but you have an obvious favorite, try using other languages ​​more often.
• If you programmed only by adhering to imperative or object-oriented programming, try the functional
• If you constantly use any one development methodology, try something new.
• Before making inertia decisions (and using your golden hammer) - think about possible alternative solutions.



Trap # 6: Cross Platform




Cross-platform applications - those that run on multiple operating systems and / or multiple platforms.

And here again there are two extremes - some developers are trying to write an application so that it works on all possible operating systems and is equally well suited for PCs and for tablets and smartphones.

For everyone


Often, people want to achieve an incredible degree of cross-platform.

As a result, they get that the application does not work completely correctly on any OS and it is equally inconvenient to use it on a PC and on a tablet and on a smartphone!

They fell into the trap of excessive cross-platform!

Signs that you're trapped
• Belief in the fact that you can write such code that would produce acceptable results on all target platforms, without changes
• Attempts to cover as many operating systems and platforms as possible, while not wanting to port and change at least part of the code
• Dislike any code that targets only one platform.


There is only Win32


And vice versa - some programmers write software that will run only on the same OS as the author, moreover, we need the exact same mouse, keyboard and virtual reality helmet.

Often the reason for this is simply that the programmer does not think that there are other operating systems and platforms besides those that he uses.

Signs that you're trapped
• Rewrite all (or most) application code for each target OS / platform
• Writing obviously hard-to-port code where it can be avoided
• Using non-standard compiler / interpreter extensions


Output

• Carefully identify target OS / platform
• Be prepared for the fact that for some OS / platforms you have to change part of the code or even write a separate version from scratch
• Do not tie the code to one platform specifically
• Try to cover multiple platforms if this complicates the development



Trap # 7: Protection




(Without) defensive programming is another great trap in which you will probably see yourself (present or past).

Defenseless programming


Defenseless programming is the opposite of defensive programming practice, it is the belief that the functions will always be passed the correct arguments that there are no side effects, or they will not affect the operation of the code, that the pointer will never be null, and similar things.

Sometimes this is good, it makes the code free from many checks, but debugging such code is hell. That is why it is a trap.

Signs that you're trapped
• Fearlessness before overflowing, dividing by zero and rounding errors
• Belief in absolute infallibility of standard and library functions / classes
• Believing that the user will not make a mistake when entering
• Belief that memory will never end
• Belief that all configuration files necessary for an application exist and that they always have access


Security programming


Millions of tests for obviously working parts of the application, 15 ASSERTs within each function, own library of exceptions, logging, attempts to drop the application with the slightest deviations.

This is the other side of the coin - a defensive programming trap.

Signs that you're trapped
• Each function in a project begins with an assertion bundle or excitation exception.
• Tests cover absolutely all code, including third-party libraries.
• The project has its own class MyProjectException and a complex hierarchy of at least 10 of its heirs, the meaning of which comes down to the message about invalid function arguments
• Writing to the log most of what is happening with the application
• Even small deviations are unacceptable for you and should drop the application with an error message and automatically send a bug report with a full memory dump.


Output

• Consider carefully what is worth checking and what is not.
• Pay special attention to user input and external resources.
• If possible, try using standard exception classes.
• Do not try to check everything.
• Separate critical errors from minor ones, allow the application to work further if nothing really terrible has happened
• Log only the most important data in the log, implement the unobtrusive opportunity to send a bug report



Trap # 8: Putting it Forward




The trap is quite interesting, because it is very difficult to find a balance in this issue.

The essence of the trap is that often implementing any functionality, we put the marks - TODO, HACK, and some others.

Realization of these tasks is delayed for oneself, rarely anyone remembers TODOshki and they remain unfinished for a long time.

Signs that you're trapped
• Many TODO and HACK marks in the project and their number does not decrease
• Code Review does not bring any results, except for the placement of new TODO and WTF
• The inability to distract from the task being performed for a short time in order to implement an indirectly associated with it (instead of leaving TODO) or correct a detected error (instead of leaving FIX or HACK)


Multitasking programmers


There are programmers who cannot switch over to the implementation of any part of the project to another, even if directly connected with it (say, write an exception class and throw it away, instead of marking “TODO: check argument to null”).

And vice versa, there are programmers who can do this, I call such multitasking programmers, but the trouble is that there is no real multitasking and in fact they just quickly switch from one task to another.

This has its plus - TODO and HACK are not put in the code, but are corrected immediately, errors found in another code are eliminated.

And as usual, it is not given free of charge, as a result of a programmer switching too often, the programmer may forget about the original task or not have time to finish it, and when he returns to it again, do not remember which direction he was moving.

If you like to quickly and often switch between different parts of a project, I have bad news for you.

Signs that you're trapped
• You do not leave a single TODO for later to concentrate on the task
• You switch so often that starting to implement one functional, you implement two completely unrelated features instead
• When you are programming in pairs, the partner cannot keep up with your thoughts.


Output

• Before you postpone the task and put the TODO think, it can be implemented quickly
• Do not be afraid to be distracted from the main task, but do not do it too often and for a long time.
• Inspect the code, fix the errors found immediately
• Postpone a large functionality that is not related to the current task - leave TODO
• When programming in a pair, avoid switching in general, defer all extraneous tasks



Links



• AlenaC ++: Who actually owns the quote about premature optimization
• Wordpresse: Security Programming

• Habrahabr: Late optimization
• Habrahabr: 5 stages of programmer incompetence
• Habrahabr: These countless paradigms, concepts, tools and frameworks
• Habrahabr: Analysis paralysis: you know too much to just write code
• Habrahabr: Three key software principles that you must understand
• Habrahabr: Cross-platform is cool
• Habrahabr: Hardware cross-platform: is there a way out?
• Habrahabr: Security Programming

• Wikipedia: KISS
• Wikipedia: YAGNY
• Wikipedia: DRY
• Wikipedia: Perfectionism
• Wikipedia: Golden Hammer
• Wikipedia: Procrastination

Instead of conclusion


Good luck to everyone walking on a rope!

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


All Articles