本文通过一个Solana智能合约中的奖励分配逻辑的实际案例,强调了使用集合论的思维方式来确保代码的健壮性。核心思想是将问题划分为完整的子集,从而全面考虑所有可能的情况,减少bug的产生,并优化链上存储的使用。
昨天,在审查一位团队成员的代码时,我在一个看似简单的方法中发现了一个有趣的问题。这是一个 Solana 智能合约,我们需要最大限度地减少存储使用,因为链上有约束,这使得高效且无错误的实现更加重要。
任务是实现一个简单的奖励分配逻辑:如果一天的交易数量超过 K,则发放奖励,但每天只发放一次。
最初的实现如下所示:
// 变量
latestDispatchedTime // 记录上次发放奖励的时间
tradeCount // 记录当天的交易数量
// 实现
// 如果今天有交易,首先清除交易计数
// 以确保我们不会累积未达到 K 交易的历史值
if latestDispatchedTime != yesterday and latestDispatchedTime != today {
tradeCount = 0
}
// 累积交易
// 检查是否达到阈值 K,发放奖励
该实现存在一个 bug,可能导致多次奖励发放。当然,我们可以在奖励发放点添加额外的检查,以验证今天是否已经发放了奖励,但我认为这揭示了一种次优的问题解决方法。
编写 bug 最少的代码从根本上取决于我们对问题的思考是否完整——我们是否考虑了所有可能的场景。
我们如何确保全面考虑?
在本科计算机科学中,有一门课程叫做离散数学,它讨论了全集的概念,它的真子集 A,以及它的补集,它们共同覆盖了整个集合。我们需要找到对问题的划分,以提供完整的覆盖。
对于这个特定案例,我们可以这样思考:
当给定的一天有交易时,有两种可能的场景:
这两种情况完全涵盖了奖励发放问题的所有可能性。
如果已经发放了奖励,我们不需要做任何事情——只需返回。如果尚未发放奖励,则有两种子场景:
— 清除历史记录
— 累积交易计数
— 累积交易计数
— 检查是否达到阈值 K;如果是,则发放奖励并更新奖励时间
并不是说这种方法更优雅;而是,我们的问题解决模型和思考过程决定了代码中出现 bug 的可能性。
更正后的实现将是:
// 如果今天已经发放了奖励,只需返回
if latestDispatchedTime == today {
return
}
// 如果这是当天的第一笔交易
if latestDispatchedTime > 0 {
tradeCount = 0 // 清除历史记录
}
// 累积交易计数
tradeCount += 1
// 检查是否达到阈值
if tradeCount == K {
latestDispatchedTime = today // 记录奖励发放时间
tradeCount = 0 // 重置交易计数
// 奖励发放逻辑
}
要编写 bug 较少的代码,我们思考问题的方式至关重要。当我们的思维全面时,出现 bug 的可能性会大大降低。在 Solana 智能合约的背景下,存储效率至关重要,这种方法不仅会产生更可靠的代码,还有助于优化我们的链上存储使用。
完整的思考帮助我们:
在日常开发中,培养这种“划分和完整性”的思考习惯将大大减少程序中潜在的 bug,这在处理区块链环境的约束时尤为重要。
- 原文链接: medium.com/@MrMaxPi/how-...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!