Goodbye if $ DEBUG!

    I think that any Perl programmer pretty regularly adds auxiliary code to the program, which should not always be executed. This can be debugging code, collecting statistics about the speed of different parts of the code, outputting to the log, etc. There are several problems with this code:
    1. It interferes with reading the main code. It slows down the program. Because of the first two reasons, it is often deleted as soon as the need for it disappears ... only, unfortunately, the need for it regularly arises again, and this code, swearing, is written again ... so that a few hours later to remove again. Fighting the first problem is usually doomed to failure. For if the code must be executed, then it must be written. And if it is written, it scratches its eyes, breaks the main code, inflates the code, distracts and annoys. As a rule, this problem can be solved only when this code should be written at the very beginning and / or end of the function - then you can automatically generate a wrapper function that hides this code inside itself.

      But the second problem can be fought quite successfully:
      warn "i=$i\n" if $DEBUG;
      In this case, performance losses when they are $DEBUG==0limited to checking one scalar, i.e. in fact, the code is as follows:
      0;

      Unfortunately, this solution leads to the fact that the "extra" code becomes even larger: in each such line is added if $DEBUG. They sometimes try to fight this ifby moving this one inside the called function: Unfortunately, performance drops significantly more, because to check the scalar is also added input / output to the function. And since the meaning of existence is that productivity does not fall, this method is usually not popular.
      sub log { return if !$DEBUG; warn "$_[0]\n"; }
      log("i=$i");

      $DEBUG

      Another option is to use source filter technology. With its help, you can change the program code before perl begins to compile and execute it. Change like any other text, usually using regular expressions. For example, turn the code into comments, or vice versa - this will completely avoid slowing down the program (for example, see the Smart :: Comments module) The first problem with this approach is that the syntax of the Perl language is very complicated, and the regular expressions used to modify the program code (usually quite simple) are sometimes wrong ... and finding and fixing such bugs is quite difficult. The second problem is that there is a feeling of losing control over your code - you no longer know exactly which code is being executed, because Your code has been modified somehow. It’s a paradox, but the second problem completely negates the meaning of the existence of such modules - after all, they initially appeared to facilitate the work with code by removing “extra” commands from it, and as a result, working with the code, on the contrary, became more complicated.

      I want to bring to your attention another way to solve this problem: The idea is that when debugging mode is disabled, the function
      BEGIN {
        *log = $ENV{DEBUG} ? sub {warn "@_"} : sub () {0};
      }
      log+ "data", 123;

      logis defined as a constant, and perl optimizes constant functions and simply substitutes their values ​​into the code instead of calling them. (The code BEGIN { *log = sub () {0} }is identical to the code use constant log => 0;.) As a result, the real code that perl will execute will be: As a result, we got rid of it, and the function is not called when the debug mode is turned off. (And when the debugging mode is turned on - an extra unary plus should not spoil the first argument of the function in any way.) Unfortunately, this perversion has two side effects. The first - use warnings swears at attempts to add non-numbers. The second - this method is still a bit slower than option c , because the arguments to the log function are evaluated even when debug mode is disabled.
      log( +"data", 123 ); # if $ENV{DEBUG}
      0 + "data", 123;     # if !$ENV{DEBUG}

      if $DEBUG

      if $DEBUG

      However, despite the shortcomings, this method has a right to exist, and, perhaps, it will be useful to someone. In addition, I came up with it only a couple of hours ago, and perhaps it will still be possible to develop and rid it of flaws.

    Also popular now: