编程范式 | 青训营笔记

126 阅读4分钟

前言

过程式编程的核心在于模块化,在实现过程中使用了状态,依赖了外部变量,导致很容易影响附近的代码,可读性较少,后期的维护成本也较高。

函数式编程的核心在于“避免副作用”,不改变也不依赖当前函数外的数据。结合不可变数据、函数是第一等公民等特性,使函数带有自描述性,可读性较高。

面向对象编程的核心在于抽象,提供清晰的对象边界。结合封装、集成、多态特性,降低了代码的耦合度,提升了系统的可维护性。

不同的范式的出现,目的就是为了应对不同的场景,但最终的目标都是提高生产力。

机器语言

机器语言是机器能直接识别的程序语言或指令代码,无需经过翻译,每一操作码在计算机内部都有相应的电路来完成它,或指不经翻译即可为机器直接理解和接受的程序语言或指令代码。机器语言使用绝对地址和绝对操作码。

汇编语言

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。

中级语言

以 C 为代表

  • 可对位,字节,地址直接操作
  • 代码和数据分离倡导结构化编程
  • 功能齐全∶数据类型和控制逻辑多样化
  • 可移植能力强

高级语言

  • C++

    • C with Classes
    • 继承
    • 权限控制
    • 虚函数
    • 多态
  • Lisp

    • 与机器无关
    • 列表∶代码即数据
    • 闭包
  • JavaScript

    • 过程式
    • 面向对象
    • 函数式
    • 响应式

编程范式

什么是编程范式

  • 是否允许副作用
  • 操作的执行顺序
  • 代码组织
  • 状态管理
  • 语法和词法

过程式编程

  1. 特点
  • 自顶向下

  • 结构化编程

    • 顺序结构
    • 选择结构
    • 循环结构
  1. JavaScript 中的面向过程

     //数据
     export var car = {
         meter:100,
         speed:10,
     }
     //算法
     export function advanceCar(meter){
         while(car<meter){
             car.meter+=car.speed;
         }
     }
    

面向对象编程

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

  1. 单一职责原则SRP(Single Responsibility Principle)
  2. 开放封闭原则OCP(Open - Close Principle)
  3. 里式替换原则LSP(the Liskov Substitution Principle LSP)
  4. 依赖倒置原则DIP(the Dependency lnversion Principle DIP)
  5. 接口分离原则ISP(the Interface Segregation Principle lSP)

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

函数式编程

  • First Class Function函数是第一等公民

    函数和其他数据类型具备同等的地位,可以赋值个某个变量,也可以作为函数的参数,返回值

  • Prue Function纯函数/无副作用

相同的输入,总会得到相同的输出,在执行过程中没有任何的副作用

纯函数:不依赖于外部环境

无副作用:产生外部可观察的变化,比如对外界的数据进行修改

  • Carrying柯里化

利用函数与高阶函数,将接受多个参数的函数编程接受一个参数的函数,并返回余下的参数而且返回结果的新函数

  • Composition组合式

如果一个函数需要铜鼓哦多个函数处理才能得到最终结果,可以把中间过程的函数合并成一个函数

函数组合默认式从右向左执行,满足结合律

 //手动组合
 const toUpperCase = x => x.toUpperCase();
 const log = x => console.log;44function alertUppercase(str){
     log(toUpperCase(x));
 }
 ​
 //自动组合
 const alertUppercaseFn = compose(log,toUpperCase);
 复制代码
  • Functor仿子

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

常见Functor:Arry.map,Promise.then

可以将特殊情况都封装到容器中

 a.b=null?(a.b.c!=null?(a.b.c.d!=null?a.b.c.d.e:null):null)
 //可以改写成
 new Maybe(a).map(prop('b')).map(prop('c')).map(prop('d')).map(prop('e'));
 ​
 class Maybe{
     constructor(x){
         this.$value = x;
     }
     
     map(fn){
         return this.$value == null?this:new Maybe(fn(this.$value));
     }
 }
  • Monad

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

常见Monad:Array.flatMap,Promise.then

  • Applicative

对两个容器直接操作

响应式编程

异步/离散的函数式编程

  • 数据流

  • 操作符

    • 过滤
    • 合并
    • 转化
    • 高阶

1.Observable

  • 观察者模式
  • 迭代器模式

2.操作符

响应式编程的“compose”

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

3.Monad

去除嵌套的Observable

领域特定语言

领域特定语言(例如:HTML,SQL)一般都是由通用语言(例如:C,C++)实现的

语言的运行:

  1. 词法解析器处理形成短语
  2. 语法解析器处理形成语法树
  3. 遍历分析
  4. 代码生成

创造DSL

  • lexer

领域特定语言(例如:HTML,SQL)一般都是由通用语言(例如:C,C++)实现的

语言的运行:

  1. 词法解析器处理形成短语
  2. 语法解析器处理形成语法树
  3. 遍历分析
  4. 代码生成
  • parser

    推导式:表示非终结符到(非终结符或终结符)的关系。

    终结符:构成句子的实际内容。可以简单理解为词法分析中的token。

    非终结符﹔符号或变量的有限集合。它们表示在句子中不同类型的短语或子句。