编程范式 | 青训营笔记

133 阅读9分钟

编程范式

课程介绍

JavaScript 做为一种融合了多种编程范式的语言,灵活性非常高。前端开发人员需要根据场景在不同编程范式间自如切换。进一步需要创造领域特定语言抽象业务问题。 本次课程会帮助你了解不同编程范式的起源和适用场景。掌握 JavaScript 在不同的编程范式特别是函数式编程范式下的使用。进一步帮助你掌握创建领域特定语言的相关工具和模式。

课程重点

  • 编程语言

    • 机器语言
    • 汇编语言
    • 中级语言
    • 高级语言
  • 编程范式

    • 过程式
    • 面向对象
    • 函数式编程
    • 响应式编程
  • 构建领域特定语言

    • 词法解析
    • 语法分析
    • 工具生成
    • 解释与编译

一、编程语言=》能把人类的指令转换成机器能听懂的指令

机器语言

image.png

汇编语言

汇编语言是使用字母来代替数字,方便输入,不同字母在不同的机器架构下代表不同的数值,这样提高了语言的可移植性。

image.png

高级语言

为了进一步提高了可移植性,更加贴近自然语言和人类思维,出现了编译器,编译器的出现使得高级语言转变为汇编语言进一步转变为机器语言,这样就可以在较少的源码情况下,获得较大的编译。

image.png

C/C++

C:“中级语言”,是面向过程式语言代表,将高级语言的基本结构和语句与低级语言的适用性结合

·可对位,字节,地址直接操作,这三者就是计算机最基本的数据结构单元

·代码和数据分离倡导结构化编程,使程序除必要内容外,其余保持独立

·功能齐全:数据类型和控制逻辑多样化,引入指针的概念,可以使程序效率更高

·可移植能力强

image.png

C++:面向对象语言代表,在C的基础上增加了对类的指示

.C with Classes

·继承

·权限控制

·虚函数

·多态

image.png

Lisp

Lisp:函数式语言代表

·与机器无关

.列表︰代码即数据

·闭包

0698f70828670d963773cd623cc2fa7.png

JavaScript

基于原型和头等函数的多范式语言,融合的范式包括以下几种

·过程式

·面向对象

·函数式

·响应式*

总结

a301536f2cb32fbf0d65ab3e516c51b.png

二、编程范式

根据以下特性进行分类

7debb9c5ad2e375af9f7001924be99f.png

常见的编程范式

命令式和声明式

image.png 命令式主要侧重于程序员如何操作机器改变状态,过程式是把操作用过程进行分组,而面向对象则是根据操作和状态进行分组

声明式是指程序员声明所想要的结果而不是命令具体的操作,函数式通过一系列的函数组合来声明逻辑,响应式通过数据流和映射函数来表现结果

过程式编程

过程式的两大特点是自顶向下的程序设计和结构化的编程思想

image.png

结构化编程

结构化编程是过程式编程的最佳实现,它采用子程序、块结构、for循环、while循环 3bdde874a6a82e241196b07ae4e0546.png

JS面向过程

be56cd09fd6891c5b5b5b57ffa14b1b.png

面向过程式编程的缺点:

在结构化编程中。函数和它操作的数据没有直观的体现。随着程序规模的扩大,程序变得难以理解,很难直接看出来函数之间存在怎样的调用关系。同时这种情况下,查错也会变得非常困难。=>数据与算法关联弱;

面向过程没有封装和底层的概念,可以直接访问,当有改动时需要把所有的数据拿出来修改=>不利于修改和扩充;

面向过程程序大量函数之间的关系变复杂,要抽取可重用片段出来就变得很复杂=>不利于代码重用。

面向对象编程

封装

封装就是把客观事物封装成具体的类,类数据与方法可以只让可信的类和方法操作,对不可信的进行隐藏,一个类就是封装了数据以及操作这些数据的代码逻辑形式

4c5cb08a495b9c4678e4f1f66102828.png

继承

继承可以是让某个类型的对象可以获得另一个类型对象的属性和方法,支持按级分类的概念,继承可以使用现有类的所有功能,并且在无需重写的情况下对类的功能进行扩充

4500ba35f0a58399eae29a993c64268.png

多态

一个类实例的相同方法在不同的情形下有不同的表现形式,多态机制使得具有不同内部结构的对象可以共享相同的外部接口

d4dc0735dc8decf44cca0640ebb5da0.png

依赖注入

46752afdd80f5cfcffba594910bbffc.png

依赖注入是面向对象编程的高级特性,依赖注入是指在程序运行过程中,需要对另一个对象进行使用时,无需在代码中进行创建被调用者,而是依赖于外部注入,也叫控制反转。可以降低计算机代码之间的耦合度,要借助一些类库的操作

1f732637020133be8538b056af24e65.png

面向对象编程_五大原则

  • 单一职责原则:一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化;
  • 开放封闭原则:用抽象构建架构,用实现扩展原则;
  • 里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能;
  • 依赖倒置原则:程序依赖抽象(抽象类和接口), 而不依赖于具体的实现, 就是对抽象进行编程, 不要求对实现进行编程
  • 接口分离原则:将不同的功能定义在不同的接口来实现接口的隔离, 避免了其他类在依赖该接口时依赖其不需要的接口, 可以减少依赖的冗余性和复杂性

面向过程

面向对象编程有什么缺点?

面向对象编程语言的问题在于,它总是附带着所有它需要的隐含环境。你想要一个香蕉,但得到的却是一个大猩猩拿着香蕉,而且还有整个丛林

推荐函数式编程

函数式编程

用纯函数的组合来描述计算过程。

根据lambda演算,如果一个物体能够用一系列函数组合的算法来描述,则可证明该物体是可计算的。就可以用编程的函数语言来计算过程。

函数式编程尽量减少变化的部分,由此让代码变得更清晰

其实JavaScript并不是纯粹的函数式编程,但通过一些编码规范和函数库工具ramdajs就可以实现JavaScript函数式编程

函数式编程特点

  • 函数式“第一等公民”
  • 纯函数/无副作用
  • 高阶函数/闭包

函数式编程_First Class Function(一等函数)

ca5b5692691aefb771342b6046fac13.png

函数式编程_Pure Function(纯函数)

d4f62783bd7b26a15b893748a24e362.png

优势

  • 可缓存
  • 可移植
  • 可测试
  • 可推理
  • 可并行

函数式编程_Currying(kelihua)

解决参数传来传去的麻烦 该特点实现利用了闭包和高阶函数的特性,把之前的参数暂存起来,同时返回一个新的函数 26e03215f5db15c3b9d41c83b86afc5.png

函数式编程_Composition(函数组合)

ebf36ac0959fd277e5b9831c4a44412.png

通过组合形式返回一个高阶函数

函数式编程_Functor

可以当做容器的类型,类型支持对容器内的元素进行操作

将异常和处理逻辑保存在容器中 4eb3323a781b8a41879f988298e6373.png

函数式编程_Monad

可以去除嵌套容器的容器类型

3fdb3ade635db42b34bff7dbb02a8ab.png

函数式编程_Applicative

直接对两个容器直接操作

2f73cf91a1aa53175bce4c98e139fd9.png

响应式编程

  • 异步/离散的函数式编程

    • 数据流

    • 操作符

      • 过滤
      • 合并
      • 转化
      • 高阶 同样没有纯粹的响应式编程,需要借助一些工具库的帮忙,比如RxJS

响应式编程_Observable

  • 观察者模式
  • 迭代器模式
  • Promise/EventTarget超集* promise代表数据不会只有一次;EventTarget对数据进行向上传导 913efbcc3d37929b94761ab71e06d33.png

3596af76f800b87f67597724e298227.png

响应式编程_操作符

要对数据流进行处理 响应式编程的“compose”

  • 合并
  • 过滤
  • 转化
  • 异常处理
  • 多播

响应式编程_Monad

取出嵌套的Observable

1036b493f39d0a430fff9cb93524d97.png

总结

9113e081c6ae17812a7ca998d6e2acf.png

三、领域特定语言

领域特定语言(domain-specific language)(DSL)是一种旨在特定领域下的上下文的语言。这里的领域是指某种商业上的(例如银行业、保险业等)上下文,也可以指某种应用程序的(例如 Web 应用、数据库等)上下文。与之相比的另一个概念是 通用语言(general-purpose language) (GPL,LCTT 译注:注意不要和 GPL 许可证混淆),通用语言则可以广泛应用于各种商业或应用问题当中。

e72e944004dc1b841a667f1877562d3.png

语言运行

语言运行:一个语言字符串要先经过词法解析器。处理之后形成一些短语,短语经过语法解析器后形成语法树,之后对树状结构进行遍历分析,遍历过程中既可以执行语句,也可以将树转化成另一种语言(编译)(代码生成)。 1886cb538a42b64e9f7928518e14a82.png

lexer

SQL Token分类

  • 注释
  • 关键字
  • 操作符
  • 空格
  • 字符串
  • 变量 72fd4c7ed65d1d957e2a9000ea0eace.png

b59d93fa9fec9648b4dfbba69e01f3f.png

Parser_语法规则

LL:从左到右检查,从左到右构建语法树

da873301eab7e3794f80a01abc19e3f.png LL:从右到左检查,从右到左构建语法树

k和1代表我们需要往下看的时候token语法数量 1f4ccb8cd3da27f4b9d507b330a6d38.png

tools

4e1cb0d196ca6044add189ff9cbf14d.png

生成语法树

visitor

从上到下从左到右遍历语法树

f2a23d031aedb2be40097b2ec4daac8.png

总结

fa916cc0acf91ca8baa5eb794461270.png

感想:

这门课程是第一次学习前端知识的编程范式。之前有了解过Java语言的面向对象过程,面向对象的五大编程原则在设计模式中也了解过。今天学习到了JavaScript使用工具库转化成面向对象编程和函数式编程。也了解了很多工具库ambdajs等。这门课包含的概念内容很多。需要记住的很多,目前是半懵半懂的姿态。当然后续自己也需要课后多加练习才能熟练掌握编程范式。