大家好,欢迎来到停止重构的频道。
上一期我们讨论了如何学习编程语言,学习完了编程语言后,很多人就开始学习各种框架或工具了。
这样当然是可以的,而且这样可以更快地出活。
但是这样往往也会出现一个很严重的问题,框架、工具的学习会只停留在使用方法上,而不了解其运行原理。
基本上每一个框架、工具都需要重新学习,而且一旦发生一些奇怪问题且网上查不到的话,那基本就翻车了。
所以学会了编程语言后,我们建议不要立即学习框架、工具,而应该先了解这些:
1、文件操作
2、网络通信
3、线程与线程同步
4、进程与进程同步
如果是会C语言且了解linux系统的小伙伴,可以买一本《UNIX环境高级编程》,这本书一般也叫APUE里面有系统且详细的介绍。
这里需要特别说明的是:本期内容是不适合前端开发的,因为前端网页是被浏览器隔离的,不与操作系统直接交互。
文件操作
文件操作也就是读写文件、删除文件等对文件的操作。
文件操作是很简单的,但通过文件操作的学习,会让你对文件有一个更直接的认知,文件只不过是一堆字符串,而这堆字符串的具体意义是程序决定的。
比如说,通过自己写的程序拷贝图片文件,每次读取10字节,并写入新文件,新文件照样可以作为图片打开。
知道了这些后,再去学习文件下载、文件上传、分片上传等工具或框架时。
你就会明白,无论文件是视频还是文档,其实过程都是一样的,程序每次只获取到一部分字符串,程序处理完一部分字符串后,再处理下一部分的字符串。
对于文件操作,会有很多衍生的做法,比如,浏览器对HTML文件的流式处理PHP服务器动态渲染网页等。
网络通信
网络通信可以理解为跨机器的文件操作。
比如,浏览器观看视频,浏览器不断通过网络获取视频文件,并解析显示视频内容。
一般网络通信需要了解TCP/IP的工作原理,因为很多协议都是基于TCP的,如HTTP、SMTP、RTMP等。
不同协议的网络通信工作原理基本都是差不多的,客户端向服务端建立连接,连接成功后客户端、服务端就可以通信了。
期间,通信的内容其实就是字符串,且与文件操作一样,都是一次只发送一部分再发送下一部分。
理解了网络通信的好处是,再去学习一些操作服务软件的框架工具时,就会更加简单,比如,数据库、Redis等的操作工具。
以MYSQL为例,在前面《数据库工作原理》里说过SQL语句只不过是一条字符串。
所以在学习数据操作工具时,如JPA、MyBatis时,就可以更有针对性地快速学习,我们并不需要从零慢慢学习他们的工作原理、具体特性,我们只需要知道该工具如何建立连接,如何生产我们想要的SQL语句即可快速上手。
线程与线程同步
线程可以理解为一个程序内同时执行多个任务,一个任务就是一个线程。
而线程同步就是线程间的协调,所有的线程同步场景都可以归为“生产者、消费者问题”。
一般场景是,生产者是负责获取或生成数据的线程,生产者线程会把每次生产的数据放到仓库中。
消费者线程会不断从仓库中获取数据并对其进行处理,如果当前仓储为空,消费者线程会进入等待状态。
当然,根据具体场景可能会有一些变化,如仓库是有上限的,那么当仓库满了,生产者线程需要等待消耗后再生产等。
以浏览器对HTML文件的流式处理为例,下载HTML文件的线程为生产者线程,解析HTML文件的线程为消费者线程,下载线程会不断获取HTML文件内容并放到一个数据仓库中(仓库),解析线程会不断从数据仓库中获取数据并解析。
当然,具体的线程同步会涉及到很多工具,如线程锁、条件变量等。不仅这些工具复杂,具体的线程模型编程也是很复杂的,特别是功能复杂的软件。
了解线程与线程同步的好处,其实不仅仅是可以编写复杂的软件,我们还可以更好地理解一个软件的运行原理。
如在前面《后端工作原理》里介绍过Tomcat是有连接池、线程池的每个请求会先进入链接池,有空闲的线程再处理这个请求。
那了解这些服务软件的运行原理有什么好处呢?
可以更好地归纳这些服务软件,使用过Tomcat后,配置node的后端服务时,不需要别人提醒就知道要配置线程池了。
进程与进程同步
一般一个程序运行的实例就是一个进程,不同进程是完全独立的。
当然,一个程序的实例也可以创建多个进程,那进程与线程的区别在哪呢?
进程间是资源完全独立的,而线程间是部分资源共享的,如线程间可以共享堆空间变量、全局变量等。
进程间的同步同样也可以归结为“生产者、消费者模型”,但是进程间同步问题在具体实现上更为简单。
比如,后端程序和数据库程序,由于是两个完全独立的进程,所以一般就是通过网络通信同步发送请求,等待结果就可以了,等待结果的方式也可以是同步或异步。
进程同步的工具除了网络通信,还有共享内存、信号等等,但这些都要求这些进程在同一个机器上才可行,这里不作详细介绍。
了解了进程与进程同步,就可以更好地理解网站系统或其他大型系统的结构,就可以更好地理解我们往期的《网站系统调优基本思路》。
总结
文件操作、网络通信、进程线程及其同步,我们只做了最浅显的介绍,要想真正领悟还是需要做一些编程练习。
虽然这些练习远没有学习数据库、后端框架有成就感,但是从长远来看,这些知识却能帮我们更好、更快速地使用更多的工具、框架,我们也能写出更加复杂的程序。
一直以来,停止重构的内容其实更偏向于关键问题及对应的关键理论,而非手把手教学。
一个很重要的原因是我们的重点是架构、而非某个具体工具的使用,错误的问题认知前提下,再好的工具也是没有用的。
另外一个重要原因是,很多年前,我问过我的老师一个问题,这个回答直到目前我都是比较认可的。
我们为什么要花4年学习专业理论,而非直接学习现成工具呢?很多工人也可以从工作经验归纳经验技巧。
老师说,先不论工具会不断升级改造,完整的理论基础能让你俯瞰这些工具,推演出这些工具的核心设计和了解它们解决的核心问题,工具的学习和使用是简单的,也能让你更容易创造新工具、发展或修正理论。
这是站在巨人肩膀上的道理,毕竟一个行业的理论是很多个时代的人共同归纳、试错的经验。
反过来,如果仅从工具学习、工作经验出发,虽然感觉更有用,也更快做出点什么,但是这样是很容易被某个具体的工具、技术、技巧所蒙蔽,这样归纳出来的经验很大概率是片面的,会越走越窄。