这里有一份简洁的前端知识体系等待你查收,看看吧,会有惊喜哦~如果觉得不错,麻烦star哈~
前言
知识分为两种,一种是技能性知识,一种是关于路径选择和自我认知的知识。
技能性知识需要你在日常的学习和工作中勤学苦练,练成之后你就会成为某一类问题的 “解答题高手”。
而关于路径选择和自我认知的知识,它能让你在成长的不同阶段重新认识自己,因为 “知” 从而改变你的 “行”。有时选择对了合适的路,比光顾着赶路要重要得多。
本文是关于程序员的成长路径,它会围绕程序这个行业、程序员这个职业,画出一条清晰的成长路径,并解答这条路径上可能面临的各种问题与困惑。
这条成长路径,或许是长这样子:
这是一条成长线的表意图,有两个部分:图上左侧的路径,是匹配不同成长阶段,对应不同职业角色;右侧是一条由不同成长阶段组成的成长线。
“启程之初”,是你刚踏上程序之路面临的一些问题和感悟。
“程序之术”,是你工作早期的主要内容,以修炼编程技能为主。
除了编程写代码,还有很多其他的内容,这是另外一个维度的修行之路,也即 “由术入道”。
工作数年,成长到一定阶段,你可能会面临一个成长平台期的困扰,在此就进入了 “道中彷徨” 的徘徊期。
这些困扰和彷徨很多都关乎选择,这期间是你发出 “路在何方” 之问的寻路期。
最后,你坚定了道路,继续前行,前面的路上还有一道 “断层”,突破之后你将会蜕变,最终 “破茧成蝶”。
本系列文章为程序员提供了可供参考的路标,一言以蔽之:“走在同样的路上,遇见自己的风景。”
关于本系列文章,是整理自极客时间《程序员进阶攻略》,节选了我认为最有价值的内容,更详细的版本请看这里。当然,如果你喜欢这个课程,请购买正版。
征途:启程之初
技术方向的选择
选择语言
选择那些展现出蓬勃生命力的语言。
美国作家纳西姆·塔勒布(《黑天鹅》《反脆弱》等书作者)曾说:信息或者想法的预期寿命,和它的现有寿命成正比。
而编程语言以及由它编写的所有软件系统和程序,本质就是信息了。换句话说就是,如果你想预测一门语言还会存在多久,就看看它已经存在了多久。存活时间足够长的语言,可以预期,它未来也还可能存活这么长时间。当然这一论断并不绝对,但它更多想说明越是新的语言或技术,升级换代越快,也越容易被取代。
选择回报
选择技术方向,选择语言,本质都是一种投资。
越年轻的语言和方向,风险越高。一个今年刚出现的新方向、新语言,你怎么知道它能在明年幸存下来?
所以,考虑确定性的回报和更低的风险,你应该选择有一定历史的方向或语言,也许不能带来超额的回报,但最起码能带来稳定的回报,让你先在这个行业里立稳脚跟。在此基础上,再去关注新潮流、新方向或新技术,观察它们的可持续性。
在选择技术方向时,你还要看看当前的市场需求是什么,最需要什么,以及长期需要什么。
比如,今天技术的热潮在人工智能、机器学习、区块链等上面,这是市场最需要的,而市场给的价格也是最高的。所以,你应该投入这里么?先别头脑发热,看看自己的基础,能否翻越门槛,及时上得了车吗?
世纪之初,互联网时代的到临,网络的爆发,你会写个 HTML 就能月薪上万。上万,似乎不多,但那时北京房价均价也才 5000 多啊。2010 年左右,移动互联网兴起,一年移动开发经验者的平均待遇达到了五到十年 Java 开发的水平。如今,你只会 HTML 基本找不到工作,你有五年移动开发经验和有五年 Java 开发经验的同学,薪资待遇也变得相差不多了。
关于技术,有一句流行的话:“技术总是短期被高估,但长期被低估。”今天,在人工智能领域获得超额回报的顶级专家,实际数十年前在其被低估时就进入了这个领域,数十年的持续投入,才在如今迎来了人工智能的 “牛市” ,有了所谓的超额回报。
所以,不妨投入到一些可能在长期被低估的基础技术上,而不是被技术潮流的短期波动所左右。
技术的选择,都是赚取长期回报,短期的波动放在长期来看终将被抵消掉,成为时代的一朵小浪花。
选择行业
选语言,就是选职业,而选职业首先选行业。
先想想自己想从事哪个行业的软件开发;然后,再看看:这个行业的现状如何?行业的平均增速如何?和其他行业相比如何?这个行业里最好的公司相比行业平均增速又如何?最后,再看看这些最好的公司都用些什么样的技术栈和语言。如果你想进入这样的公司,那就很简单了,就选择学这样的技术和语言。
这里要区分职业跟兴趣的关系!
职业可不是为了发展什么业余爱好,而是为了获得安身立命的本领,获得竞争的相对优势。而兴趣,就是这件事里有些吸引你的东西,让你觉这是 “很好玩” 的事。但有个通常的说法是:“一旦把兴趣变成了职业也就失去了兴趣。”因为,职业里面还有很多 “不好玩” 的事。
兴趣能轻松驱动你做到前 50%,但按二八原则,要进入前 20%的高手领域,仅仅靠兴趣就不够了。兴趣给你的奖励是 “好玩”,但继续往前走就会遇到很多 “不好玩” 的事,这是一种前进的障碍,这时功利,也算是给予你越过障碍所经历痛苦的补偿吧。
有时这样的选择确实很难,因为我们缺乏足够的信息来做出最优选择。赫伯特·西蒙说:“当你无法获得决策所需的所有信息时,不要追求最优决策,而要追求满意决策。”
定下自己的满意标准,找到一个符合满意标准的折中方案,就开始行动吧,停留在原地纠结,什么也不会改变。
技能地图
在程序的技能地图中,包含两个维度:
- 掌握
- 了解
红色区域相对更小而聚焦,是需要掌握的部分,要求深度;蓝色区域的部分更广而泛,需要广度。
十多年后,这张图上的每一个分类都出现了新的技术迭代,有了新的框架、算法和产品等,但它们并不过时,依然可以为你的技能点亮之路提供方向指引。也许,你程序生涯的第一个一万小时你就会花在这张图上了。
下面逐一介绍下:
掌握
开发平台
开发平台,它包括一种编程语言、附带的平台生态及相关的技术。
在如今这个专业化分工越来越细的时代,开发平台决定了你会成为什么类型和方向的程序员。比如:服务端、客户端或前端开发等。其中进一步细分客户端还可以有 Windows、Mac、iOS 和 Android 等不同的平台。
一、编程语言
语言的选择基本决定了开发平台的性质,但有些语言可能例外,如:C++、JS、C# 等,这些语言都可以跨多个平台。
但即使你选的是这些语言,基本也会归属到某一类平台上。好比你选了 C++,如果你去做了客户端开发,就很少可能再去用 C++ 写服务端程序了。
选择了语言,我们不仅仅是熟悉语言自身的特性,还需要掌握支撑语言的平台库。Java 若仅从语言特性上来说,有其优点,但其瑕疵和缺陷也一直被吐槽,要是没有 JDK 强大的平台库支撑,想必也不会有今天的繁荣。
二、平台生态
与语言平台关联的还有其技术生态以及各种技术框架的繁荣程度。
这些平台技术生态的存在让使用这门语言编程完成特定的任务变得容易和简单得多。Java 的生命力除了 JDK 的强大支撑,实际还有其平台生态的繁荣,也起了决定性的作用。
在选择了开发平台后,除了语言和平台库之外,其生态体系内主流的技术框架和解决方案也是必选的掌握内容。
常用算法
算法,表达的是一个计算的动态过程,它引入了一个度量标准:时空复杂度。
当我回思时,发现这个度量标准思维在工作十余年中一直在发挥作用。如今,几乎所有的经典算法都能在开发平台库里找到实现,不会再需要自己从头写。但结合工作实际的业务场景,我们需要去设计更贴合需求的算法,而只要是算法它都受到时空复杂度的约束,而我们只是在其中进行平衡与折衷。
数据结构
数据结构通常都和算法一起出现,但算法表达的是动态特性,而数据结构表达的是一种静态的结构特性。
大部分开发平台库都提供了最基础和常用的数据结构实现,这些都是我们需要熟悉并掌握的,包括:
- 数组 Array
- 链表 Linked List
- 队列 Queues
- 堆栈 Stacks
- 散列 Hashes
- 集合 Sets
另外,还有两种数据结构不属于基础结构,但在现实中有非常广泛的直接映射场景。
- 树 Trees
- 图 Graphs
每种结构都有各种变体,适用于不同的场景,甚至很多时候你还需要会组合不同的结构去解决一些更复杂的问题。
了解
需要了解的内容比需要掌握的更广泛,但了解了这些方面会让你更高效地协作并解决问题。
数据存储
不管你写什么样的程序系统,估计都离不开数据存储。数据是一个业务系统的核心价值所在,所以怎么存储不同类型的生产数据,是你必须要了解的。如今广泛流行的数据存储系统有下面三类:
- SQL 关系型数据库(如:MySQL、Oracle)
- NoSQL 非关系型数据库(如:HBase、MongoDB)
- Cache 缓存(如:Redis、Memcached)
每一种数据存储系统都有其特定的特性和应用场景。作为程序员,我们通常的需求就是最有效地用好各类数据存储,那么按了解的深度需要依次知道如下几点:
- 如何用?在什么场景下,用什么数据存储的什么特性?
- 它们是如何工作的?
- 如何优化你的使用方式?
- 它们的量化指标,并能够进行量化分析?
这 4 点虽不要求一开始就能掌握到一定程度,但你最好一开始就有这个层次思维,在日后的工作中不断去迭代它的深度。
测试方法
为什么我们做开发还需要了解测试?
测试思维是一种与开发完全不同的思维模式。有一种流行的开发方法论叫 “测试驱动开发(TDD)”,它的流行不是没有道理的。在写代码的时候,用测试的思维与方式(提供单元测试)去审视和检测代码,也就是说明确要开发某个功能后,先思考如何对这个功能进行测试,并完成测试代码的编写,然后编写相关的代码满足这些测试用例。
开发与测试这两种相反视角的切入维度,能真正长期地提高你写代码的效率和水平。
工程规范
每一种开发平台和语言,估计都有其相应约定俗成的一些工程规范要求。最基础的工程规范是代码规范,包括两个方面:
- 代码结构
- 代码风格
像 Java 这么多年下来,逐渐形成了一种基于 Maven 的代码组织结构规范,这种约定俗成的代码结构规范省却了很多没必要的沟通。有时候,同样的内容,有更规范的结构,其可阅读性、理解性就能得到提升。
而至于代码风格,相对没那么标准化。但为了写出更清晰、易读的代码,我们至少要坚持自己写的代码具有某种一致性的风格。
另外,除了风格问题,也可以借助静态代码检查工具来规避一些新手爱犯的低级错误,而老手也可以通过这些工具来找到自己的认知与习惯盲点。
开发流程
在开发流程方法论上,敏捷基本已经横扫天下,所以我们至少要了解下敏捷开发方法论。
虽然敏捷方法论定义了一些参考实践,但它依然是一组非常松散的概念。每个实践敏捷的开发团队,估计都会根据自己的理解和摸索建立一整套逐渐约定成型的开发流程规范。而为了和团队其他成员更好地协作,估计每个新加入团队的成员都需要了解团队演进形成的开发流程规范。
源码管理
既然我们生产代码,自然也需要了解如何管理好代码。
在我的从业经历中,源码管理工具经历了从 CVS 到 SVN 再到 Git 的变迁。Git 诞生的背景是为 Linux 这样超大规模的开源项目准备的,自然决定了其能应对各种复杂场景的源码管理需求。所以,你至少要了解 Git,并用好它。
当工具变得越来越强大时,工具背后的思想其实更重要,对其的理解决定了我们应用工具的模式。而对源码进行管理的最基本诉求有以下三点:
- 并行:以支持多特性,多人的并行开发
- 协作:以协调多人对同一份代码的编写
- 版本:以支持不同历史的代码版本切换
修炼:程序之术
架构与实现
把一种想法、一个需求变成代码,这叫 “实现”,而在此之前,技术上有一个过程称为设计,设计中有个特别的阶段叫 “架构”。
软件架构,就是软件系统的结构与行为设计。而实现就是围绕这种已定义的宏观结构去开发程序的过程。
架构师的交付成果是一整套决策流,文档仅仅是交付载体,而且仅仅是过程交付产物,最终的技术决策流实际体现在线上系统的运行结构中,而实现的最终交付物是程序代码。
架构
从定义上,你已知道架构是一种结构设计,但它同时可能存在于不同的维度和层次上:
- 高维度:指系统、子系统或服务之间的切分与交互结构。
- 中维度:指系统、服务内部模块的切分与交互结构。
- 低维度:指模块组成的代码结构、数据结构、库表结构等。
在不同规模的团队中,存在不同维度的架构师,但不论工作在哪个维度的架构师,他们工作的共同点包括下面4个方面:
- 确定边界:划定问题域、系统域的边界。
- 切分协作:切分系统和服务,目的是建立分工与协作,并行以获得效率。
- 连接交互:在切分的各部分之间建立连接交互的原则和机制。
- 组装整合:把切分的各部分按预期定义的规则和方法组装整合为一体,完成系统目标。
实现
实现一般会有6个方面的考虑:选型评估;程序设计;执行效率;稳定健壮;维护运维;集成部署。
我以交付一个功能需求为例,讲述下这个过程。
实现一个功能,可能全部自己徒手做,也可能选择一些合适的库或框架,再从中找到需要的API。
确定了合适的选型后,需要从逻辑、控制与数据这三个方面进一步考虑程序设计:
- 逻辑,即功能的业务逻辑,反映了真实业务场景流程与分支,包含大量业务领域知识。
- 控制,即考虑业务逻辑的执行策略,哪些可以并行执行,哪些可以异步执行,哪些地方又必须同步等待结果并串行执行?
- 数据,包括数据结构、数据状态变化和存取方式。
开始编码实现时,你进一步要考虑代码的执行效率,需要运行多长时间?要求的最大等待响应时间能否满足?
你还需要考虑系统的稳定健壮:并发吞吐能力如何?运行的稳定性和各种边界条件、异常处理是否考虑到了?
还有维护运维的问题:上线后,出现 Bug,相关的监控、日志能否帮助快速定位?是否有动态线上配置和变更能力,可以快速修复一些问题?新上线版本时,你的程序是否考虑了兼容老版本的问题等?
最后你开发的代码是以什么形态交付?如果是提供一个程序库,则需要考虑相关的依赖复杂度和使用便利性,以及未来的升级管理。如果是提供服务,就需要考虑服务调用的管理、服务使用的统计监控,以及相关的 SLA 服务保障承诺。
以上是整个实现过程的思维框架。如果你每次写代码时,都能有一个完善的思维框架,应该就能写出更好的代码。如果漏掉了其中某个部分,可能会以某种线上 Bug 或问题的形式返回。
关注点
架构的一个核心关注点: 熵。也就是系统的混乱程度。
系统只要是活跃的,“熵”值就会在生命周期中不断波动。需求的增加和改变,就是在不断增加“熵”值(系统的混乱程度)。但软件系统的“熵”有个临界值,当达到并超过临界值后,软件系统的生命也基本到头了。
而黑线表示,实现中重构与优化的动作则是在不断进行减“熵”,作出平衡,让系统的“熵”值在安全的范围内波动。
实现的核心关注点,是:简。
简,是简单、简洁、简明、简化,都是在做减法,但不是简陋。关于实现的全部智慧都浓缩在了这一个字里,它不仅减少代码量,也减少了开发时间,减少了测试时间,减少了潜在 Bug 的数量,甚至减少了未来的维护、理解与沟通成本。
架构关注复杂度的变化,自然就会带来简化,而实现则应当顺着把“简”做到极致。
断裂带
架构与实现之间,存在断裂带。
断裂带出现在架构执行过程之中,落在文档上的架构决策实际上是静态的,但真正的架构执行过程却是动态的。
造成架构和实现之间断裂带的原因,主要有有:
- 沟通问题:如信息传递障碍。
- 水平问题:如技术能力不足。
- 态度问题:如偷懒走捷径。 4.现实问题:如无法变更的截止日期(Deadline)。
当系统规模足够大了,架构师的关注点应该放在战略性细节上。而其他大量的实现细节,只要没有越出顶层宏观结构定义的边界即可。
模式与框架
“设计模式” 是前人解决某类问题的总结,是一种解决问题域的优化路径。
开发框架是可复用的设计组件,它统一定义了高层设计和接口,使得从框架构建应用程序变得非常容易。因此,框架可以算是打开“快速开发”与“代码复用”这两扇门的钥匙。
框架和模式的共同点在于,它们都提供了一种问题的重用解决方案。其中,框架是代码复用,模式是设计复用。
软件开发是一种知识与智力的活动,知识的积累很关键。框架采用了一种结构化的方式来对特定的编程领域进行了规范化,在框架中直接就会包含很多模式的应用、模式的设计概念、领域的优化实践等,都被固化在了框架之中。框架是程序代码,而模式是关于这些程序代码的知识。
代码与分类
编程,就是写代码,但代码其实可以分为如下三类:
- 功能
- 控制
- 运维
如果你想提高编程水平,写出优雅的代码,那么就必须要清晰地认识清楚这三类代码。
功能
功能代码,是实现需求的业务逻辑代码,反映真实业务场景,包含大量领域知识。
要把功能代码写好,最难的不是编码本身,而是搞清楚功能背后的需求并得到正确的理解。之后的编码活动,就仅是一个“翻译”工作了:把需求“翻译”为代码。
真正地理解并满足用户的原始需求,这一步操作就很困难。这是因为从用户心里想要的,到他最后得到的之间有一条长长的链条,如下所示:
用户心理诉求 -> 用户表达需求 -> 产品定义需求 -> 开发实现 -> 测试验证 -> 上线发布 -> 用户验收
需求信息源自用户的内心,然后通过表达显性地在这个链条上传递,最终固化成了代码,以程序系统的形态反馈给了用户。
但信息在这个链条中的每个环节都可能会出现偏差与丢失,即使最终完成了系统开发、测试和发布,也可能发现用户的心理诉求要么表达错了,要么被理解错了。
用户经常会把他们的需要,表达成对你的行为的要求,也就是说不真正告诉你要什么,而是告诉你要做什么。所以你才需要对被要求开发的功能进行更深入的思考,努力去理解业务及其背后用户的真实需求,这是写好功能代码的基本能力。
程序存在的意义就在于实现功能,满足需求,但这仅仅是第一步。
控制
控制代码,是控制业务功能逻辑代码执行的代码,即业务逻辑的执行策略。
编程领域熟悉的各类设计模式,都是在讲关于控制代码的逻辑。而如今,很多这些常用的设计模式基本都被各类开源框架固化了进去,程序员被解放出来专注写好功能业务逻辑。
控制代码,都是与业务功能逻辑不直接相关的,但它们和程序运行的性能、稳定性、可用性直接相关。提供一项服务,功能代码满足了服务的功能需求,而控制代码则保障了服务的稳定可靠。
有了控制和功能代码,程序系统终于能正常且稳定可靠地运行了,但难保不出现异常,这时最后一类 “运维” 型代码便要登场了。
运维
运维代码,就是方便程序检测、诊断和运行时处理的代码。它们的存在,才让系统具备了真正工业级的可运维性。
最常见的检测诊断性代码,应该就是日志了,打日志太过简单,因此我们通常也就疏于考虑。其实即使是打日志也需要有意识的设计,评估到底应该输出多少日志,在什么位置输出日志,以及输出什么级别的日志。
在现实中,检测诊断类代码经常不是一开始就主动设计的。但生产环境上的程序系统可能会偶然出现异常或故障,而因为一开始缺乏检测诊断代码输出,所以很难找到真实的故障原因。现实就这样一步一步逼着你去找到真实原因,于是检测诊断代码就这么被一次又一次地追问为什么而逐渐完善起来了。
但如果一开始你就进行有意识地检测诊断设计,后面就会得到更优雅的实现。有一种编程模式:面向切面编程(AOP),通过早期的有意设计,可以把相当范围的检测诊断代码放入切面之中,和功能、控制代码分离,保持优雅的边界与距离。
而对于特定的编程语言平台,比如 Java 平台,有字节码增强相关的技术,可以完全干净地把这类检测诊断代码和功能、控制代码彻底分离。
运维类代码的另一种类,是方便在运行时,对系统行为进行改变的代码。通常这一类代码提供方便运维操作的 API 服务,甚至还会有专门针对运维提供的服务和应用,例如:备份与恢复数据、实时流量调度等。
功能、控制、运维,三类代码,在现实的开发场景中优先级这样依次排序。有时你可能仅仅完成了第一类功能代码就迫于各种压力上线发布了,但你要在内心谨记,少了后两类代码,将来都会是负债,甚至是灾难。而一个满足工业级强度的程序系统,这三类代码,一个也不能少。
而对三类代码的设计和实现,越是优雅的程序,这三类代码在程序实现中就越是能看出明显的边界。为什么需要边界?因为,“码以类聚,人以群分”。功能代码易变化,控制代码固复杂,运维代码偏繁琐,这三类不同的代码,不仅特征不同,而且编写它们的人(程序员)也可能分属不同群组,有足够的边界与距离才能避免耦合与混乱。
而在程序这个理性世界中,优雅有时就是边界与距离。
跨越断层,突破边界
在前文中定义过程序员的职场阶梯,而阶梯不过就是很多人已经走过的路,我们只需要沿着这条路去持续成长就能爬上还算不低的楼层。只是到了一定楼层后我们会发现上面似乎还有几层,但却看不见下一层的楼梯了。因为再往上走的人就不多了,也就没能成了路,自然也就看不见,这可能就是所谓成长阶梯的断层。
在程序员的成长阶梯上,到了一定阶段,我们可能会面临方向的选择,不同的方向选择意味着不同的路径,会碰到不同的断层,而跨越断层也需要不同的方法。
那我们会面临怎样的方向选择呢?
方向
在我的技术成长路上,我看到了三个方向,正好可以用三个字来表 达:“高”“精”“尖”。
“高” 指的是 “高级(High-grade)”,“精” 代表 “精确(Precision)”,而 “尖” 则是 “尖端(Advanced)”。这是我所看到的技术人前进的三个主要方向,而这 三个方向的走向往往还是互斥的。
高级,说的不是更高级的技术,因为技术之间的横向比较没有高低级之分,比如操作系 统、数据库、网络编程、机器学习等技术,没法比出个高下。这里的“高级”,如其英文 是更高等级的意思,是职位和人的级别。而往高等级走的技术人,离 “精” 自然只能越来 越远,毕竟站的高就只能看得广,但很难看得精确了。
精确,就是把一门技术做到真正的精通。现在技术的分工越来越细,通常能精通一两个细 分领域已实属不易。而要做到精,其实越往后付出越多,但感觉提升却变得越来越慢。都 到 95 分了,再往后每提升 1 分都需要付出艰辛的努力。走到细微深处,也很难再看得 远、看得广了。
尖端,似乎听起来像 “精” 的极致,其实不然,这完全是另一条路。“高” 与 “精”, 是工业界的实践之路,而 “尖” 是理论界的突破之路。只有能推进人类科技进步的技术才 称得上尖端,就如 IT 界历史上著名的贝尔实验室里的科学家们做的工作。
“高” 是往宏观走,“精” 是往微观走,“尖” 是去突破边界。
这三条路,“高” 和 “精” 的方向在业界更常见,而 “尖” 不是工业界常规的路,毕竟 业界拥有类似贝尔实验室这样机构的公司太罕见,所以 “尖” 的路线更多在学术界。因而 后面我们主要探讨 “高” 和 “精” 两个方向的路径断层与跨越方法。
高
高的两条典型路线如下:
- 程序员—架构师—技术领导者
- 程序员—技术主管—管理者
往高处走,每一次角色的转变,都是断层。有时候,公司里到了一定级别的程序员就会被冠以架构师的称呼,但工作的实质内容依然是资深程序员平时做的事,如:一些关键系统的设计和实现,解决一些困难的技术问题。
这些工作中的确有一部分也算是架构师的内容,但如果不能认识到架构师工作内容的实 质,再往高处走也就很难实现断层的跨越了。而架构工作的实质是创造一个模型,来连 接、匹配关于业务、技术和团队之间的关系。
其中的 “业务” 属于架构师工作内容中的领域建模;“技术” 是匹配领域模型的技术实 现模型;“团队” 是关于个体之间如何组合的结构,需要满足个体技术能力与技术实现模 型的匹配。由这三个元素连接和匹配构成的模型中,“业务” 是变化最频繁的,其次是 “团队”,而变化频次最低的反倒是 “技术”。
每一项元素发生变化,都意味着架构模型需要去适应这种变化,适应不了变化的模型就需 要升级。而常见的组织架构调整,也就意味着 “团队” 的沟通路径变化了,因为康威定律 (系统设计的通信结构和设计系统的团队组织的沟通结构是一致的)的缘故,必然带来架 构模型的适应性变化调整。
透过具体的实质再往高处抽象到本质,你会发现架构工作的本质是在通过模型调优生产关系,从而提高生产效率和生产力。这是一条杠杆之路,通过找到其中的关键支点去放大输出,扩大价值。
在架构模型三元素中,技术本身就是一种杠杆,而团队和业务是价值支点。
曾经,技术的草莽时期,是一个英雄辈出的年代。两个人可以创造 Unix、C 语言,一个人 也可以发明 Linux,也可以写出 Foxmail。掌握了技术,就可能创造历史,那时技术的杠 杆很高。
如今,是技术的成熟时期,个体英雄少了,更多是一种团队和集团军作战的方式。如果你是技术的绝世高手(精的极致),那你也需要找到一支契合你技能的场景与队伍,加入进去。此时个人的技术杠杆也许不像曾经那么高,但也许你们这个队伍还是有机会能创造历史的。
前几年,Facebook 曾收购了一家叫 WhatsApp 的公司,花了 190 亿美元。这家公司当 时仅 50 人,而其中一半是技术人员,这应该是近年用技术杠杆撬动价值之最了吧。
在 WhatsApp 这个例子中的价值支点是什么?是产品(业务),连接用户、形成网络。技 术本身的价值通过这个产品业务形态支点,在每个活跃用户身上得到了放大。
而另一个价值支点,是借助团队,但这只适合高级别的技术人员,比如:技术管理者或架构师。但团队也需要能创造真正的价值,才能实现利用杠杆放大价值的效果。在商业环境下,任何一种产品业务形态,其最终能实现价值,都会存在一个价值网络。这个网络中覆盖了各种角色,技术只是其一,若要找到最好的价值支点,那么通常会在离价值来源比较近的地方。
技术像是一根棍子,能发挥多大价值,取决于棍子本身的品质和运用的方式。而往高处走的技术人,要跨越这条路径的断层,就是要认识清楚这个价值网络,并找到最适合技术发挥的价值点。
精
精的路线是一条 “专家” 之路。
曾经在前文《定义:阶梯与级别》中定义过 “专家”,我说:专家可能就是某个领域中你 绕不过去的人吧。这个定义中包含两个点,一个是领域,另一个是绕不过去。第一点表达 了某个范围,第二个则模糊地表达了这个范围的大小,绕不过去其实是一个很大的范围 了。
比如,若你处在物理学领域,牛顿就是你绕不过去的人,之后是爱因斯坦。而在计算机领域,图灵定义了计算机的边界,也是这个领域绕不过去的人。但这样的天才人物,百年来才出一个,如果都要达到这个水平才算是专家,可能就太难了,从而失去了指导意义。
如今反思,其实用这两点来定义专家也是可以的,只是需要更清晰地明确领域和量化范围。大至国家、社会、行业,小到公司、团队、小组,都有自己关于专家的定义。
走向专家之路,就是精确地找到、建立你的领域,并不断推高壁垒和扩大边界的过程。
那么如何建立属于自己的、更大范围内且具备足够识别性的领域?这就是 “精” 的路径中 的非连续性断层问题。曾经读过一篇吴军的文章,谈到了工程师成长中的类似问题,他用 了一个公式来描述解法:
成就 = 成功率 x 事情的量级 x 做事的速度
在连续的成长阶段,我们的成长主要体现在不断提升做事的熟练度,也就是上述公式中的速度和成功率,但这两个指标到了一定的熟练度阶段后就会碰到物理极限。实际情况是,一个资深的工程师的速度甚至不会比一个初级工程师快两倍,但可能成功率会高几倍,甚至十倍,这就是传说中的一个顶十个的程序员,但离极限也就差不远了。
而要成为传说中以一敌百的程序员,只有一个可能,他们做的事情和其他人不在一个量级 上。现实案例中,就有如 Linus 这样的人。所以,一直做同样的事,都是写代码,也可以 跨越断层,但关键是,你写的代码体现在什么量级的事情上。
之前在工程思维中总结过:问题的量级变了,逻辑就不一样了。作为程序员,我们会有直 观的感受,用户量级越过了一定的门槛后,我们编写、维护和部署程序系统的方式都会发 生本质的变化。而提升量级最难的就在于我们要放下曾经熟悉的方式和习惯,站在更高的 维度去看更大量级的事情,并且找到适合这个量级事情的合适解决方案。
面临成长路上的非连续断层,以及角色之间的无形壁障,该如何跨越断层,突破边界?我 们着重从成长路线的两个方向:“高” 和 “精”, 提供了分析和解法。
- 高的路线,需要借助技术的杠杆,认清所处的价值网络,找到合适的价值点,撬动更大的价值;
- 精的路线,在做事情的成功率和速度接近自己的极限后,只能去提升事情的量级,才能发挥出专家的价值。
成长蓝图,进化跃迁
回顾过去,我们会清晰地看见走过来的路线,但面向未来我们又该如何走下去?但凡过往,皆为序章,过去不可变,未来才是希望,而如何去规划并管理好未来的成长进化之路,才是我们当下要面临的主要任务。
我们先从一个高度抽象的维度,来看看这条成长之路。
一、成长路线
结合我自己的经历、思考与总结,我对走过的路和未来的路概括成如下这张图:
图中描述了好几个阶段,从一个阶段到下一个阶段,都会经历一次转折。
1. 开发代码(Develop Code)
从刚走出学校到进入职场成为一名新手程序员,在最初的一两年内,你可能都处在这个阶 段。不停地大量写代码,为各类系统的“大厦”添砖加瓦,像块海绵一样,把自己吸得满 满的,朝 9 晚 24 地工作与学习,并不时自嘲为 “码农”。
这个阶段,你为生存所需(迫),会强烈地渴望成长。
2. 开发系统(Develop System)
三、五年后,你可能从初级、中级成长到了高级,此时你不再仅仅是写代码搬砖,而是开始负责起或大或小的整个系统。这时,你最关心的是如何用最好的技术方案,去开发、优化和完善系统。
3. 开发产品(Develop Product)
从高级走向资深、专家或架构师,你会发现你的技术执行技能已经优化到了相当的程度,这时往前多走一步,关注你所实现的系统所属的产品,会让你打开新的空间,找到更有效率和效果的实现路径,减少做无用功。而且在技术的世界里,有很多面向开发者的技术型产品,这个领域中最适合承担起产品经理角色的就应该是各类资深的技术专家和架构师了。
4. 开发团队(Develop Team)
当你选择走上技术主管并转变为一名管理者,那么人和团队将成为你的主要开发对象,而 不再是代码了,这是成为管理者的必经之路。
5. 开发梦想(Develop Dream)
梦想这个东西也会随着岁月与你相伴成长,梦想实际永远在前方,它只是不断引领着你往 前走。梦想相对而言是一个感觉上很 “虚” 的概念,它可能需要产品作为载体,也需要团 队来一起开发创造。如此,梦想的引力就会引发你向一名创新者或领导者的方向进化跃 迁。比如说,十多年前,刚毕业时,我的梦想是成为一名架构师,如今已然实现。
以上这张图只是帮你看清从过去到未来的一条路,但如何走好这条路,就需要另一个视角维度的蓝图了。
二、战略蓝图
战略这个词,通常会和组织、公司关联在一起;那假想下,如果个人是一家公司,那么这 家 “公司” 的战略该如何确定?
在分析战略之前,我们需要先分析下公司的业务。为了更好地分析清楚公司的主要业务, 这里借鉴下咨询公司爱用的商业分析模型:波士顿矩阵。实际有很多不同的分析模型,我 只是觉得这个最简单,比较适合像个人这样的小小微 “公司”。
波士顿矩阵模型,把公司业务分成下面四类:
- 现金牛业务
- 明星业务
- 问题业务
- 瘦狗业务
现金牛业务,比较形象地表达了就是产生现金的业务。比如谷歌的搜索业务、微软的 Windows 操作系统,都是它们的现金牛业务,有很高的市场占有率,但成长率相对就比 较低了。
就个人来说,现金牛业务自然是一份稳定的工作,产生现金,维持个人生活的基本面,当 然稳定之外越高薪越好。程序员这个职业就是很好的现金牛业务,行业繁荣,工作也比较 稳定,专注于这个业务,不断提升薪资水平,这就是:活在当下。
明星业务,比较形象地表达了很有前景的新兴业务,已经走上了快速发展的轨道。比如: 亚马逊的云计算(AWS)就是它的未来之星。而个人呢?如果你的现金牛业务(级别和薪 资)已经进入行业正态分布的前 20%,那么再继续提升的难度就比较大了。
个人的明星业务是为未来 5 到 10 年准备的,就是现在还并不能带来稳定的现金流但感觉 上了轨道的事。于我而言,是投资理财。人到中年,除了劳动性收入,资产性收益将作为 很重要的补充收入来源,而当资本金足够大时,很可能就是未来的主要收入来源。当你开 始在考虑未来的明星业务时,这就是:活在未来。
问题业务,比较形象地表达了还有比较多问题的业务领域,面临很多不确定性,也就是还 没走上正轨。将来到底是死掉,还是成为新的明星业务,现在还看不清楚。比如谷歌的无 人驾驶、机器人等业务领域都属于此类。
就个人而言,可能是一些自身的兴趣探索领域。于我来说,目前就是写作和英语,即使写 作已经开了专栏,但并不算是稳定可靠的收入来源,主要还是以兴趣驱动,投入时间,不 断探索,开拓新的维度,这就是:活在多维。
瘦狗业务,比较形象地表达了一些食之无味、弃之可惜的业务。瘦狗业务要么无法产生现 金流,要么产生的现金流不断萎缩。今日之瘦狗,也许是昨日的明星或现金牛,比如像诺 基亚的功能机。
就个人而言,行业在发展,技术也在进化,曾经你赖以为生的 “现金牛” 技能,可能过几 年后就会落后,逐渐变成了 “瘦狗”,无法果断地放弃旧技能、开发新技能,可能就如诺 基亚一般在新的时代被淘汰。固守瘦狗业务,那就是:活在过去。
业务模型构成了你的蓝图,而对你的各种业务进行与时俱进地布局与取舍,这就是战略。
三、进化跃迁
明晰了路线,掌握了蓝图,该如何完成你的成长进化跃迁呢?
跃迁是量子力学里的概念,指电子吸收能量后,突然跳到更高的能量级,这种不连续、跳 跃的突变,我们称之为 “跃迁”。我借用了这个概念来类比成长,从如上定义中有几个关 键点:
- 吸收能量
- 更高能量级
- 非连续跳跃
个人成长的跃迁也需要能量,在这里能量就是知识、技能和能力。完成 “能量” 的积累就 需要持续地学习和实践行动,而持续行动又靠什么来驱动?
内心的自驱力,这是稳定有效 的驱动力来源,若没有自我驱动的力量是不太可能带来持续行动的。
学习行动计划、养成行动习惯都是为了提升行动的效率,行动积累了足够的 “能量” 后, 就向更高能量级跳跃。这里更高的能量级是对知识和能力的更高维度抽象的比喻,比如: 知识模型和技能体系,就比孤立的知识点和技能拥有更高的能量级。
而第三个关键点:非连续跳跃,说明这样的进化有突变的特征。而个人知识的积累与能力的提升,其实都是比较缓慢而连续的,非连续的跳跃其实体现在机会和运气上。合适的机会若没能降临,你就没法完成跃迁。
连续的成长积累是你能掌控的部分,而跃迁的机会、运气则属于概率成分,你的努力可能一定程度上提高了概率,但它并不能导致必然的跃迁结果发生。即使机会没能到临,努力过后也许有无奈,也该当无悔了。
最后,我们总结下:
从开发代码到开发梦想,你可以画出一张你的成长路线图,从而走上进化跃迁的道路;上了路后,接着你可以利用工程师的思维模式和商业工具模型,建立一个你的成长战略蓝图去指导你如何走这条路。剩下的,就让你的努力、选择和运气来帮助你完成不断的跃迁变化吧。