# 第 1 章 软件开发本质论 关于软件以及软件开发,已经有很多定义、介绍和专业的解说。在进行代码编写前,或者说在正式进入软件开发这一领域前,我们有必要对当前的时代背景,以及软件开发所面临的问题,所应对的解决方案再简单温习一下。 ## 1.1 信息与价值 中学的教科书告诉我们,人类社会分别经历了农业时代和工业时代,而现在正处于信息化时代。 根据全球通史的介绍,人类由于耕种技术的成熟,从游牧狩猎进入了农业时代,定期收割的大量食物保障了人们不受饥饿而迎来了人口的激增。到了工业时代,世界到处是尚未开采的矿石、材料、石油、能源,这时通过蒸气机和电动机等产生的巨大能量,使得这些遍布世界的资源能快速流通,从而造就了人类财富的快速增长,随之而来的则是人们生活水平的又一次极大提升。 如今,信息量以指数级的速度增长,产生了爆炸性的海量数据。曾有数据指出,如今一天的信息量,就远比19世纪80年代华盛顿邮报一年产生的信息还要多。纵使如此,人们还是比以往需要更多的信息。以我母亲为例,自从使用微信后,就每天都在看朋友圈、和亲朋好友发语音、视频聊天,此外还浏览各种新闻资讯信息,学习养生健康知识等。虽然她才刚刚学会使用智能手机不久。这是我们日常生活中的例子,也是作为对信息使用的常见例子。 在现实的物理世界中,有物质守恒和能量守恒定律。作为高中选修物理学科的我相信,同样在虚拟的互联网世界中,也存在着信息守恒定律。即信息不会凭空产生,信息也需要经历产生、收集、处理、传播等一系列操作。通俗来说,信息在被使用前,需要先产生。我们很容易发现身边使用信息的现象,因为我们正处于一个信息无处不在的时代。例如我们可以看到这一周有哪些即将上映的电影,可以在网上进行购物、在线支付,可以使用手机新闻客户端随时查看世界各地发生的奇闻趣事,可以预订下周出国旅游的飞机票,可以通过远程办公处理商业事务。 正如每次社会变革来临一样,总会发生一些巨大的变化。善于观察,敢于冒险和有商业头脑的人,会从这些错综复杂的信息中发现商机,从而创造财富。而作为从事软件开发的技术人员,我们应当从中看到信息处理、加工、传播这一过程背后需要的技术与软件支持。可以说,那些善于使用各种信息资源的百姓,在生活、工作和学习上都会获得极大的便利;那些善于将信息与其他资源整合,并为需要的人提供服务的商人,在财富上会有极大的积累;最后那些善于开发软件,为商业提供信息化技术支持,并能快速响应市场变化,满足客户需求的程序员,将能创造出更大的商业价值,同时实现更大的自我人生价值。 在更短的时间内,通过开发软件,满足人们对信息的最大化需求,从而间接帮助提升人们的工作效率、提高生活水平,将是我们作为软件开发工程师引以为豪的事情。 反过来讲,那些成为行业巨头或者世界500强的公司,很多都是对信息进行了价值最大化处理的公司。例如谷歌为全球提供了非常强大的搜索功能,脸书为十几亿用户提供了交流平台。同样,这条规律也适用于我们程序员个人。个人职位的晋升、所获得的工资收入、在技术上的成长与收获、在行业内的声望和地位,是对我们多年从事信息化工作和科技类工作,或直接或间接的嘉奖。 对于在公司就职的开发人员,如果你觉得是在为上级领导而工作,这是片面的;如果你认为是在为公司而上班,这是不全面的;本质上,我们都是在为了社会,为了与日俱增的信息而工作。 这就是我们所处的大时代,大背景。 ## 1.2 代码,软件和价值 作为一名软件开发人员,我希望可以:**致力于编写容易理解的代码,专注于软件开发领域,努力创造更大的价值**。 ### 1.2.1 编写容易理解的代码 最近比较流行“工匠精神”,搜了一下,百科解释如下: > 工匠精神,是指工匠对自己的产品精雕细琢,精益求精、更完美的精神理念。 在编写代码时,我们也能亲近深切地体会到这一过程里微妙的精神。 对于一个功能的代码集,再到一个函数的代码块,最后到可执行的一行代码甚至是一个变量的命名,我们可以粗糙地实现功能即可,也可以按照良好的设计、遵循统一的代码风格、结合测试驱动开发进行小步重构,还可以再进一步深入思考、探索应用业务领域,从而编写出能够存活很久并仍具有活力的浮现式代码。 可能会有同学觉得,需求总是那么赶,留给开发的时间总是那么少,又要调试,又要修bug,还要开会联调等等,没有那么多时间对所写的每一行代码进行精雕细琢。但是,我们能不能反过来想,会不会是因为我们还没具备比较良好的专业素养和技能,未能在短时间内一步到位交付高质量的代码,才导致需求迭代不够顺畅呢? 现在有多混乱,以后就有多痛苦。 如果说编程是一种艺术,那么在开发项目时,我们应该把项目当作一个艺术品来创作。既然我们开发人员作为软件系统这一艺术品的创造人,那么就应该是由我们来决定何时(当然应该是在合理的排期内)交付产品,而不是迫于需求方的时间压力就随意交付次品。因为根据守恒的定律,研发一个高质量产品所需要的时间是一定的,现在为了赶进度,投入的时间和精力少了,那么日后维护时就需要更大的成本来填补曾经所留下的坑。 那么问题来了,受限于局促的开发时间,又要交付高质量、有价值的产品,我们应该怎么做?参考中学时代的这一公式: ``` 路程 = 速度 * 时间 ``` 我们可以类似得出这样的开发公式: ``` 产品 = 开发速度 * 时间 ``` 所以当所需要的产品功能点和开发时间是固定时,要想在预期的里程碑内按时交付,我们只好提高自身的开发速度了。提高效率其中一个途径就是少返工,一步到位,把所发现的问题以及可预见的问题在开发初期就早早地解决,这些都要求我们能够编写出容易理解的代码。正如托尼·霍尔所说的: > 设计软件有两种方法:一种是简单到明显没有缺陷,另一种复杂到缺陷不那么明显。 尤其是现在,计算机的硬件成本已经越来越廉价,曾经开发者前辈需要排队才能用得上大型计算机,现在随手都是笔记本这些智能移动设备,而且花几十块钱就能租到一台24小时运行的服务器。相比之下,人的成本则越来越高,而且人的工作效率在某种程度上容易受到情绪的影响。只要能通过编译的代码,计算机都可以不断重复完美地精确运行并得到期望的结果,不管代码是汇编写的还是高级语言写的,也不管代码有多么丑陋。但如果开发人员看到难以理解的代码,会大大增加理解成本,而且心情烦躁,产生抵触心理,进而导致开发不顺畅,障碍重重。毕竟,程序员的快乐,更多在于创造,而不是维护历史遗留系统。但如果原来的代码是短而美,那么将会是另一番景象。 作为外行人士,他们可能关注的是产品界面好不好看,交互够不够人性化这些表面的东西,但作为内行,作为开发人员,我们应该关注隐藏在系统背后的代码是否规范,是否能让别人容易理解,是否能够恰到好处地体现所要表达的意思。 不管怎么说,编写容易理解的代码,总是会有好处的。 ### 1.2.2 专注于软件开发领域 我刚毕业时,我的Team Leader兼导师不止一次地告诫我:不要只限于技术。诚然,我觉得程序员所学的东西也不要局于代码,所做的事情也不要局限于编码。作为开发人员,代码是我们和外界交流、交互的媒介,也是我们用于构建有价值服务的基础,但除了关注代码,我们还需要关注软件开发这一领域,还要深入了解探索软件开发的各个方面,才能更有把握交付成熟稳定的系统。 如果想要给家里的花园砌一道墙,那么只需要掌握把一块块砖头和搅拌好的水泥粘合在一起就差不多了,即便不美观,但能够起到防护的功能也算是一道很好的墙。但如果需要建筑的是一个客流量高达成千上万的大型商场,那么除了要掌握砌墙外,还要掌握排水通风、防雷抗震、商场的业务性质、各个店铺的设计等一系列问题,这时就不再是建一道墙那么简单,而是相当于构建一个复杂的系统。 同样,在软件开发中,我们要构建的系统越大、价值越大,就要求我们所要掌握的范围面更广,要考虑的因素就越多。因为这时,软件开发是一门工程,一门需要团队一起交流、协助、共同努力完成既定目标的工程。 专注于软件开发领域,意味要专注于复杂系统、软件工程和跨学科的融合。 ### 1.2.3 创造更大的价值 以前一百万人养活一个君王,现在一个天才就能养活一万多人。 当然,不是每个人都能成为天才,但我们作为软件开发工程师,可以通过软件创造更大的价值。 某种程度上,软件开发也是一种服务,它服务于特定的用户。但不同银行的业务窗口,速度慢而且同一时间一个业务员只能服务于一个客户,相反,我们的软件一旦开发完成发布上线后,就可以同时服务大量的用户,而且还可以是遍布世界各地的用户。可想而知,所能创造的价值有多大。 一个包子做好了,只能给一个人吃(当然也可以分着吃),所以包子铺老板创造的价值,相比之下不会特别大(这里完全没有其他意思,对于辛勤劳动的人民,我总是致于崇高的敬意)。而且,包子铺老板要是哪天休息放徦了,他就没有包子可卖,自然就没有创造新的价值。值得庆幸的是,开发好的软件系统与此不同,软件不仅能同时服务于大量的用户,而且一旦发布上线后,我们就可以抽身继续开发新的软件,不断创造更大的价值。我觉得这是一件很棒的事情! 想一想,如果有成千上万的人们使用我们开发的软件,那是一件多么让人激动的事情。真正让我们兴奋的不是我们所研发的产品出名了,而是我们的产品每天都被人们在生活中不断使用,被依赖,被需要。 我一直认为,开发出来的软件,应该是能够帮人们解决某种问题,如提升工作效率、帮助更好地学习、或是改善生活,而不是给人们带来苦恼,带来压力。我很庆幸我这一生能有机会一直从事我所深爱的职业——软件开发,也非常庆幸我能有创造更大价值的机会。 当然,能力越大,责任越大。 如果处理得不好,我们也会面临项目夭折,或是交付有诸多问题的产品,甚至是系统上线运行后出现故障而导致损失重大。所以,在这里,我希望能通过分享一些自己的经验和总结,帮助更多的同学提升开发效率,了解软件开发这一领域,一起创造更大的价值。 ## 1.3 一行代码值多少钱? 一个问题的意义,不仅在于解决了这个问题,更在于通过这个问题引伸出更多富有意义、更具挑战性的问题。我们将尝试探索“一行代码到底值多少钱”这一问题,进而通过这个问题,引出更多深层次的问题,最后收敛于线上故障。 ### 1.3.1 简单的计算 最简单粗暴但明显是错误的计算,假设一位开发工程师的月薪是1W,按每月22天折算,其工价约为:1RMB/分钟。又假设,写一行代码,平均需要10分钟。 用一张逻辑推断图表示即: ![图像说明文字](http://epub.ituring.com.cn/api/storage/getbykey/screenshow?key=180892cb53ca5849ce2f) 图1-1 一行代码值10 RMB 这是局限于开发人员个体在单纯进行编写一行代码本身所需要的造价,这明显是不全面的,因为还没考虑开发人员在编写这行代码之前进行需求分析、领域模型设计所需要花费的时间,更不用说与其他干系人在项目开发过程中进行的沟通协作成本。 但这很可能正是很多人眼中或潜意识中错误认识的观念:写一行代码不是几分钟的事情吗?由此暗示一行代码低兼的造价。 实际上,真的是这样吗?一行代码,真的只是值10块钱吗? ### 1.3.2 进一步地计算 更为合理地评估一个项目的经费,应该是从完成交付的系统功能点以及开发团队为此付出的精力和时间这两方面进行衡量。如果只是单纯按代码行数来计算,则会导致开发人员本来用一行代码完成的事情分拆成N行,而不是激励程序员编写更短更美更达意的代码。 这样,进一步计算,我们可以把功能点和投入的时间所需要的成本,再平均分摊给每一行,从而也可以得出每一行代码值多少钱。继续用一张逻辑推断图表示即: ![图像说明文字](http://epub.ituring.com.cn/api/storage/getbykey/screenshow?key=1808afccd3daf52567d3) 图1-2 一行代码值55 RMB 这似乎更为合理,因为我们考虑了更多的因素。但,一行代码,真的就只值几十块钱吗? ### 1.3.3 未知的损失 如何计算一行代码到底值多少钱,我觉得,不仅要考虑已知的成本,还应涉及未知的损失。即: ![图像说明文字](http://epub.ituring.com.cn/api/storage/getbykey/screenshow?key=1808a0b34f92b3223942) 图1-3 一行代码值多少钱? 损失即存在的风险,既包括了可预见的风险,还包括了不可预见的风险。而造成的损失则会根据影响的时长、涉及的用户数以及对现实世界造成的损害和为此而付出的代价而定,小则几百,大则上万。况且,还有很多损失的代价是不能直接从经济方面衡量的,甚至是不可逆的惨痛教训,例如对品牌形象的损害。 所以,一行代码值多少钱,不仅要考虑沟通、测试、开发、文档、部署、宣传、维护的成本,还要考虑由于代码问题而损失的代价。 假设某次故障导致的损失为5W,而最终导致故障发生的原因为代码问题,并且假设出错的代码只有一行,那么这行代码则处于关键的位置,并价值甚大。 在我曾任职的公司里,我就因为一行代码造成商品无尺码显示的线上故障,当时由于导致用户无法购买,评估的损失约为数十万。而这次故障正是因为一行代码而导致的! ### 1.3.4 浅谈损失 造成的损失,不仅有因为做错过什么而导致的损失,还有因为没做什么而造成的损失。 + 该做异常处理的却没捕捉导致程序crash异常退出; + 该做超时重试的却没设置导致进程无限等待最终导致服务器内存耗尽; + 该做SQL注入防范的却没转换导致数据库被入侵甚至泄露敏感用户数据,一如账号密码; + 该做负数判断的却没检测导致在金额消费扣除时负负得正,反而钱越花越多。 而这些,对应的解决方案, + 可能需要联系各个渠道重新全量发版以修复用户app崩溃的问题; + 可能需要紧急发布以修复服务器集群运行到一定时间就突然down机的奇怪现象; + 可能需要统一对外公告并告知用户及时修改密码; + 可能需要开发人员不仅要修复上线,还要花好几天的时间排查各个用户的日记,通过grep找出不合法的“充值”纪录然后追踪其消费流水过程,进行相应的处理甚至封号、列入黑名单。 “做错过什么”是不小心而为的,“没做什么”中很多时候明知多做一点就能预防,却因为一时偷懒、侥幸而没做,最终在生产环境被触发,继而放大,酿成故障,实在是不应该。 ### 1.3.5 一行代码的生命历程简史 若把每一行代码都比作是有生命的小个体,我想它终其一生也许会是这样的: 当开发人员按下Enter回车键后,一行由特定的字符排列而成的代码就从混沌中诞生了。当它的“创世者”点击保存后,这一行代码就来到了人世间。那时,一切都还很平静,它既感到好奇又觉得陌生,于是便和身边的小伙伴亲切交流了起来,以便彼此互相认识。随后,开发人员会把它提交到版本控制系统,进入到质量测试环节。 这时,会有一些专门的测试团队会找出编写不合理的代码并反馈给开发进行相应调整。经过多次打磨,在投入到真正的战场前,它还要走过一段漫长的道路,如持续集成、回归测试、灰度发布等。 最后,它们被部署到了最终真正线上的环境,一个更为复杂、严酷、激烈的环境。每时每刻,它们都在 CPU中穿梭运行,每天处理了上百万次的请求,接收/输出上T级的数据,为各种各样的用户提供着有价值的服务。在这些用户中,除了有正常的用户,还有一些恶搞的用户、非人类的用户,诸如:爬虫、机器人、搜索引擎等等。有些用户会尝试从这一行行的代码获取他们需要的业务功能,有些用户则会尝试获取一些更高级但非法的功能,甚至有些不怀好意的用户则试图发现极有破坏性的代码行,然后触发它…… 当它老了,需要退役时,应当能够做到优雅地退出历史舞台而不会给现有的系统造成其他影响,否则会变成熔浆式代码,影响后生的代码。 可以说,每一行代码所处的环境,都是已知的,但又是未知的。 已知是因为我们知道它在那个位置需要担当什么功能,实现什么业务;未知因为没办法完全了解它会面临怎样的系统平台、怎样的数据、以及怎样的用户、怎样的一个处境。 这要求我们在写每一行代码时,不仅需要知道编程语言本身的语法特性,还要了解它的运行机制、原理,还要清楚需要实现的业务功能,还要能考虑到它未来将会运行于怎样的一个场景下,最难得可贵的是,可以深入考虑到它将会面临怎样的重大问题,包括功能性的以及非功能性的。 也就是我们通常所说的可扩展性、安全性、稳定性这些质量属性,正是由这一行行的代码日积月累、聚合而成的。 ### 1.3.6 如何写出好的代码 终其代码的一生,我们需要在一开始就为它将要面临的问题与挑战做好充分的准备。每个问题之所以会发生,都是因为我们想得还不够深入。只要我们再想多一点,就可以避免重大问题的发生。而且,往往我们觉得会有问题发生的可能时,往往都就发生。 何谓好的代码?好的代码,就是一行也不能少,一行也不会多。 好的代码,应该是高度自治的,即它不会以损害其他的代码为代价来完成自己的事情或功能。而是应该本身是健康的,既无腐蚀性,又对系统不具入侵威胁,反而能帮助其他的代码行一起完成重大而严谨的使命任务。同时能适应更多的情境。 反观过往的经验,问题发生的节点更多在于与外部系统的交互上,比如调用了远程的接口而没有设置超时而陷于漫长等待,进行了数据库访问而没考虑到并发量而导致了阻塞,调用了Android的系统API而没进行版本判断而导致崩溃。 出现问题的代码,通常都是脆弱、不规范、有问题的代码。 因为代码的编写原则和规范都有很多相关说明,下面再简单补充一下: + 遵循惯例 + 忠于代码本身 + 功能导向 + 考虑上下文 + 能够适应更多的环境 下面分别说之。 #### 遵循惯例 各个语言都有语法上微妙的容易犯的错误,一如: + 10 Most Common PHP Mistakes + The 9 Most Common Mistakes That Ionic Developers Make #### 忠于代码本身 在编写一行代码时,我们应当理性地进行编写,而不应感性地编写。也就是说,我们应该遵循编码的开发规范、满足项目面临的约束、保持系统架构的风格和原则。再直白一点,这一行代码的结果需要加强判断的则加强判断,这一行代码需要考虑容灾的则添加容灾,这一行代码需要向前兼容的则向前兼容。 而不能因为我本来也知道需要进一步完善的,但因今天心情不好、或因需求频繁变动而有抵触情绪,或抱着可能不会发生的侥幸心理,使得应当加强的没加强,应当容灾的没容灾,应当兼容的没兼容,最终导致线上重大的故障发生。这属于感性编程,而非始终忠于代码本身功能的专业体现。 存在即合理。但我们也可以反过来理解:代码因为合理而存在。不合理的代码,即有缺陷的有bug的代码,最终还是会被修复优化、甚至被移除的。既然,一开始就可以做好的事情,为什么要付出代价后才肯回来弥补呢? #### 功能导向 在我刚毕业时,曾就职于一家游戏公司。当时我很自然地敲出以下操作命令: ``` $ php ./all_in_one.php >> run.log 2>&1 ``` 而站在一旁的一位资深架构师(也是我颇为敬仰的大神)突然问我:你知道这行命令的意思吗?当时,我愣住了。仿佛回到了当年校招面试时被问到了一个完全不懂的问题,一脸不知所措。更为尴尬的是,我一直在使用这样的命令,它每个参数的作用我竟然不知! 所以在写每一行代码时,都需要知道它确切的意思,各个参数的作用,内部的原理,与其他类似接口的微妙关系与区别。需要多想想,多查查,这一行代码是否能很好地胜任我们将要赋予给它的任务?我们需要用它来做什么,我们又不需要它在背后做什么? #### 考虑上下文 **一切不考虑上下文场景的代码,都是耍流氓。** 在一次性能优化中,我们发现有一行代码被调用了17K次!几乎占用了接口响应时间的10%! 绝大多数的情况下,以下这样的写法都是没有问题的: ``` $bufLength = TStringFuncFactory::create()->strlen($this->buf); ``` 而且我们也确实看不出有什么问题。这是一个很好的封装,也使用了工厂方法模式,可以说这是一行很合格且写法清晰的代码。再来看下TStringFuncFactory::create()内部的实现,也是使用了单例模式,没有特殊之外。但令人颇为惊讶的是,在xhprof的报告中,我们发现此函数竟然被调用了17K次! 回顾TStringFuncFactory::create()被调用的场景,我们从图中,可以看出TFramedTransport::read()竟然调用了11,700次!最终优化后,调用次数从17K降到了只有100多次,三个级别的差距!为了有一个更形象的对比,若用米作为单位,试这样粗算对比前后优化的效果: 表1-1 优化前后的调用次数对比 |函数调用次数|等效的长度(单位:米) ---|---|--- 优化前|17K次|相当于田径场跑44圈 优化后|100多次|相当于百米冲刺的距离 优化前,相当于田径场跑44圈;优化后,相当于只有百米冲刺的距离!值得提醒的是,实际的优化效果与接口返回的报文长度成正比。报文长度越大,差距越明显。关于这部分的信息,后面会再来详细讲解。 #### 能够适应更多的环境 软件开发发展至此,已大概有30多年。我们所编写的代码,最终会运行于不同的平台、不同的系统、不同的硬件、还需要配套不同的外部系统或依赖系统,以及各编程语言的支持,而这些平台、系统、硬件、外部系统、编程语言又会分为不同的版本。 这就有点像,一行弱小的代码,被扔进了一个错综复杂的世界,不仅需要满足各个霸主苛刻的要求,还要面对不可预见的未来——因为它不知道将会接收处理怎样的数据。此时,我们应当考虑到代码的健壮性,以便它能适应更残酷的环境。 任何问题,最终都是团队问题,而不是个人问题。正如《清单革命》说道的那样:团队犯错的概率会更低。我们应该充分发挥集体智慧,赋予代码更顽强的生命力,从而适应更苛刻的环境。 代码虽小,影响甚大。 ## 1.4 问题域和解空间 软件行业自诞生以来,就如同一个懵懂的小孩一直在跌跌撞撞,愉快而艰难地成长着。在这过程中,我们遇到了很多前所未有的问题与挑战,也提出了饱含智慧、成熟的解决方案。但依然,形势是严峻的。每天,还是会有很多项目失败在途中,在还没公布于众之前就悄无声息了。每天,依然有各种故障、Bug、漏洞、项目延期等困扰着我们,即便很小的系统也难逃此命运。 为什么会这样呢?为什么在建筑行业随处而立的高楼大厦过了百年仍能稳如泰山,为什么我们一个小小的网站都会问题多多? 是的,软件行业还很年轻。关于行业的标准、规范,我们还没形成共识。从现实世界映射到软件虚拟世界,需要一个建模的过程。对于特定领域业务来说,这个建模的过程可以更方便地在软件开发工程师与领域专家之间建立起沟通的桥梁。单单对于这一领域建模过程,我们也都还未建立起公认的体系,甚至有些专业开发人员都不知道或者认为不需要这一过程。 我个人觉得,在需求现实世界和软件虚拟世界之间进行建模是很有必要的,并且越发倾向和支持问题域和解空间这一说法。 在《领域驱动设计》中,Eric为我们介绍了软件核心复杂性应对之道。他的真知灼见明确告诉了我们如何结合实体、服务和值,以及上下文绑定、释意接口等“大声地”构建领域模型。只有当我们对项目的需求,对系统将要实现的领域业务有深刻的理解和认识后,我们才能更有效地对其进行设计、开发、测试、集成和交付。试想一下,如果客户想要实现的是无人汽车驾驶智能系统,而我们因为误解而最后交付的是二手汽车拍卖平台,那会是怎样一个结果? 在对特定领域进行恰如其分的建模后,我们才能更好地把捏项目的需求,然后进入正确的迭代流程。还是那句话:做正确的事,比把事情做正确更重要。 软件会越来越复杂,越来越庞大。有开发经验的技术人员会很容易发现,开发一个新功能的难度并不在于它的本身,而是在于如何在现有错综复杂的系统中,准确无误地嵌入这个新功能。如果一开始的问题域理解有误,所选择的解空间也就难以与系统本质的领域匹配。这无疑是雪上加霜,偶然的复杂性再加上本质的复杂性。 准确理解问题域后,后面的事情就相对好办了。鉴于各项不断涌出的新技术,以及过往既有的成熟解决方案,我们可以根据项目的特点进行技术选型,构成与问题域对应的解空间。但这个解空间,包含的内容和知识,以及实践、理论、标准非常之多,需要我们投入大量的时间和精力来研究和操作。 就如网站前端开发来说,除了要掌握Javascript、HTML、CSS这些基本的编程技术外,还要了解HTTP/HTTPS协议、CDN加速,不同浏览器的标准、支持度和兼容性,以及H5混合应用开发,打包压缩和构建等等。基本每一个细分的专业岗位,都有一系列完整的学习路线。 你,准备好了吗? ## 1.5 不要急,但要快! 经典武侠小说经常会说道,天下武功,唯快不破。在我们软件开发领域,也有着类似的说法:不要急,但要快! 一个软件产品的生命周期,通常都会比较短,因为产生的软件太多,淘汰率太高。即便是成熟成功的软件系统,也需要不断自我更新,自我变革,否则就会容易被市场淘汰。人们对信息日益增长的需求,加上全球化的影响,如今市场的变化是日新月异,这造成了软件开发需求的频频变更。此外还有政策变化的影响,很有可能,某一天政府出台一条政策,并要求企业对此迅速作出响应和整改。公司则需要找出相关技术负责人进行修改调整,甚至加班加点赶这需求。 不管怎样,不管出于何种原因,我们将要面对的都是变化节奏比以往任何时候都要更快的社会。这势必会要求在互联网行业内的我们,时时刻刻,都要快速响应。需求分析要快,设计要快,开发要快,测试要快,上线要快,修复Bug要快,反馈要快,推广要快! 再说一次:做事情,不要急,但要快! ## 本章小结 信息即价值,信息量越大,蕴藏的价值就越高。软件开发所从事的工作正是通过有效的方式来开采这个信息金矿。为了做正确的事情,我们需要通过领域建模准确理解问题域,然后找到与之匹配的解空间。简单了解一些理论后,接下来让我们进入实战部分。