Skip to content

Latest commit

 

History

History
253 lines (170 loc) · 11.5 KB

File metadata and controls

253 lines (170 loc) · 11.5 KB
created_date 2020-11-16

[TOC]

程序

  • 程序由两部分组成: 运算 和 IO操作。

计算机语言

  • cpu与语计算机言

    1. 编译类型语言:优化为二进制,cpu直接进行解读。
    2. 解释型语言:运行时,使用解释器进行解读。
    3. 混合语言:被优化的中间码,再由解释器进行解读。
  • 针对代码:

    1. 动态语言:运行时可以改变其代码结构:例如新的函数、对象、代码可以被引进,已有的函数可以被删除或是其他结构上的变化。
    2. 静态语言:运行时代码结构不可变的语言。
  • 针对数据类型:

    1. 动态类型语言:运行期间才去做数据类型检查。
    2. 静态类型语言:编译期间或者运行前进行数据类型检查。
  • 针对变量的数据类型是否可以被改变:

    1. 强类型语言:当一个变量被指定为某个数据类型,如果不经过强制类型转换,那么它就永远是这个数据类型。
    2. 弱类型语言:一个变量可以被赋予不同数据类型的值。

编程范式

  1. 面向过程

  2. OOD 面向对象设计(Object-Oriented Design)

  3. OOP 面向对象编程(Object Oriented Programming)

    1. 只能通过对象内的方法实现修改对象的属性。将一切东西都抽象为对象,将所有的行为都抽象为对象的方法。
  4. FP 函数式编程(Functional programming)

    1. 不会改变对象的属性,只会输入对象和创建新的对象。不会更改函数外的对象,所有的更新都在函数内进行,输出新的对象。
  5. TDD 测试驱动开发(Test-driven development)

    1. 在开发功能代码之前,先编写单元测试用例代码。

GC

  1. 解放双手,不需要手动管理内存
  • GC算法设计时考虑的指标:
    1. 程序吞吐量:GC对程序效率的影响,也就花费在GC的时间和程序处理正常业务的时间比。
    2. GC吞吐量:单位时间内垃圾回收的数量。
    3. 暂停时间:Stop-the-world 的时间。
    4. 并发:垃圾回收机制如何使用多核。

编程技巧

  1. 哪些变量应该常驻内存,哪些变量应放在函数里。

编程相关

stack&heap

    • 栈(Stack)可以存放函数参数、局部变量、局部数组等作用范围在函数内部的数据,它的用途就是完成函数的调用。
    • 对每个线程来说,栈能使用的内存是有限的,一般是 1M~8M,这在编译时就已经决定了,程序运行期间不能再改变。如果程序使用的栈内存超出最大值,就会发生栈溢出(Stack Overflow)错误。

反射

  • 反射式编程(reflective programming)
  • 早期计算机的原生汇编语言本质上就具有反射特性。因为最初架构可以通过定义指令作为数据及使用自修改代码来编程,实现反射功能是很平常的。
  • 反射的概念是由Smith在1982年首次提出的,主要是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。
  • 反射主要用途就是使给定的程序,动态地适应不同的运行情况。

鸭子类型 vs 结构化类型 vs 标称类型

  • Duck Typing vs Structural Typing vs Nominal Typing System

  • 参考

  • 编程语言具有类型概念

    • 布尔类型,字符串,整型或者被称为类或者结构体的更加复杂的结构。
  • 根据如何将类型解析并赋值给各种构造(例如变量,表达式,函数,函数参数等),编程语言可以归类为鸭子类型,结构化类型,标称类型。

  1. 鸭子类型
    • 代码里不需要声明此类型可以赋值给此构造。
    • 编译期不进行类型检查。类型的解析和解释发生在运行时,这可能导致运行时错误。
    • 例如 Python 和 Javascript 等语言。
  2. 结构化类型
    • 代码里不需要声明此类型赋值给了此构造。
    • 编译期,编译器会进行类型的检查。
    • 例如 Go 语言。
  3. 标称类型
    • 代码里需要声明此类型赋值给了此构造。(例如Java里需求强调这个类型实现了这个接口)
    • 编译期,编译器会进行类型检测。
    • 例如 Java,C++, Rust 等语言。

编程系统设计

  • 依赖倒置原则
    • 因为底层比上层更容易发生变化,因此产生了依赖倒置原则。
    • 比喻:我们有一辆车子,轮子坏了我们直接去更换,车窗坏了我们也直接去更换,这些组件都是为了这辆车而进行定制的,而不是这辆车为这些组件进行定制。
    • 俗话说,业务决定技术实现,而不是相反。

控制反转

  • 控制反转 IoC(Inversion of Control)
  • 定义:一种软件设计模式,是践行依赖倒置原则的一种设计模式,是将组件间的依赖关系从程序内部提到外部来管理。
  • 目的:降低代码的耦合度,使得程序更加的模块化,更易于扩展.

控制反转实现方式一

  • 依赖注入(dependency injection)
  • 定义:各个组件的关系由第三方管理,组件也有第三方进行创建,当程序内一个组件依赖于另一个组件时,第三方则将其注入进程序内部。
  • 有三种类型的依赖注入
    1. 构造函数注入(Spring支持注解+xml)
    2. setter 注入(Spring支持注解+xml)
    3. 接口注入

并发编程

并发的发展

  1. 单线程服务器
  2. 多线程服务器 Java
  3. 单线程,多IO线程 Nodejs
  4. 协程
    • 线程:操作系统处理线程的调度需要复杂的上下文切换,其中包括用户态和内核态的切换,所以它的效率不够高,尤其是如果我们需要大量的随用随抛的线程时。
    • 协程的实现方式
      • 在 golang 里是 goroutine
      • 在 erlang 里是 process
      • 在 python 里是 coroutine
      • 在 rust 里是 future

线程间的通讯

  • 通讯方式: 静态变量、全局变量、内存映射、文件、socket、管道、消息等。
  1. 内存共享,通过锁的机制保护状态的一致性
  2. 通过管道,线程间通过通讯传递消息

其它

  • 语法糖指的是某种语法的原理相同的便捷替代品

  • 异常 程序中一般会出现两种错误:可恢复错误和不可恢复错误。

    • 可恢复错误的典型案例是文件访问错误,如果访问一个文件失败,有可能是因为它正在被占用,是正常的,我们可以通过等待来解决。
    • 不可恢复错误是由编程中无法解决的逻辑错误导致的,例如访问数组末尾以外的位置。
  • 泛型机制是编程语言用于表达类型抽象的机制,一般用于功能确定、数据类型待定的类,如链表、映射表等。

  • 宏与函数

    • 宏:在编译时执行的指令。
    • 函数:在运行时执行的指令。
  • 代码语句可以分为四种类型

    1. 声明语句: 例如定义结构体、定义函数、引入模块、赋值等等。
    2. 流程控制语句: 例如条件、分支、循环等等。
    3. 表达式语句: 专门用来产生值的一种构造式。
    4. 宏语句: 专门用来文本替换或生成指定代码。

编译器

GCC编译C源代码有四个步骤

  1. 预处理
    • 将C程序的头文件编译进来
    • 进行宏的替换
    • 可以用gcc的参数-E来参看
  2. 编译:转换为汇编语言文件
    • 将输入的文本转换成一系列的Token(标识符、关键字、符号、字面量等),同时忽略注释(文档注释除外)与空白字符等。
    • 词法分析
    • 语法分析
    • 语义分析
    • 可用gcc的参数-S来参看
  3. 汇编:转换为机器语言文件
  4. 链接 :转换为可执行的目标文件

程序间通信

  • 进程间通信的目的

    1. 数据传输
    2. 共享数据
    3. 通知事件
    4. 资源共享
    5. 进程控制
  • 实现方式

    1. 在不同的计算机系统中,它们之间要通过网络之间的协议才能实现。
    2. 在同一台计算机系统中,它们之间只需一定的通道就能实现。
  1. Socket 套接字通信

    1. 适用于client/server通信方式。
    2. 适用于点对点通信方式。
    3. client/server模型工作时要求有一套为客户机和服务器所共识的惯例来保证服务器能够监听解析信息,这一套惯例包括了一套协议,它必须在通信的两头都被实现。
    4. 根据不同的实际情况,协议可能是对称的或是非对称的。在对称的协议中,每一方都是server;在非对称协议中,则只有一方是server。 TELNET是对称协议。HTTP是非对称协议。
  2. file 文件

    1. 利用文件作为程序间通信的通道,程序A向一文件写入数据,程序B通过读取这个文件中的数据从而与程序A进行通信,同时这一过程也可以是反向的。
  3. signal 信号

    1. 这种方法仅用于进程控制,不能进行数据交换。例如在发生非法内存访问、执行无效指令、某些按键(如CTRL+C,DEL等)等都会产生一个信号,其他程序调用有关的系统调用或用户自定义的处理过程进行处理。
  4. pipe 管道

    1. 管道是一种简单的进程间通信(IPC)机制,分为无名管道和有名管道两种。
    2. 管道对数据采用先进先出的方式管理,并严格按顺序操作,管道不能被搜索,管道中的信息只能读一次。
    3. 管道是单向的。
    4. 管道实际上是内存中的一个临时存储区,由系统安全控制,并且独立于创建它的进程的内存区。
    5. 无名管道只是在父子进程之间或者一个进程的两个子进程之间进行通信的。无名管道其实是通过用给了一个指定名字的有名管道来实现的。
  5. MQ 消息通信

    1. 消息通信方式以消息缓冲区为中间介质,通信双方的发送和接收操作均以消息为单位。
    2. 在存储器中,消息缓冲区被组织成队列,通常称为消息队列(MQ)。
    3. 消息队列是独立于生成它的进程的一段存储区,任何具有正确访问权限的进程都可以访问消息队列,它非常适用于在进程间交换短消息。
    4. 消息队列在创建后将一直存在,直到使用相关的调用删除它为止。
  6. SM 共享内存

    1. 允许多个进程在外部通信协议或同步/互斥机制的支持下使用同一个内存段作为中间介质进行通信。
    2. 在进行通信之前,先创建一个共享内存段,然后进行映射和分离操作。同时可以根据需要改变共享内存段的存取权限以及其他的一些特征。
  7. 集中通信

    1. 通过中间件的方式,中间件是一类软件,它对应用程序隐含了实际网络和通信协议的细节。高级编程接口帮助开发者在不同的环境中创建应用程序,而不需要对将使用的网络和通信协议有更多的了解。
    2. 中间件在使用不同网络通信协议的客户机/服务器环境。它可以对客户机/服务器应用隐藏协议,从而使开发人员集中精力于改进应用程序,而不是开发通信接口。
    • PRC Remote Procedure Call
      • RPC机制强制通信的两个应用程序必须同时处于运行状态。
      • 做远程调用时,两者必须先建立连接,而且通讯链路质量对它的效果影响很大。
      • 优点是应用程序采用调用/返回方式通讯,拥有很高的潜在效率,
      • 缺点是需要应用程序间的紧密耦合,通讯线路必须在通信期间一直保持良好的状态,而且必须进行大量的底层通讯的编程工作。
    • conversations 会晤
    • MQSeries 消息队列