MST

星途 面试题库

面试题:Ruby代码审查里模块与类设计的常见缺陷及改进

在Ruby项目中,对模块和类进行代码审查时,经常会发现哪些设计上的缺陷?如何对这些缺陷进行改进?请详细阐述并给出相关代码修改前后的对比示例。
22.0万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

常见设计缺陷及改进方法

  1. 模块和类职责不单一

    • 问题:一个模块或类承担了过多不同类型的职责,导致代码臃肿、可维护性差。
    • 改进:将不同职责拆分成多个独立的模块或类,遵循单一职责原则。

    示例

    • 修改前
class UserManager
  def initialize
    @users = []
  end

  def add_user(user)
    @users << user
  end

  def send_email(user, subject, content)
    # 邮件发送逻辑
    puts "Sending email to #{user}: #{subject}, #{content}"
  end
end
- **修改后**:
class UserRepository
  def initialize
    @users = []
  end

  def add_user(user)
    @users << user
  end
end

class EmailSender
  def send_email(user, subject, content)
    # 邮件发送逻辑
    puts "Sending email to #{user}: #{subject}, #{content}"
  end
end
  1. 模块和类之间耦合度过高

    • 问题:模块或类之间过度依赖,使得一个模块的修改很可能影响到其他模块,降低了代码的可扩展性和可维护性。
    • 改进:通过接口、抽象类等方式降低耦合度,使模块之间通过抽象进行交互。

    示例

    • 修改前
class Database
  def get_user(id)
    # 从数据库获取用户逻辑
    "User #{id}"
  end
end

class UserService
  def initialize
    @database = Database.new
  end

  def get_user(id)
    @database.get_user(id)
  end
end
- **修改后**:
class DatabaseInterface
  def get_user(id)
    raise NotImplementedError
  end
end

class Database < DatabaseInterface
  def get_user(id)
    # 从数据库获取用户逻辑
    "User #{id}"
  end
end

class UserService
  def initialize(database)
    @database = database
  end

  def get_user(id)
    @database.get_user(id)
  end
end
  1. 缺少必要的抽象

    • 问题:重复的代码片段在多个模块或类中出现,没有进行抽象提取,导致代码冗余。
    • 改进:提取重复代码到抽象模块或方法中,提高代码复用性。

    示例

    • 修改前
class OrderProcessor
  def calculate_total(order)
    total = 0
    order.items.each do |item|
      total += item.price * item.quantity
    end
    total
  end
end

class CartCalculator
  def calculate_total(cart)
    total = 0
    cart.items.each do |item|
      total += item.price * item.quantity
    end
    total
  end
end
- **修改后**:
module TotalCalculator
  def calculate_total(items)
    total = 0
    items.each do |item|
      total += item.price * item.quantity
    end
    total
  end
end

class OrderProcessor
  include TotalCalculator
  def calculate_total(order)
    calculate_total(order.items)
  end
end

class CartCalculator
  include TotalCalculator
  def calculate_total(cart)
    calculate_total(cart.items)
  end
end
  1. 继承层次过深

    • 问题:继承层次过多,导致代码理解和维护困难,同时可能会违反里氏替换原则。
    • 改进:尽量减少继承层次,优先考虑组合方式来复用代码。

    示例

    • 修改前
class Animal
  def speak
    "I'm an animal"
  end
end

class Mammal < Animal
  def speak
    "I'm a mammal"
  end
end

class Dog < Mammal
  def speak
    "I'm a dog"
  end
end

class Labrador < Dog
  def speak
    "I'm a labrador"
  end
end
- **修改后**:
class Animal
  def speak
    "I'm an animal"
  end
end

class Dog
  def initialize(animal)
    @animal = animal
  end

  def speak
    "I'm a dog, based on #{@animal.speak}"
  end
end

class Labrador
  def initialize(dog)
    @dog = dog
  end

  def speak
    "I'm a labrador, based on #{@dog.speak}"
  end
end