编程范式 | 青训营笔记

102 阅读4分钟

面向过程编程

用一系列流程来完成任务,没有返回值,存在副作用。强调过程性,以解决问题为导向编写函数并且依次调用。 过程式函数是自定向下的, 结构化编程是过程式编程的最佳实践,包括了顺序结构、选择结构和循环结构。 面向过程编程存在以下问题:

  • 数据与算法(函数)的关联弱。当数据的值不正确时难以找到哪个函数导致,因此差错会很困难。
  • 不利于修改和扩充
  • 不利于代码重用

面向对象编程

面向函数编程有几个主要特征:

  • 封装
  • 继承
  • 多态
  • 依赖注入

面向对象编程的五大原则:

  • 单一职责原则SRP(Single Resposibility Principle)
  • 开发封闭原则OCP(Open Closed Principle)
  • 里氏替换原则LSP(Liskov Substituion Principle)
  • 依赖倒置原则DIP(Dependecy Inversion Principle)
  • 接口分离原则ISP(Interface Segregation Principle)

SRP:一个类尽量只做一件事,比如说STL中的迭代器设计就体现了这个原则。类的职责过多,容易导致类间职责依赖,提高耦合度,降低内聚性。设计类时要尽量避免类的冗杂功能。
OCP:对扩展开放,对修改封闭。扩展开放,指的是对已有不变的类可以扩展更多功能,一般由继承和多态实现。对修改封闭,指的是对设计好的类不要去修改,关键是要抽象化事物以得到无需修改的稳定的类。
LSP:子类可以替换父类并出现在父类能够出现的任何地方,保证了继承复用的可靠。
DIP:细节依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都依赖于抽象;抽象不依赖于具体,具体依赖于抽象。依赖倒置原则是对传统过程性设计方法的“倒转”,也就是确定一个抽象类后再细化,是高层次模块复用及其可维护性的有效规范。
ISP:使用多个小的专门的接口,而不要使用一个大的总接口。

函数式编程

面向对象编程语言的缺点是,在实际应用中往往不需要获得一整个类,而是某个类中的某个方法。而面向对象不利于这种实现。 函数式编程将电脑运算视为函数运算,并且避免使用程序状态以及可变对象。

  • 在函数式编程中,函数是头等对象即头等函数,这意味着一个函数,既可以作为其它函数的输入参数值,也可以从函数中返回值,被修改或者被分配给一个变量。
  • 函数式编程鼓励使用纯函数。所谓纯函数,就是指符合以下条件的函数。
    • 此函数在相同的输入值时,需产生相同的输出。函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关。
    • 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等。 纯函数的使得:可缓存、可移植、可测试、可推理、可并行。
  • 函数式编程实现了柯里化。Carrying指把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
  • 函数式编程鼓励使用组合。Composition可以对代码进行优化重写。
  • functor。容器概念的出现可以避免对异常容器元素的直接考虑,异常情况的判断都将封装到容器内部。
  • applicative。可以直接对两个容器直接操作。

响应式编程

响应式编程时一种异步/离散的函数式编程,是一种面向数据流和变化传播的声明式编程范式。比如在a=b+c中,b、c在赋值之后的变化同样会影响a的变化。这和命令式编程有着本质区别。

  • observable。observable分为冷、暖、热三种,具体的区别可以参考RxJS进阶-响应式编程与Observable类型 - 掘金 (juejin.cn)
  • compose。操作符只对数据做搬运和加工,对下游是作为发布者(Publisher),传递上游的数据到下游;对上游是作为订阅者(Subscriber),传递下游的请求到上游。

领域特定语言

Domain-specific language(DSL) 编写DSL的基本流程:

Pasted image 20230424193435.png 关于parser:

  • Parser_LL:从左到右检查,构建语法树。只适用于简单语法。
  • Parser_LR:从左到右检查,从右到左构建语法树。表达力强,效率高。但是需要事先构建查询表,因此适合工具生成,不适合手工编写。