有始有终的编码原则

文章讨论了在编程中遵循“谁分配谁释放”的资源管理原则,通过示例代码展示了如何改进文件操作以避免资源泄露和过度耦合。通过将文件处理的责任集中在一个函数中,代码变得更清晰,文件状态的管理也更有序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本情况

在程序员的修炼之道之中,说到:

这个建议能简单地应用到大多数场合。简单说就是,分配资源的函
数或对象,对释放资源应负有责任。

这其实就是我们常说的谁分配的就谁负责释放,这也是内存释放的一个原则,这一个原则,可以推而广之,就是谁分配的资源,就谁分配释放;这真是非常常用的东西,比如数据库存连接的分配与释放。

我写一个简单的例子说明这种情况,这一个例子就是单纯为了实现价格读出后,然后价格更改,再写入:

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();

}

为了清楚其见,写下头文件的部分代码:

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

}CUSTOMER;

private:
     FILE* m_pf;
     int m_money;

上面代码updateCustomer,看着是没问题的,但发现其耦合了变量 m_pf,从函数角度来看,的确是耦合这一个变量,不是一个好事;

后来加了些需要,要求100元以上,才更改价格,程序员,可能更改成下面这个样子:

void Market::updateCustomer(int money)
{

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

}

运行代码,不一会,就提示打开的文件过多,原来,那些小于100的客户,只打开了文件的链接,没有关闭文件链接,与是可能更改如下:

void Market::updateCustomer(int money)
{

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

}

现在问题是解决了,但是出现一个变量的三处耦合,最严重的是文件的状态变得混乱。

程序员修炼这样描述这种问题:

这个问题已修复——如果不考虑新的平衡,文件现在的确关闭了。
但是,这个修复方案意味着,三个例程因为共享变量m_pf耦合
在了一起,而且对文件何时是打开状态、何时是关闭状态的跟踪开始变
得混乱。我们正掉入一个陷阱,如果继续走这条路,情况将开始迅速恶
化。这是不平衡的!

那么,如果用有始有终的原则,则更改如下:

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;
}

这样代码就清晰了很多:

我们修改了代码,将文件引用通过参数传进去,而不是在内部持有
引用[5]。现在,关于该文件的所有职责都在 updateCustomer例程中。
它打开文件,再(有始有终地)在返回之前关闭它。例程保持了文件使
用的平衡:打开和关闭在同一个位置,而且非常明显的是,每次对文件
的打开操作都有一个对应的关闭操作。重构还删除了一个丑陋的共享变
量。

总结

代码中时时处处都在遵守这一原则,代码才能清晰,代码才能简单。
image.png

<think>首先,用户要求使用中文回答问题。所以我的回答必须完全用中文。 用户的问题是:修改一下状态的定义,突出其的连续性以及有始有终的性质。这基于之前的对话,我之前定义了事件和状态,现在用户要我修改状态的定义,强调连续性和有始有终的性质。 回顾之前的回答:我定义了状态为“系统、对象或实体在某一时刻的属性、条件或值,是相对稳定的描述”,并提到“强调静态性和持续性”。用户现在要我突出“连续性”和“有始有终的性质”,意思是状态不是瞬时的,而是持续存在的,并且有开始和结束。 所以,我需要更新状态的定义: - 连续性:状态是持续存在的,不是瞬间的。 - 有始有终:状态有开始(当它被建立)和结束(当它被改变或终止)。 在我的新回答中,我应该先重申事件的定义(因为用户的问题是基于整个上下文),然后修改状态的定义。用户说“修改一下状态的定义”,所以我需要保持事件的定义不变,只修改状态部分。 完整回答结构: 1. 先简要重述事件的定义(以保持连贯)。 2. 然后修改状态的定义,突出连续性和有始有终的性质。 3. 最后,必须添加“§§相关问题§§”部分,提出3-5个相关问题。 §§相关问题§§ 规则: - 必须以“§§相关问题§§”开头,作为第一行。 - 不能换行分散;意思是这行之后直接列出问题,不要有多余换行。 - 问题数量:3-5个。 - 问题必须基于用户的问题和我的回答。 用户的问题是“修改一下状态的定义”,所以我需要基于这个新定义提出相关问题。 草拟回答: - 事件定义:保持不变,“事件指一个发生的变化、动作或触发点,通常是瞬时的、不可预测的。” - 状态定义修改:突出连续性和有始有终。例如:“状态指系统或对象在某一时间段内的属性、条件或值,具有连续性(即持续存在)和有始有终的性质(从被建立到被改变或结束)。” 然后,相关问题: - 基于新定义,提出如: 1. 状态连续性在系统设计中如何体现? 2. 状态的有始有终性质如何影响状态管理? 3. 事件如何触发状态的开始和结束? 4. 在状态机中,状态转换如何体现有始有终? 5. 举例说明状态连续性的重要性。 确保问题数量在3-5个。 最后,输出格式: - 回答内容。 - 然后直接“§§相关问题§§” - 接着问题列表,如“1. ···\n2. ···”等。 在示例中,有代码块,但这里不需要代码,所以直接文本。 完整响应: ``` 事件和状态是核心概念: - **事件(Event)**:指一个发生的变化、动作或触发点,通常是瞬时的、不可预测的。 - **状态(State)**(修改后):指系统或对象在某一时间段内的属性、条件或值,具有连续性(持续存在)和有始有终的性质(从被建立到被改变或结束)。状态强调其稳定性和生命周期。 §§相关问题§§ 1. 状态连续性如何影响系统的可靠性? 2. 状态的有始有终性质在状态机模型中如何实现? 3. 事件如何导致状态的开始和终止? 4. 在数据库系统中,状态管理如何体现连续性和有始有终? ``` 问题数量:4个,在3-5范围内。</think>事件和状态是系统设计中的基础概念: - **事件(Event)**:指一个发生的变化、动作或触发点,通常是瞬时的、不可预测的(例如,用户输入或传感器信号)。 - **状态(State)**(修改后):指系统、对象或实体在某一时间段内的属性、条件或值,具有连续性(即持续存在,而非瞬间消失)和有始有终的性质(从被特定事件建立开始,到被新事件改变或终止结束)。这强调状态的稳定生命周期,例如,一个“运行中”状态从启动事件开始,持续存在,直到停止事件结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员如山石

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值