Damage-Oriented Programming

Original author: Typical Programmer
  • Transfer
Damage-oriented programming is a set of approaches that encourages code reuse and ensures the long-term use of code produced by programmers in combat systems. The number of lines of code is a commonly used indicator of the importance of an application, and the number of lines that a programmer writes per working day is a useful metric used in project planning and resource allocation. Damage-oriented programming is one of the most effective ways to get the most voluminous source in the shortest possible time.

Damaged - having a defect , inferior. Harmful, insufficient.

Inheritance


Inheritance is a way to take advantage of the old code in the new code. A programmer inherits from an existing function or block of code by copying this piece to himself and making edits. Inherited code, as a rule, is concretized for new needs with the help of features that the old code did not support. In this sense, the old code remains untouched, but the new one is inherited from it.

Programs that use inheritance can be identified by a large number of almost identical code fragments, which nevertheless contain small differences. Another sign of inheritance is static fields.- variables and code blocks that are not directly used anywhere but serve as a link between the new code and the old one.

Pseudo-code inheritance example:

function getCustName(custID)
{
    custRec = readFromDB("customer", custID);
    fullname = custRec[1] + ' ' + custRec[2];
    return fullname;
}
function getCustEmail(custID)
{
    custRec = readFromDB("customer", custID);
    fullname = custRec[1] + ' ' + custRec[2];
    /***************
    * 4/15/96 git : адрес email хранится
    * во втором поле для факса
    ***************/
    return custRec[17];
}

The function getCustEmailwas inherited from the function getCustNamewhen support for email addresses appeared in the application. Inheriting the code in this way avoids accidentally introducing new bugs into the program.

Type polymorphism is one of the types of inheritance. In it, when inheriting the code, the types of the source variables are replaced.

Modularity


The modular program is divided into several files that have a common header with comments. The module usually includes:

  • Copyright
  • Denial of responsibility
  • Three to five rows with asterisks
  • Change history
  • Description of what the module was originally supposed to do
  • Three to five more with asterisks
  • A large block with spaces and blank lines, surrounded by asterisks or other characters, which lists the names of all functions, the name or initials of the author, as well as the date of writing
  • The code

They usually try to keep the size of the modules within reasonable limits in order to reduce connectivity and improve power . If the module becomes too large - it can be divided into several parts, copying into each copyright, disclaimer and more. Comments can always be inherited without fear, so it’s best to transfer all the original comments to the rendered module .

Components and Libraries


In flawed programming, plugins and components are commonly used — pieces of code found on the Internet or books. Googling allows a savvy programmer to save a lot of time due to the fact that there are already written components in advance for almost anything. The best among them are black boxes : the programmer does not need to know or think about how the component works. Many large applications are written using inheritance from other applications and components found on the network.

Encapsulation


The essence of encapsulation is to separate data from code. Sometimes this approach is also called data hiding , but the data is not really hidden - they are placed in an additional layer of code. For example, when database queries are everywhere in the code, this is bad practice. The damaging-oriented approach involves writing wrappers for these functions, thereby encapsulating the database. In the method getCustNamepresented above, the database is not accessed directly, but through such a special wrapper that reads one record. Both of these methods (as well as many others similar to them) “know” where the client record contains the data they need. A way to read a record from the database инкапсулированin some other module.

In some programming languages, fields can be marked with modifiers private, publicor protected. This has nothing to do with the flawed approach. The author of the module cannot know in any way what internal variables from his module will be required to implement the required functionality in the future! Therefore, all fields should be made public, and variables global, and let the external code decide for itself what to touch and what not.

Polymorphism


While studying the flawed approach, the concept of polymorphism causes problems for many programmers. However, the idea is simple and easy to implement. Polymorphic code is a code in which the format or content of the output varies depending on the input.

For example, the functions above can be rewritten into a single polymorphic function using inheritance and polymorphism:

function getCustData(custId, what)
{
    if (what == 'name') {
        custRec = readFromDB("customer", custId);
        fullname = custRec[1] + ' ' + custRec[2];
        return fullname;
    } else if (what == 'email') {
        custRec = readFromDB("customer", custId);
        fullname = custRec[1] + ' ' + custRec[2];
    /***************
    * 4/15/96 git : адрес email хранится
    * во втором поле для факса
    ***************/
        return custRec[17];
    }
    /* ... и так далее. */
}

Polymorphism is also associated with non-deterministic Turing finite state machines , which you can remember from the computer science course.

" It is " against " contain "


This is the subtlety of a good flawed design. Novice programmers often abuse inheritance (the “is” model), while with the advent of experience it becomes clear that in many places the “contains” relationship is more appropriate. In the example above, information about each client contains a name, while custRec is a record in the database.

Virtual classes and functions


A virtual class or function is code that the program will need in the future, but has not yet been written. As a rule, this is implemented through the base class on which the final code will be based.

function calcSalesTax(price, isTaxable, state)
{
    /****************************************
    *
    * TO DO:
    *
    * получать тариф для пользователя
    * из какой-нибудь таблицы, когда ее сделают
    *
    *
    ****************************************/
    /** 02/07/99 git -- пока возьмем такой тариф **/
    return price * (7.25 / 100.0);
}

A fragile base class is a class or module that has existed in a project for a long time, any changes in which break the entire application.

Overload


Overloading is an approach where one module or block of code performs more than one task. For example, a function that returns the username, email address and state value added tax. Overloaded functions save on dispatching methods , which is often the cause of slow-running code written using other approaches.

Documentation


Authorities say code needs to be written so that it is easy to read. It follows that documentation should be written in the least readable way. It should be maintained for each new module and updated as changes are made to the combat code - well, or at least when there is nothing special to do.

A great time to take up documentation is when someone applies for termination of employment. in the two weeks that an employee is supposed to work out, it would be nice to write documentation for all the code he developed.

Clogging the code with comments declaring the mechanisms of its operation distracts attention and slows down compilation. Therefore, programmers who follow the “best practices” of flawed programming keep documentation in the workflow accounting system so that programmers cannot accidentally overwrite it.

Version control


This, of course, is not that programming practice, but the followers of the flawed approach apply it. Keeping previous versions and change history handy is important, even if one person is working on the project. Experienced flaw-oriented programmers adhere to the following rules:

  • Always add your initials and last modified date to the file header
  • If you touch the file and understand that the changes will be difficult to roll back, save a copy with the extension .bak.
  • Keep several copies of the code, attributing your initials and the date of change to the file name. For example: custdata_git20040321.bak.
  • Always store backups in the same folder as the original files, so that the change history is easier and more convenient to track.

Conclusion


You will probably notice that many enterprises follow some (or even all) flawed programming practices. New-fashioned trends such as flexible or extreme methodologies come and go, but flawed programming has passed the test of time. Managers are always aware of the flawed approach and expect that you will be able to work with projects written in this style.

From a translator: although the article was also published in 2007, it has not lost relevance. Thanks to vovochkin for the link in the article " How to develop unsupported software ."

Also popular now: