返回

只因900行 代码重构,我流着泪:由此总结了6大重构类必须遵守的原则

闲谈

长类危机

最近,在对已有项目进行扩展的时候,发现要改动的一个类它长900行,开放了近40个public接口,我流着泪把它给改完了。

通过这次教训,我总结了以下6个关于代码重构的原则:

  1. 单一职责原则(SRP) :一个类应该只做一件事,而且应该做得很好。
  2. 开闭原则(OCP) :一个类应该对扩展开放,对修改关闭。
  3. 里氏替换原则(LSP) :一个子类应该能够替换其父类,而不会改变程序的行为。
  4. 接口隔离原则(ISP) :一个类应该只依赖于它真正需要的接口。
  5. 依赖倒置原则(DIP) :一个类应该只依赖于抽象,而不是具体的实现。
  6. 合成/聚合复用原则(CARP) :一个类应该通过组合或聚合其他对象来实现其功能,而不是通过继承。

单一职责原则(SRP)

SRP是最基本也是最重要的代码重构原则之一。它规定一个类应该只做一件事,而且应该做得很好。这有助于提高代码的可读性、可维护性和可扩展性。

例如,在一个简单的银行应用程序中,我们可以有一个Account类来表示一个银行账户。Account类应该只负责与银行账户相关的事情,如存款、取款、查询余额等。它不应该负责与用户界面、数据存储或其他无关的事情。

如果Account类违反了SRP,那么它就可能变得很臃肿、难以理解和维护。例如,如果Account类还负责与用户界面交互,那么当我们更改用户界面时,Account类也需要随之更改。这会给我们的代码带来不必要的耦合,并使之难以维护。

开闭原则(OCP)

OCP规定一个类应该对扩展开放,对修改关闭。这意味着我们可以很容易地向类中添加新的功能,而不需要修改类的现有代码。

例如,在上面的银行应用程序中,我们可以很容易地向Account类添加一个新的功能,如转账。我们只需要创建一个新的方法,如transfer(Account toAccount, double amount),而不需要修改类的现有代码。

如果Account类违反了OCP,那么当我们想要向类中添加新的功能时,我们就需要修改类的现有代码。这会使我们的代码变得难以维护,并可能导致错误。

里氏替换原则(LSP)

LSP规定一个子类应该能够替换其父类,而不会改变程序的行为。这意味着我们可以放心地用一个子类来替换其父类,而不需要担心程序会出问题。

例如,在上面的银行应用程序中,我们可以创建一个新的子类SavingsAccount来表示一个储蓄账户。SavingsAccount类应该继承自Account类,并覆写deposit()withdraw()方法,以便对存款和取款操作收取利息。

如果SavingsAccount类违反了LSP,那么当我们用SavingsAccount类来替换Account类时,程序的行为可能会发生变化。例如,如果SavingsAccount类没有正确地覆写deposit()withdraw()方法,那么存款和取款操作可能不会收取利息。

接口隔离原则(ISP)

ISP规定一个类应该只依赖于它真正需要的接口。这意味着我们应该避免创建一个包含很多方法的臃肿接口,而应该创建多个更小的、更具体的接口。

例如,在上面的银行应用程序中,我们可以创建一个IAccount接口,该接口只包含与银行账户相关的方法,如deposit()、withdraw()getBalance()。我们可以再创建一个ISavingsAccount接口,该接口继承自IAccount接口,并添加一个新的方法`calculateInterest()”。

如果我们违反了ISP,那么我们的代码可能会变得难以理解和维护。例如,如果IAccount接口包含了很多与储蓄账户无关的方法,那么当我们使用IAccount接口时,我们就需要实现这些与储蓄账户无关的方法。这会使我们的代码变得更加臃肿和难以维护。

依赖倒置原则(DIP)

DIP规定一个类应该只依赖于抽象,而不是具体的实现。这意味着我们应该使用接口或抽象类来定义我们的依赖关系,而不是使用具体的类。

例如,在上面的银行应用程序中,我们可以创建一个IAccountService接口,该接口定义了与银行账户相关的所有操作,如deposit()、withdraw()getBalance()。我们可以再创建一个AccountService类,该类实现了IAccountService接口。

如果我们违反了DIP,那么我们的代码可能会变得难以理解和维护。例如,如果Account类直接依赖于AccountService类,那么当我们想要更换AccountService类时,我们就需要修改Account类的代码。这会使我们的代码变得更加耦合和难以维护。

合成/聚合复用原则(CARP)

CARP规定一个类应该通过组合或聚合其他对象来实现其功能,而不是通过继承。这意味着我们应该尽量使用组合或聚合来复用代码,而不是创建新的子类。

例如,在上面的银行应用程序中,我们可以创建一个Bank类,该类包含一个Account类的数组。Bank类可以通过Account类来实现其功能,如存款、取款和查询余额等。

如果我们违反了CARP,那么我们的代码可能会变得难以理解和维护。例如,如果我们创建了一个新的Bank子类,那么我们需要重新实现Bank类中的所有方法。这会使我们的代码变得更加臃肿和难以维护。

总结

以上6个原则是代码重构中最重要的原则之一。通过遵循这些原则,开发人员可以编写出更健壮、更易于维护的代码。