SOLID 是面向对象设计和编程中几个重要编码原则的首字母缩写。
- SRP: The Single Responsibility Principle 单一责任原则
- OCP: The Open Closed Principle 开放封闭原则
- LSP: The Liskov Substitution Principle 里氏替换原则
- ISP: The Interface Segregation Principle 接口分离原则
- DIP: The Dependency Inversion Principle 依赖倒置原则
当这些原则被一起应用时,它们使得进行软件维护和扩展变得更加可控。SOLID所包含的原则是通过引发编程者进行软件源代码的代码重构进行软件的代码异味清扫,从而使得软件清晰可读以及可扩展时可以应用的指南。
每一个类或则方法都应该有且仅有一个职责,而且他的这个职责应该被完全封装在这个类里面。
如何去判断你的代码是否符合这一原则的最好方式就是去问问自己:
这个类或者方法到底做了什么? 如果他干了不只一件事情的话,那么他就违反了SPR原则。
最佳实践:
- The use of concern, e.g. models/funding.rb
- Pundit Policy
- api_version.rb
- 使用Service, Concern, PORO, Pundit Policy分离耦合代码。
可以重构:
- MarketingMessageController#push_marketing_message
一个类或者模块对扩展开放,对修改关闭。 什么意思呢?他的意思就是:一旦一个类已经实现了当时的需求,他就不应该为了去实现接下来的需求而被修改。你是不是觉得这样做没有意义?
class NewCoolLogger < MyLogger
def initialize
@format_string = "[LOG] %s: %s\n"
end
def log(msg)
STDOUT.write @format_string % [Time.now, msg]
end
end
上一段代码中的format_string可能会被经常修改,将其开放出去,可以减少自身被修改的可能。
class MyLogger
def log(msg, formatter: MyLogFormatter.new)
STDOUT.write formatter.format(msg)
end
end
当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系。
客户模块不应关心服务模块的是如何工作的;同样的接口模块之间,可以在不知道服务模块代码的情况下,进行替换。即接口或父类出现的地方,实现接口的类或子类可以代入。
可以重构: mailgunjob.rb,抽象出SendGrid,MailGun无关的接口。
不应该强迫客户端依赖一些他们用不到的方法或接口。换句话说,多个特定客户端接口要好于一个宽泛用途的接口。
遵循Restful,提供基本的CRUD,不要过渡封装。
认为一个方法应该遵从依赖于抽象而不是一个实例。 依赖倒置原则代表了一种软件模块解耦的方式,他的定义有两部分:
- 上层模块不应该依赖下层模块,他们应该都依赖抽象。
- 抽象不能依赖具体实现,具体实现应该依赖抽象。
最佳实践:
- service 层中的抽象层,如report_service.rb/kpi_service.rb 中的 prepare_data_for_*方法,对 Service 中的具体逻辑进行抽象。
当业务逻辑越来越复杂时,传统的MVC三层并不能完全解决问题,Server 端的 Controller 与 Model 层变得越来越 Fat 难以维护;遵循 SOLID 原则合理的运用concern、service、poro等,可以帮助我们把代码变得简洁而又健壮,同时易于扩展和维护。
在CSS中应用SOLID原则,分离代码,减少冗余,增加复用。
降低View层的复杂度,使用MVVM。