代码重构|代码的坏味道及其重构建议

概述

在软件开发过程中,随着项目规模的增长,代码中可能会出现一些不良的编程习惯,这些习惯被称为“代码的坏味道”。识别并消除这些坏味道是重构过程的重要组成部分。本文档将详细介绍几种常见的代码坏味道,并提供具体的重构建议。

1. 重复代码 (Duplicate Code)

描述: 当相同的代码片段出现在多个地方时,这通常意味着代码需要被提取成单独的方法或模块。

例子:

public class ShoppingCart {

    public void calculateTotalPrice(List<Item> items) {
        double total = 0;
        for (Item item : items) {
            total += item.getPrice();
        }
        System.out.println("Total price: " + total);
    }

    public void calculateShippingCost(List<Item> items, double shippingRate) {
        double totalWeight = 0;
        for (Item item : items) {
            totalWeight += item.getWeight();
        }
        double shippingCost = totalWeight * shippingRate;
        System.out.println("Shipping cost: " + shippingCost);
    }
}

重构建议:

public class ShoppingCart {

    private double sumOfItems(List<Item> items, Function<Item, Double> sumFunction) {
        double total = 0;
        for (Item item : items) {
            total += sumFunction.apply(item);
        }
        return total;
    }

    public void calculateTotalPrice(List<Item> items) {
        double total = sumOfItems(items, Item::getPrice);
        System.out.println("Total price: " + total);
    }

    public void calculateShippingCost(List<Item> items, double shippingRate) {
        double totalWeight = sumOfItems(items, Item::getWeight);
        double shippingCost = totalWeight * shippingRate;
        System.out.println("Shipping cost: " + shippingCost);
    }
}
2. 冗长的方法 (Long Method)

描述: 如果一个方法执行了太多的操作或者代码过长,这可能意味着它应该被分解成更小的部分。

例子:

public class ReportGenerator {

    public void generateReport(Employee employee) {
        System.out.println("Employee Report:");
        System.out.println("----------------");
        System.out.println("Name: " + employee.getName());
        System.out.println("ID: " + employee.getId());
        System.out.println("Department: " + employee.getDepartment());
        System.out.println("Position: " + employee.getPosition());
        System.out.println("Salary: " + employee.getSalary());
        System.out.println("Email: " + employee.getEmail());
        System.out.println("Phone: " + employee.getPhoneNumber());
        System.out.println("Address: " + employee.getAddress());
        System.out.println("Joining Date: " + employee.getJoiningDate());
    }
}

重构建议:

public class ReportGenerator {

    public void generateReport(Employee employee) {
        printEmployeeDetails(employee);
    }

    private void printEmployeeDetails(Employee employee) {
        System.out.println("Employee Report:");
        System.out.println("----------------");
        printLine("Name", employee.getName());
        printLine("ID", employee.getId());
        printLine("Department", employee.getDepartment());
        printLine("Position", employee.getPosition());
        printLine("Salary", employee.getSalary());
        printLine("Email", employee.getEmail());
        printLine("Phone", employee.getPhoneNumber());
        printLine("Address", employee.getAddress());
        printLine("Joining Date", employee.getJoiningDate());
    }

    private void printLine(String label, String value) {
        System.out.println(label + ": " + value);
    }

    private void printLine(String label, int value) {
        System.out.println(label + ": " + value);
    }

    private void printLine(String label, double value) {
        System.out.println(label + ": " + value);
    }

    private void printLine(String label, Date value) {
        System.out.println(label + ": " + value);
    }
}
3. 过多的参数 (Too Many Arguments)

描述: 如果一个方法接收了过多的参数,这可能意味着参数列表需要被精简或替换为一个更复杂的对象。

例子:

public class OrderProcessor {

    public void processOrder(String orderId, String customerName, String product, int quantity, double price, String address, String paymentMethod) {
        // 处理订单逻辑
    }
}

重构建议:

public class OrderProcessor {

    public void processOrder(Order order) {
        // 处理订单逻辑
    }
}

public class Order {

    private final String orderId;
    private final Customer customer;
    private final Product product;

    public Order(String orderId, Customer customer, Product product) {
        this.orderId = orderId;
        this.customer = customer;
        this.product = product;
    }

    // Getters and other methods...

    public String getOrderId() {
        return orderId;
    }

    public Customer getCustomer() {
        return customer;
    }

    public Product getProduct() {
        return product;
    }
}

public class Customer {

    private final String name;
    private final Address address;
    private final String paymentMethod;

    public Customer(String name, Address address, String paymentMethod) {
        this.name = name;
        this.address = address;
        this.paymentMethod = paymentMethod;
    }

    // Getters and other methods...

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

    public String getPaymentMethod() {
        return paymentMethod;
    }
}

public class Product {

    private final String productName;
    private final int quantity;
    private final double price;

    public Product(String productName, int quantity, double price) {
        this.productName = productName;
        this.quantity = quantity;
        this.price = price;
    }

    // Getters and other methods...

    public String getProductName() {
        return productName;
    }

    public int getQuantity() {
        return quantity;
    }

    public double getPrice() {
        return price;
    }
}

public class Address {

    private final String street;
    private final String city;
    private final String zipCode;

    public Address(String street, String city, String zipCode) {
        this.street = street;
        this.city = city;
        this.zipCode = zipCode;
    }

    // Getters and other methods...

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }

    public String getZipCode() {
        return zipCode;
    }
}
4. 散乱的变动 (Scattered Changes)

描述: 当相关的变更分散在多个地方时,这表明代码需要更好的组织。

例子:

public class UserManagement {

    public void updateUser(User user) {
        // 更新用户信息
        user.setName("New Name");
        user.setEmail("new.email@example.com");
        // 更改密码
        user.setPassword("newPassword123");
    }

    public void resetUser(User user) {
        // 重置用户信息
        user.setName("Default Name");
        user.setEmail("default.email@example.com");
        // 更改密码
        user.setPassword("defaultPassword123");
    }
}

重构建议:

public class UserManagement {

    public void updateUser(User user, String name, String email, String password) {
        user.setName(name);
        user.setEmail(email);
        user.setPassword(password);
    }

    public void resetUser(User user) {
        updateUser(user, "Default Name", "default.email@example.com", "defaultPassword123");
    }
}
5. 冗余注释 (Redundant Comments)

描述: 当注释重复了代码本身的功能说明时,这样的注释是没有必要的。

例子:

public class Calculator {

    /**
     * This method adds two numbers.
     * @param a the first number
     * @param b the second number
     * @return the sum of a and b
     */
    public int add(int a, int b) {
        // Add the two numbers
        return a + b;
    }
}

重构建议:

public class Calculator {

    /**
     * Adds two numbers.
     *
     * @param a the first number
     * @param b the second number
     * @return the sum of a and b
     */
    public int add(int a, int b) {
        return a + b;
    }
}
6. 复杂的条件语句 (Complex Conditional Logic)

描述: 如果条件语句过于复杂,这可能意味着需要简化逻辑。

例子:

public class DiscountCalculator {

    public double applyDiscount(Order order) {
        double discount = 0;
        if (order.getTotalAmount() > 100 && order.getTotalAmount() <= 200) {
            discount = 10; // 10% off
        } else if (order.getTotalAmount() > 200 && order.getTotalAmount() <= 500) {
            discount = 20; // 20% off
        } else if (order.getTotalAmount() > 500) {
            discount = 30; // 30% off
        }
        return order.getTotalAmount() - (order.getTotalAmount() * (discount / 100));
    }
}

重构建议:

public class DiscountCalculator {

    private static final Map<Integer, Integer> DISCOUNTS = Map.of(
        100, 10,
        200, 20,
        500, 30
    );

    public double applyDiscount(Order order) {
        double discount = 0;
        int totalAmount = order.getTotalAmount();

        DISCOUNTS.forEach((threshold, rate) -> {
            if (totalAmount > threshold) {
                discount = rate;
            }
        });

        return order.getTotalAmount() - (order.getTotalAmount() * (discount / 100.0));
    }
}
7. 过大的类 (Large Class)

描述: 如果一个类承担了过多的责任,这通常意味着类需要被分割成更小的、职责更单一的类。

例子:

public class EmployeeManager {

    public void createEmployee(String name, String email, String department) {
        // 创建员工
    }

    public void updateEmployee(Employee employee, String newName, String newEmail, String newDepartment) {
        // 更新员工信息
    }

    public void deleteEmployee(Employee employee) {
        // 删除员工
    }

    public void listEmployees() {
        // 列出所有员工
    }

    public void sendEmail(Employee employee, String subject, String message) {
        // 发送邮件给员工
    }
}

重构建议:

public class EmployeeManager {

    private final EmployeeRepository repository;
    private final EmailService emailService;

    public EmployeeManager(EmployeeRepository repository, EmailService emailService) {
        this.repository = repository;
        this.emailService = emailService;
    }

    public void createEmployee(String name, String email, String department) {
        // 创建员工
        Employee employee = new Employee(name, email, department);
        repository.save(employee);
    }

    public void updateEmployee(Employee employee, String newName, String newEmail, String newDepartment) {
        // 更新员工信息
        employee.setName(newName);
        employee.setEmail(newEmail);
        employee.setDepartment(newDepartment);
        repository.update(employee);
    }

    public void deleteEmployee(Employee employee) {
        // 删除员工
        repository.delete(employee);
    }

    public List<Employee> listEmployees() {
        // 列出所有员工
        return repository.findAll();
    }

    public void sendEmail(Employee employee, String subject, String message) {
        // 发送邮件给员工
        emailService.sendEmail(employee.getEmail(), subject, message);
    }
}

public interface EmployeeRepository {
    void save(Employee employee);
    void update(Employee employee);
    void delete(Employee employee);
    List<Employee> findAll();
}

public interface EmailService {
    void sendEmail(String to, String subject, String message);
}
结论

通过识别和消除代码中的“坏味道”,我们可以显著提高代码的质量、可读性和可维护性。重构是软件开发过程中不可或缺的一部分,它有助于确保代码随着时间的推移仍然易于理解和修改。上述示例提供了一些基本的指导原则,但在实际应用中可能还需要根据具体情况做出适当的调整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的小白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值