这是一个创建于 1976 天前的主题,其中的信息可能已经有所发展或是发生改变。
编者是一个从事 Java 开发的普通软件攻城狮,迄今为止,粗粗算来不过刚刚进入编程的世界不过两年,但在这两年的光阴里,每当我抬头仰望星空(苦命加班)时脑海里总有这样一个疑问——“什么是编程”?
对于这个问题百度百科是这么说的,编程,是编定程序的中文简称,就是让计算机代为解决某个问题,对某个计算体系规定一定的运算方式,使计算体系按照该计算方式运行,并最终得到相应结果的过程。为了使计算机能够理解人的意图,人类就必须将需解决的问题的思路、方法和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的要求一步一步去工作,完成某种特定的任务。这种人和计算体系之间交流的过程就是编程。
文字很长,让我们稍微换个换个简单点的说法——用高度逻辑化的方法去描述一个模型,并以这个模型为基础来解决具体的问题。
作为 Java 开发大军的一员,经历诸多项目的洗礼(称为摧残更符合实际)之后,我对编程也有了更清晰的一些认知。作为一名接受了国家九年义务教育的理科少年,我喜欢理性地分析一件事情。苏格拉底说过理性分析有两种常见的方法,向上超越和向下还原(好吧,其实是我说的)。
现在让我们来进行向上还原的思考,编程是用于做什么的呢?最常见的使用方式就是做项目,一般一个完整且分工明确的项目都会需要这几部分人员,需求->开发->测试->运维,当然在小公司可能就会有人一肩挑之,撸起袖子来啥都能干。在经历了竞选投标等一番很有意思的操作拿到项目以后,就到了我们需求人员闪亮登场的时刻,需求人员一般会直接对接客户,细心了解甲方爸爸的要求——哪怕是手机壳变色这种,然后将客户的要求加工后传达给开发人员。
开发人员就是大众最耳熟能详的程序员,以加班多死的早闻名遐迩,做为加班狗的代言人充分贯彻了加班的奋斗美学。"改变世界"是我们的口号,和产品经理相爱相杀是我们的日常,如何避免掉发和颈椎病是我们聊天不可或缺的话题。
测试小姐姐们负责对项目质量的把控,平时可能活泼可爱,催你改 Bug 的时候能吼得你怀疑人生。一个高质量的项目必然有一个高水平的测试团队,如果说开发人员的工作是在建造大楼,那么测试人员就是负责让这栋大楼不会盖偏,不然随着楼层的累积必然有一天会无以为继,这个项目基本上也就算是死掉了。
运维老大哥们负责对大楼状态的监控以及对紧急情况的处理,比如有生产出了事故这时候就需要任劳任怨的运维人员出马了,这是一群 7*24 的狠人,我见过 too young too naive 的运维小姐姐被累哭,她曾坦言我只想睡个好觉。
扯得有些远了,回到正题,在上述人群中会涉及到编程的一般是我们的开发人员和测试人员,在开发人员那里它是生产工具,负责将项目从人的想法转化为计算机语言,也因此开发人员的水平将直接决定项目的质量,而在测试人员那里它是验证工具,时下流行的自动化测试就是将重复性的功能验证也交给代码。
现在让我们进入向下还原的环节,进行一些细节上的探讨。在开发领域随着项目规模几何级的上升,慢慢开始分工为前端和后端,前端小姐姐们专注于数据的可视化展示(怎么炫酷怎么来),后端则将精力集中在数据的处理之上。自从 Http 和 Json 出来以后日渐成为前后端交互的标准,也在更大程度上解放了双方。但在这里我还要做一个友情提醒,语言本身其实并不区分前端和后端,JavaScript 也可以直连数据库进行数据处理,Java 和 C 也可以用来写前端,但这些方式本身都存在着各种各样的缺陷,在历史的大浪淘沙中有些语言逐渐被弃之不用,而残存的语言也找到了它们各自发光发热的领域,比如前端现在基本上 JavaScript 一统天下(但时下有一些更火热的超集,比如 TypeScript),而 Java、C、Python、C#则被认为是更适合后端的语言。
那么后端所谓的数据处理究竟是什么呢?数据处理的最终目标是持久化,即将数据及数据的变更保存下来,就好比我取了一万块钱我要有数据标识这个账户属于我、是我取了这一万块当然还有其它细节比如何时何地,何种方式等等。数据持久化最常见的方式有文件、数据库(RDBMS 和 NoSql),数据库几乎是最常见的存储方式,时至今日,数据库技术日新月异,但主流数据库大致可以分为 RDBMS(关系型数据库)和 Nosql,关系型数据库里 Oracle 享有盛名,但出于开源和免费的原因 Mysql 在变得越来越流行,越来越受到大公司的青睐(许多分库分片型数据库以 mysql 为基础,比如阿里的 DRDS,TELEDB),除了这俩货 Sysbase、SQL Server、DB2、Postgresql 也在各自的领域占有一定的地位。Nosql 则可以大致分为以下几种类型——临时性键值存储( Memcached、Redis )、永久性键值存储(Redis、Tokyo Tyrant)、面向文档的数据库( MangoDB、Elasticsearch )、面向列的数据库( Hbase、Clickhouse ),其中 Redis 拥有持久化机制(RDB 和 AOF)可以进行持久化,Elasticsearch 是一个搜索引擎。在已有的基础之上还发展出了一些针对高可用和和高性能的技术,如主备、主从复制、读写分离、分库、分表、分片、负载、代理等等等等。顺便说一句 Sql 其实也是一种编程语言,在其中也能进行大量的业务处理,在这方面登峰造极的是 Oracle,几千几万行的 Sql 比比皆是,但这种做法褒贬不一,用 Sql 处理业务的方式可以节省数据库 IO 提升性能(非一定),但是会对原来并没有强关联关系的数据产生强耦合,现如今更倾向于在后端编程语言(如 Java、C++)中处理业务逻辑,而将数据库简单地仅用于存储。
倘若说数据库是用来储存数据的话,那么后端语言就是来指定不同情况下计算机的处理策略,有这么一个笑话:
某程序员的老婆叫他上街买几个桃子,吩咐如果有西瓜,买一个,然后他就真的只买了一个桃子回来。
这种情形就是典型的对情况分析的不透彻导致的悲剧,我不知道那位兄弟如今是否还健在。业务逻辑处理是我们的真正的核心,在这种应该严格限定输入和输出,会有什么输入也就是会发生哪些场景,会有哪些输出也就是会发生什么结果,在开始动手敲代码之前这些就应该了然于胸,不然测试小姐姐让你改 Bug 的时候你的心情绝不会美丽。
在明确了输入输出之后就是学习如何操作数据,在实际运行的时候数据以二进制的形式存储在内存中,高级语言使得我们不必再去通过繁杂的指令操作内存,诸多数据结构可以让我们更便捷地操作内存,从逻辑结构的角度看,线性结构里有线性表、队列、栈等,非线性结构有树(二叉树、二叉查找树、二叉平衡查找树、红黑树、B+树、B*树)、堆(本质上也是树)、图、多维数组等,在实际的使用面对复杂的场景又出现了集合,线性表中最基础的结构是顺序表也即数组(内存连续),此外还有单链表、双链表、循环链表(链表的内存非连续)等等。
数据结构还往往与算法紧密相连,数据结构是帮助我们完成数据的操作,那么算法就是让这件事完成的更快更好更安全。很多人觉得算法离自己很远,其实不然,Java 的 HashMap 中就使用了一些精妙的算法,除了最如雷贯耳的 Hash 算法还使用了红黑树进行树化处理,降低了 Hash 攻击的危险性,还有一些算法你也绝对有所耳闻—— MD5、RSA、DES,在信息时代数据安全的重要性自然不言而喻,而算法的设计也常常依托于数据结构,两者息息相关。
接下来我们再来聊聊操作系统,我们的 Windows 就是一种操作系统,它有着极其人性化的交互,图形化的操作极大地降低了使用者的操作门槛,但本质上所有的图形化操作底层仍然是 Dos 指令,我们可以简单地理解为这些图形操作是对底层指令的封装。不过我们今天的主角不是它,而是一个叫 Linux 的男孩,呸,操作系统,它出生于 1991 年 10 月 5 日,老爸是一个叫 Linus 的爱爆粗口的硅谷程序员。严格来讲,Linux 这个词本身只表示 Linux 内核,但实际上人们已经习惯了用 Linux 来形容整个基于 Linux 内核,并且使用 GUN 工程各种工具和数据库的操作系统。Linux 因其免费开源(这个世界就是如此现实)的特性饱受青睐,如今我们很多商用环境都已经采用它。Linux 在世界上越来越多的开发者的建设下茁壮成长,时至今日已经成为了一个庞大而复杂的系统,对于开发、测试以及运维人员来讲,熟知 Linux 的相关指令是一项基本要求,如果你还不熟悉那说明骚年你该充充电了。在操作系统中有两个很有名的概念——进程和线程。进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程是进程中执行运算的最小单位,你大可以把它们简单理解为老子和儿子,一个线程只能属于一个进程(只有一个爸爸),但是一个进程可以拥有多个线程(多个儿子),当然真相绝不如此简单,操作系统是一门博大精深的学问,如果不能牢牢掌握它,那么学好编程语言无异于痴人说梦。
在编程领域还有一块不得不谈的东西——通信,这个通信不是指线程间或是进程间的通信,而是不同机器之间的通信,它是当前互联网的基石,你大可以想象你的手机或者电脑没有网的样子,据说这被称为现代的第一大酷刑。如果要进行通信那么就要制定协议和标准,没有统一标准的通信就像鸡同鸭讲,信息根本得不到有效交换。国际标准化组织 ISO 为此制定了 OSI 模型,该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架。OSI 模型把网络通信的工作分为 7 层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。有些尴尬的是由于过于庞大和复杂,在事实上它已经被 TCP/IP 4 层模型逐渐淘汰掉了,在当今世界上并没有大规模的使用,但它仍有很强的参考价值,像我们所听过的 TCP、UDP 分属于传输层,IP 则对应于网络层,至于是个网民都知道的 Http 则属于最外层的应用层,现如今正在占领地球的 Https 其实本质上可简单理解为 Http + SSL(TLS),SSL 在传输层对数据进行了加密,让我们的数据不至于裸奔在浩瀚的公网之上。这里需要重点注意的是 TCP 和 Http,我们应该知道 TCP 的三次握手四次挥手究竟干了什么,而应用最广泛的通讯协议 Http,我们可以以其庞杂的消息头作为切入点进行系统的学习。OSI 开放式系统互联.png
说了这么多好像几乎没怎么说到 Java 的东西,但我只是希望大家能明白编程绝不仅仅只限于某一门语言,它不是简单地使用人家所提供的 API 去进行功能的堆叠,作为一门精深的学问,它需要你很用心地去钻研。Java 本身的特性其实并不是太多,JVM 的内部设计、JMM 模型、锁机制,这些对于想进阶的开发人员来说都是必会选项。除此之外,还有很多和 Java 并无强耦合关系的技术也值得我们去了解,就好比消息队列,目前十分流行的有 Kafka、RocketMQ、ActiveMQ、RabbitMQ 等(甚至 Redis 也有简单的消息队列功能)。消息队列号称削峰填谷、异步解耦,但是否采用如何使用其实需要结合实际业务去分析,盲目地使用消息队列并不是一个明智的选择。如果对 Java 线程有些了解的朋友可能还会发现消息队列和线程池在某种程度上极为相似,假如有感兴趣的朋友可参见我另一篇博客对两者的比较 http://52.81.103.103:8080/articles/2019/06/25/1561441394679.html。对于对线程不太熟悉的人来说,直接操作线程其实是一件有很高风险的事情,一个误操作可能会把整个系统搞挂,所以出现了线程池对线程进行一定的资源限制和资源管理。有的同学可能会好奇为什么一定要多线程呢?因为在有限资源的情况之下,多线程能更充分的利用 CPU(适用于 IO 密集型应用),提升机器的利用率,你经常会听到互联网企业提到高并发,现如今高并发几乎快和多线程要等价了,多线程是成为高级工程师不可绕过的一座高峰。
在实际的工程应用中,日志是经常被轻视的一个环节,很多人可能连使"用占位符提升打印日志性能"的小技巧都不知道,日志作为完整项目不可或缺的一个环节,是我们排查问题的主要依据,也是我们了解系统状态的直接手段。日志的分类、分级、采集、分析,都是很有必要去做的事情。
对了,差点忘了 Java 里的 Boss —— Spring,在现今的 Java 应用里,Spring 几乎成为了业内标准,其轻耦合高扩展的特性让它一统江湖,其功能繁多难以在这里展开篇幅介绍,先简单介绍下其最著名的两个特性,IOC 和 AOP,很多人都没有理解 IOC 的作用,以为只是简单地省略了 new 对象的步骤,但事实远不仅仅如此,当服务间的调用关系并不复杂时 IOC 的重要性仍不太明显,但试想一下你的后台有数万个服务,每个服务都可能依赖其他数十上百个服务,现在你要调用一个服务就需要把其所依赖的服务也要创建出来(或从容器中获取),这是一件非常恐怖的事情,程序员不应该把精力放在这种事情上。而 AOP 作为 Spring 最有名的 Hook (简单理解为扩展接口好了),诸多功能都依托于它实现,比如必不可少的事务控制,还有权限控制、懒加载、缓存、记录跟踪这些与业务并无多大关系的处理等。AOP 的核心原理是动态代理,又分为 JDK 代理和 Cglib 代理两种模式,Cglib 是基于字节码的动态代理,功能要更加的强大,其底层使用了 ASM 去操作字节码,ASM 的强大毋庸置疑,你都可以重写字节码了还有什么不能做(为所欲为),但对使用者 JVM 指令的熟悉程度有着极高的要求。
还值得一提的是分布式系统,随着业务复杂度的急剧上升,为了避免牵一发而动全身的风险,我们将庞大复杂的业务系统划分为多个更小的子系统,每个系统相对独立但在某些方面互相依赖,前些年流行的微服务即是其中翘楚,而 Spring Cloud 是微服务的典型代表,它采用 Http 作为通讯协议,将各模块的耦合度几乎降到了最低。但 Http 是一种性能较低的协议,在传输中大量消息头(消息头还不可压缩)造成了极重的网络开销,故而各种轻量的 RPC 框架应运而生,比较有名的有阿里的 dubbo、hsf、grpc 和 thrift
等等。
设计模式在很多人的眼里都是玄学,大多数人都是看一次忘一次,在实际工作中更是难以学以致用,其实在我们使用的框架中就有很多设计模式的踪迹,Spring 的服务 Bean 模式是单例的(单例模式),这样可以减少创建和销毁对象的开销,Spring 的 BeanFactory 你看名字就知道它使用了工厂模式,还有 Mybatis 底层的 SqlSessionFactory 亦是如此。学习设计模型不能立即让你编码的能力有一个显著提升,但是就像我常和同事说的那样,写代码不是用手写的而是用脑子写的,好的设计模式能让你的代码更加优雅,在未来的扩展或重构中你绝对会感谢以前的自己。
走马观花地说了这么多,是希望读者们能对编程有个整体的认识,较为高效的学习方式是先构建知识体系再去完善细节,很多人每天这些书那些书地看,但对自己在学什么该学什么没有一个清晰的认知,这其实是十分低效的一种学习方式。
愿大家在编程的学习道路上昂首阔步地大步前行,有一份美好的前途加钱途。
完。
标题:编程浅谈-以一个初出茅庐的 Java 程序员视角
作者:Aresxue
地址: http://52.81.103.103:8080/articles/2019/06/17/1560773357548.html
12 条回复 • 2019-11-05 14:08:55 +08:00
|
|
1
guorui112 2019-06-25 17:28:49 +08:00
看完后才反应过来,我是一个前端,不过里面的一部分还是挺有用的,感谢,看完眼睛疼
|
|
|
2
VensonEEE 2019-06-25 17:31:10 +08:00
完全没抓到你的中心思想是啥。
|
|
|
3
XieHan 2019-06-25 20:18:27 +08:00
老哥,不要和我讲这些高屋建瓴的东西,我这个人很俗,我就想知道学会哪些三年能搞到 18K :)
|
|
|
4
secondwtq 2019-06-25 20:28:37 +08:00
again,这说的是互联网技术,不是编程
|
|
|
5
chenliangngng 2019-06-25 21:20:42 +08:00
3 年前,我也在想了这些东西,然后一事无成 现在只想赚钱,已经小有所成
|
|
|
6
Frank2 2019-06-26 05:56:12 +08:00 via Android
@ guorui112 您是自学的前端么?有什么好的教程资源推荐么
|
|
|
7
Aresxue 2019-06-26 09:16:51 +08:00
@ guorui112 通篇基本上是概念,了解下以后做项目或者和后端交互的时候还是有点用的。
|
|
|
8
Aresxue 2019-06-26 09:18:18 +08:00
@ VensonEEE 把编程涉及到的东西大体过了一下,让小白知道编程究竟是个什么东西,有哪些内容。
|
|
|
9
Aresxue 2019-06-26 09:21:26 +08:00
@ XieHan 三年 18k 看在哪,在北京的话躺着就好了,在二线的话把我从向下还原开始涉及到概念全部了解一遍,着重研究下多线程和分布式就差不多了。
|
|
|
11
guorui112 2019-06-26 09:28:26 +08:00
@ Frank2 我是培训机构出来的,培训只会教一些简单的,深入的还需要自己学,犀牛书红宝书看起来吧
|
|
|
12
MagicBoy 2019-11-05 14:08:55 +08:00
楼主你博客怎么打不开了?关了吗?还是换了?
|