[译]合约整洁之道-智能合约形式和理论指南

binance社区 4 20

区块链和智能合约的开发仍是相对较新的且高度试验性的。 他们需要与传统收集或应用开发差别的工程思维体例,传统收集或应用开发已成为“快速动作并突破常规”的原则。

区块链开发更像是硬件或金融办事开发。 智能合约是复杂的东西,能够供给具有通明,防窜改和不成变信息的自我施行合约。 他们有权在复杂系统之间分配高价值资本。 合约往往自主工做,面对庞大的财政丧失风险,使得智能合约成为那些系统中的关键组件。 开发此类组件需要更多的投入,设想和前期工做。 扎实的工程理论,严酷的测试和强大的平安意识。

在一系列博客文章中,我方案介绍几种可应用于区块链和智能合约开发的形式,理论和原则,以降低与之相关的风险。

代码整洁之道

在第一篇文章中,我将介绍更多基于Clean Code概念的通用工程理论。 整洁代码是软件开发行业中寡所周知的概念。 罗伯特·C·马丁(Robert C Martin),也称为“鲍勃叔叔”(Uncle Bob),写下了出名的手册。 它的原理以至能够逃溯到敏捷宣言和软件工艺的早期概念。 那是我们思虑,编写和阅读代码的体例的常识库。 以数十年的软件开发聪慧为根底。

“Truth can only be found in one place: the code”(实理只能在代码中发现)- Robert C. Martin

整洁的代码是易于阅读的代码,容易理解,而且易于维护。简洁的代码是一种测验考试,以领会我们正在处置的系统的复杂。 它是一种防御机造,当你不确定某个更改将若何影响代码库时,它能够供给指点。虽然手册存在有效的攻讦,而且示例被认为已过时,但那些原则仍然十分相关。 出格是关于面向对象的语言,例如Solidity。 它们适用于设想和编写平安,开源和稳定的代码,如智能合约。

合约、函数或变量的定名应该提醒其企图、存在原因以及若何利用。若是一个名字需要正文来解释,那么它不会透露它的企图。

代码的定名要一致。出格是当你利用一个大型的代码库时。在多个合约中,对笼统概念利用不异的名称。

利用可读得出的名字。

利用可搜刮的名称。

“There are only two hard things in Computer Science: cache invalidation and naming things.”(计算科学中最难的两件事是缓存失效和定名) - Phil Karlton

References

代码示例 Solidity 气概指南 构造 挨次

挨次帮忙读者确定能够挪用哪些函数,更容易找到构造函数和回退定义。

构造挨次

按以下挨次摆列合约元素

Pragma 语句 Import 语句 Interfaces Libraries Contracts

在每个合约、库或接口中,利用以下挨次

类型声明 形态变量 Events Functions 函数排序

函数应该按照其可见性和挨次停止分组

constructor receive 函数 (若是存在) fallback 函数 (若是存在) external public internal private

明白标识表记标帜函数和形态变量的可见性。能够将函数造定为 external, public, internal, 或 private. 请领会它们之间的区别。

润色符的排序

函数的润色符挨次应为:

Visibility Mutability Virtual Override Custom modifiers

References

代码示例 Solidity 气概指南 文档 Natspec

Solidity合约能够接纳正文的形式,为阅读代码的其别人以及最末用户供给丰硕的文档。 那称为以太坊天然语言标准格局,或 NatSpec.

本文档分为面向开发人员的动静和面向最末用户的动静。那些动静能够在与合约交互时显示给最末用户(人)(即签名一个交易)。

建议对所有公共接口(ABI中的所有内容)利用NatSpec对Solidty合约停止完全正文。

References

代码示例 NatSpec

阅读代码应该像阅读那个博客、一篇文章或一本书一样。它应该被很好地格局化。Solidity气概指南为编写Solidity代码供给了指点。它的目的不是准确的或独一的办法,而是要连结一致。

能够通过利用lint来实现一致性。 那不只供给格局和款式指南验证,还包罗平安验证。

Solidity可用的lint

Ethlint (原名 Solium) Solhint VS Code Solidity

为您的dapp开发利用常规的lint(例如eslint,详细取决于您的语言)。

References

代码示例 Solidity 气概指南 合约 数据构造 合约公开了行为并隐藏了数据 (笼统地说。现实上并未向其别人隐藏数据。现实上,区块链上没有数据被隐藏,请拜见章节-合约)。那使得在不更改现有行为的情况下添加新的对象变得容易。 那也使得很难向现有对象添加新行为。 数据构造公开数据,没有显著的行为。那使得向现有数据构造添加新行为变得容易,但向现有函数添加新数据构造却变得困难。

因为合约的不成变性,明白区分两者是很重要的。若是希望添加逻辑或摆设新合约,则希望可以操纵现有的数据构造。将两者别离能够通过存储合约实现。我们将在另一篇博客文章中更详细地介绍那些。

连结简单曲白(Keep it Simple Stupid ,KISS)。 复杂性增加了呈现错误和不测行为的可能性。合约应该只要一个责任,只要一个变动的理由,撑持单一责任原则(Single Responsibility Principle)。它是OO设想中最重要的概念之一。

连结你的合约规模小。智能合约中的每一行代码施行起来都要花钱,存储数据也很高贵。更佳理论是在智能合约中存储数据指针,而不是存储数据自己。例如,能够利用去中心化的数据存储供给商(如IPFS)存储数据。

将您的合约模块化,使其连结较小的规模,并操纵现有的尺度和库(拜见章节“尺度 库”)。

功用同样如斯。函数应该只做一件事。他们应该做好。他们只能如许做。

在区块链上,一切都是公开的。智能合约中的私有数据和变量现实上不是私有的。 “Private”是指在合约的施行范畴内,但数据是公开的,任何人都能够读取。 设想法式时请记住那一点。

仅将区块链和智能合约用于需要去中心化的部门。

“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.”(函数的第一个规则是它们应该很小。 函数的第二个规则是它们应该比小更小) - Robert C. Martin

尺度 库

智能合约的一个固有特征是它的可组合性。将每份合约酿成其别人能够操纵的构成部门和潜在的构建基块。 那些构件良多,已经存在,而且尺度确保了易于利用和开发。最出名的尺度是为新兴通证生态系统(token ecosystem)及其办事的交易所创建的:ERC20尺度。

在起头编写本身的、自定义的智能合约之前,明智的做法是查抄能否存在任何尺度或开源组件。若是存在如许的尺度合约,而且颠末恰当的测试和审计,它们能够将您的法式中的风险降到更低。

以太坊改良建议(Ethereum Improvement Proposals,EIPs)描述了以太坊平台的尺度,包罗合约尺度 describe standards for the Ethereum platform, including contract standards. 最末的ERC OpenZeppelin Contracts 错误处置

异常是现代软件工程的关键部门。它们需要特殊处置,而且功用十分强大。与其匹敌,我们应该测验考试操纵它们,因为未处置的异常可能会招致不测行为。

当在Solidity代码中引发异常时,所有形态更改都将回滚并停行进一步施行。幸运的是,Solidity内置了异常处置功用(自0.6版本起头)。那仅适用于外部挪用(external calls)。

为异常供给足够的上下文,以确定错误的来源和原因。测验考试编写引发那些异常的测试。

测验考试编写抛出那些异常的测试。

不要返回null。不要将null传递给函数。

庇护查抄(Guard Checks)能够帮忙确保智能合约的行为及其输入参数契合预期。

准确利用 assert(), require(), revert() . assert 应该用于测试内部错误,并查抄常量。require 应该用于测试输入,合约形态变量或来自外部合约的返回值能否有效。

若是交易没有足够的gas来施行,则不会捕捉gas溢出错误。

Testing

整洁代码的不异规则也适用于测试。整洁的测试是易于阅读的测试,容易理解,而且易于维护,测试能够帮忙您连结代码的灵敏性,可维护性和可重用性。它们能够验证行为,降低停止不测更改的风险,并节省调试和编写代码的时间。

F.I.R.S.T Fast — 测试速度应该足够快,以便经常运行它们。它应该有助于加速您的开发过程,而不是障碍它 Independent — 测试应该彼此独立而且能够按任何挨次运行 Repeatable — 测试应该在任何情况中都是可反复的 Self-validating — 若是测试通过,则应该有一个明晰的(布尔)输出 Timely — 测试需要及时编写。就在消费代码之前。

AAA (Arrange-Act-Assert) 形式是软件测试中最常见的尺度之一。它建议将测试划分为响应的部门:arrange、act和assert。它们中的每一个都负责它们被定名的部门。

Arrange -设置测试所需的代码 Act - 被测试办法的挪用 Assert - 查抄能否到达预期

每个测试只利用一个断言。

测试别离 单位测试 确定一个源代码单位能否合适利用。那凡是是一个零丁的函数,利用差别的参数停止测试,以确保它返回预期值。 集成测试 确定独立开发的软件单位在毗连时能否一般工做。关于智能合约,那意味着单个合约的差别组件之间或多个合约之间的交互。 测试笼盖率

编写好的测试来确保你的应用法式按预期工做是不敷的。若是你没有丈量任何工具,很难说到底有几代码正在被测试。测试笼盖率(或代码笼盖率)是查找代码库中未测试部门的有用东西。

关于笼盖几有良多争论。就你更好的判断,但要尽可能高。未经测试的代码可能会施行任何操做并招致不测行为。

测试东西 Buidler - 一个面向以太坊智能合约开发人员的使命运行器,允许您摆设合约、运行测试和调试代码 OpenZeppelin Test environment - 是一个智能合约测试库:它供给帮忙您编写测试的适用法式,但它不会为您运行测试。与Mocha一路工做 Brownie - 针对以太坊虚拟机的智能合约基于Python的开发和测试框架 Truffle - 利用以太坊虚拟机(EVM)的区块链开发情况、测试框架和资产管道 Ganache - 用于以太坊开发的小我区块链,可用于摆设合同、开发应用法式和运行测试 Solidity-coverage (原名 Solcover) - Solidity智能合约的代码笼盖率 平安 代码阐发

静态代码阐发是对没有现实施行法式的软件停止的阐发。在大大都情况下,阐发是在源代码的某个版本上施行的。阐发凡是由主动化东西(如Sonarqube)施行。

智能合约阐发东西有助于识别智能合约破绽。那些东西运行一套破绽检测器,打印动身现的任何问题汇总。

阐发东西 Echidna - 以太坊智能合约模糊器 Manticore - 符号施行东西 Mythril - EVM字节码的平安性阐发东西 Oyente - 智能合约阐发东西 Slither - Solidity静态阐发东西 Gas优化

优化gas成本可能是一项值得勤奋的工做,以削减您本身的摆设以及最末用户的成本。 跟着当前gas成本到达高峰,收集利用量正在逐渐增加。跟着生态系统的不竭开展,gas优化的价值也将随之增长。我们将在另一篇博客文章中更详细地介绍那些内容。

能够利用eth-gas-reporter阐发代码。 它打印每个函数或每个已摆设合约的gas成本预算。

持续集成

固然不是整洁代码原则的一部门,但持续集成(continuous integration,CI)已经成为任何类型软件开发的根本理论。持续集成的一个次要益处是,您能够快速检测错误并更容易地定位错误。

它基于一系列关键原则。

连结一个存储库,所有代码都存放在此中,任何人都能够获适当前和以前的版本(例如Git) 主动化构建过程,以便任何人都能够利用它间接从源代码停止构建(例如Truffle团队、Travis CI) 主动化您的测试,如许任何人都能够在任何时候运行完好的测试套件(拜见章节 测试) 确保任何人都能够查看成果并从构建过程中获取最新的可施行文件

也许您对下面的内容还感兴趣:

留言4

  1. 犬走楚萓
    回复
    有人愿意呗,不见黄河心不死
  1. 雨巷少年来玉
    回复
    以前比特时代买币的时候,其他的都额度太小不给提现
  1. 无冬玉华
    回复
    他一直发推没啥用吧,,隔三差五发一次还行
  1. 是沈思吖
    回复
    等!我已经看两次狗币爬,所有币基本跌

评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。