答疑解惑 如何分解一个你不了解的技术任务?
在“任务分解”这个模块,我以测试为核心,讲解了任务分解这个原则,同时也给你介绍了一些最佳实践,帮助你更好地理解任务分解的重要性,以及应该怎样分解任务。
同学们对任务分解这个原则大多是表示认同的,但就一些具体应用的场景,还是提出了自己的问题。
在今天的答疑中,我选择了几个非常典型的问题来进行深入讨论。
问题1:面对不了解的技术,我该如何分解任务?
pyhhou 同学提到
很想听听老师的意见,就是在一个自己不熟悉的,充满未知的项目中该怎么更好地进行任务分解?- ——《11 | 向埃隆·马斯克学习任务分解》 |
shniu 同学提到
想请问一下老师,面对探索型的需求,调研型的需求如何做任务分解呢?- ——《15 | 一起练习:手把手带你分解任务》 |
这是一个很好的问题。在这个模块讨论开发中的任务分解时,我说的都是确定了解的某项技术,比如,数据库、REST 服务等等,因为这是开发中最常见的场景,也是最基础的能力,连熟悉的技术都做不好分解,就别说不熟悉的技术了。
那如果不了解这项技术呢?答案很简单,先把它变成你熟悉的技术。一旦变成了你熟悉的技术,你就可以应用在这个模块中学到的,面对确定性技术的分解方案。
我知道,这个答案你并不满意。
其实,你真正的问题是,怎么把它变成你熟悉的技术。
我的答案是,做一次技术 Spike。这里之所以用英文,是因为我没有找到一个特别合适的词来翻译。
Spike 这个词的原意是轻轻地刺,有人把它翻译成调研,我觉得是有些重了。
Spike 强调的重点在于快速地试,和调研的意思不太一样。
既然是快速地试,就要在一定的时间内完成,比如,五人天,也就是一个人一周的时间,再多就不叫 Spike 了。
一些简单的技术,用一天时间做 Spike 就差不多了。
这里强调的重点在于,要做一次技术 Spike。
Spike 的作用就在于消除不确定性,让项目经理知道这里要用到一项全团队没有人懂的技术,需要花时间弄清楚。
项目经理比你更担心不确定性,你清楚地把问题呈现在他面前,项目经理是可以理解的,他更害怕的是,做到一半你突然告诉他,项目进度要延期。
把事情做在前面,尽早暴露问题,正是我们要在下一个模块要讨论的一个主题。
好,那么接下来的问题变成了:怎么做技术 Spike 呢?
这里,我假设你已经通过各种渠道,无论是新闻网站,还是技术 blog,又或是上级的安排,对要用的技术有了一些感性的认识,至少你已经知道这项技术是干什么的了。
接下来,我们要进入到技术 Spike 的任务分解。
首先,快速地完成教程上的例子。
稍微像样点的技术都会有一个教程,跟着教程走一遍,最多也就是半天的时间。
之所以要快速地完成教程上的例子,是为了让你有一个直观的认识,这时候,你对这项技术的认识就会超过新闻网站的报道。
其次,我们要确定两件事:
这项技术在项目中应用场景和我们的关注点。
技术最终是要应用到项目中的,本着“以终为始”的原则,我们就应该奔着结果做,整个的 Spike 都应该围绕着最终的目标做。
很多程序员见到新技术都容易很兴奋,会把所有的文档通读一遍。如果是技术学习,这种做法无可厚非,但我们的目标是做 Spike,快速地试,没有那么多时间,必须一切围绕结果来。
项目中的场景有无数,我们需要选择最重要的一个场景,而针对着这项最重要的场景,我们还要从这项技术无数功能中选取最需要的几个,而不是“满天撒网”。
再有是我们要找准关注点,比如,采用新的缓存中间件是为了提高性能,那关注点就是性能,采用新的消息队列是为了提升吞吐,那关注点就是吞吐。
我们选用一项新技术总是有自己的一些假设,但这些假设真的成立吗?这是我们需要验证的。
无论是场景,还是关注点,我们要在前面先想清楚,其目的就是为了防止发散。
当时间有限时,我们只能做最重要的事,这也是我在专栏中不断强调的。
确定好场景和关注点,接下来,我们要开发出一个验证我们想法的原型了。
这个原型主要目的就是快速地验证我们对这项技术的理解是否能够满足我们的假设。开发一个只有主线能力的原型,对大部分程序员来说并不难,这里就不赘述了。
当你把想法全部验证完毕,这项技术就已经由一项不熟悉的技术变成了熟悉的技术。我们前面的问题也就迎刃而解了。这时候,你就可以决定,对于这项技术,是采纳还是放弃了。
但是,我这里还有一点要提醒,当你确定要使用这项技术时,请丢弃掉你的原型代码。
你或许会说,我辛辛苦苦写了几天的代码就这么丢了?
是的,因为它是原型,你需要为你的项目重新设计。
如果顺着原型接着做,你可能不会去设计,代码中会存在着大量对这项技术直接依赖的代码,这是值得警惕的,所有第三方技术都是值得隔离的。
这是我们会在“自动化”模块讨论的内容。
问题2:项目时间紧,该怎么办?
在这个模块里,我花了大量的篇幅在讲测试,很多同学虽然认同测试的价值,却提出了开发中普遍存在的一些情况。
玄源 同学提到
很多时候,项目时间很紧,经常会提测后,再补测试,或者直接code review,测试就不写了。- ——《12 | 测试也是程序员的事吗?》 |
这是一个非常典型的问题,我在之前做咨询的时候,经常会遇到很多团队说,项目时间紧,所以,他们没有时间做测试。
这里面有一个非常经典误区:混淆了目标与现状。
目标是应该怎么做,现状是我们正在怎么做。我们都知道现状是什么样的,问题是,你对现状满意吗?如果每个人都对现状是满意的,就不会有人探索更好的做法。
假设现在不忙了,你知道该怎么改进吗?
遗憾的是,很多人根本回答不了这个问题,因为忙是一种借口,一种不去思考改进的借口。
我之所以要开这个专栏,就是为了与大家探讨行业中一些好的做法。
回到这个具体问题上,我们在专栏开始就在讲以终为始,首先要有一个目标,专栏中介绍的各种实践都可以成为你设置目标的参考。有了这个目标再来考虑,如何结合我们工作的现状来谈改进。
接下来,我们以测试为例,讨论一下具体的改进过程。用我们专栏最初讲过的思考框架看一下,假如我们的现状是团队之前没什么自动化测试,而我们的目标是业务代码100%测试覆盖。如果要达成这个目标,我们需要做一个任务分解。
这时你会发现,分解的过程主要需要解决两方面的问题,一个是与人的沟通,另一方面是自动化的过程。
与人的沟通,就是要与团队达成共识。
关于这点,你可以尝试将专栏里讲到的各种最佳实践以及其背后的逻辑,与团队进行沟通,也可以把专栏文章分享给他们。
再来,我们考虑一下自动化的改进,因为我们的现状是没什么测试,所以,不能强求一步到位,只能逐步改进。下面我给出了一个具体的改进过程:
-
把测试覆盖率检查加入到工程里,得到现有的测试覆盖率。
-
将测试覆盖率加入持续集成,设定当前测试覆盖率为初始值。测试覆盖率不达标,不许提交代码。
-
每周将测试覆盖率调高,比如,5%或10%,直到测试覆盖率达到100%。
这样,我们就找到了一条由现状通往目标的路径,接下来,就是一步一步地具体实施了,由团队成员逐步为已有代码补充测试。
问题3:多个功能同时开发,怎么办?
妮可 同学提到
公司经常存在有两个需求同时开发的情况。请问老师所在的团队如何解决单分支上线不同步的情况呢?- ——《14 | 大师级程序员的工作秘笈》 |
在主分支开发模型中,有一些常见的解决多功能并行开发的方法,其中,Feature Toggle 是最常用的一个,也就是通过开关,决定哪个功能是对外可用的。
关于这一点,Y024 同学也补充了一些信息。
Feature toggle(功能开关)分享两篇文章:-
不过,如果用户故事划分得当,你可以很快完成一个完整的业务需求。
实际上,Feature Toggle 只是一个非常临时的存在。但如果你在一个遗留系统上工作,一个功能要跨越很长的周期,Feature Toggle 才显得很有用。
额外补充一个与主分支开发模型相关的常用技术,如果你想对遗留系统做改造,传统的做法是,拉出一个分支。
如果在一个分支上怎么做呢?
可以考虑采用 Branch by Abstraction,简言之,再动手改造之前,先提取出来一个抽象,把原先的实现变成这个抽象的一个实现,然后,改造的过程就是提供这个抽象的一个新实现。
这种做法对设计能力有一定要求,所以,对很多团队来说,这是一个挑战。
好,今天的答疑就到这里,请你回想一下,你在工作中是否也遇到过类似的问题呢?你又是怎么解决的呢?欢迎大家在留言区写下你的想法。
如何在实际工作中推行新观念?
在整个专栏的最后一个大模块”综合运用”中,我们把前面学到的各种原则和知识穿插在一起应用在了不同的场景中。
在这个模块的答疑中,我们也综合汇总一次,把整个专栏中出现的一些有趣却还没有来得及讨论的问题放在一起。
问题1:想要推行 DDD,阻力很大怎么办?
段启超 同学提到
想在公司内推行DDD,阻力真的很大,首先是很多人对DDD没概念,需要一定的学习成本,二是团队间相互隔离,沟通成本很高,起码的通用语言都很难达成。- ——《37 | 先做好DDD再谈微服务吧,那只是一种部署形式》 |
段启超同学提到的这个问题是一个非常典型的问题,而且,这个问题并不仅仅局限于 DDD。
你在一个地方看到了一些好东西:技术、实践,或是想法,然后想把它运用在自己的项目中,希望项目越做越好,越来越顺利。但在实际情况中,想在一个组织内推广一些不一样的东西,都会面临层层阻力。
我在《40 | 我们应该如何保持竞争力?》中提到了一个学习模型,你只要在学习区不断地练习新技能,很快就可以超越同侪。其中的原因是,大部分人只习惯待在舒适区,在舒适区的人能力上的进步非常有限。也因为在舒适区实在太舒适了,走出舒适区会让人产生焦虑,所以,人的内心是惧怕改变的。 |
你有良好的愿望,驱动你自己去改变是一件可控的事,有愿意和你一起改变的人是一件幸运的事,但你指望所有人一下子和你走上同一条道路,这是一件几乎不可能的事,即便你是很高层的领导,让所有人与你保持一致也不现实。
我曾经在一个大公司做过敏捷咨询,这还是由他们顶层领导推动的敏捷转型,但依然是困难重重。那些习惯于待在自己舒适区的人总会找到各种神奇的理由告诉你,他们的情况有多么特殊,这些最佳实践在他们那里是不适用的。
我们放弃了吗?并没有。
我们的做法是,找一个团队来做试点。
换句话说,我们找到了几个愿意改变的人,把这些最佳实践应用在他们的项目上。在这种情况下,大家的目标是一致的,就是希望让这个项目得到改善。所以,大家自然会想尽一切办法,克服遇到的困难。比如,我们当时的切入点是持续集成。
他们的代码都在老旧的 ClearCase 上,每个人修改文件要先去竞争文件锁,特别不利于小步提交,所以,我们推动着将 ClearCase 改成了稍微进步一点的 Subversion。
(好吧,你能听出来这是一个有些年头的故事。)
代码是用 C 语言编写的,在他们的代码规模下,编译时间会很长。于是,我们决定搭建一个分布式构建系统,这需要有很多台电脑。不过,他们的硬件是严格管控的,申请电脑是很困难的,虽然花了很大的力气,但最终我们做到了。
以往团队都是几天甚至几周才提交一次代码,我们先将代码提交的要求限定在每人每天至少提交一次,为此,我们专门坐下来与团队成员一起分解任务,将他们理解的大任务拆分成一个一个的小任务。
……
想做事,只需要一个理由就够了,不想做,理由有一万个。劝那些不想改变的人改变是异常耗时而且收效甚微。最好的办法是,找到愿意和你一起改变的人,做一件具体的事。
我们并没有劝说谁去听从我们的想法,只是在一个一个地解决问题。我们花了很长时间,最终建立起了持续集成,看到大屏幕上的绿色标识,我颇为感动。原本只需要一两天搭建的持续集成,在一个复杂组织中,它要花费那么长时间,这也是我从未经历过的。
当我们把这件事做成之后,其他团队看到了效果,开始纷纷效仿。于是,原本复杂的各种规定也开始纷纷松绑,比如,他们再也不需要为申请电脑发愁了。至于之前质疑我们的人,因为看到了成效,他们的关注点就成了怎么把事能做成。
后来我听说,他们在组织内部专门建立了一个持续集成中心,为各个团队提供了公共的构建资源,提升了整体的效率。
Linus Torvalds 曾经说过:“Talk is cheap. Show me the code. ”讲道理很容易,但也难以让人真正的信服。同样,做事很难,但成果摆在那里,让人不得不信服。
在英文中对这种行为有一个说法叫“Lead by Example”,通常用来形容团队领导以身作则的行事风格。当你寻求改变时,无论你的角色是什么,你都需要扮演好领导者的角色,“Lead by Example”送给你!
问题2:测试怎么写?
andyXH 同学提到
目前对于 TDD 还是处于理解状态,不知道如何真正的在项目工程中使用。因为项目工程往往还有很多其他调用,如rpc,数据库服务,第三方服务,不知道在这个过程如何处理。期待老师在之后文章中讲解。- ——《13 | 先写测试,就是测试驱动开发吗?》 |
梦倚栏杆 同学提到
从数据库或者第三方api查询类内容需要写测试吗?这种测试怎么写呢?如果不需要写,会发现大量展示类系统不需要写测试了,感觉怪怪的。- ——《16 | 为什么你的测试不够好?》 |
闷骚程序员 同学提到
假设我要测试的函数是一个关于tcp的网络发送函数,我想问一下,老师在写类似这样功能的单元测试是怎么实现的?- ——《39 | 面对遗留系统,你应该这样做》 |
TimFruit 同学提到
问个问题,一般web服务依赖数据库,这部分如何做好单元测试?如果去掉数据库,很难测试相应的sql语句。- ——《39 | 面对遗留系统,你应该这样做》 |
大家看到了,这是一类非常典型的问题。一般来说,如果写的测试是一些业务逻辑的测试,大多数人还知道怎么测,一旦涉及到外部系统、数据库,很多人就不知道该怎么办了。
我们先来回答一个问题,你要测外部系统的什么?
你当然会说,我的整个系统都依赖于外部系统,没有了它,我的系统根本运行不起来,不能完成工作啊!但是,我的问题是你要测的是什么?
我知道很多人一想到外部系统,第一反应是:“我的整段代码都是依赖于外部系统的,因为外部系统不好测,所以,我这段代码都没法测了。”如果你是这样想的,说明你的代码将对外部系统的依赖在业务代码中散播开了,这是一种严重的耦合。
外部系统对你来说,应该只是一个接口。
我在《13 | 先写测试,就是测试驱动开发吗?》中说过,想写好测试,先要站在可测试的角度思考。假设我同意你关于外部系统不好测的观点,那应该做的是尽量把能测的部分测好。将对外部系统的依赖控制在一个小的范围内。 |
一个好的做法就是设计一个接口,让业务代码依赖于这个接口,而第三方依赖都放在这个接口的一个具体实现中。
我在《34 | 你的代码是怎么变混乱的?》中提到了 SOLID 原则,这种做法就是 接口隔离原则(ISP)的体现。 |
如果你能够站在系统集成的角度思考,这个部分就是系统与系统之间的集成点。
我在《37 | 先做好DDD再谈微服务吧,那只是一种部署形式》提到了 DDD。 |
在 DDD 的战略设计中,有一个概念叫上下文映射图(Context Map),在不同上下文中集成最常见的一种模式是防腐层(Anti-Corruption Layer,ACL)。
很多系统在实现时就是缺少了防腐层,造成的结果就是系统耦合极其严重。
因为外部服务的任何修改都会造成自己的代码跟着大幅度变动,更极端的情况是,我见过一个网关系统在自己的业务逻辑中直接依赖于第三方服务传过来的 JSON 对象,造成内存资源的极大浪费,网关本身极其不稳定。
至此,你知道了,如果有任何外部系统,都要设计防腐层,用接口做隔离。
这样,才能保证你的业务代码是可测的。如果外部系统真的不好测,这种做法将大幅度降低不可测的比例,尽可能提高测试覆盖率。
我们前面的假设是,外部系统不好测,但真的不好测吗?
通过 MOCK 进行测试。
对于数据库的测试,如果你采用的是 Spring Framework,它就提供了一套完整的方案,比如:你可以在运行测试时插入一些数据,然后,在测试执行完毕之后,回滚回去,保证测试的可重复性。
事实上,它对测试的支持已经非常强大了,远不止于数据库。
如果你采用的是 Spring Boot,对测试的支持就更加完整了,但基础还是 Spring Framework 提供的。如果用到真实的数据库,最好是一套独立的本地数据库,保证环境的可控。
对于外部服务的测试,简言之,能模拟的就模拟,能本地的就本地。如果你的服务没有现成的工具支持,也许就是一个打造新工具的好时机。
总结一下。关于外部系统的测试,你可以先通过接口隔离开来,然后,通过模拟服务或本地可控的方式进行测试。
好,今天的答疑就到这里,你对这些问题有什么看法呢?欢迎在留言区写下你的想法。
如何管理你的上级?
在这个模块里,我围绕着“以终为始”这个原则为你进行了详细地讲解,还给你介绍了应用“以终为始”原则的一些行业最佳实践。
同学们的留言特别踊跃,很多同学表示有收获的同时,也提出了大量的问题,大家比较关心怎样将这些实践在自己的实际工作中落地,部分问题我已经在留言中回复了。
在今天的答疑环节中,我挑选了一些非常典型的问题来更详细地回答一下。
问题1:领导要求的,无力反驳怎么办?
achenbj 同学提到
讲得很好,感觉落地还需努力。我们就是领导给了功能,跟你说下要做啥,就那么做就行。没有了。- —— 04 | 接到需求任务,你要先做哪件事? |
Alexdown 同学提到
考虑到地位的不对等以及我的“人设”已经定型了,实施起来有点难度。- —— 02 | 以终为始:如何让你的努力不白费? |
这类问题很经典,很多同学留言提到,我就不一一列举了。
在我的职业生涯中,无数次听到不同的人有过同样的抱怨。我最初也觉得这是一个无解的问题,直到后来我读到了一本书。
管理大师彼得·德鲁克有一本经典著作《卓有成效的管理者》,虽然标题上带着管理者几个字,但在我看来,这是一本告诉我们如何工作的书,每个人都可以读一下。
当年我读这本书时,其中的一个观点让我很受震撼:如何管理上级。
什么?上级也可以管理?这对于我们这些习惯了接受上级指挥的人来说,观念上的转变几乎是天翻地覆一般。
在很多人看来,自己累死累活,只是因为自己的笨蛋上级,没有很好地处理好他该处理好的事情,还把“锅”扣到了自己的头上。
不过,在德鲁克看来,上级也是人,一样有着长处和短处。我们应该发挥其长处,减少其短处带来的不良影响。管理上级,也就是要发挥上级的长处,不能唯命是从,应该从正确的事情入手,以上级能够接受的方式向其提出建议。
具体到我们的日常工作中该怎么管理上级呢?我给你一些小建议。
我们要敢于管理上级,对上级不合理的要求说“不”,这是一个思想上的转变。很多人受到传统官本位思想的影响,对上级的服从达到了不健康的程度。勇于改变,是有效管理上级的前提条件。如果不从思想上转变,我接下来的建议都是没有价值的。
那具体要从哪些方面着手呢?
第一,管理上级的预期。
上级问你:“一个产品特性,你多长时间能做完?两天?一天行不行?”你想了想,如果不写测试,确实能够省下不少时间,于是,你决定答应上级的要求。是的,大部分人就是这么妥协的。
妥协很容易,但再往回扳就不容易了。下次,他还会再进一步压缩:“半天能不能搞定?两小时行不行?”人的欲望是无限的,所以,就不要让上级有错误的预期。
如果是我,我会告诉上级,这个压缩会影响到什么。
比如,要想做这个调整,你需要放弃的内容是什么;或者,我可以给出一个快速上线的临时方案,但接下来的几天,我需要调整,让代码回到一个正常的状态中。所以,你就不要给我安排新工作了。
这个过程,相当于我把自己看到的问题暴露给上级,让他选择。他有更多的上下文,他会平衡该做的事情。
第二,帮助上级丰富知识。
不是每个上级都是经验丰富的,知道所有事情。比如,有些成长得比较快的负责人,自己甚至都还没来得及了解软件开发全生命周期。在IT这个快速发展的行业里,这是非常可能出现的情况。所以,在某些局部,你比他了解得多是非常有可能的。
在那些他做得不够好的领域,他肯定有许多烦恼。比如,盲目给需求的产品经理,可能也会影响到他对需求的判断。
这个时候,你就不妨把自己知道的内容找个机会给他讲讲。一个简单的方式是,把我专栏的内容发给他,和他一起探讨怎么做是合理的。然后,大家一起协同,改进工作方式。因为你是在帮他解决问题,他会更愿意接受。
第三,说出你的想法。
如果你什么都不做,上级会按照他自己的理解安排工作。比如,小李擅长处理消息队列,那消息队列的活都给他。
如果你有自己的想法和打算,不妨提出来,主动承担一些职责。比如,你接下来打算多学点消息队列,那就大大方方地告诉上级,下次有相关的活,考虑一下自己,上级再安排工作的时候,他就会多想想。这其实就是我们熟悉的一个最简单的道理:会哭的孩子有奶吃。
如果经过你的种种努力,发现你的上级真的是完全没法影响,只能以令人无语的方式行事,那你需要仔细考虑一下与他合作的前景了。
不过,更可能出现的场景是,你还没去尝试改变就放弃了,将全部责任都归结于上级的问题。
如果你是这种思考问题的逻辑,不论到哪个公司,结果都不会比现在更好。
产品经理总拿老板说事,怎么办?
此方彼方Francis 同学提到
很多时候产品要做这需求的理由就一个:老板要的!- ——01 | 10x程序员是如何思考的? |
西西弗与卡夫卡 同学提到
有的产品经理会使出必杀技——这是老板的需求- ——06 | 精益创业:产品经理不靠谱,你该怎么办? |
用老板来“甩锅”,这在软件行业中特别常见。
实际上,老板要求的是方向,不是产品特性。大老板不会安排那么细的细节。所以,一个产品经理该做的事就是把老板给的方向,变成一个个可以实现的产品特性,他要分析其中的合理与不合理。
不合理的部分应该是他和老板去沟通的,而不是让开发团队来实现。
在真实世界中,更有可能的情形是,产品经理“拿着鸡毛当令箭”,老板说的是试一下,到他这里就变成了必须完成。他不敢对老板提问,就只能压迫下游了。
这种情况,你就不妨和产品经理一起去见老板。我们在《解决了很多技术问题,为什么你依然在”坑“里?》这篇文章中提到,要扩大自己工作的上下文,这种做法也可以帮助你解决问题,在自己上下文中解决不了的问题,就放到更大的上下文中去解决。
别人能做的,我们也要做
Xunqf 同学提到
当你和产品经理理论的时候,他往往会拿出来一个现有的产品给你看:“人家怎么就能做到,人家能做到说明技术上是可行的,做吧。”
时间久了你会发现他的需求全是抄的的别的APP,然后就觉得别人能做到的我们也一定能做。- ——《06 | 精益创业:产品经理不靠谱,你该怎么办?》 |
你会发现,在这个问题里,提到了两个与产品经理交流可能出现的典型问题:一个是竞争对手有的产品,我们也要有;另一个是人家能做到的,说明技术上可行,我们也能开发。
我带你来分别看下,这两种说法你该如何应对。
第一,竞争对手有的产品,我们也要有。
没有哪个企业是靠纯粹抄袭成功的。我知道,你想说腾讯。腾讯当年做 QQ,从形式上看,是和 ICQ 极其相似的,甚至名字都是极为相似的:OICQ。但腾讯却做了自己的微创新,它将信息保存到了服务器端,而 ICQ 是保存在客户端的。
正是有了这样看似微小的创新,让当时大部分家里没有电脑的普通用户,可以在网吧里不同的电脑上继续自己的网络社交,适应了时代发展的需要。腾讯“抄”得好的东西,都是有自己微创新的,包括如今的微信。
“抄”不是问题,问题是无脑地抄。
所以,如果你的产品经理只想无脑抄袭,本质上,他就是在偷懒,没干好他该干的活。
竞争对手有这个特性,他为什么要做?他做这个特性与它其他特性是怎么配合的?我们做这个特性,在我们的产品里怎样发挥价值?
作为产品经理,你必须给我讲清楚这些。
即便我们最终的结果是,做的与竞争对手一模一样,经过思考之后的“抄袭”也是一件价值更大的事。
第二:人家能做到,说明技术上是可行的。
关于这一点,我不得不说,产品经理说得对。别人能做到,说明技术上肯定是可行的。
不过,我们必须分清楚两件事:需求和技术。
要做什么是需求,怎么做是技术。
与产品经理要确认的是,这个需求是不是合理,该不该做。技术上能否实现,这是开发团队要考虑的事情,并不是产品经理说事的理由。
还有一种情况是,需求确实合理,但技术实现的成本极高,所需花费的时间很长。在这种情况下,你和产品经理之间很难互相说服。
解决方案是,将问题升级,放到更大的上下文中,让上一层的领导来决定,此时此刻,在现有的资源约束下,是否要按照这种方式做。同时,你最好再提供一个可选的替换方案,这样领导才能更好做选择。
还有一些同学问了很好的问题。
比如,程序员充当了太多角色,很困惑。这个问题我在专栏中已经回答了,在《 接到需求任务,你要先做哪件事?》中,我们说,每次扮演好一个角色。在《 解决了很多技术问题,为什么你依然在“坑”里?》中,我们提到程序员应该多了解不同的角色。
还有人问,计划赶不上变化快,怎么办?简单回答就是靠任务分解,因为这个话题涉及到“任务分解”这个模块的内容,等这个主题讲完之后,如果大家还有疑惑,我们再来详细讨论。
好,今天的答疑就到这里,请你回想一下,你在你工作中是否也遇到过类似的问题呢?
你又是怎么解决的呢?
欢迎在留言区写下你的想法。我会从中筛选出典型的问题,与大家进行互动交流。
持续集成、持续交付,然后呢?
“自动化”模块落下了帷幕,这是四个工作原则中最为“技术化”的一个,也应该是程序员们最熟悉的主题。
我从软件外部的自动化——工作流程讲起,让你能够把注意力专注于写好代码;讲到了软件内部的自动化——软件设计,选择恰当的做法,不贪图一时痛快,为后续的工作挖下深坑。
既然是一个大家都熟悉的话题,同学们自然也有很多经验分享,也有很多人看到了与自己不同的做法,提出了各种各样的问题。
在今天的答疑中,我选出了几个很有意思的问题,让大家可以在已有内容上再进一步延伸。
持续交付是否可以再做扩展?
毅 同学提到
为达到有效交付的目标,用户能够尽早参与,我觉得也是比较重要的一环。从生产环境获得结果,是否可再做扩展,将用户也作为一个独立节点?- ——《32 | 持续交付:有持续集成就够了吗?》 |
西西弗与卡夫卡 同学提到
持续交付可以是持续交付最大价值,那范围就不仅限于软件,还可以进一步延伸到运营,比如说结合ABTest,自动选择最有效的运营策略,为用户交付最大价值。- ——《32 | 持续交付:有持续集成就够了吗?》 |
两位同学能提出这样的想法,说明真的是已经理解了持续集成和持续交付,所以,才能在这个基础上继续延伸,思考进一步的扩展。
我在专栏中一直在强调,别把自己局限在程序员这个单一的角色中,应该了解软件开发的全生命周期。
在前面的内容中,我讲了不少做产品的方法,比如,MVP、用户测试等等。如果只把自己定位在一个写代码的角色上,了解这些内容确实意义不大,但你想把自己放在一个更大的上下文中,这些内容就是必须要了解的。
回到两位同学的问题上,如果说我们一开始把持续集成定义成编写代码这件事的完成,那持续交付就把这个“完成”向前再推进了一步,只有上线的代码才算完成。
但放在整个软件的生命周期来说,上线并不是终点。把系统送上线,不是最终目的。那最终目的是什么呢?
回到思考的起点,我们为什么要做一个软件?因为我们要解决一个问题。那我们是不是真正的解决了问题呢?其实,我们还不知道。
在《06 | 精益创业:产品经理不靠谱,你该怎么办?》这篇文章中,我给你讲了做产品的源头。如果是采用精益创业的模式工作,我们构建产品的目的是为了验证一个想法,而怎么才算是验证了我们的想法呢?需要搜集各种数据作为证据。 |
所以,我曾经有过这样的想法,精益创业实际上是一种持续验证,验证想法的有效性,获得经过验证的认知(Validated Learning)。
现在有一些获取验证数据的方式,比如,西西弗与卡夫卡 同学提到的 AB 测试。
AB 测试是一种针对两个(或多个)变体的随机试验,常常用在 Web 或 App 的界面制作过程中,分别制作两个(或多个)版本,让两组(或多组)成分相同的用户随机访问不同版本,收集数据,用以评估哪个版本更好。每次测试时,最好只有一个变量。因为如果有多个变量,你无法确认到底是哪个变量在起作用。
AB 测试的概念在其他领域由来已久。2000年,Google 的工程师率先把它应用在了软件产品的测试中,时至今日,它已经成为很多产品团队常用的做事方式。
AB 测试的前提是用户数据搜集。我在《09 | 你的工作可以用数字衡量吗?》这篇文章给你介绍了在开发过程中,用数字帮助我们改善工作。在产品领域实际上更需要用数字说话,说到这里,我“插播”一个例子。 |
很多产品经理喜欢讲理念、讲做法,偏偏不喜欢讲数字。用数字和产品经理沟通其实是更有说服力的。
我就曾经遇到过这样的事情,在一个交易平台产品中,一个产品经理创造性地想出一种新的订单类型,声称是为了方便用户,提高资金利用率。如果程序员接受这个想法,就意味着要对系统做很大的调整。
我问了他几个问题:第一,你有没有统计过系统中现有的订单类型的使用情况?第二,你有没有了解过其他平台是否支持这种订单类型呢?
产品经理一下子被我问住了。我对第一个问题的答案是,除了最基础的订单类型之外,其他的订单类型用得都很少,之前做的很多号称优化的订单类型,实际上没有几个人在用。
第二个问题我的答案是,只有极少数平台支持类似的概念。换句话说,虽然我们想得很美,但教育用户的成本会非常高,为了这个可能存在的优点,对系统做大改造,实在是一件投资大回报小的事,不值得!
再回到我们的问题上,一旦决定了要做某个产品功能,首先应该回答的是如何搜集用户数据。对于前端产品,今天已经有了大量的服务,只要在代码里嵌入一段代码,收集数据就是小事一桩。
前端产品还好,因为用户行为是比较一致的,买服务就好了,能生成标准的用户行为数据。对于后端的数据,虽然也有各种服务,但基本上提供的能力都是数据的采集和展示,一些所谓的标准能力只是 CPU、内存、JVM 之类基础设施的使用情况。对于应用来说,具体什么样的数据需要搜集,还需要团队自己进行设计。
说了这些,我其实想说的是,持续验证虽然是一个好的想法,但目前为止,还不如持续集成和持续交付这些已经有比较完整体系做支撑。想做到“持续”,就要做到自动化,想做到自动化,就要有标准化支撑,目前这个方面还是“八仙过海各显神通”的状态,没法上升到行业最佳实践的程度。
其实道理上也很简单,从一无所有,到持续集成、再到持续交付,最后到持续验证,每过一关,就会有大多数团队掉队。所以,真正能达到持续交付的团队都少之又少,更别提要持续验证了。
Selenium 和 Cucumber 的区别是什么?
没有昵称 同学提到
老师,Selenium 跟 Cucumber 有区别吗?- ——《33 | 如何做好验收测试?》 |
这是一个经常有人搞混的问题。为了让不熟悉的人理解,我先讲一点背景。
Selenium 是一个开源项目,它的定位是浏览器自动化,主要用于 Web 应用的测试。它最早是 Jason Huggins 在2004年开发出来的,用以解决 Web 前端测试难的问题。
之所以取了 Selenium 这个名字,主要是用来讽刺其竞争对手 Mercury 公司开发的产品。我们知道,Mercury 是水银,而 Selenium 是硒,硒可以用来解水银的毒。又一个程序员的冷幽默!
Cucumber 的兴起伴随着 Ruby on Rails 的蓬勃发展,我们在之前的内容中提到过,Ruby on Rails 是一个改变了行业认知的 Web 开发框架。
所以,Cucumber 最初主要就是用在给 Web 应用写测试上,而 Selenium 刚好是用来操作浏览器的,二者一拍即合。
于是,你会在很多文章中看到,Cucumber 和 Selenium 几乎是同时出现的,这也是很多人对于二者有点傻傻分不清楚的缘由。
讲完了这些背景,结合我们之前讲的内容,你就不难理解了。
Cucumber 提供的是一层业务描述框架,而它需要有自己对应的步骤实现,以便能够对被测系统进行操控;而 Selenium 就是在 Web 应用测试方面实现步骤定义的一个非常好的工具。
IntelliJ IDEA 怎么学?
hua168 同学提到
IDEA 怎么学呢?是用到什么功能再学?还是先看个大概,用到时再仔细看?- ——《30 | 一个好的项目自动化应该是什么样子的?》 |
一个工具怎么学?我的经验就是去用。
我没有专门学过 IntelliJ IDEA,只是不断地在使用它。遇到问题就去找相应的解决方案。
如果说在 IDEA 上下过功夫,应该是在快捷键上。我最早写代码时的风格应该是鼠标与键盘齐飞,实话说,起初也没觉得怎么样。加入 ThoughtWorks 之后,看到很多人把快捷键运用得出神入化,那不是在写一行代码,而是在写一片代码。我当时有一种特别震惊的感觉。
我自以为在写代码上做得已经相当好了,然而,有人却在你很擅长的一件事上完全碾压了你,那一瞬间,我感觉自己这些年都白学了。这种感觉后来在看到别人能够小步重构时又一次产生了。
看到差距之后,我唯一能做的,就是自己下来偷偷练习。幸好,无论是快捷键也好,重构也罢,都是可以单独练习的。花上一段时间就可以提高到一定的水平。后来,别人看我写代码时也会有类似的感觉,我会安慰他们说,不要紧,花点时间练习就好。
其实,也有一些辅助的方法可以帮助我们练习,比如,我们会给新员工发放 IntelliJ IDEA 的快捷键卡片,写代码休息之余,可以拿来看一下;再比如,IntelliJ IDEA 有一个插件叫 Key Promoter X,如果你用鼠标操作,它会给你提示,帮你记住快捷键。有一段时间,我已经练习到“看别人写代码,脑子里能够完全映射出他在按哪个键”的程度。
写代码是个手艺活,要想打磨手艺,需要看到高手是怎么工作的,才不致于固步自封。如果你身边没有这样的人,不如到网上搜一些视频,看看高手在写代码时是怎么做的,这样才能找到差距,不断提高。
好,今天的答疑就到这里,你对这些问题有什么看法呢?欢迎在留言区写下你的想法。
答疑解惑 持续集成,一条贯穿诸多实践的主线
“沟通反馈”模块又告一段落了,在这个模块中,我们把自己与真实世界的距离又拉近了一步。
一方面,我们强调主动沟通,把自身的信息更有效地传达出去;另一方面,我们也重视反馈,让真实世界的信息,更多地回到我们身边。同学们分享了很多经验,也提出了不少的问题。
在今天的答疑中,我选择了几个非常好的问题,从不同的角度丰富一下之前讲解的内容。
单元测试做不好,是否会影响到 CI 的效果?
毅 同学提到
如果单元测试做的不到位,或者不满足A-TRIP,是不是执行CI的效果就会弱很多?- ——《24 | 快速反馈:为什么你们公司总是做不好持续集成?》 |
这是一个非常好的问题,问到了各种实践之间的关联。我们在前面用了两讲的篇幅介绍了持续集成这个实践,为什么要做持续集成以及如何做好持续集成。
在自动化模块,我们还会在这个基础之上继续延伸,介绍持续交付,这些内容是从操作的层面上进行介绍,都是对单一实践的描述。
利用这次答疑的机会,我再补充一个维度,谈谈实践之间的关联。
持续集成的价值在于,它是一条主线,可以将诸多实践贯穿起来。也就是说,想要真正意义上做好持续集成,需要把周边的很多实践都要做好。
我们具体地说一下这些实践。但请记住我们说过的,做好持续集成的关键是,快速反馈。
比如,我们想要做好 CI,需要有一个稳定的开发分支,所以,最好采用主开发分支的方式。
想用好主分支开发,最好能够频繁提交;而频繁提交需要你的任务足够小,能够快速完成;将任务拆解的足够小,需要你真正懂得任务分解。
要想在一个分支上开发多个功能,那就需要用 Feature Toggle 或者 Branch by Abstraction。
在这条线上,你有很多机会走错路。
比如,你选择了分支开发模式,合并速度就不会太快,一旦反馈快不了,CI 的作用就会降低;再者,如果不能频繁提交,每次合并代码的周期就会变长,一旦合并代码的周期变长,人们就会倾向于少做麻烦事,也就会进一步降低提交的频率,恶性循环就此开启。
同样,即便你懂得了前面的道理,不懂任务分解,想频繁提交,也是心有余而力不足的。而多功能并行开发,则会让你情不自禁地想考虑使用多分支模型。
我们再来看另外一条线,也就是这个问题中提到的测试。
想做好 CI,首先要有可检查的东西,什么是可检查的东西,最简单的就是编译、代码风格检查,这些检查可以无条件加入构建脚本。
但更重要的检查,应该来自于测试,而要想做好 CI,我们要有测试防护网。
什么叫测试防护网呢?就是你的测试要能给你提供一个足够安全的保障,这也就意味着你要有足够多的测试。换个更技术点的术语来说,就是要有足够高的测试覆盖率。
如果测试覆盖率不够,即便提交了代码,CI 都通过了,你对自己的代码依然是没有信心的,这就会降低 CI 在你的心中的地位。
如果想有足够高的测试覆盖率,你就要多写单元测试。
我们在前面讲过测试金字塔了,上层测试因为很麻烦,你不会写太多,而且很多边界条件,通过上层测试是覆盖不到的,所以,测试覆盖率在经过了初期的快速提升后,到后期无论如何是提上不去的。
要想提升测试覆盖率,唯有多写单元测试。
要想多写单元测试,就需要编写可以测试的代码,而要想编写可测的代码,就要懂软件设计,将系统之间耦合解开。
通过上面的分析,你已经看出来做好持续集成,让它完全发挥自己的价值,需要做的工作还是相当多的。但也请别灰心,实际上,我做咨询时,很多团队就是从持续集成下手,开始改造他们的软件开发过程。
这是一个“以终为始”的思路,先锁定好目标,就是要把持续集成做好,然后围绕着这个目标改进其他做得欠佳的方面。
比如,原来是多分支的,就先固定一个主分支,然后,逐步改变大家的开发习惯,让他们进入单分支的开发状态。
再比如,原来没有测试,那就在 CI 上先加一个最低的测试覆盖率,然后定期去提高,比如,第一周是10%,第二周是20%,这样一步一步地提高,开发团队可以一边开发新东西,一边为既有代码补测试。
等到覆盖率到了一定程度,提高有困难了,团队就可以考虑怎么改进设计了。
所以,CI 作为一个单独的实践,本身是很简单的,但它可以成为提纲挈领的主线,帮助团队不断改善自己的开发过程。
问题2:老板参加复盘,不敢说真话怎么办?
grass10happy 同学提到
复盘是不是最好是团队内部进行,每次老板参加复盘,好像就没人说出真话了。- ——《25 | 开发中的问题一再出现,应该怎么办?》 |
感谢 grass10happy 同学这个提问,把我因为篇幅原因省掉的一个部分给挽救了回来。
回顾会议的目的在于改进,它不仅仅在于让大家参与进来,更重要的是让团队成员能够敞开心扉,把问题暴露出来。
暴露问题,是改进的前提条件。
我在《27 | 尽早暴露问题: 为什么被指责的总是你?》这篇文章中说过了,对于很多人来说,敢不敢暴露问题是个心理问题。你会发现,同事之间聊天,普遍是没有任何压力的,你几乎可以放心大胆地谈论各种问题,而一旦有领导在,很多顾虑就会出现了。 |
于是,问题就变成了怎么能够让大家放心地把问题暴露出来,一个办法就是设置一个安全的环境。
怎么设置一个安全的环境呢?对于标准的回顾会议来说,第一步应该是做安全性检查。
先由大家投票,最简单的方式是就是,给当前的环境打分。你觉得可以畅所欲言就打1分,你觉得还好,就打0分,如果你觉得不方便表达,比如,你看领导在,很多问题不适合反馈,就打-1。
每个与会者都投出属于自己的一票。然后,主持人根据投票结果决定回顾会议是否进行,比如,有人投-1就不能继续。
会议能继续固然好,一旦会议不能继续,可以有多种解决方案。
比如,把在场职位最高的人请出去,这个人可能就是老板。老板也许心里很不爽,但在这个过程中,大家都是按照规则在办事,并不存在对谁另眼相待的情况。
当老板离席之后,我们再进行一轮投票,判断环境是否变得安全了。
如此反复,也许要进行几轮投票,直到大家觉得安全了。
当然,也有可能进行多轮,有人始终觉得不安全,那可能最好的选择是,取消今天的回顾会议,换个时间地点从头再来。而项目负责人则需要私下里解决一下团队内心安全的问题。
通过安全性检查之后,我们才会进入回顾会议的正式环节,具体内容在正文中已经讲过了,这里就不再赘述了。
问题3:国内的技术信息落后吗?
One day 提到
老师能否多多介绍一下技术方面的网站之类的,新技术发展见闻之类的,或者技术总结方面。国内的技术基本都多少有些滞后。- ——《23 | 可视化:一种更为直观的沟通方式》 |
这个问题让我感觉自己一下子回到了好多年前。我刚入行的那会,学习新知识确实要多看看英文网站,当时的信息传播速度不快,中文技术网站不多。
但在今天,显然已经不是这样了,如果只是想获得最新的技术信息,我在《23 | 可视化:一种更为直观的沟通方式》这篇文章中介绍了 InfoQ 和技术雷达,这上面的信息量已经很丰富了。你再只要稍微看几个网站,关注几个公众号,各种信息就会送到你面前。 |
所以,你根本不用担心会错过什么新技术,反倒是信息量太大,需要好好过滤一下。
国内程序员真正落后的不是信息,而是观念。
我讲的很多内容是软件工程方面的,以我对国内外程序员的了解来看,发达国家的程序员在这些内容的普及上,要比国内程序员好很多。
国内程序员的平均水平,大多停留在实现一个功能的理解上,而发达国家的程序员做事要专业许多。所以,以专业素养来看,国内程序员还有很大的提升空间。
在经济学里有“边际效用递减法则”(The Law Of Diminishing Marginal Utility),说的是当你手里某一物品总数越来越多时,新增一个单位该物品所获得的效用通常会越来越少。
当你的技术知识积累到一定程度时,还采用原来的学习方式,就很难获得真正意义上的提高,这是很多人抱怨 IT 行业不好混的原因。
同时,这也是我开设这个专栏的初衷,希望给大家一些不同的视角,一些新的前进动力。
好,今天的答疑就到这里。我想请你分享一下,你是怎么理解这些问题的呢?欢迎在留言区写下你的想法。
结束语 少做事,才能更有效地工作
在这个专栏里,我讲过很多东西,几乎涉及到软件开发的方方面面,但有一个重要的方面,我却从来没有说过,那就是算法。
因为我一直把它当做不言而喻的基本功,认为每个程序员都应该掌握。
在我们专栏的结束语中,我就用这个没有涉及过的话题来开篇吧!
算法的差异
排序算法是每个程序员都会学到的内容,大家对各种算法也是如数家珍:插入排序、冒泡排序、归并排序、堆排序、快速排序等等。
我们也知道各个算法的复杂度,比如,插入排序是 O(n^2),快速排序平均情况下是 O(nlogn)等等。
你有没有想过一个问题,不同算法的复杂度本质差别到底是什么呢?我们就以插入排序和快速排序为例,为什么快速排序要比插入排序快呢?
我不打算做算法分析,直接公布答案:因为做比较的次数少。
为什么同样的排序,比较次数会有差异呢?因为插入排序每次循环只关注当前的目标,循环之间没有关系,而快速排序在做不同划分时,上一次的结果对下一次有助力,因此它省下了不少的比较次数。
明白了这个道理,再来看所谓的算法优化,其实就是尽可能利用已知的信息,少做不必要的事。
再来看一个常见的面试题,给你一堆数,找出前100个。很多人直觉就会想到排序,然后选出前100个。这种做法固然可行,但一定是做多了,因为这里需要的是找出前100个数,而不是要100个有序的数字,更不是要所有的数都有序。
说到这里,你就知道了,只要把数据划分开就好,并不需要排序,如果划分点不是第100个元素,就向着100所在的方向继续划分就好。
计算机是最擅长处理繁琐重复工作的,即便如此,我们依然要做算法优化,原因是当数据规模大到一定程度时,不同复杂度的算法差别就非常明显了。
算法没用好,计算机硬件再好,也是徒劳的。
有一则《计算机程序设计艺术》作者高德纳(Donald Knuth)的轶事,他年轻时参加算法大赛,用最差的系统击败了诸多对手,拿到算法执行效率的冠军,凭借的就是其强大的算法优化功力。
对于计算机,算法尚且如此重要,我们面对工作时何尝不是如此呢!
有效工作
《10x 程序员工作法》,也许有的同学最初看到这个标题就急急加入了,以为会从这个专栏中学习到一些“以一抵十”的编程技法,对不起,我彻底让你失望了。我非但没讲太多编程的技法,甚至还从各种角度劝你少写代码:无论是向产品经理提问题,还是让你在前面多考虑设计。
难道不是做得越多才越高效吗?
插入排序并不会因为干的活多,就比快速排序得到更高的评价,因为它们比的是谁排得快。工作效率高,不是因为代码写得多,而是有效工作做得多。
如果 CPU 都被无效指令占据了,哪有时间执行有效指令呢?
即使你很忙碌,但工作进展依然是收效甚微,因为无效工作占据了你太多的大脑,让你不能聚焦在正经事上,当然就是效率不高了。
其实,这个专栏的内容在我脑子里已经盘旋很多年了。不过,即便在专栏筹备期,我已经备了很多篇稿子之后,我依然没有找到一个准确的说法能够描绘内心的想法。
我想过“程序员的职业素养”,但似乎这会让专栏朝着职场行动指南的方向努力;我想过“高效工作”,但实际上我也不打算讨论那些工作技巧。直到上线日期临近,我的编辑实在受不了我的拖延,坐下来与我交流了很久,我才终于找到了内心的那个词:有效。
我在这个专栏真正探讨的主题是,有效工作。
有效工作,需要我们把力量聚焦到正确的地方,做本质复杂度(Essential Complexity)的事情,少做无意义的事情。
我曾经在一个大公司做咨询,按照他们的统计,线上60%的代码从来没有运行过。我们都知道,一多半的代码增加的可不只是一多半的工作量,团队可能需要的是几倍甚至几十倍的心力去维护它。
当然,有效工作最终没有成为这个专栏的名字,而用了更有个性的《10x 程序员工作法》。这个名字也不错,因为在我看来,很多程序员做的是负功,比如,写那60%代码的程序员。只要能做到有效工作,效率自然会高出业界平均水平很多。
怎么才能有效工作呢?我在专栏中已经给你讲了很多,小结一下就是:
拓展自己的上下文,看到真正的目标,更好地对准靶子,比如,多了解用户,才不至于做错了方向;站在公司的层面上,才知道哪个任务优先级更高;站在行业的角度,而不局限于只在公司内成为高手,等等。
去掉不必要的内容,减少浪费,比如,花时间分析需求,不做非必要的功能;花时间做好领域设计,别围着特定技术打转;花时间做好自动化,把精力集中在编码上,等等。
要想有效工作,有两点非常重要。一方面,意识上要注意自己工作中无效的部分。这就像一个开关,拨过去就好了。所以,读这个专栏,有人常有恍然大悟的感觉,也有人觉得很简单。
很多时候,你只是不知道,就像我在专栏中提到,要问产品经理问题,这是很多人没想过的。每篇文章后面的那一句总结,就是这样的开关,拨过去就好。
另一方面,要构建自己关于软件开发的知识体系,这是要花时间积累的。
在这个专栏中,我给你讲了很多最佳实践,就是让你知道,在某些方面,有人已经做得很好了,花时间学习,比自己从头摸索好很多。
这就像所有的数学公式一样,理论上你都可以自行推导,但肯定不如从教科书上学得快。
藏经阁目录
虽然我讲了这么多内容,但实际上,因为篇幅的关系,这只是冰山一角。
其实,我给你讲的这部分内容并不是具体的知识,而是告诉了你哪些东西要去学习,给了你一张学习地图,把各种知识贯串了起来。
我曾与朋友打趣道,我的专栏实际上是藏经阁的目录,真正的经书还要等你自己去参悟。只不过,有一个人把这些经书之间的知识连接给你补齐了。这些连接恰恰是在学习相关内容时,让我苦思冥想许久的。
大约一年前(2018年4月),极客时间编辑找到我,问我是否有兴趣在极客时间开个专栏,作为“得到”重度用户的我,一直对知识服务很感兴趣。有这样的机会让我体验,我当然想试试,甚至最初给自己定下了写100篇的宏伟计划。
真正开始写,我才知道,在繁忙的日常工作之余,坚持写作还是一件很有挑战的事,今天看来,100篇的目标显得那么无知无畏。
不过,也正是因为压缩到一半左右的篇幅,在专栏后面的部分,我才极大地提高了知识密度,比如,微服务和DDD,这两个可以分别写成一个系列内容的话题,我用一篇文章就将其精华和知识脉络提炼呈现了出来。
因为我想尽我所能,帮助大家构建起一个软件开发的知识体系,让你在未来遇到问题时,知道可以在哪个方面进一步加强。希望这个专栏真的起到帮你理清思路,答疑解惑的作用。
还记得我在开篇词中的最后一段话吗?
也许在这个专栏的最后,你发现自己并不认同我的原则,却能够用自己的原则来与我探讨,那么,恭喜你,因为那是最美妙的事情!
不知道你是否形成了自己的原则呢?欢迎与大家分享。因为它代表着你已经形成了自己的知识体系。与我讲了些什么相比,你学到了什么才是一件更重要的事。
希望在学习了这个专栏之后,你可以用自己的工作原则做更多本质复杂度的事情,减少无意义的时间消耗。
其实,这个专栏的最大收益人是我自己,感谢这次的专栏之旅,我终于强行治疗了我的拖延症,把自己对于有效工作的思考完整地整理了出来,那些在脑子里模糊的印象现在终于有了一个完整的体系。这个体系就是我在专栏里提到的工作原则,现在我可以更好地表达自己的想法了。
不过,这个专栏对我而言也是有遗憾的。因为我想表达的内容很多,给大家打开更多大门的同时,也给很多同学留下了更多的疑问。
有些同学期待在某个方面再深入细节地讲一下,比如,DDD,那可是值得再写一个专栏的主题。限于这个专栏的主题和篇幅关系,我没办法深入展开,只能对大家说声抱歉了。
如果以后有机会,我会再来与你分享我对软件开发的理解,这次的《10x程序员工作法》之旅就暂告一段落了!
再见!
参考资料
http://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/10x%e7%a8%8b%e5%ba%8f%e5%91%98%e5%b7%a5%e4%bd%9c%e6%b3%95/%e7%ad%94%e7%96%91%e8%a7%a3%e6%83%91%20%e5%a6%82%e4%bd%95%e5%88%86%e8%a7%a3%e4%b8%80%e4%b8%aa%e4%bd%a0%e4%b8%8d%e4%ba%86%e8%a7%a3%e7%9a%84%e6%8a%80%e6%9c%af%e4%bb%bb%e5%8a%a1%ef%bc%9f.md