AI 驱动的开发者(MEAP)(二)(3)

简介: AI 驱动的开发者(MEAP)(二)

AI 驱动的开发者(MEAP)(二)(2)https://developer.aliyun.com/article/1516330

第六章:测试、评估和解释大型语言模型

本章内容包括

  • 轻松草拟单元测试
  • 生成集成测试
  • 确定代码质量和覆盖率
  • 评估软件复杂性
  • 翻译代码和文本

本章将探讨软件工程的一个关键方面:测试。测试软件的行为有多个重要目的。首先,它有助于识别可能会影响软件功能、可用性或性能的错误和问题。此外,它确保软件符合所需的质量标准。通过进行全面的测试,我们可以验证软件是否满足指定的要求,正如预期的那样工作,并产生预期的结果。通过全面的测试,开发人员可以评估软件在各种平台和环境中的可靠性、准确性、效率、安全性和兼容性。在开发过程的早期检测和解决软件缺陷可以节省大量的时间和成本。

当我们完成测试的制定后,我们将评估代码的质量。你将了解到几个有助于评估软件质量和复杂性的度量标准。此外,如果我们需要对代码的目的有更清晰的了解,或者是首次审核代码,我们将寻求解释以确保全面理解。

6.1 测试,测试…一、二、三种类型

测试在软件工程中扮演着重要的角色,因此我们将详细探讨各种类型的测试。这包括单元测试、集成测试和行为测试。首先,我们将利用 Copilot Chat 来帮助我们创建一个单元测试

单元测试

单元测试是一种专注于测试单个组件或代码单元的测试类型,以确保它们在独立环境中的正确运行。通常由开发人员执行这种测试,以帮助识别特定软件单元中的错误和问题。

6.1.1 单元测试

在本节中,我们将创建单元测试来测试我们的软件组件。Python 的有几个用于单元测试的测试框架。每个框架都有其独特的特点,适用于不同的场景。在我们的 AI 工具提供的建议基础上,我们将简要介绍每个框架,然后选择一个特定的框架。

第一个框架是unittest:这是 Python 用于创建单元测试的标准库。它与 Python 捆绑在一起,无需单独安装。unittest提供了丰富的断言集,并非常适合编写简单到复杂的测试用例,但是代码量可能会相当庞大。unittest适合编写基本的单元测试,特别是如果您不想在项目中引入其他依赖项时。在任何需要独立于系统其余部分确认代码功能的情况下,它都非常有用。

接下来,让我们来看一下pytestpytest是一个流行的第三方库,用于单元测试,尽管它足够灵活,可以处理更多不仅仅是单元测试。它比unittest需要更少的样板代码,并且具有强大的功能,例如设置和拆卸的 fixture,参数化测试,以及运行unittest和 nose 测试套件的能力。pytest非常适合简单和复杂的单元测试用例。它也适用于功能和集成测试。如果你重视简单和易用性,并且你的项目不限于仅使用 Python 标准库,那么pytest是一个绝佳的选择。

接下来,我们有nose2,它是被废弃的"nose"测试框架的继承者。它扩展了unittest,使测试变得更容易。它以其测试发现功能而闻名,该功能可以自动找到您项目中的测试,因此您无需手动列出它们。nose2适用于大型项目,其中测试发现可以节省时间。与pytest一样,它可以运行unittest测试套件,因此如果您正在从unittest迁移但希望保留现有的测试,它也是一个不错的选择。

最后,还有doctest。这是 Python 标准库的另一个模块。它不像其他模块那样是一个功能齐全的测试框架,但它允许你直接在文档字符串中编写测试。doctest最适合简单的情况,你想演示如何使用一个函数或模块,并确认示例代码是否按预期工作。这是确保你的文档与代码保持最新的好方法。

Copilot Chat 建议我们使用unittest,所以我们会这样做。你可以自己尝试询问它,并看看它是否会得出不同的结论,这取决于你如何提问。

首先,我们将通过创建从unittest.TestCase类继承的类来定义测试用例。在编写我们的第一个单元测试时,我们将发现一个相当隐匿的错误,这个错误迄今为止一直使我们束手无策。我们马上就要解决这个问题了。最后,我们将测试DepartmentStatisticsVisitor类的正确性。

我们从提示开始,请 Copilot Chat 创建一个DepartmentStatisticsVisitor的单元测试。回复将提醒我们上下文的重要性。Copilot Chat,考虑到我们开始了一个新的聊天会话,将尝试创建这个单元测试,但它缺乏我们任何类的定义。

列表 6.1:为DepartmentStatisticsVisitor定义单元测试的第一次尝试
import unittest
from department_visitor import DepartmentStatisticsVisitor
class TestDepartmentStatisticsVisitor(unittest.TestCase):
    def test_visit_department(self):
        visitor = DepartmentStatisticsVisitor()
        department = {'name': 'Sales', 'employees': [{'name': 'John', 'salary': 50000}, {'name': 'Jane', 'salary': 60000}]}
        visitor.visit_department(department)
        self.assertEqual(visitor.total_salaries, 110000)
        self.assertEqual(visitor.num_employees, 2)
        self.assertEqual(visitor.avg_salary, 55000)

我们应该继续将定义输入到 Copilot Chat 中,以便它可以完善测试用例。我们可以告诉它更多关于访问者类的信息,如下面的代码片段所示。

The DepartmentStatisticsVisitor class visits to determine the total asset depreciation based off of the asset allocation for each department

有了这些更新的信息,Copilot Chat 即将更好地估计我们的单元测试应该如何运行。

列表 6.1:为DepartmentStatisticsVisitor定义单元测试的第一次尝试
import unittest
from department_visitor import DepartmentStatisticsVisitor, Asset
class TestDepartmentStatisticsVisitor(unittest.TestCase):
    def test_visit(self):
        visitor = DepartmentStatisticsVisitor()
        asset1 = Asset(1000, 500, 0.5)
        asset2 = Asset(2000, 1000, 0.3)
        visitor.visit(asset1)
        visitor.visit(asset2)
        self.assertEqual(visitor.get_total_cost(), 3000)
        self.assertEqual(visitor.get_total_depreciation(), 1500)
        self.assertEqual(visitor.get_total_allocation(), 0.8)

单元测试接近所需的内容;但是,Asset 的定义是错误的。我们应该从我们的 asset.py 类中输入正确的定义。Copilot 聊天将继续完善单元测试。

第 6.2 节 在 Copilot 聊天了解如何定义 Asset 后,对 DepartmentStatisticsVisitor n 定义单元测试的下一次尝试。
import unittest
from datetime import date
from typing import List
from dataclasses import dataclass
@dataclass
class Location:
    name: str
    address: str
@dataclass
class Asset:
    id: int
    name: str
    status: str
    category: str
    cost: float
    useful_life: int
    salvage_value: float
    purchase_date: date
    locations: List[Location]
class TestAsset(unittest.TestCase):
    def test_asset(self):
        location1 = Location('Office', '123 Main St')
        location2 = Location('Warehouse', '456 Elm St')
        asset = Asset(1, 'Computer', 'In use', 'Hardware', 1000.0, 3, 100.0, date.today(), [location1, location2])
        self.assertEqual(asset.id, 1)
        self.assertEqual(asset.name, 'Computer')
        self.assertEqual(asset.status, 'In use')
        self.assertEqual(asset.category, 'Hardware')
        self.assertEqual(asset.cost, 1000.0)
        self.assertEqual(asset.useful_life, 3)
        self.assertEqual(asset.salvage_value, 100.0)
        self.assertEqual(asset.purchase_date, date.today())
        self.assertEqual(asset.locations, [location1, location2])

这更接近了,我们还应该提醒 Copilot 聊天,Asset 类还有一个名为 FundingDetails 的类。一旦我们提供了 FundingDetails 的定义,并告知 Copilot 聊天它应该是 Asset 的一部分,我们就更接近了。

第 6.3 节 第三次尝试编写一个相当接近的单元测试。
import unittest
from department_visitor import DepartmentStatisticsVisitor, Asset, FundingDetails
from datetime import date
from typing import List, Dict
from dataclasses import dataclass
@dataclass
class Location:
    name: str
    address: str
class TestDepartmentStatisticsVisitor(unittest.TestCase):
    def test_visit(self):
        visitor = DepartmentStatisticsVisitor()
        location1 = Location('Office', '123 Main St')
        location2 = Location('Warehouse', '456 Elm St')
        asset1 = Asset(1, 'Computer', 'In use', 'Hardware', 1000.0, 3, 100.0, date.today(), [location1, location2])
        asset2 = Asset(2, 'Printer', 'In use', 'Hardware', 500.0, 2, 50.0, date.today(), [location1])
        funding_details1 = FundingDetails(asset1, 'Straight Line', 0.33, { 'IT': 0.5, 'HR': 0.5 })
        funding_details2 = FundingDetails(asset2, 'Double Declining Balance', 0.25, { 'IT': 0.3, 'HR': 0.7 })
        visitor.visit(asset1, funding_details1)
        visitor.visit(asset2, funding_details2)
        self.assertEqual(visitor.get_total_cost(), 1500.0)
        self.assertEqual(visitor.get_total_depreciation(), 550.0)
        self.assertEqual(visitor.get_total_allocation(), 0.8)

唯一需要手动更新的是导入语句。

注意

让这个练习成为对使用大型语言模型的警示,强迫它们在高度专注的任务上表现得很具有挑战性,甚至可能不值得付出这种努力。在现实世界中,没有人会责怪您放弃提示工程,而回到只是编写出这个测试的代码。然而,通过一些坚持,您可能能够建立一个模板库,用于构建一套类似形状的类的单元测试。另一个额外的注意是 Copilot 聊天可以生成编辑器窗口中文件的测试,如果您指示它“为我的代码生成一个单元测试”,但是,它将模拟所有不直接属于正在测试的类的对象/属性。根据您尝试测试的内容,此功能的效用可能值得怀疑。

当我们尝试运行此测试时,我们发现 visitor、asset、funding details 和 depreciation strategy 之间存在循环依赖。循环依赖是指两个或多个模块或组件直接或间接地彼此依赖的情况。在我们的情况下,当 Python 尝试实例化 Asset 时,它会加载 FundingDetails 的定义。

我们通过摆脱对 FundingDetails 类的直接实例化或引用来修复这个问题。

第 6.4 节 更新后的 Asset 类,不再直接引用 FundingDetails 类。
@dataclass
class Asset():
    id: int
    name: str
    status: str
    category: str
    cost: float
    useful_life: int
    salvage_value: float
    purchase_date: date
    locations: List[Location]
    funding_details: None or 'itam.domain.funding_details.FundingDetails'

我们需要对 FundingDetails 类执行相同的操作。它不应该直接引用 DepreciationStrategy 类。

第 6.5 节 更新后的 FundingDetails 类,不再直接引用 DepreciationStrategy 类。
@dataclass
class FundingDetails:
    depreciation_rate: float
    department_allocations: Dict[Department, float]
    depreciation_strategy: DepreciationStrategy or 'itam.domain.depreciation_strategy.DepreciationStrategy'
    asset: None or 'itam.domain.asset.Asset'

正如我们所见,我们能够使用 Copilot 聊天创建一个单元测试。然而,如果我们没有使用 Copilot,可能会更容易地创建它。这个工具非常擅长提供何时以及如何测试您的代码的指导,但是实施(至少目前)还有待改进。

在现实世界中,我们将继续添加单元测试来建立一个实质性的测试体系。你可能会问,什么样的测试是实质性的?我们马上就会探讨这个问题。但是,我们应该首先把注意力转向下一种类型的测试:集成测试

集成测试

集成测试涉及测试软件的不同组件或模块之间的交互,以确保它们能够无缝地配合工作。它验证集成系统是否按预期功能,并检测模块之间的任何不一致或通信问题。

6.1.2 集成测试

在本节中,我们将开发一个集成测试,以便测试端到端的系统。幸运的是,fastapi 自带了自己的测试客户端,这将帮助我们创建这个测试。

我们首先将 AssetController 的定义复制到 Copilot Chat 窗口中。然后我们可以询问 Copilot Chat 如何为这个控制器创建集成测试。鉴于我们在定义中包含了路由,Copilot Chat 应该能够为我们提供准确的集成测试。我们需要指定我们将使用 InMemoryAssetRepository 类,或者在生成测试后修复它。

列表 6.6 AssetController 生成的 Copilot Chat 集成测试
from fastapi.testclient import TestClient
from itam.infrastructure.adapters.memory_asset_repository import MemoryAssetRepository
from itam.infrastructure.ports.asset_rest_port import AssetRestPort
from itam.interfaces.asset_controller import AssetController
def test_get_assets():
    # Create an instance of the InMemoryAssetRepository
    asset_repository = InMemoryAssetRepository()
    # Add some assets to the repository
    asset_repository.create(Asset(name="Asset 1", unit_cost=1000))
    asset_repository.create(Asset(name="Asset 2", unit_cost=2000))
    # Create an instance of the AssetRestPort using the MemoryAssetRepository
    asset_rest_port = AssetRestPort(asset_repository)
    # Create an instance of the AssetController using the AssetRestPort
    asset_controller = AssetController(asset_rest_port)
    # Create a TestClient instance using the AssetController's router
    client = TestClient(asset_controller.get_router())
    # Send a GET request to the /assets endpoint
    response = client.get("/assets")
    # Check that the response status code is 200 OK
    assert response.status_code == 200
    # Check that the response body contains the expected assets
    assert response.json() == [
        {"id": 1, "name": "Asset 1", "unit_cost": 1000},
        {"id": 2, "name": "Asset 2", "unit_cost": 2000},

现在我们将注意力转向我们要检查的最后一种测试类型:行为测试

行为测试

行为测试是一种侧重于系统整体行为的测试类型,从最终用户的角度来看待。行为测试通常用于测试系统的功能,并确保它符合为其定义的要求和规范。

6.1.3 行为测试

从某种意义上说,所有测试都是行为测试,因为测试验证系统的行为。然而,行为测试在某些方面是独特的。让我们总结一下到目前为止我们遇到的不同类型的测试,并将其与行为测试进行对比。

单元测试是一种侧重于测试系统的单个单元或组件的测试类型,通常使用自动化测试。单元测试旨在测试单个函数或方法的功能,并确保它们在各种条件下表现正确。

另一方面,集成测试是一种侧重于测试系统的不同组件或单元之间的交互的测试类型。集成测试通常用于测试不同组件或单元之间的接口,并确保它们正确地配合工作。集成测试可以手动执行或使用自动化测试,并且通常涉及测试系统的不同组件或单元之间的交互,而不是整个系统。

行为测试侧重于根据用户故事或场景定义软件的行为。这些场景以一种特定的格式写入,称为“给定-当-那么”(GWT),用于驱动开发过程。GWT 格式描述了特定场景的前提条件(给定)、操作(当)和预期结果(那么)。

随着我们在测试中的进展,我们可能会发现一些行为或组件在我们的测试中很难设置。此外,我们可能会发现难以隔离特定对象或模块的行为,并测试不同对象之间的交互。为了解决这个限制,我们可以使用一个模拟对象

模拟对象

模拟对象是一种以受控方式模拟真实对象行为的测试替身。它们也可以用来模拟难以通过真实对象复制的错误条件或边缘情况。模拟对象可以手动创建,使用诸如unittest.mockpytest-mock等模拟库。这些库提供了用于创建和配置模拟对象的函数和类。模拟对象可以配置为在调用其方法时返回特定值或引发特定异常。它们还可以用于记录对其方法的调用,以便您可以验证是否正确地使用了正确的参数调用了正确的方法。

我们将在提示中引入模拟对象,以创建AssetManager的行为测试。

列表 6.7 设置AssetManager行为测试的提示
We have a class called AssetManager. AssetManager's constructor takes two class BaseRepository and AssetLocationMediator. The BaseRepository is a repository in which Assets are stored. We want to use InMemoryAssetRepository, which is a subclass of BaseRepository that stores the Assets in memory. Use a mock object for AssetLocationMediator. The AssetManager stores Assets using the method create and gets all of the Assets using the method get_assets. An asset has 10 required positional arguments: 'id', 'name', 'status', 'category', 'cost', 'useful_life', 'salvage_value', 'purchase_date', 'locations', and 'funding_details'. Use named parameters to make it clear which param is going where. Create a BDD script that will add two Assets to the AssetManager, confirming that all Assets cost $4000.00\. This should be implemented in Python. Take it step by step, telling us the tools and libraries you will use.

Copilot Chat 将告诉我们需要创建一个名为asset_manager.feature的新文件(称为特性文件)。在这个文件中,我们将定义AssetManager的属性(以及任何支持类)。例如,在特性文件中定义了一个场景,将两个资产添加到AssetManager,确认所有资产的总成本为$4000.00,并模拟AssetLocationMediator类。

列表 6.8 根据 Copilot Chat 定义的asset_manager.feature文件
Feature: Asset Manager
  As an IT Asset Manager
  I want to be able to manage assets
  So that I can keep track of all IT assets in my organization
  Scenario: Add two assets to the Asset Manager
    Given the Asset Manager is running
    And the InMemoryAssetRepository is initialized
    And the AssetLocationMediator is mocked
    When I create an asset with a cost of $2000.00
    And I create another asset with a cost of $2000.00
    Then the total cost of all assets should be $4000.00

我们应该在项目的根目录中创建一个名为features的目录。我们应该将这个文件放在那个目录中。此外,我们应该添加一个名为steps的子目录。我们将很快得到steps

接下来,我们将创建一个名为 steps.py 的新 Python 文件,并将其放置在 steps 目录中。这个 Python 文件定义了用于场景的步骤实现。AssetManagerInMemoryAssetRepositoryAssetLocationMediatorAsset 类被导入,并定义了六个函数来对应场景中的步骤。这些函数使用 context 对象在步骤之间存储和检索数据。使用 unittest.mock 库的 Mock 类来为 AssetLocationMediator 类创建一个模拟对象。Asset 类使用命名参数来实例化,以澄清哪个参数属于哪个属性。如果我们向 Copilot Chat 请求 steps.py 文件的内容,我们将看到类似以下列表的输出。

列出 6.9 我们在 steps.py 中定义的行为测试的实现细节
from behave import given, when, then
from itam.service.asset_manager import AssetManager
from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
from itam.domain.asset import Asset
from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
from unittest.mock import Mock
@given('the Asset Manager is running')
def step_impl(context):
    context.asset_repository = InMemoryAssetRepository()
    context.asset_location_mediator = Mock(spec=AssetLocationMediator)
    context.asset_manager = AssetManager(context.asset_repository, context.asset_location_mediator)
@given('the InMemoryAssetRepository is initialized')
def step_impl(context):
    pass
@given('the AssetLocationMediator is mocked')
def step_impl(context):
    pass
@when('I create an asset with a cost of ${cost}')
def step_impl(context, cost):
    asset = Asset(id=1, name='Test Asset 1', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
    context.asset_manager.create(asset)
@when('I create another asset with a cost of ${cost}')
def step_impl(context, cost):
    asset = Asset(id=2, name='Test Asset 2', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
    context.asset_manager.create(asset)
@then('the total cost of all assets should be ${total_cost}')
def step_impl(context, total_cost):
    assets = context.asset_manager.get_assets()
    assert sum(asset.cost for asset in assets) == float(total_cost)

如果您尚未安装它,请使用 pip 安装 behave 库:pip install behave. 此外,您应将其添加到 requirements.txt 文件中,以确保在稍后构建可部署版本的此应用程序时会被引入。我们将通过从项目的根目录发出以下命令来运行行为测试。

列出 6.10 运行行为测试并生成输出
% behave features
Feature: Asset Manager # features/asset_manager.feature:1
  As an IT Asset Manager
  I want to be able to manage assets
  So that I can keep track of all IT assets in my organization
  Scenario: Add two assets to the Asset Manager          # features/asset_manager.feature:6
    Given the Asset Manager is running                   # features/steps/steps.py:8 0.000s
    And the InMemoryAssetRepository is initialized       # features/steps/steps.py:14 0.000s
    And the AssetLocationMediator is mocked              # features/steps/steps.py:18 0.000s
    When I create an asset with a cost of $2000.00       # features/steps/steps.py:22 0.000s
    And I create another asset with a cost of $2000.00   # features/steps/steps.py:27 0.000s
    Then the total cost of all assets should be $4000.00 # features/steps/steps.py:32 0.000s
1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 0 skipped
6 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.001s

在本节中,我们通过使用三种类型的测试:单元测试、集成测试和行为测试,为良好的软件开发奠定了基础。现在,有人可能会争辩说它在项目的开发生命周期中出现得很晚。这个争论也不无道理。在现实世界中,我们会在开发代码时开发我们的测试。有些人可能会认为我们应该在编写代码之前构建测试。您可能持有这种信念,也可能不持有,但无论如何,您都应该尽早测试,并经常测试。

在本书的下一部分中,我们将深入研究一些可用于确定我们软件总体质量的指标,并请求 Copilot 帮助我们评估到目前为止我们代码的质量。

6.2 评估质量

理解软件应用程序的性能、可靠性、可维护性和总体质量是软件工程的重要方面。本章将深入探讨软件质量指标领域的迷人和复杂内容 – 这些量化标准和基准指导我们理解软件系统质量的。

软件质量指标是必不可少的工具,它允许利益相关者 – 开发人员、测试人员、经理和用户 – 评估软件产品的状态,识别其优点和改进空间。它们为产品开发、测试、调试、维护和改进倡议等各种流程提供了经验基础。通过量化软件的特定特性,这些指标提供了一种具体的方法来理解软件质量这一抽象概念。

在本节中,我们将探讨软件质量度量的几个重要类别,包括产品度量、过程度量和项目度量。我们将分析它们的重要性、计算方法以及如何有效利用它们来评估和提高软件质量。这个探讨将包括静态度量,即应用于静态软件系统的度量,以及动态度量,它们评估系统在执行过程中的行为。

软件质量度量不仅有助于软件系统的技术完整性,还有助于确保客户满意度、盈利能力和长期的商业成功。因此,了解这些度量是对软件开发领域的任何从业人员都是非常宝贵的,从工程师和项目经理到高管和软件用户。

在本节中,我们将研究类或代码复杂性和可维护性的一些常见指标。复杂的软件很难理解,这使得开发人员,尤其是新手开发人员,很难把握软件不同部分是如何相互交互的。这可能会减慢员工的适应速度和开发时间。

复杂的代码往往会导致更高的维护工作量。当代码复杂时,修改或修复 bug 可能需要更长的时间,因为很难预测改动系统中某一部分的影响。这可能会导致软件整个生命周期的更高成本。

复杂的软件往往更容易出错。因为它更难理解,开发人员在进行改动时更有可能引入 bug。此外,复杂的代码可能存在许多相互依赖的关系,一处的改动可能在其他地方产生意想不到的影响。

软件越复杂,就需要更多的测试用例来进行彻底测试。由于涉及逻辑的复杂性,编写这些测试用例可能也更加困难。

编写简单和易维护的代码应该是我们的首要任务之一。观察与我们的代码相伴的度量变化应该有助于我们在这方面的努力。在这个目标的推动下,我们可以(也应该)首先使用的度量是圈复杂度

圈复杂度

圈复杂度是量化软件模块中独立路径的数量的度量。它衡量了代码中的决策复杂性,包括循环、条件和分支。较高的圈复杂度值表示增加的复杂性,并暗示着可能存在更多的 bug 和理解、维护代码的挑战。

在文件 department_visitor.py 中,输入片段 6.3 的提示任何位置。Copilot 将立即输出答案。

# Question: What is the cyclomatic complexity of the class DepartmentStatisticsVisitor?
# Answer: 1

Copilot 会告诉您这个类的复杂性为 1。您可能不清楚这个值的含义。如果是后者,您可以要求 Copilot 加以解释。

# Question: Is 1 an excellent cyclomatic complexity?
# Answer: Yes
# Question: Why is one a good value for cyclomatic complexity?
# Answer: Because it is low

Copilot 告诉我们,如果圈复杂度低,则好。 这在直觉上是有道理的。 代码复杂度低意味着更容易理解,因此更容易理解和推理。 也更有可能更容易维护。 我们将要探讨的下一个指标是Halstead 复杂度度量

Halstead 复杂度度量

Halstead 复杂度度量评估软件程序的复杂性,基于代码中使用的唯一运算符和操作数的数量。 这些度量包括程序长度(N1)、程序词汇量(n1)、体积(V)、难度(D)、工作量(E)等。 这些度量提供了有关代码的大小和认知复杂性的见解。

与上次类似,我们将从一个提示开始,要求 Copilot 确定我们的访问者类的 Halstead 复杂度度量。

# Question: What is the Halstead Complexity Measure of the class DepartmentStatisticsVisitor?
# Answer: 2
# Question: What is the Halstead Difficulty Measure of the class DepartmentStatisticsVisitor?
# Answer: 1
# Question: Is 2 a good Halstead Complexity Measure?
# Answer: Yes
# Question: Is 1 a good Halstead Difficulty Measure?
# Answer: Yes
# Question: What is a bad Halstead Difficulty Measure?
# Answer: 10
# Question: What is a bad Halstead Complexity Measure?
# Answer: 10
# Question: What does a high Halstead Difficulty Measures mean?
# Answer: It means that the code is hard to understand

您可能想要继续进行一段时间的问答会话,以查看 Copilot 可以从中获取的信息。 一旦您准备好继续,还有一个指标要探讨:可维护性指数

可维护性指数

可维护性指数是一个综合指标,结合了多个因素,包括圈复杂度、代码行数和 Halstead 复杂度度量,以提供软件可维护性的整体度量。 更高的可维护性指数表示更容易维护和潜在较低的复杂性。

您应该在访问者文件中开始一个类似的讨论,以了解可维护性指数。

# Question: What is the maintainability index of the class DepartmentStatisticsVisitor?
# Answer: 100
# Question: Do we want a high Maintainability Index or low Maintainability Index?
# Answer: high
# Question: Why do we want a high Maintainability Index?
# Answer: Because it is easier to maintain

如果我们得到一个较低的可维护性指数,我们可以重构以减少这个数字。 指标在于它给了我们一个钉子来挂我们的帽子;也就是说,我们可以采取这个措施来改善它。 指标使我们超越了个体的纯美感或主观性。 指标是真实的、可操作的数据。 但 Copilot 还有(至少)一项更多的技巧。 Copilot 不仅能够编写和评估我们的代码,还可以解决代码的缺陷。 让我们来捕虫吧。

AI 驱动的开发者(MEAP)(二)(4)https://developer.aliyun.com/article/1516333

相关文章
|
4天前
|
人工智能 Python Shell
CodeFormer——AI驱动的面部图像修复与增强
CodeFormer是由南洋理工大学和商汤科技联合研发的AI人脸复原模型,结合VQGAN和Transformer技术,能从模糊或马赛克图像中生成清晰图像。它具备老照片修复、黑白照片彩色化、马赛克修复和低码率视频增强等功能。安装过程涉及miniconda3、Python环境配置、相关库的安装及模型训练数据下载。在测试视频增强时,虽然初期遇到ffmpeg导入问题,但通过安装ffmpeg-python得以解决,不过CPU占用率高。此外,还展示了对图片进行增强的命令行操作及结果示例。
|
4天前
|
机器学习/深度学习 人工智能 数据挖掘
AI技术对开发者职业天花板的双重影响
随着AI技术的不断创新和飞速发展,人工智能技术在软件开发、数据分析、自动化等领域的应用愈发广泛,并产生了深远的影响。尤其是在程序圈中,对于开发者这一职业群体而言,AI技术的融入不仅改变了传统的开发流程,还对开发者的职业前景带来了全新的挑战和机遇。那么本文就来简单聊聊AI技术究竟对开发者的职业天花板是提升还是降低呢?讨论一下AI技术如何影响开发者的职业天花板。
138 3
AI技术对开发者职业天花板的双重影响
|
10天前
|
机器学习/深度学习 人工智能 算法
关于AI技术,是 提高 or 降低 开发者的职业天花板
【6月更文挑战第5天】关于AI技术,是 提高 or 降低 开发者的职业天花板
|
11天前
|
人工智能 自然语言处理 算法
AI技术对开发者的职业天花板是提升还是降低?
AI技术对开发者的影响复杂多面,既提升也降低了职业天花板。一方面,AI提高开发效率,自动化重复工作,扩展了应用领域,促使开发者持续学习新技能。另一方面,它带来职业转型压力,技能可能过时,竞争加剧。开发者应持续学习,跨领域发展,培养创新思维,以适应和利用AI技术提升自身职业发展空间。
15 0
|
11天前
|
机器学习/深度学习 人工智能 算法
探索软件测试的新时代:AI驱动的自动化
【6月更文挑战第4天】随着人工智能技术的不断进步,软件测试领域正经历着一场革命。本文将探讨AI如何改变传统的软件测试方法,提高测试效率和准确性,以及这一趋势对测试工程师未来技能要求的影响。
21 6
|
14天前
|
机器学习/深度学习 人工智能 算法
后端开发者如何利用AI进行跨学科融合
【6月更文挑战第1天】后端开发者如何利用AI进行跨学科融合
17 6
|
15天前
|
机器学习/深度学习 人工智能 安全
探索软件测试的新时代:AI驱动的测试自动化
本文深入探讨了人工智能(AI)如何革新软件测试领域,特别是测试自动化。随着AI技术的不断进步,它为测试自动化带来了前所未有的效率和准确性,从而极大地提高了软件开发的速度和质量。本文将详细介绍AI在软件测试中的应用,以及它如何帮助测试人员克服传统测试方法的局限性。
|
16天前
|
人工智能 自然语言处理 安全
构建未来:AI驱动的自适应网络安全防御系统提升软件测试效率:自动化与持续集成的实践之路
【5月更文挑战第30天】 在数字化时代,网络安全已成为维护信息完整性、保障用户隐私和企业持续运营的关键。传统的安全防御手段,如防火墙和入侵检测系统,面对日益复杂的网络攻击已显得力不从心。本文提出了一种基于人工智能(AI)技术的自适应网络安全防御系统,该系统能够实时分析网络流量,自动识别潜在威胁,并动态调整防御策略以应对未知攻击。通过深度学习算法和自然语言处理技术的结合,系统不仅能够提高检测速度和准确性,还能自主学习和适应新型攻击模式,从而显著提升网络安全防御的效率和智能化水平。 【5月更文挑战第30天】 在快速迭代的软件开发周期中,传统的手动测试方法已不再适应现代高效交付的要求。本文探讨了如
|
3天前
|
人工智能
当AI“复活”成为产业:确保数字生命技术始终用于正途的探讨
随着科技的飞速发展,AI技术日益成熟,我们迎来了一个令人瞩目的时代——当AI“复活”不再是科幻电影的情节,而是逐渐成为现实世界的产业,这其中就包括所谓的“数字生命”技术。在这一背景下,通过人物已有影像、声音、语言等内容的学习,克隆数字化的人物形象成为了可能,创造出数字化的“复活”形象。但是正如电影《流浪地球2》所展示的那样,图恒宇将女儿的意识上传到超强计算机,创造出拥有自我意识的数字图丫丫,这一技术奇迹引发了关于伦理、法律和社会责任的深刻探讨,所以说当AI“复活”技术逐渐从实验室走向产业化,我们不得不面对一个严峻的问题:如何确保这项技术始终用于正途?那么本文就来聊聊如何确保数字生命技术始终用于
14 1
当AI“复活”成为产业:确保数字生命技术始终用于正途的探讨
|
16小时前
|
数据采集 存储 人工智能
利用AI技术改善数字化转型项目的九种方法
利用AI技术改善数字化转型项目的九种方法