学习后端技术和学习其他的技术并没有什么大的不同. 因此, 题目换做如何学习技术也是讲的通的. 概括来讲, 有以下几点建议:
扎实的计算机基础知识
知其然更要知其所以然
动手实践
频繁练习
持续学习
自我总结
学会规划
扎实的计算机基础知识
数据结构和算法: 程序是由数据和算法组成的, 因此这两个东西是计算机软件的基础. 诸如 B 树, 哈希表, 栈以及七大排序算法, 查找算法这些, 在很多软件的代码中都可以看得到. 有时候, 一个优秀的工程师和一个普通工程师的区别也就在于是否能够合理使用合适的数据结构和算法.
计算机操作系统: 操作系统可以说是集大成于一身的一个软件程序. 资源调度, 任务调度, IO 调度, 进程通信等等, 每一个设计都是很精华的, 也是很多其他应用软件设计的思想来源.
计算机网络: 目前只要有数据传输功能的程序绝大多数都是离不开网络的. 网络七层或者四层协议栈的设计非常精妙. 了解网络连接如何建立, 断开以及每个连接状态的意义都有助于对程序网络问题的排查.
计算机组成原理: 这是计算机最底层的设计, 也是计算机一切的基础. 了解这些有助于消除你对计算机的神秘感, 毕竟符合冯诺依曼原理的计算机无非就是存储数据, 程序按序运行.
以上是计算机专业的一些比较普遍的基础知识课程. 这里不得不说的一点是, 虽然现在各大高校的计算机专业课程是比较落后的, 但是这些基础课程, 由于多少年也没有怎么变过, 因此不管怎样都是需要扎实掌握的. 也许上学的时候你感觉不到有多大的用处. 但是进入实际的开发工作中, 是否能够掌握扎实的基础知识往往决定了一个开发工程师的上限, 这也是很多大的互联网公司无论是校招还是社招, 都侧重于一些底层知识考察的原因. 毕竟, 你会使用什么东西只能决定你的下限, 而你的基础知识和学习能力才决定了你的上限.
此外, 其实很多平时开发中的一些技术都可以类比到一些基础知识的. 比如, 我们经常为了提高查询性能而使用的缓存技术, 和为了兼容 CPU 和 IO 速度不匹配的而设计的 CPU Cache 就是同样的东西; 操作系统中的进程间通信方式和服务之间的异步同步通信也是差不多的道理. 诸如此类, 其实计算机科学基础凝聚了很多精华的设计, 无论是计算机硬件架构, 计算机操作系统还是计算网络.
知其然更要知其所以然
经常遇到来面试的工程师, 他们简历上写了很多项目, 也用过很多技术, 怎么看都是非常不错的候选人. 但是面试一旦深入到原理或者是优化层面, 很多工程师甚至是一些公司的资深架构师都会支支吾吾, 答非所问或者说是没关注过. 听到最多的解释就是业务压力太忙, 没有时间去研究这个. 其实, 自我经历来看, 业务忙是原因, 但是没有时间却肯定是借口, 毕竟阅读一个项目的源码虽然比较耗费时间, 但是去网上看看已有的原理分析其实是花不了太多的时间的. 归根结底, 还是没有一种知其然更要知其所以然的基本意识. 很多东西, 你学会了使用会很兴奋, 但是你有没有想过这么兴奋的功能是如何实现的呢? 最简单的例子, Java 中的 HashMap, 大家都在用, 但是他到底是怎么实现的呢? 很多人甚至都不知道这和数据结构课程上的哈希表是什么关系, 更别说让他说出解决冲突的方式了.
这也可以映射到现在的一种现象: 很多开发工程师工作了很久, 看着经验丰富, 但基本都是拿着一年的工作经验重复 n 年的. 基本上每一份工作, 每一个项目都在那里做重复劳动, 而且也并不去考虑如何避免重复劳动这件事.
进一步的, 除了遇到问题再去看源码, 究底层, 主动阅读经典类库, 高质量开源项目的源码以及其他同事写的代码, 学习其中好的架构, 设计, 编码风格以及类库的使用也是促进自身技术进步的一个非常有效的方式.
这也牵扯到了技术的广度和深度的问题. 就我自己来看, 对于刚刚毕业或者刚刚入职的工程师来说, 首要的是深度问题, 只有你在某一领域有了深入的研究和造诣了, 你才能融汇贯通, 迅速地扩大自己的知识面, 在广度上做到突破. 而对于有一定工作经验的工程师来说, 虽然深度不是那么必须了, 但是遇到的问题, 新学到的东西还是刨根问底才好, 否则一旦出现问题再去盲羊补牢会让你显得非常被动, 也不利于自己的技术发展. 毕竟, 一个什么都做过, 什么都用过却什么也不精的人可替代性太强了.
动手实践
学习领域有所谓 721 模型: 个人的成长 70% 来自于岗位实践, 20% 来自向他人学习, 10% 来自于培训. 虽然这种理论存在争议, 但在笔者看来对于程序员来说按照实践, 学习和培训的方式进行重要性排序是合理的. 普遍公认的一种学习技术的最佳实践 -"项目驱动型学习", 也就是这里说的动手实践. 很多技术, 只是看书, 你会云里雾里, 看了就忘. 必须要经过你自己的实践或者项目中使用到了这种技术, 你才能很快地掌握并熟练. 此外, 现在朋友圈, 微博上都充斥各种所谓干货, 很多人阅读大量的资料自以为收货满满, 其实对于里面的东西根本就没有去实践过. 甚至有时候就是感叹一下别人真厉害而已. 真正的干货是需要自己消化的, 消化的一种最好的模式就是实践, 无论是对资料中的例子还是一笔带过的知识.
频繁练习
动手实践能够让你快速入门, 但只有频繁练习才能让你熟练使用.
"一万小时" 理论讲的是任何一个行业都至少需要一万小时的实践才能成为专家. 先不去争论此理论是否正确, 可以想想当你长时间不写代码或者不用某个技术后你再去做相关的开发, 那种生涩陌生感想必是每个人都有体会的. 可见对于研发这个角色, 频繁练习是有多么的重要.
当然, 这里的频繁练习并非指的重复劳动. 应该是带着自己的思考去练习, 多去想一下为什么这么做? 有没有更好的方式?
持续学习
"活到老, 学到老" 这句话用在程序员这个职业上再合适不过. IT 技术尤其是互联网开发中的技术, 其迭代是非常迅速的. 也许你今天学的, 过不了几年就成了被抛弃的. 虽然相比起前端技术, 后端技术算是比较稳定的, 但相比起其他行业, 迭代速度还是非常快的, 像 Struts 这种当年火的一塌糊涂的技术现在也成了过时的东西. 因此, 一定要对新事物, 新技术具有敏感性, 要不断地去涉猎业界最新的知识点, 扩充自己的知识库.
这里还需要提到一点就是要 "逃离舒适区". 人对自己熟悉的东西都比较亲切, 对自己熟练掌握的技术一般也能够自信地使用, 然而当需要使用自己没接触过的技术时, 很多人就望而却步, 不敢尝试, 进而也就丧失了学习新的知识, 扩充自己知识库的机会. 最好的方式应该是敢于 "逃离舒适区", 敢于使用新的技术, 这样才能让自己具有持续的学习兴趣, 促进自己的持续进步.
自我总结
相信很多人在平常的工作中, 经常会遇到一些问题, 然后通过查阅网上资料, 询问同事, 翻看源码等手段解决了, 当再次遇到类似的问题甚至是相同的问题时, 还是一头雾水. 先不提记忆力的问题, 造成这种情形的很大一个原因就是没有去总结. 当然, 这里的总结不仅仅指的是把你平时遇到的问题记录下来, 更深一层的是要找到问题发生的本质原因, 如何避免发生同样的问题, 从中有什么启发和收获. 再进一步的则需要经常将自己一段时间内的知识收获组织成体系或者融入到自己的知识体系中, 这样才能举一反三, 遇到相同的问题可以有据可循.
而自我总结的方式包括记笔记, 写博客, 做分享. 其中, 比起记笔记来说, 写博客, 做分享是笔者更为推荐的方式. 毕竟, 和别人交流一方面能促使你对总结质量的把控, 另一方面分享知识给别人带来的 "荣誉感" 反过来会产生某种正向反馈让你更加乐于总结和分享.
学会规划
平时和不少工程师聊过关于职业规划的事情, 其中有些人对自己的职业道路有很清晰的认识, 但更多的则是没有任何概念, 只是觉得能挣钱养家就好. 很明显前者是属于有规划的人, 对于这种人来说, 其努力是有目标的, 因此走的路也会更踏实, 更具有可持续性.
对于研发职位来说, 学会规划是一个很关键的特质. 而规划可以分为长期规划和短期规划. 上面说的职业规划就是一种长期规划, 需要高瞻远瞩的定下自己前进的方向. 如在五年内成长为一个后端服务架构师就可以看做一个长期规划. 笔者自己的长期规划如下:
35 岁之前只做能提高自己技术水平的事情, 能够成为公认的某一个技术领域的专家.
绝不为了钱加入自己并不认同的企业或者团队.
而对于短期规划来说, 则是一些具体技能, 晋升, 学习方面的规划. 如, 笔者近一年的学习计划包括:
学习机器学习技术, 能够成为 "调参工程师".
加强自身的管理技能, 能够带领部门有好的业绩.
完成增长黑客,分布式系统概念与设计等十本书的阅读.
需要注意的是, 对于这些短期规划, 要设定的比较合理, 具有可达性, 也要设定好优先级, 根据优先级逐步去完成. 此外, 规划不要定死, 可以根据实际情况灵活调整.
如何学习一门新技术
上面主要讲述了宏观层面的如何学习技术, 而具体到学习某一个新技术, 其实也是有法可循的. 如下图所示:
由于很多技术的模块非常多, 源码也非常复杂, 很多时候在看源码的时候会陷进去越看越不得章法, 因此这里着重说明一下 "看源码" 的一个典型流程:
阅读该技术的架构文档, 了解其总体架构和组成.
根据总体架构, 将源码文件以模块或者上下层级进行分类.
从未阅读过的模块中选择最独立 (依赖性最小) 的模块代码读起.
阅读此模块的功能介绍文档.
阅读此模块的源代码.
一边阅读一边整理调用关系(以表或者树的形式).
转到第三步.
总结
程序员是一个金字塔结构的职业体系, 越往上, 人越少也越难达到. 如下图所示:
本文给出一个架构师的能力列表, 供大家参考:
基础技术能力: 精通某种技术, 能够从本质上理解并能够触类旁通. 架构师需要具有良好的性能优化能力, 能够在应用上线前预估到可能出现的性能问题并给出解决方案; 架构师需要具有扎实的调试能力, 不管是在代码开发阶段还是线上环境, 在应用发生 bug 或者线上故障时, 能够快速识别问题并解决.
设计能力: 能够识别问题的本质, 区分来自需求方的需求是伪需求还是真正的需求, 避免把解决方案当做问题; 精通设计模式和各种技术架构, 但又不滥用; 具有解耦系统的能力, 使得系统之间松耦合, 原来只能串行的任务可以并行开展.
技术选型能力: 平等对待所有技术, 只有合适与不合适, 没有喜欢与不喜欢; 了解主流技术的优缺点, 能够辨别是否需要总爱轮子.
技术前瞻能力: 能够预料到需求可能产生怎样的变化, 做好前瞻性设计; 能清楚地知道系统的瓶颈在什么地方, 不断地定位技术难度, 研发进度, 性能, 内存等各方面的瓶颈, 不断调整骨干力量解决瓶颈, 在风险爆发之前就消除隐患.
管理能力: 此能力在笔者看来并非是架构师必须的, 但确实是能够锦上添花的, 包括项目管理和团队管理. 对于前者, 需要合理划分系统模块, 知人善用, 有效沟通, 控制成本, 合理把握进度; 对于后者, 则需要多倾听团队成员的意见, 主动承担责任, 多站在成员角度考虑问题, 为成员的成长负责.
一步步走到金字塔顶部需要不断的学习和进步, 包括正确的态度, 正确的方法以及持续的努力. 本文所述只是笔者自己的体会, 也是自己一直在践行的东西. 除此之外, 肯定还有很多其他优秀的方法和思想能够促进这个过程.
本文节选自Java 工程师修炼之道一书.
本书可以看作一本 Java 工程师的入职指南, 也可以看作一本串联 Java 后端技能点的参考手册. 通过精心编排的内容, 刚入门的 Java 工程师能够体系化地学习相关开发技能, 有经验的 Java 工程师能够查漏补缺, 巩固自己的相关开发技能, 进一步完善自身的 Java 技术体系.
来源: https://juejin.im/post/5af971fa51882542857eb7d7