前言
不错的好书,作者本身是从事JAVA为主,但以从业15年的角度看待计算机语言的发展史,有个概括通俗易懂的角度来讲述编程方面的知识。
程序员的精进
对技术的好奇心/兴趣是一切的基础。
如果你看到新技术、新产品没有像小孩看到新玩具那样两眼放光,没有立刻在自己的电脑上试试的冲动,你就需要仔细考虑一下是否真的对软件开发有兴趣。如果根本没兴趣,那不要浪费时间,还是趁早转行,有更多适合你的职业在等着你。没有好奇心,就不愿意追本溯源,追求技术的本质。
没有好奇心,就难以静下心来,耐得住寂寞,远离浮躁,更难以跨过这个行业所带来的种种挑战,走到架构师这个位置。
没有好奇心,就不愿意学习新技术。一名架构师,如果没有对技术的敏感度和前瞻性一直抱着一套技术架构不变,估计很快就会被淘汰。很多人会语法,也懂框架,但是在基本功上却不过关,因而只能在初级程序员上踏步。
这个基本功的训练就是数据结构和算法,我的经验是多做习题,让这种思维在脑子里固化,以后的编程就可以信手拈来了。计算机的组成原理、操作系统、编译原理、计算机网络、数据库、汇编语言,把这些知识融会贯通,打通任督二脉,在我们的脑海里建立一幅计算机运算的图景。
计算机软硬件的基本思想在这几十年里其实变化不大,如缓存、增加抽象层等。有了这些基本思想的武装,去学习新的东西不但学得快,而且理解得会更透彻。要透彻地理解一门技术的本质。公司里基本上不会有空闲的时间,一个个新需求压得大家透不过气来。偶尔有空闲时间,大家也都犯懒了,总是想着休息。
惯性的力量是惊人的,大家都愿意待在舒适区里,不愿意变化,虽然也看到了新工具的好处,但大家都懒得换新的。
抽象能力
- 把乱无头绪的需求抽象成一些“概念”,在概念的层次进行思考,用于系统的设计
- 把纷杂的事物抽象到数学层面是最高的抽象。但是抽象成数学模型和算法通常是可遇而不可求的,在这种情况下,我们需要退而求其次,试图抽象成若干个正交的概念,以此来降低复杂度。
- 抽象能力的训练没有捷径,就是经验的积累,勤于思考和学习。
例如: 学习 Java Web开发的可以思考一下为什么Spring有Controller、ViewResolver这样的概念?学习Android的可以思考一下Android是怎么对未知的、纷繁复杂的应用程序进行抽象的?为什么有 Activity、Service、 BroadcastReceiver、ContentProvider 这四大组件?
学习相关
自认为掌握了一门技术,其实并没有真正掌握,大脑只是对这个技术点建立了一个整体的概念,在一些细节处做了想当然的假设,等到你用语言再来表达的时候就会发现,原来这个假设并不完全成立,是有问题的。
如果你能把一门技术通俗易懂地给别人讲明白,那就说明你已经掌握了。这种“转教别人(Teach others)”的办法属于主动学习,效率是最高的。
既然没法给别人讲,那就退而求其次吧,把自己的理解写出来。技术文章,不是泛泛地记流水账,或者把几个孤立的点罗列在那里,而是要把思路厘清楚,尤其要写出为什么要有这门技术、这门技术解决了什么问题,然后才是这门技术是怎么使用的。当你逼着自己去回答这些问题的时候,很快就会发现,自己的理解还不够,还需要查找更多的资料。
在网上查找资料过程中,整理资料和思考的过程是很珍贵的,只有这样才能把信息变成你自身的知识。
如果实在搞不定,就带着问题去论坛提问,去QQ群发言,找大牛请教,总是可以解决的。
网上的大部分文章都是复制、粘贴的,大部分都在讲述怎么使用,对于“为什么”从来都是只字不提,或者犹抱琵琶半遮面,羞羞答答地不说出来。不把自己的理解写出来,很容易放弃深度思考。你会觉得,我已经知道是怎么回事儿了,然而其实一些关键的细节被大脑给忽略了。写作会逼着你去思考,梳理知识体系,防止自己被碎片所填满。
其实很多人都知道写作是一件很好的事情,就是犯懒,执行不下去。还是行动起来吧!逼自己一把,对自己狠一点!有自制力的人、能够坚持的人才更有可能成功!
我们已经进入了一个碎片化的时代,我们的大脑已经养成了碎片化的习惯,一天不看碎片化的信息就觉得不舒服,这样下去会慢慢地丧失深度思考的能力。优秀和平庸的差别可能就是那一点点坚持吧!坚持不懈地做一件事,每天前进一点点,最后量变会发生质变。
每个季度定一个小目标,努力达成,获得成就感,就能刺激自己更进一步,改善半途而废的毛病。
代码相关
发现工作中的“痛点”,并且真正动手解决它给公司带来价值。这是提高自己,让自己和别人区分开来的重要方法。
大部分人只会抱怨项目很无趣、没有挑战遇到问题也只会安于现状。面向对象的代码由于是针对接口编程的,所以每当你去找接口实现的时候是比较费劲的,比起直接的面向过程代码读起来是一个不小的障碍。
重构必须有测试,先有测试用例再重构,重构的过程就是一个重新学习的好过程
框架是一个半成品,是无法独立运行的,必须由开发人员按照它定义的规则,把项目的代码放置到指定的地方,由框架整合起来,这才是一个完整的应用程序。是前辈们把各种经验固化下来的最佳实践
现在很多 Java Web Spring MVC、 Hibernate、 MyBatis ixf这样的流行框架构造起来的,框架不得不学。但是如果只会使用框架,只会填充代码,那只能是一名HTML填空人员。
你如果对Java后端编程感兴趣,那还有很多东西可学。用框架实现了业务只是很小一方面,还有系统架构设计、缓存、性能、高可用性、分布式、安全、备份等很多内容。你学得越多,就会发现无知的领域更多,所谓学无止境,就是如此。关于遗留代码的见解
你别看我们的代码烂,它可是在生产环境下运行的代码,每天有无数用户在用,经历了这么多年的严酷考验,已经把系统中方方面面的Bug,尤其是一些深层次的Bug暴露得差不多了,也改得差不多了。之前看到了很多FiⅸBug这样的注释,每个注释和对应的修改都是无数前人心血和时间的结晶,这里面有多少加班和熬夜你知不知道?你如果从头再来,能保证考虑到这么多种情况吗?能保证把边边角角、犄角旮旯的东西都包括进去吗?
每个程序员都梦想从头写一个东西,不愿意读别人的代码,甚至同行相轻,瞧不起别人的代码。但实际情况是,自己重写一遍,不见得能比现在已经运行的代码好到哪里去,甚至更差!除非你了解了所有的细节用大量的时间仔细规划、小心编程,但是现实中哪有时间让你这么玩啊?
测试相关
那些不存在的或者难以new出来的对象(比如访问数据库的对象、访问网络的对象)可以使用Mock工具( EasyMock Jmockit等)来“造假”。
优秀的单元测试:
(1)单元测试是“白盒测试”,应该覆盖各个分支流程、异常条件。
(2)单元测试面向的是一个单元(Unit),是由Java中的一个类或者几个类组成的单元。
(3)单元测试的运行速度一定要快!
(4)单元测试一定是可重复执行的!
(5)单元测试之间不能有相互依赖,应该是独立的!
(6)单元测试代码和业务代码同等重要,要一并维护!如果测试代码需要很复杂的setup才能开始测试,说明业务代码接口的设计很有问题
单元测试的关键,在于如何处理遗留代码。
其它
领域特定语言( Domain Specific Language,DSL),专门为某个领域而定制的语言
Maven,通过约定大于配置的概念,形成自动化Build环境
JAVA动态生成代理类的方法有两种:
第一种是使用Java动态代理技术,这种技术要求业务类必须有接口(Interface)才能工作;
第二种是使用 CGLib,只要业务类没有被标记为 final就可以,因为它会生成一个业务类的子类来作为代理类。三次握手:
第一次握手:京城发信,县衙收到了,此时县衙就会明白,京城的发信能力和自己的收信能力是没问题的。
第二次握手:县衙发信,京城收到了,此时京城就会明白,京城的发信和收信能力都是没问题的,县衙的发信和收信能力也都是没问题的。但是县衙还不知道自己的发信能力如何,所以需要第三次握手。
第三次握手:京城发信,县衙收到了,其实第二次握手的时候京城已经知道双方的收信、发信能力都是没问题的,这次回应的目的只是消除县衙对自己的发信能力和京城的收信能力的担忧而已。-
程序编译的过程: