Joh*_*ler 31 functional-programming solid-principles
来自OOP语言,我熟悉面向对象设计的SOLID原则.似乎其中一些适合功能性编程模型,而其他部分在缺乏状态的世界中毫无意义.重构功能代码是否有类似的原则?
gas*_*che 40
据我所知(我不是专家),SOLID原则并没有说明状态.它们也应该适用于函数式编程语言.他们对如何实现模块化提出了更多建议.
其中一些是相当明显的或至少是众所周知的.单一责任是UNIX原则"做一件事,做得好",在"组合"被广泛使用的功能语言中更为流行,同样如此.接口隔离原则也非常自然(将接口模块化并保持正交概念分离).最后,依赖性反转只是"抽象"的名称,在函数式编程中无处不在.
"OL"原则,Open/Closed和LSP,更倾向于基于继承作为核心软件工程概念的语言.函数式语言值/模块默认情况下没有开放递归,因此"实现继承"仅在非常特殊的情况下使用.组合物是优选的.我不确定你应该如何解释那个环境中的开放/封闭原则.您可能会认为这是关于封装,哪些功能程序也使用了很多,使用抽象类型等.
最后,Liskov替代原则似乎与继承有关.函数式语言并不总是使用子类型,但是当它们这样做时,确实假设"派生类型"应该保留"基类型"的规范.功能程序员当然要谨慎地指定和尊重他们的程序,模块等的接口和属性,并且可以在编程,重构时使用代数推理(这相当于我可以替代......).但是,一旦你摆脱了"默认继承"的想法,你就会有更少的接口违规问题,所以LSP并不像OOP那样被强调为重要的保护措施.
实际上,SOLID可能是一个好主意,可以为函数式编程提供更好的原则:
SRP:每个功能或模块应该只有一个职责或变更理由。这意味着每个函数应该执行特定的任务或计算,而不应该负责多个不相关的任务。通过遵循 SRP,代码可以变得更加模块化、更易于理解,并且不易出现 bug 和错误。
OCP:软件实体(例如函数、模块或类)应该对扩展开放,但对修改关闭。这意味着不应修改现有代码来添加新功能,而应通过添加新代码来扩展。通过遵循 OCP,可以使代码更加灵活和可维护,并且可以避免在修改现有代码时引入可能出现的错误和错误。
LSP:父类型的对象或函数应该能够被子类型的对象或函数替换,而不改变程序的正确性。这意味着对父类型进行操作的任何函数或模块都应该能够对任何子类型进行操作,而不会出现任何意外的行为或错误。通过遵循 LSP,可以使代码更加模块化和可扩展,并且可以避免在代码对其依赖项的行为进行过多假设时可能出现的错误和错误。
ISP:软件界面的设计应使其具有凝聚力并专注于一组特定的相关功能。这意味着模块或函数不应依赖于包含其不使用的方法或属性的接口。通过遵循 ISP,可以使代码更加模块化、更易于理解,并且可以避免引入不必要的依赖项,从而增加复杂性并降低可维护性。
DIP:高层模块不应该依赖于低层模块,而应该依赖于抽象。这意味着模块或函数应该依赖于接口或抽象类,而不是具体的实现。通过遵循 DIP,可以使代码更加灵活和可扩展,并且可以避免在模块之间引入紧密耦合,从而增加复杂性并降低可维护性。DIP 可以通过使用高阶函数、依赖注入或其他允许模块和函数解耦的技术在函数式编程中实现。
提示:SOLID 原则可以像面向对象编程一样应用于函数式编程,但需要进行一些调整。每个原则(SRP、OCP、LSP、ISP 和 DIP)都可以通过鼓励关注点分离、避免模块之间的紧密耦合以及促进抽象和接口的使用来帮助编写更加模块化、可维护和可扩展的功能代码。通过遵循 SOLID 原则,函数式程序员可以创建更可靠、更容易理解、更能适应变化的代码。