Theory of Correct Scripts

    What is the difference between a script and a program? Not at all used language or interface.

    The main difference is that the program has a vast shell that is not bound by the "contents" of the program. Depending on the platform, these may be manual pages, support for several languages, availability of functionality for installing / uninstalling, execution of interface agreements (command line, or other means of interaction), interfaces in the general registry, etc ... The program should be able to work in in any documented environment, provide for various situations (the best thing with this is for unix programs that use ./configure to determine in fact where they are, what is possible and what is not possible on this (regular) platform).

    The script is in the exact opposite sense: it is designed to solve a specific problem "here and now." No one expects a script that sends statistics to be able to do this simultaneously on solaris, freeBSD and windows embedded standard with cygwin on board.

    According to mathematical and programmatic ideas, there is no difference between administration scripts and programs. They work on the same principles, generally speaking, they perform almost the same thing.

    The difference between a script and a program is administrative .


    Almost any program has THREE important components:
    • Nontrivial algorithm.
    • Technical support, proven best practices, typical implementation schemes and ready-made configurations.
    • Proper integration into the working environment in any permitted (documented) configuration.


    Let’s learn more about these components ...

    1) Algorithm. Any program has, firstly, a certain idea (which, in fact, does the program), and secondly, the binding. Reading configs, output to syslog, notification by mail and a thousand more operations not related to the main task. But the program is not used for reading configs and writing to the log, but for the sake of what it DOES. Accordingly, usually the idea is to perform some kind of action according to some algorithm. Nontrivial idea. In the actual code, this may be less than reading the xml-config, but at the same time, the working algorithm is the essence of the program. It can be either "data processing" (like SQL), or mathematical (like md5sum), or working with specific features of a particular piece of iron (file format) - but it always requires high qualification in the subject area for an adequate understanding of the principles of work. Clear, that any programmer can read OpenSSL code. It is clear that only a good mathematician can understand the OpenSSL algorithm.

    But we are not writing about programs - about scripts. So, the script should not implement non-trivial algorithms. If you write an analog of base64 in your script, this is a bad script. If you write a message sending via smtp in your script using the “open socket, write” method - this is a disgusting script. If you are catching data from the com port in your script and write the answer there (to control the UPS) - this is some kind of scribe, not a script.

    The script SHOULD not contain the algorithm in terms of the "subject area". The script does not have a subject area, the script is a binding around programs that already work with subject areas. In some cases, the scripting language can provide all the tools:
    if md5.md5sum (open. ($ check) .read ())! = url.openurl ($ control) .read ():
         smtp.sendmail ($ from, $ to, "data check failed", "md5sum of $ check does not match control sum form $ contol.").
    

    This is a script. Just a script. Despite the fact that he implements an awesome amount of work. But if you have md5 - the class declared in the script 5 lines above with the implementation of md5 (or url, or open, or smtp, etc) - this is already an attempt to the program. But a program is much more complicated than the algorithm that makes it up, and this should not be implemented in scripts. NEVER.

    2) Any program should have known behavior. Mathematicians propose describing program behavior in comprehensive terms; practice says that usually, in addition to the algorithm, the program also contains bugs and features that affect its behavior, which you need to adapt to. Adapting to them is much easier when there is some practice of using the program.

    "KDC has been valid once but invalid now" - if this message is from a script - everything, bury. Right here on the spot. The program has a very reasonable message on which you can google and find out what exactly is wrong. This is a direct consequence of the presence of a certain objective logic in the program, specific and requiring users not to study it through, but to accept it behaviouristically. That is, as a set of statements about the behavior of the program. "This version of the program does not understand files larger than 2GB in size." This does not fit into the algorithm (and if it does, it will occupy that way of discrete mathematics) - but you need to know this in a practical sense. “This program behaves badly under the conditions of a symmetrical load on the upload / download, it’s better to run two copies, each of which will work in its own direction symmetrically ”- understanding _Why_ will require titanic efforts, it is easier to take it for granted. The more complex the algorithm, the more life you need to spend on its research, adaptation and in-depth study. There isn’t enough life for everything, which means it’s easier to accept as given and concentrate on the important.

    The script, on the contrary, should be crystal clear to everyone who sees it (with amendments to the knowledge of the scripting language). No(if every in self.__datarange__ is not in any map(__systable__.lang, __localtable__.map, lambda (a,b):[a in b or b in a for every __sys__.pair(a,b)])) raise "Missed i18n constitution".

    3) The script solves the problem HERE AND NOW. The program solves the problem _TAM_I_ ALWAYS_ (adjusted for operating experience from clause 2). When you write a script, you make it work on your system. It is not suitable for free use in other systems (although it can be EASY (see point 1) adapted). The program must be adaptable to a bunch of applications, the implementation of this adaptation in the script leads to the loss of its simplicity and its transformation, in fact, into a program. In addition (alas, ah), but knowing HOW TO CORRECTLY write a program is not equivalent to writing the correct algorithm. You can write an awesome library, but if you can’t run it on a machine that has Monday the first day of the week (or the second - as if you're lucky), then your library is worthless.

    Well, another important difference between scripts and programs. Programs (in the form of libraries) can “overlap” each other. This program needs libYYY, which uses libZZZ and libAAA, while libAAA uses libZZZ and libc. This is normal.

    Scripts SHOULD NOT DEPEND ONE FRIEND. The situation when the script depends on the services of another script that depends on the third is abnormal.

    Note that we are talking about addiction. It is quite possible to imagine a script that calls other scripts and produces a generalized result on them, but this is already the edge. A little more complicated (for example, “run script A if script B did not work”) is already beyond the scope of the foul. Not good. And if script A did not work but did not report it? Or did it work a little, but then fell off so that script B could not be completed (and we, as the authors of script A, could not think of such a thing)?

    So what should a good script do? Merge several programs into a specific system. You can count programs as constructor details. And the constructor himself - for the script. You SHOULD NOT cut the screw thread on the spindle - take the threaded spindle. You should not make an elliptical roller from this gum - it will still work poorly. If you don’t have a square plate with holes in the edges, then this is a problem of lack of details. You can try to make a square plate from a pair of rectangular, but you should not do it and hundreds of long strips.

    It so happens that scripts degenerate into programs. Suddenly a certain logic (algorithm) appears in the script, which becomes non-trivial (and useful). At this point, you need to catch this - and not be too lazy to spend three times as much time, but to make it a program. Provide it with "meat", which distinguishes the program from the script. Add a hundred condition checks, replace all constants with configurable variables, prepare it for work in “unusual” conditions. It is advisable to make it public (then the practice of use can be gained).

    An ordinary pipe is an almost perfect tool for constructing simple programs:
    lssomething | grep "bla-bla" | sendmail root@host.ru -s "bla-bal for something".
    


    It is difficult to find the line where the script ends. Let's just say the cycle is still bearable. Checking the condition is normal. But checking the condition in the loop (more than exiting the loop) is already bad. If you have a cycle in which a cycle is started to check the conditions, this is a 100% program. If she does not have everything that the program should have, then this is simply a very bad program . But not a script.

    When I look at collections of “useful scripts” ( here (forum.sysadmins.ru), for example), I understand that these are programs. Horrible programs without supporting documentation, installation procedures, without checking conditions ... It’s not possible.

    The use of such scripts is a sign of extreme kutsesti working environment. At one time I tried to get along with them, but came to the conclusion that this is a mistake. It is much more correct to have a set of toolkits (i.e. full-fledged programs that implement specific things completely and well) than a set of similar scripts (I repeat once again - a program can be written in the same scripting language - the difference between a script and a program is in non-programmatic binding: documentation and adaptability to life in a wide range of systems).

    The use of copy-pasted scripts is like an early dos copying of useful programmines on floppy disks. It works - we rejoice, it does not work - do not care, everything has broken - we are angry. In the conditions of a choice between a copy-pasted script and a program (and minimal binding), you should choose programs. Even if the implementation of the program requires additional efforts to study, establish, etc. Having established the program, you will receive the program. Having debugged the script, you will get only a crutch, the strength and durability of which even the author does not know.

    Each time a similar situation arises: to make a script or search for a program, you should start by searching for a program. Because programming is fascinating (yes, nagios, we will write a bunch of monitoring scripts ourselves), and learning someone else’s tiring (well, doesn’t it work like hell?). But the consequences of "under-programming" are the lack of documentation for the "chimney" that you made. And the consequence of the implemented solution is a system that can work on its own.

    Also popular now: