常见优秀代码汇总

汇总常见的编程习惯

1. 语义简单明确

 含义:写代码时考虑读者,优先采取易于读者理解的写法。

#define THROTL_UNSET      -2
#define THROTL_NO_LIMIT   -1

bool throttle_is_quota_valid(int64_t value)
{
    // 复杂的判断条件
    // 请你在三秒内说出 value 如何取值是合法的?
    if (value < 0 && value != THROTL_UNSET && value != THROTL_NO_LIMIT)
    {
        return false;
    }
    return true;
}

bool throttle_is_quota_valid(int64_t value)
{
    // 这是修改后的代码,value 取值合法有三种情况,一目了然
    return value >= 0 || value == THROTL_UNSET || value == THROTL_NO_LIMIT;
}

2. 简洁 ≠ 代码短

简洁≠代码短,复杂的问号表达式反而不如 if..else 方便理解。

void RecycleBin::Load(BindCallbackR1<Status>* done)
{
    ......
    FOREACH(iter, fileStats)
    {
        RecycleFile item;
        Status status = ParseDeletedFileName(iter->path, &item.timestamp);
        if (!status.IsOk() { ...... }
        item.fileName = iter->path;
        item.size = iter->size;
        item.physicalSize = iter->refCount > 1 ? 0 : iter->physicalSize;
        ......
        // 这是修改前的代码
         earliestTimestamp[item.medium] =
             item.timestamp != 0 && item.timestamp < earliestTimestamp[item.medium] ?
             item.timestamp : earliestTimestamp[item.medium];
         }
        // 这是修改后的代码
        if (item.timestamp != 0 &&
            item.timestamp < earliestTimestamp[item.medium])
        {
            earliestTimestamp[item.medium] = item.timestamp;
        }
    }
    ......
}

3. 提前返错

提前返错能减少主体逻辑的缩进数量,让主体代码逻辑显得更醒目。

Status Foo()
{
    Status status = Check1();
    if (!status.IsOk())
    {
        return status;
    }
    else
    {
        status = Check2();
        if (!status.IsOk())
        {
            return status;
        }
        else
        {
            ..............
        }
      }
}
//修改为

Status Foo()
{
   Status status = Check1();
   if (!status.IsOk())
   {
       return status;
   }
   status = Check2();
   if (!status.IsOk())
   {
       return status;
   }
}

4.利用析构函数做清理工作(针对C++)

利用 C++ 析构函数做清理工作,在复杂冗长代码中不会漏掉。典型的清理工作有执行回调、关闭文件、释放内存等。


void Foo(RpcController* ctrl,
         const FooRequest* request,
         FooResponse* response,
         Closure* done)
{
    Status status = Check1(request);
    if (!status.IsOk())
    {
        response->set_errorcode(status.Code());
        // 第一处
        done->Run();
        return;
    }
    status = Check2(request);
    if (!status.IsOk())
    {
        response->set_errorcode(status.Code());
        // 第二处
        done->Run();
        return;
    }
    DoSomeRealWork(...);
    // 第三处
    done->Run();
}

//修改为:
void Foo(RpcController* ctrl,
         const FooRequest* request,
         FooResponse* response,
         Closure* _done)
{
    // 仅一处,不遗漏
    erpc::ScopedCallback done(_done);
    Status status = Check1(request);
    if (!status.IsOk())
    {
         response->set_errorcode(status.Code());
         return;
    }
    status = Check2(request);
    if (!status.IsOk())
    {
         response->set_errorcode(status.Code());
         return;
    }
    DoSomeRealWork(...);
}

5. 用朴素直观的算法

在非关键路径上,优先使用朴素直观的算法,此时代码可维护性更重要。


void CompactTask::checkFileUtilizationRewrite()
{
    // 此处采取朴素的排序算法,并未采取更高效的 TopK 算法
    std::sort(sealedFilesUsage.begin(), sealedFilesUsage.end(), GarbageCollectionCompare);
    
    int64_t sealedFileMaxSize = INT64_FLAG(lsm_CompactionSealedMaxSize);
    int32_t sealedFileMaxNum = INT32_FLAG(lsm_CompactionSealedMaxFileNum);
    int64_t targetFileSize = 0;
    int32_t sourceFileCnt = 0;                                                                                                                                      
    // 前者简单清淅,并在几十个 File 中选择前几个文件的场景并不算太慢
    FOREACH(itr, sealedFilesUsage)
    {
        LogicalFileId fileId = itr->fileId;
        const FileUsage* usage = baseMap->GetFileUsage(fileId);
        const File* file = fileSet->GetFile(fileId);
        targetFileSize += usage->blocks * mBlockSize;
        sourceFileCnt++;

        if (targetFileSize > sealedFileMaxSize || sourceFileCnt > sealedFileMaxNum)
        {
            break;
        }
        mRewriteSealedFiles[fileId] = true;
    }
    ......
}

6.用轮循代替条件变量

在非关键路径上使用简单的轮循代替精巧的条件变量同步,代码简洁且不容易出 bug。

7. 避免有歧义的函数名和参数表

函数名和参数表要符合直觉,大多数使用者没空读你的注释,小部分使用者读了你的注释也看不明白。

参考文献:

1. 阿里云块存储团队软件工程实践

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

帅气滴点C

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

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

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

打赏作者

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

抵扣说明:

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

余额充值