📜 ⬆️ ⬇️

Signs of a bad programmer

Inability to talk about code


“To talk about the code” means to understand the order of execution of instructions (“to execute the program in the head”), knowing what the purpose of the code is.

Symptoms



Treatment

To cope with this flaw, the programmer should use the debugger built into the IDE as an aid in the event of an inability to “step along” the code line by line. In Visual Studio, for example, you can set a breakpoint at the beginning of the “problem” zone and then step by pressing F11, while simultaneously watching the values ​​of variables, until it becomes clear what exactly the code does. If there is no such possibility in the target environment, one should practice in that in which it is possible.

The goal is to reach a level where you no longer need a debugger to execute code “in your head”, when you are patient enough to think about how the code changes the state of a program. As a reward, you will be able to determine redundant and unnecessary code, as well as the ability to find errors in existing code without re-implementing the entire algorithm.
')

Poor understanding of the programming language model


Object-oriented programming is an example of a programming language model, as well as functional, and declarative programming. All of them are significantly different from procedural or imperative programming, just as procedural programming is significantly different from assembler or programming using GOTO instructions. There are also languages ​​that follow some common programming model (say, object-oriented programming), but make some improvements in it, such as generator expressions (list comprehensions), generic programming, duck typing (duck typing) ) etc.

Symptoms



Treatment

If your fault is the result of ineffective learning, then your best teacher is the compiler. There is no more effective way to learn a new programming model than to start a new project by deciding to use new constructions, no matter what degree of awareness. You also need the practice of explaining the capabilities of the new model through terms that you are already familiar with, and recursively building your new vocabulary until you understand all the subtleties. For example:

Step 1: "OOP is just a structure with methods."
Step 2: "Methods in OOP are simply functions that execute a mini-program with its own set of global variables."
Step 3: "Global variables are called fields, some of which are private and invisible outside mini-programs."
Step 4: "The very idea of ​​having private and public elements is to hide implementation details and expose a clean interface, and this is called encapsulation."
Step 5: "Encapsulation means that my business logic should not be clogged with implementation details."

The last step is the same for all languages, since all languages ​​are trying to lead the programmer to the possibility of expressing the meaning of the program without burying this meaning in the implementation details. Take functional programming:

Step 1: "Functional programming is when everything is done through chains of deterministic functions."
Step 2: “When the functions are deterministic, they do not need to be computed until it is required in the output data, and only the part that is really required is to be computed. This is called lazy and partial computing. "
Step 3: “In order to support lazy and partial calculations, the compiler requires me to write functions in terms of the transformation of one parameter, sometimes making such transformations another function. This is called currying. ”
Step 4: “When all functions are curried, this allows the compiler to choose the best execution plan with the help of the constraint solver.”
Step 5: “By allowing constraint solver to solve all the unimportant details myself, I can write programs describing what I want, and not exactly how to get it.”

Lack of research skills / Chronically poor knowledge of the capabilities of the platform



Modern languages ​​and frameworks now come with a surprisingly large number of built-in commands and features. Some technologies (Java, .Net, Cocoa) are perhaps too great to expect from any programmer, even very good, that he will learn them faster than in several years. But good programmers will look for built-in functions that do what they need before they start writing their own. And excellent programmers will be able to split their tasks into parts, identify abstract problems, and then find the frameworks, patterns, models and languages ​​that can be applied.

Symptoms

The following symptoms do indicate a problem only if they continue to manifest themselves in the programmer’s work for quite a long time after he began to master a new platform.


* - random duplication also happens, usually proportional to the size of the framework, so to estimate, proceed from the number.

Treatment

The programmer can not acquire such knowledge without stopping, and, most likely, it was a desperate attempt to make each function work, no matter what it cost. He needs a technical reference book on the platform and the ability to look at it with minimal effort, which means that he must have either a hard copy on the table next to the keyboard, or a second monitor for the browser. To get the initial habit of writing “correctly”, he should try to refactor his old code, aiming to reduce the number of instructions by at least an order of magnitude.

Inability to understand pointers


If you do not understand pointers, then there remains a very small range of program types that you can write, since this understanding allows you to create complex data structures and reasonable APIs. Managed languages ​​use links instead of pointers that are similar, but provide automatic dereferencing and prohibit pointer arithmetic to eliminate a whole class of errors. They are still quite similar, but the misunderstanding of the concept of pointers will be reflected in poor data design and errors, the reasons for which lie in the difference between passing by value and by reference.

Symptoms


Treatment

My friend Joe lived in the same hotel as me, but I did not know in which particular room. However, I knew where his friend Frank stayed. So I went there, knocked on the door and asked Frank: “Where did Joe stay?”. Frank did not know, but he knew in which room Theodore, Joe’s colleague, lived. So I went to Theodore's room and asked where Joe was staying, and Theodore told me that Joe was in room 414. That's where I found him!

Pointers can be described using various metaphors, data structures can be found many analogues. The above is a simple analogy for linked lists. Misunderstanding of pointers does not happen because of how exactly pointers are described (you cannot describe them in more detail than they have been described so far). Misunderstanding happens when a programmer tries to imagine what is happening in computer memory, and this picture merges with his understanding of ordinary variables, which are very similar. Help in reasoning about what is actually happening can this “translation” of the algorithm into a simple story. This is worth doing until finally the programmer has the ability to distinguish and represent pointers and data structures as easily as scalar values ​​and arrays.

Recursion issues


The idea of ​​recursion is fairly easy to understand, but programmers often have problems in presenting the result of a recursive operation or how complex calculations can be performed with a simple function. Problems with the “where you are” representation, when you start writing the condition for the continuation of recursion, or with the formalization of the parameters of the recursive function can make the development of a recursive function very difficult for you.

Symptoms



Treatment

Roll up your sleeves and be prepared for stack overflows. Begin by writing a function with one basic condition and one recursive call that uses the same, unmodified argument as it was received at the input. Stop, even if it seems to you that this is not enough, and run. Look at the stack overflow, go back and add a change to the argument when recursively calling. Overflow again? Excessive withdrawal? Then a few more iterations, switching between changes in the condition and in the call, until you start to sense how the function transforms the input data. Resist the desire to use more than one basic condition or more than one call if you do not know why you are doing this.

Your goal is to have the confidence to begin, even if you do not have the full sense of “where you are” in an imaginary recursive path. Then, when you need to write a function in a real project, you will start with a unit test and continue writing using similar techniques.

Signs of an ordinary programmer



Inability to think in collections


The transition from imperative programming to functional and declarative will require you to be able to think about operations on data sets. Collections will become your primitive instead of scalar values. This is required if you use SQL and relational databases, if you develop programs that need to be scaled proportionally to the number of processor cores, or when you write code that will run on SIMD chips (such as modern graphics cards and game consoles) .

Symptoms

These symptoms matter only if they manifest themselves in working with a platform with declarative or functional capabilities that the programmer should be aware of.



Treatment

Imagine a casino dealer who shuffles a deck of cards and shuffles the two parts together by scrolling, this can push you to think about collections and how you can operate with them. Other stimulating visualizations:

If you are writing a program that works with collections, think about all the additional data and records that your functions need in order to work on each of the elements. Use map functions to connect them in pairs, before you apply reduce to each of these pairs.

Lack of critical thinking


If you are not critical of your own ideas and do not look for flaws in the course of your thoughts, you will definitely miss problems that can be solved before you start coding. If you are also not able to critically evaluate your code, you can only learn very slowly, by trial and error. This is the root of both lazy thinking and egocentric thinking, so the symptoms can come from two completely different sides.

Symptoms


Treatment

Start with Paul and Elder's Critical Thinking, work on managing your ego, and practice resisting the desire to defend yourself when you trust your ideas to friends and colleagues to criticize.

When you get used to what other people are learning, testing your ideas, start to fully explore your ideas on your own. In addition, you need to develop a sense of proportion (to understand how design fits the size of the task), the habit of testing assumptions (so that you do not overestimate the size of the task), and a healthy attitude to failure (Isaac Newton was wrong about gravity, but we still love him , and his assumptions are very important to us).

Well, finally, you must be disciplined. Awareness of the flaws of your plan will not make you more productive until you train the will to correct and restructure what you are working on.

Pinball programming



If you kick the machine in exactly the right way, pull the spring back as far as necessary and hit the buttons on the paws in the correct sequence, only then the program will run smoothly.

Symptoms


Treatment

Imagine that your program is water. It can leak through each crack and fill any cavity, so you need to think about the consequences that it can flow anywhere else, except for the places you built for it.

You need to familiarize yourself with the mechanisms of your platform that allow you to make your program reliable and plastic. Three main types of such mechanisms:

There is also a fourth mechanism - unit testing, which you use during design and development.

The use of these mechanisms should be as natural for you as the placement of commas in a sentence. To achieve this, go through the mechanisms listed in brackets and correct some old program so that it uses them wherever you can attach them, even if it turns out to be unacceptable (especially if it turns out to be unacceptable, only so you will begin to understand why) .

Ignorance of safety principles


If the following symptoms were not so dangerous, then it would be more a question of “finishing”, “polishing” for most programs. Which means that if you manifest them, then you are not necessarily a bad programmer. You are just a programmer who should not work on network programs or secure systems until you have worked on your shortcomings.

Symptoms



Treatment

Only the basic principles are listed here, but they allow you to avoid the most blatant mistakes that can compromise the entire system. For any system that processes or stores information that is valuable to you or your users, or manages a valuable resource, always request a review of your design and implementation from a security professional.

Begin auditing your own programs with code that saves input to an array or to other allocated areas of memory. Make sure that there are checks that the size of the input data does not exceed the size of the memory allocated for them. There is no other class of errors that would cause such a huge number of “holes” in security as a buffer overflow. This means that you should seriously consider managed languages ​​and environments when writing network programs, or in any other place where security is not in the last place.

Next, check database queries that concatenate unchanged input data into an SQL query, and rewrite this code using parameterized queries, if your platform allows. Well, or add filtering / screening of all input data, if not. This is to prevent attacks from SQL injections.

After you get rid of the two most notorious classes of security-related errors, you should start thinking of all the input parameters of the program as unreliable and potentially dangerous. It is very important to determine the valid values ​​of the input arguments in the form of a valid validating code. Your program should reject the input data, if it does not pass validation, then you will be able to repair the “holes”, correcting the validation, making it more detailed, instead of looking for features specific to these or other vulnerabilities in the input data.

You should always think about what operations your program should perform, what privileges they require. You should think about this before starting development, because this is the best way to figure out how to write a program using the minimum required number of privileges. The point of this is to limit the damage to the rest of the system, if suddenly in your program there is a vulnerability. In other words: if you no longer trust the input data, you need to learn not to trust your own programs.

One last thing: you need to learn the basics of encryption, starting with the Kirkgoffs principle. It can be formulated as “security must be keyed”. There are also some interesting conclusions based on this principle.

First, you should not trust a code or other cryptographic primitive, unless it is published publicly and has not been analyzed and tested by the community. You cannot achieve security through obscurity, through propriety or through novelty.Implementations, even if trustworthy cryptographic primitives can have flaws, therefore avoid implementations that have not been carefully studied. All new cryptographic systems fall into the “pipeline” of research with a length of 10 years or more, and it would be good for you to use those that have already appeared on the other side of this “pipe” unharmed.

Secondly, if the key is weak or stored in an inappropriate way, then it is as bad as if there was no encryption at all. If your program requires data encryption, but not decryption, or if decryption is required only occasionally, consider encrypting using only a public key from an asymmetric pair, and decrypt separately, using a private key stored in the repository with a strong password that the user must enter everytime.

The more at stake, the more you have to get ready and the longer you have to design your program. This is because when your program is deployed, dozens, sometimes even millions of uninvited people will try to hack it.

The rest of the security bugs usually boil down to stupid bugs, most of which can be successfully avoided by checking the input data, using resources conservatively, relying on common sense, and developing a program at a rate not exceeding the speed with which you can reason it.

Signs that you shouldn't be a programmer


The following "diseases" are incurable. So if you still suffer from them after the school programming course, you better try yourself in a different profession.

Inability to determine the order of execution of the program



Symptoms

a = 5
b = 10
a = b

print a

You are looking at this code and are not sure which particular number will be printed.

Alternative professions



Inability to think abstractly



Symptoms













-





Alternative professions



Indifference to the result


Programming can still be your hobby, but it is in the interest of the whole society to save the software development industry from your participation in it.

Symptoms


* - most often appear under pressure from the authorities, and not at the initiative of the programmer. All the same, we will leave them here for the sake of self-examination, and note that one of them should look for a new job, and the other to return to business school and learn a few less destructive ways of making profit.

Alternative professions

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


All Articles