Aken合约开发:5步学会!告别高Gas费,席位有限

 

Kraken平台智能合约开发部署方法

Kraken交易所作为全球领先的数字资产交易平台之一,为开发者提供了智能合约开发和部署的便利。本文将详细介绍在Kraken平台上进行智能合约开发和部署的步骤,帮助开发者更好地利用Kraken平台进行区块链应用开发。

1. 开发环境搭建

在开始智能合约开发之前,构建一个完善且高效的开发环境至关重要。以下是常用的、推荐的开发环境组件,以及它们在智能合约开发流程中的作用:

  • Node.js 和 npm (或 yarn):

    Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,允许我们在服务器端运行 JavaScript 代码。npm (Node Package Manager) 是 Node.js 的默认包管理器,而 yarn 是一个可选的、更快速和可靠的包管理器。它们都用于安装、管理和更新项目所需的 JavaScript 依赖和构建工具,例如 Truffle、Ganache 和各种库。

    安装步骤:

    1. 访问 Node.js 官网 ( https://nodejs.org ) 下载适合您操作系统的最新 LTS (长期支持) 版本。
    2. 按照安装向导完成 Node.js 的安装。
    3. npm 会随 Node.js 一起安装。 安装 yarn 可以通过运行 `npm install -g yarn` 命令。
  • Truffle Suite:

    Truffle Suite 是一个全面的以太坊开发框架,它简化了智能合约的开发、部署、测试和调试过程。它包含 Truffle、Ganache 和 Drizzle 三个核心组件,形成一个完整的开发生态系统。

    Truffle 提供了合约编译、链接、部署和管理的工具,支持自动化合约迁移和复杂的测试场景。它还内置了对 Solidity 调试器的支持,方便开发者排查代码问题。

    安装步骤: 运行 `npm install -g truffle` 命令全局安装 Truffle。

  • Ganache:

    Ganache 是一个本地的、私有的以太坊测试网络,用于模拟真实的区块链环境。它允许开发者在无需连接到公共以太坊网络的情况下,快速、安全地测试和调试智能合约。Ganache 提供了一个用户友好的界面,可以方便地查看账户余额、交易记录和区块信息。它还可以自定义区块时间和 gas 限制,以满足不同的测试需求。

    安装步骤:

    1. 可以从 Truffle Suite 官网下载 Ganache 的桌面应用程序。
    2. 也可以使用 npm 全局安装 Ganache CLI: `npm install -g ganache-cli` 。
  • MetaMask:

    MetaMask 是一个流行的浏览器插件钱包,它允许用户在浏览器中与去中心化应用程序 (DApps) 和智能合约进行交互。它充当了用户和以太坊网络之间的桥梁,使用户可以安全地管理自己的以太坊账户、发送交易和签署消息。

    MetaMask 支持多种以太坊网络,包括主网、测试网 (如 Ropsten、Kovan、Rinkeby 和 Goerli) 和本地 Ganache 网络。开发者可以使用 MetaMask 连接到本地 Ganache 网络,并在浏览器中测试和调试智能合约。

    安装步骤: 从 Chrome 网上应用店或 Firefox 附加组件网站安装 MetaMask 浏览器插件。

具体步骤如下:

  1. 安装 Node.js 和 npm:

    访问 Node.js 官方网站 (https://nodejs.org/),下载适合您操作系统的最新稳定版本。Node.js 包含了 npm (Node Package Manager),它是用于安装和管理 JavaScript 包的工具。安装过程中,请确保勾选将 Node.js 添加到系统环境变量的选项,以便在命令行中直接使用 node npm 命令。

    安装完成后,打开命令行工具(例如 Windows 上的命令提示符或 PowerShell,macOS/Linux 上的终端),输入以下命令验证 Node.js 和 npm 是否成功安装:

    node -v
    npm -v
    

    这两个命令会分别显示 Node.js 和 npm 的版本号。如果成功显示版本号,则表明安装成功。

  2. 安装 Truffle Suite:

    Truffle Suite 是一套用于以太坊开发的工具,包括 Truffle 框架、Ganache 模拟器等。要安装 Truffle,请打开命令行工具,并执行以下 npm 命令:

    npm install -g truffle
    

    -g 选项表示全局安装,这意味着 Truffle 将安装在您的系统路径中,您可以在任何目录下直接使用 truffle 命令。安装完成后,可以输入以下命令验证 Truffle 是否安装成功:

    truffle version
    

    该命令会显示 Truffle 的版本信息。

  3. 安装 Ganache:

    Ganache 是一个个人以太坊区块链,用于开发、测试智能合约。它模拟了以太坊区块链的功能,但不需要连接到真实的以太坊网络,可以更快、更安全地进行开发。

    您可以选择安装 Ganache CLI (命令行界面) 版本或 Ganache GUI (图形用户界面) 版本。

    • Ganache CLI: 使用 npm 安装 Ganache CLI 的命令如下:
      npm install -g ganache
      
      安装完成后,可以使用 ganache 命令启动 Ganache CLI。
    • Ganache GUI: 您也可以从 Truffle Suite 官方网站 (https://www.trufflesuite.com/ganache) 下载 Ganache GUI 版本。下载完成后,双击安装程序并按照提示进行安装。Ganache GUI 提供了一个更友好的图形界面,方便您查看区块链的状态、账户信息等。
  4. 安装 MetaMask:

    MetaMask 是一款浏览器插件,作为一个以太坊钱包,允许用户与以太坊区块链进行交互。您可以在 Chrome、Firefox、Brave 等浏览器中安装 MetaMask 插件。

    访问 MetaMask 官方网站 (https://metamask.io/),选择您使用的浏览器,下载并安装 MetaMask 插件。安装完成后,按照 MetaMask 的引导创建一个新的钱包,或者导入一个已有的钱包。请务必妥善保管您的助记词(Seed Phrase),这是恢复您钱包的唯一方式。

    安装并配置 MetaMask 后,您可以在 Ganache 中创建一个新的账户,并将该账户的私钥导入到 MetaMask 中,以便在开发和测试过程中使用 Ganache 区块链上的资金。

2. 创建 Truffle 项目

完成开发环境的配置后,即可开始构建新的 Truffle 项目。Truffle 为开发者提供了一套标准化的项目结构和便捷的命令,可以大幅提升开发效率。

  1. 创建项目目录:

    在命令行终端中,选择一个合适的路径,创建一个专门用于存放项目文件的目录。推荐采用具有描述性的目录名,方便后续管理。

    mkdir kraken-smart-contract
    cd kraken-smart-contract
  2. 初始化 Truffle 项目:

    进入新创建的项目目录后,使用 Truffle 提供的初始化命令,生成项目所需的必要文件和目录结构。

    truffle init

    该命令执行完成后,将会自动创建一个包含以下关键目录和文件的项目结构,这些目录和文件是智能合约开发、部署和测试的基础:

    • contracts/ : 用于存放智能合约的 Solidity 源代码文件(.sol 文件)。这是开发的核心部分,所有合约逻辑都将在此目录下编写。
    • migrations/ : 存放合约部署脚本。这些脚本使用 JavaScript 编写,用于指导 Truffle 如何将合约部署到区块链网络,并执行必要的初始化操作。
    • test/ : 用于存放合约的测试代码。编写全面的测试用例是保证智能合约质量的关键步骤。测试代码通常使用 JavaScript 或 Solidity 编写,并利用 Truffle 提供的测试框架进行断言和验证。
    • truffle-config.js (或 truffle-config.ts ): Truffle 的配置文件。该文件包含了项目所需的各种配置信息,例如区块链网络的连接参数、编译器版本、部署选项等。可以根据实际需求修改该文件,以定制 Truffle 的行为。

3. 编写智能合约

contracts/ 目录下,我们将构建组成去中心化应用程序(DApp)核心逻辑的智能合约。每一个智能合约都定义了一系列数据字段和函数,这些函数用于修改和读取这些数据。通过这些函数,外部用户和合约之间可以进行交互。 为了开始,我们将创建一个名为 SimpleStorage.sol 的Solidity合约,它将演示如何在以太坊区块链上存储和检索数据。

Solidity 代码:


pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 private storedData;

    /**
     * @dev 设置存储的数据值.
     * @param x 要存储的新的uint256数值.
     */
    function set(uint256 x) public {
        storedData = x;
    }

    /**
     * @dev 获取存储的数据值.
     * @return 返回存储的uint256数值.
     */
    function get() public view returns (uint256) {
        return storedData;
    }
}

该合约包含一个私有状态变量 storedData ,类型为 uint256 ,这意味着它只能存储非负整数。 set 函数允许外部用户设置 storedData 的值。 get 函数允许用户读取 storedData 的当前值。 set 函数是一个 public 函数,任何用户都可以调用它来更改 storedData 的值。 get 函数是一个 public view 函数,这意味着它可以被外部调用,并且不会修改区块链的状态。 view 关键字表示该函数是只读的,不消耗 gas。

为了更好地理解,我们为 set get 函数添加了 NatSpec 文档注释。这些注释以 "/**" 开始,并使用 "@dev" 标记来描述函数的功能。这些注释对于生成文档和帮助其他开发人员理解你的代码非常重要。

4. 编译智能合约

编写完成 Solidity 智能合约后,下一步是将其编译成以太坊虚拟机 (EVM) 可以理解的字节码。Truffle 提供了一个便捷的编译命令,简化了这一过程。

在命令行工具中,导航到您的 Truffle 项目根目录,然后执行以下命令:

truffle compile

该命令会自动搜索 contracts/ 目录下所有扩展名为 .sol 的 Solidity 源文件,并使用 Solidity 编译器 (solc) 对它们进行编译。 编译过程会生成两个重要的文件:应用程序二进制接口 (ABI) 和字节码 (bytecode)。

ABI (Application Binary Interface) :ABI 描述了合约的接口,包括合约中可用的函数、参数类型、返回值类型等。它是一个 JSON 文件,允许外部应用程序(如前端 JavaScript 代码或另一个智能合约)与您的合约进行交互,而无需了解合约的内部实现细节。ABI 充当合约的 API 文档,使得外部应用能够正确地调用合约函数。

字节码 (Bytecode) :字节码是智能合约的编译后版本,以一系列十六进制代码的形式表示。这便是实际部署到以太坊区块链上的代码,由 EVM 执行。字节码是 EVM 可以直接理解和执行的低级指令。

编译成功后,生成的 ABI 和字节码文件会保存在 build/contracts/ 目录下。每个合约对应一个 JSON 文件,其中包含了该合约的 ABI、字节码、合约名称、源代码哈希等信息。这些文件对于后续的合约部署和交互至关重要。

5. 部署智能合约

接下来,我们需要编写部署脚本,以便将编译后的智能合约安全且有效地部署到区块链网络上。在 Truffle 项目的 migrations/ 目录下,创建一个新的 JavaScript 文件,作为部署脚本,例如 1_deploy_simple_storage.js 。此文件将包含部署逻辑,指示 Truffle 如何在目标区块链上实例化你的智能合约。

artifacts.require 函数是 Truffle 提供的一个实用工具,它允许你在部署脚本中访问已编译的合约工件(Artifacts)。这些工件包含了合约的 ABI(Application Binary Interface)和字节码,是与合约交互的关键要素。


const SimpleStorage = artifacts.require("SimpleStorage");

在上面的代码片段中, artifacts.require("SimpleStorage") 加载了名为 "SimpleStorage" 的合约工件,并将其赋值给 SimpleStorage 常量。现在,你可以使用 SimpleStorage 常量来实例化和部署你的合约。

module.exports 定义了一个函数,该函数接受 deployer 对象作为参数。 deployer 对象是 Truffle 提供的,用于管理合约的部署过程。它包含 deploy 方法,用于将合约部署到区块链。


module.exports = function (deployer) {
    deployer.deploy(SimpleStorage);
};

deployer.deploy(SimpleStorage) 指示 Truffle 将 SimpleStorage 合约部署到配置的网络。Truffle 将处理交易的创建、签名和广播,确保合约成功部署到区块链上。

在部署合约之前,必须正确配置 Truffle 以连接到目标区块链网络。为此,你需要编辑 Truffle 项目根目录下的 truffle-config.js 文件。该文件包含了 Truffle 的各种配置选项,包括网络设置。

networks 对象定义了 Truffle 可以连接的各种区块链网络。每个网络配置都包含连接到特定区块链节点所需的信息,例如主机名、端口和网络 ID。


module.exports = {
    networks: {
        development: {
            host: "127.0.0.1",      // Localhost (default: none)
            port: 7545,              // Standard Ethereum port (default: none)
            network_id: "*",         // Any network (default: none)
        },
        // Add Kraken's network configuration here (if available)
        // kraken: {
        //    provider:  () => new HDWalletProvider(mnemonic, "https://rpc.kraken.com"),
        //   network_id: 1234,        // Kraken's network ID
        //    gas: 5000000,
        //   gasPrice: 25000000000
        // },
    },

    // ... other configurations
};

development 网络配置中, host 设置为 "127.0.0.1",表示本地主机。 port 设置为 7545,这是 Ganache 默认使用的端口。 network_id 设置为 "*",表示 Truffle 可以连接到任何网络 ID 的区块链。在实际部署到测试网络或主网络时,需要将 network_id 设置为正确的网络 ID。

可以根据需要添加其他网络配置。例如,可以添加一个 kraken 网络配置,用于连接到 Kraken 区块链(如果可用)。该配置需要提供一个 provider 函数,用于创建与 Kraken 节点的连接。还需要指定 network_id gas gasPrice 等参数。

正确配置 truffle-config.js 文件至关重要,因为它决定了 Truffle 将连接到哪个区块链网络以及如何与该网络交互。

重要提示: 需要注意的是,Kraken 平台通常没有自己的 EVM 兼容的区块链,因此无法直接在 Kraken 平台上部署智能合约。智能合约通常部署在以太坊或其他兼容 EVM 的区块链上。 如果您希望在与 Kraken 相关的环境中使用智能合约,可能需要使用其他 Layer 2 解决方案或侧链。 上面的 kraken 配置是一个示例,具体需要根据 Kraken 提供的 API 和文档进行配置。

如果 Kraken 提供相应的 RPC 端点,您需要将 provider 设置为连接到 Kraken 提供的 RPC 端点,并设置相应的 network_idgasgasPrice。 同时,您需要使用一个安全的私钥管理方案,例如 HDWalletProvider 来管理您的私钥。

配置完成后,就可以使用以下命令部署合约:

bash truffle migrate

该命令会执行 migrations/ 目录下的所有部署脚本,将合约部署到指定的区块链网络上。 如果使用 Ganache,请确保 Ganache 已经启动。

6. 与智能合约交互

部署完成后,我们可以使用 Truffle Console 或 MetaMask 等工具与智能合约进行交互。

使用 Truffle Console:

Truffle Console 提供了一个交互式的环境,允许你直接与部署在区块链上的智能合约进行交互。它基于 Web3.js 库,为你提供了一整套工具,便于合约的部署、测试和调试。

在命令行工具中,导航到你的 Truffle 项目目录,并执行以下命令来启动 Truffle Console:

truffle console

启动后,Truffle Console 会连接到你配置的区块链网络(例如 Ganache)。现在,你可以使用 JavaScript 代码与你的合约进行交互。

在 Truffle Console 中,你可以使用以下命令获取已部署的 SimpleStorage 合约实例:

SimpleStorage.deployed().then(instance => {
  simpleStorage = instance;
  return simpleStorage.get();
}).then(value => {
  console.log("Stored data:", value.toNumber());
});

这段代码首先通过 SimpleStorage.deployed() 获取合约实例。然后,调用 get() 函数来读取存储在合约中的数据,并通过 console.log() 打印到控制台。注意,由于 Solidity 中默认使用大数,所以需要 toNumber() 方法将结果转换为 JavaScript Number 类型。

接下来,你可以使用以下命令调用合约的 set 函数来更新存储的数据:

simpleStorage.set(123).then(() => {
  return simpleStorage.get();
}).then(value => {
  console.log("New stored data:", value.toNumber());
});

这段代码首先调用 simpleStorage.set(123) 函数,将存储的数据更新为 123 。调用 set 函数会发起一个交易,需要消耗 Gas。交易成功后,再次调用 get() 函数读取新的数据,并打印到控制台。这种模式允许你验证 set 函数是否成功更新了合约状态。Truffle Console 提供了便捷的方式来与你的智能合约进行交互,方便你进行开发、测试和调试。

使用 MetaMask:

MetaMask 是一款流行的浏览器扩展和移动应用程序,作为您的以太坊钱包,它允许您与去中心化应用程序 (DApps) 交互。要与您部署的智能合约进行交互,您需要将 MetaMask 连接到正确的区块链网络。 这通常意味着连接到您部署合约的测试网络,例如 Ganache 或 Goerli。

连接到正确的网络后,您就可以开始与合约交互。 这通常涉及将合约地址和应用程序二进制接口 (ABI) 添加到 MetaMask。合约地址是合约在区块链上的唯一标识符。ABI 是一个 JSON 格式的接口描述,它定义了合约中可用的函数以及如何调用它们。

您可以在编译后的合约构件中找到合约的 ABI。对于使用 Truffle 或 Hardhat 等工具构建的项目,ABI 通常位于 build/contracts/ 目录下的 JSON 文件中。该 JSON 文件包含合约的所有元数据,包括 ABI、合约地址(如果您已部署)以及其他有用的信息。找到 ABI 后,您可以将其复制并粘贴到 MetaMask 中,以便 MetaMask 能够理解如何与您的智能合约进行交互。

为了确保安全性,建议您仅从可信来源获取合约地址和 ABI,并仔细验证它们与您要交互的合约是否匹配。

7. 测试智能合约

为了确保智能合约的逻辑正确性和功能完整性,我们需要编写全面的测试用例进行测试。良好的测试覆盖率能够显著降低智能合约部署到生产环境后出现漏洞的风险。在 Truffle 项目的 test/ 目录下,按照约定,测试文件应该以 .js 结尾。例如,我们可以创建一个新的测试文件,命名为 simple_storage.js ,用于测试 SimpleStorage 合约:

javascript


const SimpleStorage = artifacts.require("SimpleStorage");

contract("SimpleStorage", (accounts) => {
  it("should set and get the stored data correctly", async () => {
    // 获取已部署的 SimpleStorage 合约实例
    const simpleStorage = await SimpleStorage.deployed();

    // 调用 set 函数,设置存储的数据为 123,并指定交易发送者
    await simpleStorage.set(123, { from: accounts[0] });

    // 调用 get 函数,获取存储的数据
    const storedData = await simpleStorage.get();

    // 使用断言库 assert 验证存储的数据是否等于 123
    assert.equal(storedData.toNumber(), 123, "The stored data should be 123");
  });

  it("should retrieve the default value of 0 when contract is first deployed", async () => {
      const simpleStorage = await SimpleStorage.deployed();
      const storedData = await simpleStorage.get();
      assert.equal(storedData.toNumber(), 0, "The initial stored data should be 0");
  });

  it("should allow different accounts to set and get values independently", async () => {
        const simpleStorage = await SimpleStorage.deployed();

        // Account 1 sets the value
        await simpleStorage.set(456, { from: accounts[1] });
        const storedData1 = await simpleStorage.get({ from: accounts[1] });
        assert.equal(storedData1.toNumber(), 456, "Account 1 should retrieve 456");

        // Account 2 sets the value
        await simpleStorage.set(789, { from: accounts[2] });
        const storedData2 = await simpleStorage.get({ from: accounts[2] });
        assert.equal(storedData2.toNumber(), 789, "Account 2 should retrieve 789");

        // Verify account 1's value remains unchanged
        const storedData1Again = await simpleStorage.get({ from: accounts[1] });
        assert.equal(storedData1Again.toNumber(), 456, "Account 1 should still retrieve 456");
    });
});

该测试用例使用了 Truffle 框架提供的 artifacts.require 函数来加载 SimpleStorage 合约的 ABI (Application Binary Interface) 和字节码,并创建合约实例。 contract 函数定义了一个测试套件,它接收合约名称和一个回调函数,回调函数中包含了多个独立的测试用例。每个测试用例使用 it 函数定义,它接收测试用例的描述和一个异步回调函数。在每个测试用例中,我们首先获取已部署的 SimpleStorage 合约实例,然后调用合约的 set get 函数,并使用 assert.equal 函数来验证结果是否符合预期。

更详细地解释:

  • artifacts.require("SimpleStorage") : 这行代码指示Truffle加载名为 "SimpleStorage" 的智能合约的编译后的工件(artifacts)。这些工件包含了合约的ABI(应用程序二进制接口)和字节码,允许JavaScript代码与部署在区块链上的合约进行交互。
  • contract("SimpleStorage", (accounts) => { ... }) : 这个函数定义了一个测试套件,针对 "SimpleStorage" 合约。 accounts 参数是一个由Truffle提供的以太坊地址数组,用于模拟不同的用户与合约进行交互。
  • it("should set and get the stored data correctly", async () => { ... }) : 这定义了一个单独的测试用例。 async 关键字表明这是一个异步函数,允许使用 await 关键字来等待异步操作完成。
  • const simpleStorage = await SimpleStorage.deployed(); : 这行代码获取了已经部署到测试网络上的 "SimpleStorage" 合约的实例。 await 关键字确保在合约部署完成后再执行后续代码。
  • await simpleStorage.set(123, { from: accounts[0] }); : 这行代码调用了 "SimpleStorage" 合约的 set 函数,将存储的值设置为 123。 { from: accounts[0] } 指定了交易的发送者为 accounts 数组中的第一个账户。
  • const storedData = await simpleStorage.get(); : 这行代码调用了 "SimpleStorage" 合约的 get 函数,获取存储的值。
  • assert.equal(storedData.toNumber(), 123, "The stored data should be 123"); : 这行代码使用断言库 assert 来验证 get 函数返回的值是否等于 123。如果断言失败,测试将抛出一个错误,并显示消息 "The stored data should be 123"。 toNumber() 方法将从区块链返回的 BigNumber 对象转换为 JavaScript 数字。
  • 添加了测试用例以验证初始值为 0,并使用多个账户进行设置和检索,以确保不同账户之间的数据隔离。

要运行测试,请在 Truffle 项目的根目录下执行以下命令:

bash

truffle test

Truffle 会自动编译合约,将其部署到 Ganache 等本地测试网络,并执行测试用例。测试结果将显示在控制台中,指示测试是否通过。

注意事项

  • 安全性: 智能合约开发对安全性有着极高的要求。务必防范常见的安全漏洞,如重入攻击、整数溢出/下溢、拒绝服务 (DoS) 攻击、时间戳依赖、以及交易顺序依赖等。 可以考虑使用形式化验证工具来对合约逻辑进行验证,确保其符合设计规范。静态分析工具,例如Slither、Mythril、Securify,可以帮助你尽早发现潜在的安全风险。 进行彻底的代码审查,并邀请经验丰富的安全审计员对代码进行评估,是必不可少的步骤。严格遵循最佳安全实践,例如“检查-生效-交互”模式 (Checks-Effects-Interactions pattern) 。
  • Gas 优化: 智能合约的Gas 消耗直接影响交易成本。务必优化合约代码,尽量减少Gas 消耗。Gas 消耗过高会导致交易失败或者交易费用变得非常昂贵,从而影响用户体验。可以采取的优化措施包括: 减少链上存储的使用,尽可能利用缓存和内存变量;使用短路求值(Short-circuiting)来优化条件判断;避免在循环中进行昂贵的操作;使用位运算代替乘除运算;以及使用更有效的数据结构等。对合约进行Gas 估算,并使用Gas 分析工具进行优化。
  • 版本管理: 使用版本控制系统,例如 Git,对智能合约代码进行版本管理至关重要。使用Git 可以方便地跟踪代码变更、进行团队协作、以及在出现问题时回溯到之前的版本。建议采用合适的分支管理策略,如Gitflow,以便更好地管理代码库。 可以使用GitHub等代码托管平台,方便代码的共享和协作。提交代码时,务必编写清晰的提交信息,方便日后查找和理解代码变更。
  • Kraken API: 如果需要与 Kraken 交易所的 API 进行交互,务必仔细查阅 Kraken 官方文档,深入了解 API 的具体使用方法、参数说明、以及速率限制。 Kraken API 可能包含用于获取市场数据、创建订单、管理账户等功能。在使用 API 之前,需要申请API 密钥并妥善保管。 同时,需要注意 Kraken API 的调用频率限制,避免触发速率限制导致程序运行异常。务必处理好 API 返回的错误信息,并采取相应的应对措施。使用安全的 HTTP 客户端库,例如 Requests (Python) 或 Axios (JavaScript),来发起 API 请求。

通过以上步骤,您可以在 Kraken 平台上安全高效地进行智能合约的开发和部署。请牢记,智能合约开发是一个涉及多方面知识的复杂过程,需要持续不断地学习和实践,并密切关注最新的安全漏洞和最佳实践。