MST
星途 面试题库

面试题:Ruby复杂业务场景下TDD架构设计

考虑一个电商系统的订单模块,有下单、支付、订单状态变更等复杂业务逻辑。订单状态包括 '未支付'、'已支付'、'已发货'、'已完成' 等。请基于测试驱动开发(TDD)的原则,设计整个订单模块的架构,包括类的设计、方法的职责划分以及相关测试用例的框架设计。阐述如何通过TDD确保各个业务逻辑之间的一致性和可维护性,以及在面对业务需求频繁变更时,如何通过TDD来高效地进行代码修改和扩展。
10.4万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

1. 类的设计

  1. Order类
    • 职责:表示订单实体,包含订单的基本信息如订单号、下单时间、订单状态等。
    • 属性orderId(订单号,唯一标识),orderTime(下单时间),orderStatus(订单状态,如'未支付'、'已支付'等)。
    • 方法
      • getOrderId():获取订单号。
      • getOrderTime():获取下单时间。
      • getOrderStatus():获取订单状态。
      • setOrderStatus(String status):设置订单状态。
  2. OrderService类
    • 职责:处理订单相关的业务逻辑,如下单、支付、订单状态变更等操作。
    • 方法
      • placeOrder(Order order):下单操作,将订单状态设为'未支付'。
      • payOrder(Order order):支付订单,将订单状态从'未支付'变为'已支付'。
      • shipOrder(Order order):发货操作,将订单状态从'已支付'变为'已发货'。
      • completeOrder(Order order):完成订单,将订单状态从'已发货'变为'已完成'。
  3. OrderRepository类
    • 职责:负责与数据存储交互,对订单数据进行持久化和读取操作。
    • 方法
      • saveOrder(Order order):保存订单到数据库。
      • getOrderById(String orderId):根据订单号从数据库获取订单。

2. 方法的职责划分

  1. Order类方法
    • 访问和修改订单自身状态和基本信息,是订单数据的封装和操作基础。
  2. OrderService类方法
    • 实现订单业务逻辑,调用Order类的方法修改订单状态,并可能调用OrderRepository类方法进行数据持久化。例如placeOrder方法创建订单并保存到数据库,payOrder方法在修改订单状态后也可能保存更新后的订单。
  3. OrderRepository类方法
    • 专注于数据库层面的订单数据操作,为OrderService提供数据支持。

3. 测试用例的框架设计

  1. Order类测试用例
    • 测试获取订单号方法
      • 给定一个订单实例,调用getOrderId方法,断言返回的订单号与设置的订单号一致。
    • 测试获取订单时间方法
      • 给定一个订单实例,调用getOrderTime方法,断言返回的时间与设置的时间一致。
    • 测试获取订单状态方法
      • 给定一个订单实例,设置订单状态,调用getOrderStatus方法,断言返回的状态与设置的状态一致。
    • 测试设置订单状态方法
      • 给定一个订单实例,调用setOrderStatus方法设置新状态,再调用getOrderStatus方法,断言返回的状态为新设置的状态。
  2. OrderService类测试用例
    • 测试下单方法
      • 创建一个Order实例,调用OrderServiceplaceOrder方法,断言订单状态为'未支付',并且OrderRepositorysaveOrder方法被调用。
    • 测试支付方法
      • 创建一个状态为'未支付'的Order实例,调用OrderServicepayOrder方法,断言订单状态为'已支付'。
    • 测试发货方法
      • 创建一个状态为'已支付'的Order实例,调用OrderServiceshipOrder方法,断言订单状态为'已发货'。
    • 测试完成订单方法
      • 创建一个状态为'已发货'的Order实例,调用OrderServicecompleteOrder方法,断言订单状态为'已完成'。
  3. OrderRepository类测试用例
    • 测试保存订单方法
      • 创建一个Order实例,调用OrderRepositorysaveOrder方法,从数据库(模拟数据库操作)中查询该订单,断言查询结果与保存的订单一致。
    • 测试根据订单号获取订单方法
      • 创建一个Order实例并保存到数据库(模拟),调用getOrderById方法,传入订单号,断言返回的订单与保存的订单一致。

4. 通过TDD确保业务逻辑一致性和可维护性

  1. 一致性
    • 在TDD流程中,先编写测试用例,定义了业务逻辑的预期行为。例如在编写OrderServicepayOrder方法测试用例时,明确了只有订单状态为'未支付'时才能成功支付并将状态变为'已支付'。这样在实现payOrder方法时,必须遵循测试用例定义的规则,从而确保业务逻辑的一致性。
    • 所有相关类和方法的测试用例相互关联,如OrderService的方法依赖Order类和OrderRepository类的方法,通过测试用例可以验证这些依赖关系是否正确,进一步保证业务逻辑整体的一致性。
  2. 可维护性
    • 测试用例就像代码的文档,当开发人员需要修改或添加新功能时,可以通过阅读测试用例快速了解现有业务逻辑。例如,新开发人员接手项目,通过运行和阅读OrderService的测试用例,能迅速明白订单支付、发货等业务流程。
    • 当修改代码时,运行测试用例可以快速发现是否破坏了原有业务逻辑。如果修改OrderServiceshipOrder方法后,相关测试用例失败,说明修改可能引入了错误,开发人员可以及时调整代码,保证可维护性。

5. 面对业务需求频繁变更时通过TDD高效修改和扩展代码

  1. 修改代码
    • 当业务需求变更时,先修改相应的测试用例以反映新的需求。例如,如果订单支付规则变更,如增加支付金额限制,先修改OrderServicepayOrder方法测试用例,添加对支付金额的断言。
    • 然后修改实现代码,使代码通过修改后的测试用例。这样可以确保代码修改是符合新需求的,并且不会破坏原有功能。
  2. 扩展代码
    • 当需要添加新功能,如添加订单取消功能时,先编写新功能的测试用例,如cancelOrder方法的测试用例,定义取消订单的业务规则,如只有'未支付'和'已支付'状态的订单可以取消等。
    • 然后实现OrderService中的cancelOrder方法,确保代码通过新编写的测试用例。通过这种方式,TDD可以有条不紊地引导代码的扩展,同时保证原有功能不受影响。