📜 ⬆️ ⬇️

Translation: What I have learned in 30 years of programming

Original article by John Graham-Cumming.
Translated and published with the permission of the author.

I have been programming for over 30 years, starting with machines that are already outdated (on Z80 and 6502 processors) to modern ones, using the languages ​​BASIC, assembler, C, C ++, Tcl, Perl, Lisp, ML, occam, arc, Ruby, Go and a lot others.

The following is a list of what I learned.

0. Programming is a craft, not a science or engineering.
')
Programming is much closer to the craft than to science or engineering discipline. It is a combination of skill and experience, expressed using tools. The developer selects the necessary tools (sometimes creates his own) and learns to use them in the creation process.

It seems to me that this is a craft. I think that the best programmers are more like watchmakers than builders or physicists. Of course, programming is similar to science and engineering discipline due to the use of logic and mathematics, but it is based on the use of tools and the creation of something with their help.

Considering that this is a craft, it is easy to see that experience, tools and intuition are important.

1. Honesty is the main rule.

In the process of writing code, it is sometimes tempting to experiment to find out whether it will work and run the program, not understanding what actually happens. A classic example is an API call that you decide to leave because, magically, it allows you to get rid of the bug or add printf, as a result of which the program stops falling.

Both examples are examples of dishonesty. Ask yourself: “Do I understand why my program makes X?”. If you do not understand, later you will have problems. To know what is happening is the responsibility of the programmer, because the computer performs exactly what it is ordered, and not what it would like to.

Honesty requires a strict attitude. You need to be sure that you know what your program is doing and why.

2. Simplify, simplify, simplify

Tony Hoar said: “There are two ways to design a system. One is to make it so simple that there will obviously not be flaws in it, and the second is to make it so complicated that there will be no obvious flaws in it. The first method is much more difficult. "

Simplify, rewrite, delete.

To paraphrase Hoare, I will say: “Within each large and complex program there is a small and elegant program that does the same thing as the big one and does it right.”

The “small elements loosely connected with each other” approach is related to this. It is better to design a program consisting of small parts interacting with each other than to create a huge monolithic whole. This is why UNIX has been successful.

3. Debuggers sometimes do damage, profilers never.

I almost never use debuggers. My programs create magazines and I know what my programs do. Usually, I can understand what is wrong with my log code, without resorting to the help of a debugger.

The reason I don’t use debuggers is my belief that debuggers make you lazy. Having found an error, many developers launch a debugger, set breakpoints and examine the memory or values ​​of variables. It is easy to succumb to the charm of such a powerful tool, but insufficient thinking will lead to a greater loss of time. And if your program is so complicated that you need a debugger, see p.2

(Note: in spite of all the above, one of my dear programmers, John Osterhut, seems to be sitting in the Windows debugger all day).

Profilers, on the other hand, are necessary when you need to figure out how to handle performance. You will never stop wondering what the profiler can tell you.

4. The duplicate code will give you a leg

Do not repeat. Do everything once in your code.

This lesson is related to clause 2, but this is a special case. Even a simple piece of duplicate code will cause trouble later when you “fix” it in one place, but forget it in another.

5. Do not get used to programming languages

Some people are obsessed with specific programming languages ​​and are forced to use only them. This is mistake. There is no language suitable for all tasks.

It is important to know which language from your toolkit you will use for a specific problem. And it is better to have more tools. Try different languages, apply them in practice.

For example, you do not need Python or ML, but you can experiment with list expressions and see their power. Or play with Go and see how it works with multithreading. Or use Perl and see how flexible it is with strings. Or use PHP to quickly create a dynamic web page.

I do not like language wars. They are the lot of losers, because they argue about the wrong things. For me, PHP is an uncontrollable tool, and in the hands of others it works wonders. The same can be said about C ++.

6. Easier to grow a program than to build it

This rule is related to item 2. Start small and grow gradually. When solving a problem, it is easiest to start from a small part of it (perhaps using temporary stubs or emulating the missing parts) than to immediately come up with a whole huge system.

If you immediately create a whole system, then: (a) you do not understand it, (b) invent a maze that is very difficult to change. On the other hand, if you have many small elements that interact with each other, refactoring will be easier if you realize that you made a mistake somewhere at the beginning.

The reason is that you will never know what a truly proper architecture should be. It is rarely possible to predict what the external impacts on your program will be. You can be sure that you know how TCP traffic passes through your mail server or the number of recipients, or maybe you have never heard of spam. There is always something that breaks your assumptions, and if they form a huge, complicated, complex program, it means you are in serious trouble.

7. Learn the application levels

I think that understanding what is happening in the program, starting with the CPU and ending with the language you use, is very important. It is important to understand the levels of the application (for example, to understand what happens with compiled C code or how the Java virtual machine works).

This helps a lot when it comes to solving performance problems, as well as debugging. I remember the case when one of the clients of my company sent a screenshot of the error in Windows 2000, in which the state of a small section of memory and registers was visible. Using only this information and knowing the version of the program, we were able to detect the problem with the null pointer and its cause.

8. I am not young enough to know everything.

I still have a lot to learn. There are languages ​​with which I almost did not work, but I would like to (Erlang, Clojure). There are languages ​​with which I “played”, but I do not know them well enough (JavaScript), and there are still ideas that I hardly understand (monads).

PS: I was told that I did not mention testing. It would be worth adding, I'm sure that testing is important for any code that will be used for a long time. Perhaps, if I will be engaged in programming for another 30 years, I will have an answer to the question “Do unit tests improve the quality of programs?”. I wrote code with tests and without tests and still not sure that I know the exact answer, although I am inclined to believe that unit tests can have a positive effect.

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


All Articles