[PYTHON] If it is not easy to understand, it cannot be improved.

The bottleneck in program development is the comprehensibility of the source code for programmers. When you want to maintain, add functionality, and speed up the code that other members have written so far, the biggest bottleneck is the clarity of your existing source code.

** Why comprehension is essential **

If it is not easy to understand, the validity of the design cannot be verified and cannot be tested. To determine what the criteria are when an existing routine can be replaced, how the accuracy of the calculation results will improve, and what results can be accepted for speeding up, that routine It's easy to understand what you're doing (what you're expected to do). Unless that is met, existing code will struggle to write a single line to decipher what it wanted to do.

** What you can do if it is easy to understand **

・ You can instruct to create a test. -If you need to speed up the code, you can ask a third party to develop a high-speed version of the function.

The more busy you are in writing code, the easier it is to write code. If the code is easy to understand, you can get the help of others.

** Requirements for easy-to-understand functions **

-The fewer arguments the function has, the better. -There are no prerequisites for arguments to use correctly (there are few). -There is no case depending on the state of the argument. -Pointer passing (*) used only when realizing something that cannot be achieved by passing by reference (&) -Use [] when passing an array as an argument.

 double sum(double data[]);//Recommendation
 double sum(double *data);//Not recommended

-The formal parameters of the function should be described so that in and out can be easily distinguished.

copyObj(const dataType &src, dataType &dst);//Recommendation
copyObj(dataType *data1, dataType *data2);//Not recommended

** The hardest thing is not knowing the purpose and intention **

What you want to achieve is something that should have been communicated in your work, but it has not been fully communicated. Let's describe the information necessary to know the purpose and intention of development that can not be understood only by the description in the source code in the comments in the source code. Describe the information of the dissertation that describes the algorithm used, the information of the development specifications in the department, and the information that is essential for understanding the program. (However, there are also problems such as old comments being left behind and lying.) The important part of understanding the code should be written to avoid misunderstandings. Example: Definition of Fourier transform The Fourier transform (Fourier transform), which is often used in mathematics, has several definitions. How to define +/- of the sign of an imaginary exponential function and the standardization coefficient of the integral by the Fourier transform and the inverse Fourier transform. (There are two styles in which one coefficient is 1, and the style is distributed in the same way to both). Therefore, there are six definitions of Fourier transform. Therefore, it is necessary to clarify the definition of the Fourier integral that you are currently using, and to perform a consistent and consistent process. (Since few programmers use the Fourier transform code, it has become an example of not knowing what they are saying. (M_ _) m) Example: Definition of standard deviation It is necessary to confirm which value is required and which value is implemented, whether the value called "standard deviation" is divided by the number of samples n or n-1. I will. When the number of samples is extremely small, such as one digit, it cannot be ignored that this mistake may lead to misjudgment. It may lead to accepting what should have been excluded as a defect as a good product. Ask someone who is familiar with statistics. Example: The word "deduction" has too many different meanings. You can see that by reading the Wikipedia entry for Deductions (https://ja.wikipedia.org/wiki/%E6%8E%A7%E9%99%A4). Fortunately, I have never built a system in such a field, but in such a field, it is necessary to be aware of what to subtract from and to understand carefully. It turns out that comprehension of both what you are trying to achieve and the writing of the source code is essential for developing a program.

** Let's listen **

If the person who wrote the code is still around, do an interview. If you're adding a documentation comment for the function and you don't understand what it means, listen as much as you can. At that time, try to keep respect for the other person. The person who wrote the code before probably worked hard to write a program that would work anyway in a busy situation. Whether it's unusually deep indented code or a function with more than 1000 lines, it would have been a lot of work to write a program that would work for the desired process anyway. Interview survey If you are in a fortunate situation, do an interview survey. Even if it's a reconfirmation that you've already read and understood the code, it's worth listening and confirming.

** Try moving a piece of code **

If you don't know what the code does and how, write a program that just calls and executes the function. Even in the case of an open source library, sometimes you can't tell just by looking at the code what the library functions actually return and how to use them. So even in the case of inherited code, it is possible to help understanding by taking such an approach.

Addendum: What becomes clear when you move a piece of code If you try moving a piece of code, you may get an error with the combination of arguments. That knowledge is also important. It turns out that the combination of arguments that the caller produces must be checked to see if it causes such an error.

** If you don't know the code but know what to do **

-Manual tracing

Even if you don't know the relevant part of the inherited code, you can still do it if the program knows what to do. Experiment with what kind of data input, what to process and what kind of result should be output, including manual work. Doing so will give you a better understanding of what you need to develop.

・ Experiment with different languages and libraries

I feel that it may be better to experiment with different languages and libraries to understand what to develop. Experiment with a well-characterized library, even with manual data entry, rather than an automated, efficient, and nifty system that hasn't been validated (which should probably work). Try. If you know what to do, try these techniques to help you understand the meaning of your work and the source code. I use OpenCV a lot, so I'm using OpenCV's python binding as import cv2 from Python. By rewriting the code fragment using OpenCV in python and operating it, it helps to understand the meaning. Experimenting with different languages and libraries may help you understand the code you are looking for.

Prioritize clarity. By achieving clarity, what you want to achieve and what methods you can choose to do so will help those who take over maintenance understand. As a result, effective rewriting is possible, and the amount of calculation may be reduced to a fraction by using features unique to the calculation target.

Anyway, let's prioritize the clarity of the program. Program comprehension makes program development easier and makes program development more efficient.

** The input / output variable assert () explicitly describes the function specification **

Use assert () to check the input and return values of the function. Not only does this provide a run-time check for your program in Debug mode, but it also gives the source code reader a hint as to what data is expected to come in. .. If you write assert (img.channels () == 1), it means that you are assuming a grayscale image instead of a color image.

** Do not use pointers for what can be represented by std :: vector <> **

In the case of the vector type, the method of adding elements and the method of determining whether the element is the last are standardized, and anyone can understand the code in the same way. However, when implementing using pointers, the last element may have a specific value to determine that it is the last element. The person who wrote the code knows what the particular value is to indicate that it is the last element, but the person who reads the code for the first time does not know the particular value. (Note: I'm not saying that it's bad to use pointers, but I'm lamenting that the side that uses the data structure has an interface that can only be used with bare pointer operations. I don't want the code to increment to be scattered around the source code and not encapsulated.)

If you write using the std :: vector <> type and its method, you can see what you are trying to do at a glance. When a function equivalent to that is implemented by a unique implementation and a unique function name is used, understanding the function correctly causes unnecessary cost to understand. (If you just use the STL method, the number of items to be unit tested is greatly reduced. If you are using your own data structure for "efficiency", the effort required for development and the developer It's unfortunate that many people haven't noticed that it's detrimental to development efficiency.)

・ C = a> b? A: b; C = std :: max (a, b) is easier to understand than. ・ C = a> b? A --b: 0; C = std :: max (a-b, 0); is easier to understand than.

if( (a < x) && (x < b)){} Is better if( (x > a) && (x < b)){} It's easier for me to understand than (maybe because I can imagine a number line).

Expressions that include negation tend to be confusing, so try not to use negation unless it is easier to understand.

There are many ways to accelerate program development if the overall structure of the program, the roles of the individual modules, and the functionality of each function are well understood. There are many ways to improve execution speed, as long as the specifications are clear. The article on the case of failure to develop a large-scale system states that it was not possible to fix a sufficiently clear specification for the development.

Summary: Easy-to-understand coding accelerates program development.

Reference information ["Programming Style"](http://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F% E3% 83% B3% E3% 82% B0% E4% BD% 9C% E6% B3% 95-% E3% 83% 96% E3% 83% A9% E3% 82% A4% E3% 82% A2% E3 % 83% B3-% E3% 82% AB% E3% 83% BC% E3% 83% 8B% E3% 83% 8F% E3% 83% B3 / dp / 4756136494) Chapter 1 Recommended style to colleagues please. It states that writing grammatically correct code is not enough, and that consistency, idioms, etc. are necessary for comprehensibility.

Recommended Posts

If it is not easy to understand, it cannot be improved.
What to do if pip cannot be installed
What to do if pyenv is not enabled (zsh)
When using tf.print (), the contents of the tensor cannot be displayed if it is inside f-string.
What to do if the package dependency cannot be repaired
Did love happen to be born? Is it someone's plot?
memory is not released just by plt.close (). It should be plt.clf () → plt.close ().
What to do if PyAudio cannot be installed on Python 3.7, 3.8, 3.9 on Windows
[For beginners] Recursive function (Tower of Hanoi is easy to understand!)
I made an AI to judge whether it is alcohol or not!
If pip stops due to SSL, it is better to re-insert python itself
Binary tree traverse is difficult to understand
A story that sometimes does not work if pip is up to date
python Binary search It is surprisingly easy to implement bisect.bisect_left and bisect.bisect_right from 0
Measures to be taken when "Cannot open display" is displayed in X11 Forward
[OpenCV] When you want to check if it is read properly with imread
If an exception occurs in the function, it will be transmitted to the caller 2
Hackathon's experience that it is most important to understand the feelings of the organizer
If an exception occurs in the function, it will be transmitted to the caller 1
If you try to install Python2 pip after installing Python3 pip and it is rejected
What to do if Japanese language support is not completely installed on Ubuntu 16.04