只因900行 代码重构,我流着泪:由此总结了6大重构类必须遵守的原则
2023-10-27 06:23:52
长类危机
最近,在对已有项目进行扩展的时候,发现要改动的一个类它长900行,开放了近40个public接口,我流着泪把它给改完了。
通过这次教训,我总结了以下6个关于代码重构的原则:
- 单一职责原则(SRP) :一个类应该只做一件事,而且应该做得很好。
- 开闭原则(OCP) :一个类应该对扩展开放,对修改关闭。
- 里氏替换原则(LSP) :一个子类应该能够替换其父类,而不会改变程序的行为。
- 接口隔离原则(ISP) :一个类应该只依赖于它真正需要的接口。
- 依赖倒置原则(DIP) :一个类应该只依赖于抽象,而不是具体的实现。
- 合成/聚合复用原则(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个原则是代码重构中最重要的原则之一。通过遵循这些原则,开发人员可以编写出更健壮、更易于维护的代码。