Coding principles with a beginning and an end

basic situation

In the way of programmers' practice, it is said:

This advice can be easily applied to most situations. Simply put, the function
or object that allocates resources should be responsible for releasing resources.

This is actually what we often say that whoever allocates is responsible for releasing it. This is also a principle of memory release. This principle can be extended, that is, whoever allocates resources will allocate and release them; this is really a very common thing. , such as the allocation and release of database stock connections.

I wrote a simple example to illustrate this situation. This example is simply to read out the price, then change the price, and then write:

void Market::readCustomer()
{
    
    
    fopen_s(&m_pf, "test.txt", "r+");

    if (m_pf != nullptr)
    {
    
    
        CUSTOMER p = {
    
    0};
        fscanf(m_pf, "%s %d", p.name, &p.price);
        printf("%s %d\n", p.name, p.price);
    }
}

void Market::writeCustomer()
{
    
    
    if (m_pf != nullptr)
    {
    
    
        CUSTOMER p = {
    
     "zhangsan", m_money };
        fprintf(m_pf, "%s %d\n", p.name, p.price);
        printf("%s %d\n", p.name, p.price);
        fclose(m_pf);
        m_pf = nullptr;
    }
}

void Market::updateCustomer(int money)
{
    
    

    this->readCustomer();
    m_money = money;
    this->writeCustomer();

}

To make it clear, write down part of the code in the header file:

typedef struct Customer
{
    
    
    char name[10];
    int price;

}CUSTOMER;

private:
     FILE* m_pf;
     int m_money;

The above code updateCustomer looks fine, but it is found that it is coupled with the variable m_pf. From a functional point of view, it is indeed coupled with this variable, which is not a good thing;

Later, some needs were added, and the price was changed after requiring more than 100 yuan. The programmer may change it to the following:

void Market::updateCustomer(int money)
{
    
    

    this->readCustomer();
    m_money = money;
    if(m_money > 100)
    {
    
    
    	this->writeCustomer();
    }

}

Run the code, and after a while, it prompts that there are too many open files. It turns out that those customers who are less than 100 only open the file link, but do not close the file link. The possible changes are as follows:

void Market::updateCustomer(int money)
{
    
    

   this->readCustomer();
   m_money = money;
   if(m_money > 100)
   {
    
    
   	this->writeCustomer();
   }
   else
   {
    
    
     fclose(m_pf);
   }

}

Now the problem is solved, but there is three couplings of a variable, and the most serious thing is that the state of the file becomes confused.

Programmers practice describing this kind of problem like this:

This has been fixed - the file is now indeed closed if the new balance is not taken into account.
However, this fix means that the three routines are coupled
together by the shared variable m_pf, and keeping track of when the file is open and closed starts to get
messed up. We are falling into a trap, and things will start to deteriorate rapidly if we continue on this path
. It's unbalanced!

Then, if you use the principle of beginning and end, the changes are as follows:

void Market::readCustomer(FILE *pf)
{
    
    
    if (pf != nullptr)
    {
    
    
        CUSTOMER p = {
    
    0};
        fscanf(pf, "%s %d", p.name, &p.price);
        printf("%s %d\n", p.name, p.price);
    }
}

void Market::writeCustomer(FILE *pf)
{
    
    
    if (pf != nullptr)
    {
    
    
        CUSTOMER p = {
    
     "zhangsan", m_money };
        fprintf(pf, "%s %d\n", p.name, p.price);
        printf("%s %d\n", p.name, p.price);
    }
}

void Market::updateCustomer(int money)
{
    
       
    FILE *pf;
    fopen_s(&pf, "test.txt", "r+");
    this->readCustomer(pf);
    m_money = money;
    this->writeCustomer(pf);
    fclose(pf);
    pf = nullptr;
}

This makes the code much clearer:

We modified the code to pass the file reference in as a parameter instead of holding the reference internally
[5]. All responsibility regarding the file is now in the updateCustomer routine.
It opens the file, and (continuously) closes it before returning. The routine maintains
the balance of file usage: opening and closing are at the same place, and it is obvious that every
open operation on a file has a corresponding close operation. The refactoring also removed an ugly shared variable
.

Summarize

Only when this principle is followed everywhere in the code can the code be clear and simple.
image.png

Guess you like

Origin blog.csdn.net/maokexu123/article/details/130330119