程序员入行的思考 ¶
无论是开启一项新的健身教程,还是着手开始马拉松训练,乃至于写书、创业,以及更具体的编程,阻拦你成为你想成为的样子的最大障碍也是“如何起步”。这一点在全球范围内都是共通的,但在国内,可能还叠加了“35岁危机”的焦虑、对“内卷”的担忧以及快速变化的技术环境带来的不确定性。
思考永远要比实际迈出去哪怕一步都要简单,无休止的争论应该采取什么步骤也要比实际行动容易。但是,秘诀就是,你需要亦步亦趋、循序渐进。在国内大环境下,行动力尤为重要,因为市场和技术迭代速度极快,一个想法犹豫半年,可能风口就已过去,或者竞争已成红海。
如果你真的想改变自己的行为,把那些优良原则和最佳实践应用在自己的生活当中,最好的一种方法就是反复阅读,让你的大脑包裹与萦绕在你想要融入生活的思想与观念之中。在国内大环境下,这意味着不仅要阅读经典技术文档,也要持续关注如“掘金”、“InfoQ”、“开源中国”等本土技术社区的前沿文章和深度讨论,形成符合国内技术生态的思维模式。
入行程序员可以有两种途径,一种是参加大学体系化教育,另一种是参加培训班。
如果你不确定自己是一个可以自我激励的人,或者你是在前途不明的时候缺乏行动力与决断力的人,那么,大学体系化的教育方式可能更适合你。虽然大学不太可能教你现今作为软件开发者需要具备的实用知识(国内大学课程与工业界脱节的问题可能更为突出),但大多数学位课程都会带给你更深入的计算机科学概念的知识(如数据结构、算法、计算机组成原理、操作系统、计算机网络等),而当你进入更复杂的编程场景(如面试大型互联网公司的算法轮、处理高性能高并发问题)时,这些知识会非常有用。大学能够提供实习机会以及其他资源与联系(如校招,这是进入许多大厂的黄金通道),这些往往是你凭一己之力无法得到的。但是,大学里面所教授的内容,经常与现实世界中正在发生的软件开发工作脱节。
市场上也有很多强化编程培训班(国内称之为“IT培训”或“编程培训班”,如黑马程序员等,以及众多线上培训班)。这种培训班倾向于聚焦在如何开发软件上(快速上手Spring Boot、Vue等流行框架),而不是它背后的原因或科学理论,所以可能会给你留下一些知识上的空白(知其然不知其所以然,基础不牢,后期发展容易遇到瓶颈)。和一群目标相同的同学在一起学习时你会动力十足(称之为“学习氛围”),而且你能得到的灵感要比从自己阅读一本书或者观看一段视频得到的更直接(同学间的交流和比拼、老师的督促,符合常见的学习模式)。
如果你打算花费时间、金钱和精力去参加一个编程培训班,需要做好下面的一些准备:
- 国内培训班多以就业为导向,节奏通常非常快,强度大,需要做好心理和身体准备。
- 把所有其他的事情都从你的时间表中清除掉,全身心地投入训练营中。
- 确保你是班上最顶尖的学生,积极表现、多问问题、多参与项目,往往能获得老师更多的关注和资源倾斜。
- 制定一份是你确实花时间经过深思熟虑而成的切实可行的计划。计划不会是完美的,一定要在执行计划的过程中不断修正它,不要随心所欲。
- 设定时间表,并且遵照时间表坚持实施。对任何领域而言,累积效应都是最有力的影响。
- 拓展人脉。在找工作的时候,有人能帮你,也就是我们平常说的“内推”。培训班积累的同学、老师人脉,是获取第一份工作内推机会的重要来源。
- 找一位可以依赖的导师,在你感到迷茫的时候,可以帮助你厘清方向,重建信心。同样,你也可以用类似的方法帮助他人。
- 至少完成一个兼职项目,以检验所学的知识。这个项目最好能部署到国内的云服务器如阿里云、腾讯云上,并且有一个可访问的地址,这在面试时是巨大的加分项。
在软件开发的世界里,自学成才的程序员是特立独行的稀有动物。很多急功近利的软件开发者都在自学成才的道路上苦苦挣扎,屡受挫折。在国内,由B站、慕课网、掘金等平台提供了海量免费优质教程,自学成才的路径比以往更加清晰,但对个人的自律性、信息筛选和整合能力要求极高。
自我教育是我们最有价值的技能之一,这不仅是在计算机领域,在日常生活当中也是如此。但自学的缺点是,对学习方向不一定能正确做出判断,遇到问题容易放弃,学习的内容可能不全面。技术热点变化快,自学时需要警惕盲目追逐新框架,而应注重底层原理和通用能力的培养。
永远记住,学习是你自己的责任。不要为了通过考试而读书、做作业(国内教育体系下容易养成的习惯),而要尽可能多地学习与应用你学到的东西,这就是现实生活中的运作机制。不是有人会“教”你做什么,而是你自己要去“学”什么。在国内的职场环境中,主动学习和解决问题的能力尤为被看重。
1.如何入行 ¶
从一个开源项目开始,克隆到本地,修改、调试,不断阅读代码并试错。直接动手做要比捧起一本教科书、走进大学或者参加编程训练营都要重要得多。可以从参与一些有中文文档和社区支持的开源项目开始,例如Apache的国产项目、或是Vue、Element UI等在国内广泛应用的项目的中文版本维护,甚至是参与翻译、提交Issue和PR,这都是极好的起点。“千里之行,始于足下”,这才是踏上编程之路的正确方式。
学习编程与开启软件开发的职业生涯是截然不同的两件事情。软件开发远不止编程。编程是其中的一个重要部分,但是如果只知道如何编程,你不会走得很远,尤其是当你想在这个领域中脱颖而出的话。软技能(沟通、协作、项目管理)、业务理解能力、以及应对“996”工作模式的心理承受能力同样重要。
理解问题 ¶
软件开发的过程往往都是从对问题的透彻理解开始的。也就是,你需要自动化些什么?这个过程可以很简单,只需要与潜在客户(或产品经理、业务方)交流一下,了解需求。需求沟通可能更频繁、更直接,也可能更模糊,需要开发者有更强的主动澄清和挖掘需求的能力。
程序设计 ¶
只有理解了问题之后,你才可以构想出设计方法,也就是,问题如何以代码的方式来解决。
尽管敏捷开发的重点在于“轻前期设计”,但是设计仍然是必不可少的。想要盖好了一幢房子,你可不能把标准板材随心所欲地堆在一起就算了事。国内项目往往追求快,但良好的架构设计能避免后期无尽的“填坑”。学习一些符合国内实践的设计模式、架构思想(如阿里中间件团队提出的一些理念)是必要的。
编写和调试代码 ¶
软件设计之后,可以编写一些测试用例来定义软件应该做什么(称为测试驱动开发,即TDD),也可以着手开始编码。TDD在国内的普及度可能不如国外,但单元测试的重要性日益凸显,尤其是在大型互联网公司。
作为一个开发者,你大量的时间都将用于发掘你写的(或者别人写的)代码为什么不能正常工作的原因。熟练掌握一些流行的调试工具能极大提升效率。
代码测试和部署 ¶
代码一旦被写出来,接下来应该是测试代码的过程。同样,不同的测试方法实施的测试过程也不尽相同。
代码只有在经过了测试之后,才可以部署,这本身就是一个完整的过程。目前DevOps、持续集成/持续部署(CI/CD)发展迅速,熟悉Jenkins、GitLab CI/CD或国内云厂商提供的配套工具(如阿里云效、腾讯CODING)是重要的技能。
2.如何计划 ¶
为了避免从畏惧开始的极端转向随心所欲的另一个极端,你需要有一个计划,一份真刀真枪、切实可行的、言简意赅的计划,一份规划你怎样从一个对软件开发一无所知的小白成长为一名具备市场竞争力的软件开发者的计划。计划需要务实,紧密围绕市场需求和个人目标(如进大厂、进外企、加入创业公司、或是自由职业)。
第一,问自己:你想做哪种类型的软件开发工作?
在软件开发这一行,有很多的职业发展通道和技术专长领域,你大可以选择其中的一部分作为自己的主攻方向。国内目前热门的方向包括但不限于:
- Web前端开发 (Vue/React/小程序/跨端)
- 后端开发 (Java/Go/Python/PHP,微服务、高并发)
- 移动端开发 (Android/iOS/Flutter/RN)
- 人工智能/机器学习/数据科学 (Python)
- 云计算/DevOps/ SRE
- 嵌入式开发/IoT
太多的人终其一生都会沿着一个方向执着前行,却不会在发轫之始就去深思熟虑以谋定而动。花一些时间回答这些问题,这样你才可以在策马扬鞭走上这条职业之路时计划周全。在国内,也需要考虑不同方向的城市聚集效应(如AI/尖端技术在北京上海深圳机会更多)、薪资水平、以及长期的职业天花板。
三思之后,着手做一些调研工作。只要你的问题正确,答案也不难找到。多利用国内的招聘平台(BOSS直聘、猎聘)、牛客网、脉脉等了解市场行情和技能要求。
第二,制订计划。
制订计划的最好方式就是 以终为始,从想要达成的目标开始一步一步倒着排。你必须要制订一个具体的目标——你想成为哪种软件开发者,而不是像“学习编程”或者“成为一名软件开发者”这样泛泛的说法。
计划的内容必须尽可能具体,这样你才会了解你需要学习什么,你该如何制作简历,你应该报名参加哪种学校或者培训课程,甚至你需要申请哪些职位。
例如,如何成为一名运动员。这是一个相当宽泛的问题。你应该成为怎样的一名运动员呢?也许你应该练练举重和跑步,也许你应该练习游泳,或者也许你应该练习打网球。那你能不能把所有这些事情都做了,以便为成为一名全能运动员做准备,在任何一支队伍里都可以出色发挥。这想法听起来很不现实。事实上,当一个人许愿说“我想成为一名软件开发者”时,听起来也是同样的不现实。一旦你了解了一项运动,你就知道为了那项运动该如何训练自己。
比如,我们的目标是成为国内电商领域的Java后端开发工程师,那我们可以制定下面的学习计划:
- 学习Java SE基础知识(面向对象、集合、IO、多线程)。
- 学习Java Web基础(Servlet/JSP、Tomcat)。
- 学习主流框架(Spring、Spring MVC、MyBatis -> 重点学习Spring Boot、Spring Cloud)。
- 学习数据库(MySQL基础、SQL优化、Redis)。
- 学习常用中间件(消息队列如RocketMQ/Kafka,Elasticsearch)。
- 学习版本控制Git。
- 学习Linux基本操作和常用命令。
- 学习计算机网络和HTTP协议。
- 了解分布式、微服务概念及相关技术(Dubbo/Spring Cloud Alibaba)。
- 学习设计模式。
- 刷题(LeetCode中文站、牛客网)准备算法面试。
- 做一个完整的项目(例如模仿一个简易电商系统),并部署到云服务器。
以及对应的就业准备:
- 搜索目标城市(如杭州、北京、深圳)招聘Java开发者的JD,提炼共性要求。
- 列出心仪的公司名单(如阿里、京东、拼多多、以及各类中小型电商公司)。
- 完善GitHub和博客(如CSDN、掘金、知乎),展示学习过程和项目。
- 准备简历,突出项目经验和技术栈,量化成果。
- 开始在脉脉、牛客网等渠道拓展人脉,寻求内推机会。
- 投递简历,初期可海投,后期针对意向公司重点准备。
- 每天安排时间刷题和复习知识点。
- 每次面试后复盘,记录问题,查漏补缺。
3.必备技术技能 ¶
深入学习一门编程语言 ¶
如果你不会写代码,不能开发软件,那么你学到的所有的软技能对你而言都是“屠龙之技”。也许你会成为一个好经理、好教练,但不会成为一名软件开发者。
选择到底该学习哪一门编程语言其实并不像你想象中那么重要。但建议从学习“一门”编程语言开始,而不是试图学习每一门编程语言。因为学习很多编程语言这只会导致混乱,让你将本应用于学习其他技术技能的精力耗散殆尽。 通过聚焦,你不仅会专注于你现在必须学习的东西,而且会让自己在某一特定技术中获得更深层次的知识和能力,这会使你信心倍增,并大大提高你在这项技能上的市场竞争力,我们才有信心地说“我具备用这门语言编写代码的能力。”
许多编程语言的内核其实是很类似的。学习第一门编程语言总是最艰难的。一旦你学会了一门编程语言,学习第二门语言就容易多了,其他各种编程语言学起来都易如反掌。许多开发岗位,尤其是在如阿里、腾讯、字节这样的大公司,并不需要你懂特定的编程语言(但通常会有一个主流语言偏好,如Java/Go/C++/Python),更看重基础知识和解决问题的能力。
选择编程语言,考虑几个要素。
- 第一,这门语言的就业前景。在国内,Java后端、前端(JavaScript/TypeScript)、Python(数据/AI/后端)、Go(后端/云计算)的需求量较大。
- 第二,这门语言未来的应用前景。当然,你永远无法预测未来。
- 第三,你对哪种技术更感兴趣。因为你在学习第一门编程语言时很可能是步履维艰,因此,你对所学的东西越感兴趣,你就越容易坚持下去。
- 第四,这门语言的难度级别。比如,C++语言比较难,会让初学者容易放弃。对于想快速入行就业的人,Python或前端可能入门相对更友好。
在学习语言过程中,有一点非常重要的:搞清楚哪些是实际语言的一部分,哪些是经常与该语言一起使用的库的一部分。实际语言的部分本身并不大,而且相对容易学习,但是标准库却是非常庞大的,对于标准库,你的重点是学习如何查找库来完成你想要用编程语言完成的常见任务。例如,学习Python,要分清Python语法本身和NumPy/Pandas/Requests这些第三方库的区别。
在学习语言过程中,先从“是什么”开始学习,然后再理解“为什么”。理解程序里的每一行代码或者函数里的每一行代码的原因和方式,虽然很难很枯燥,但是值得的,在这个阶段,“为什么”不那么重要。。
在学习一门编程语言过程当中,需要了解如何正确地结构化你的代码。“结构化代码”就是编写优质的、整洁的、不需要太多注释就能理解的通俗易懂的代码,因为代码本身是用于沟通的。很多人都依此来评价一名软件开发者的技能高低和竞争力强弱。良好的代码结构体现了一个人对技术的奉献精神,而不是敷衍了事。这背后代表着态度。
即使你是一个初学者,只要你能写出优质、整洁、简洁、易懂的代码来表达它的结构、它的含义,那么任何一个看到你的代码的面试官都会认为你是一位有经验的专业人士。
在软件开发中,以“对象”的方法来思考将有助于我们定义和设计复杂的系统,我们会把一个系统看作是一群相互作用的组件,而不是试图从整体上处理这个复杂的组合体。
在计算机科学领域有很多这种算法,了解如何根据这些算法来编写自己的程序以解决实际问题是非常重要的,特别是当问题非常棘手的时候。如果你对各类算法做不到融会贯通,你就无法知晓其实优雅的解决方案早已比比皆是。因此,算法就是一项价值千金的技能。算法学习最初你肯定会觉得非常困难,没关系,只要持之以恒、坚持不懈就好了。参考高手们地解决方案,也是一个非常有效的方法,受益不浅。在国内,算法能力是进入一线互联网公司的“敲门砖”,LeetCode、牛客网等平台是必备的练习场。
具备一个开发平台经验 ¶
你应该至少具备一个开发平台的相关经验,并精通与之相关的技术或者框架。这里的“平台”指的是操作系统(OS),但它也可以指代其他类似于操作系统的抽象。例如,Linux开发者,Mac开发者,前者专注于Linux操作系统,后者则专注于Mac操作系统。在国内的后端开发和运维领域,Linux是绝对的主流,必须熟练掌握。
与选哪一门编程语言类似,该选哪种平台其实无关紧要,重要的是你必须得选一种。选择哪种编程语言与选择哪种平台没有强关联。比如,C++语言,C++开发者可以为Windows也可以为Mac、Linux甚至是嵌入式系统开发程序。
学习一种框架 ¶
库(Library)是一系列预先编写好的代码集合,供开发者在编程中调用,大大减少重复工作量。程序员第一次输出hello world用的printf就来自C语言标准库;各种SDK都是库,自己写一个字符串处理函数,包装好之后调用,也是库。
框架就是一系列用于在特定平台上或跨多个平台上编写的库。通常,框架可以使在该平台上的一般性编程任务变得更容易。框架的最大特征是它会接管程序的主控制流,开发者只需编写业务逻辑代码,具体执行工作由框架来调用。实践中经常会用到控制反转(IoC)以及模板类继承等方式。比如用Spring开发Web项目,你只需编写Controller和配置文件。具体到项目如何启动、如何监听端口、每一次网络请求的响应处理,这些都由框架来实现。在Java生态中,Spring Boot/Cloud是事实上的标准,必须掌握。前端则集中在Vue和React。
学习数据库基础知识 ¶
在软件开发中,数据库通常用来存储应用程序的数据。虽然有专职的数据库开发者或者数据库管理员(DBA),但作为程序员仍然需要了解数据库基础知识,比如:
- 数据库如何运行
- 如何查询、插入、更新,和删除数据
- 如何连接数据集
- SQL优化(面试常考)
- 索引原理
- 事务和隔离级别
- 国内常用的数据库:MySQL、PostgreSQL、Redis、MongoDB等。
熟悉如何进行源代码控制 ¶
源代码控制是任何一个软件开发项目的必要组成部分。几乎所有的专业开发者都应该知道如何使用源代码控制来签入(check-in)和签出(check-out)代码,并且能够合并来自多个源代码版本的变更。
所以,你应该熟悉至少一种源代码控制系统,并且熟悉源代码控制的基本概念。Git是全球也是国内绝对的主流,必须熟练掌握其基本工作流(如Git Flow)、常用命令以及平台(如Gitee、码云、或企业自建的GitLab)。
了解代码构建与部署 ¶
现在大多数软件开发项目都会应用某种自动化构建和部署系统。构建系统的最基本作用就是编译所有的源代码,并确保不出现任何编译错误。一个复杂的构建系统还可以运行单元测试用例或用户测试用例,执行针对代码的质量检查,并提供代码库的当前状态报告。部署系统将负责将代码部署到生产环境或者测试环境中。
在通常情况下,创建和维护构建与部署系统这个领域里最热门的话题非DevOps(Developer Operation的简写)莫属。CI/CD工具链(Jenkins, GitLab CI/CD, 云原生时代的ArgoCD等)、容器化技术(Docker)、容器编排(Kubernetes)变得越来越重要。熟悉国内云厂商(阿里云、腾讯云、华为云)的相关DevOps产品也是加分项。
熟悉基本测试方法 ¶
在敏捷模式下,Backlog会包含开发内容和对应的测试任务,软件开发者和测试人员必须更加紧密地合作,或者说开发人员就是测试人员。一个优秀的开发者会在自己测试了自己编写的代码之后才将代码交付给别人。单元测试(JUnit, pytest等)、集成测试、API测试是基础。了解TDD等理念也有帮助。
熟悉代码调试 ¶
新手程序员幻想着每天只写新代码,然而真实的世界不是这样运作的。身为软件开发者,你90%的时间都会消耗在苦苦探究“我的代码为什么不能正常工作”这个问题上。除了IDE调试器,还要学会使用日志分析、网络抓包等各种诊断工具。
了解开发方法论 ¶
目前比较流行的是瀑布式开发和敏捷开发这两种开发方法论。
当一个软件开发团队刚开始编写代码时,大多数情况下都会遵循某种软件开发方法论。不过,不要期望任何一个团队真正遵循他们声称的自己正在使用的软件开发方法。比如,大多数团队都声称他们在使用敏捷方法工作,但实际执行过程中,他们可能遵循的是他们认为的敏捷方法论。
以前软件开发是遵循传统的瀑布式进行的。顾名思义,瀑布式开发就是一步一步地构建软件,每一步都把软件开发过程带入下一个步骤,直到所有的东西都顺流而下、按部就班地完成。
构成瀑布式开发方法的就是软件开发生命周期(Software Development Lifecycle,SDLC)。每一种软件开发方法都有各自的SDLC作为自己的表达方式。在瀑布式开发中,SDLC是顺序的,是一个从需求分析到软件设计,再到实现、测试、部署,最后到维护这样的一个顺序执行的软件开发过程。每一个阶段你都在前进,你只能前进,永远不会后退。各个阶段之间可能会有一些重叠。
传统的瀑布式:
- 需求分析。这个阶段会收集软件的所有需求,即,软件应该干什么,应该具备什么特性,应该是什么样子的,它的行为应该是怎样的?然而,现实并非如此。
- 软件设计。在这个阶段,你在接受了需求之后会将它们转换成系统的架构设计、底层算法和UML图,确定将如何构建系统,并且让系统的各个部分协同工作。通常会有大量的所谓前期设计工作,这意味着软件的大部分细节在这个阶段都将被规划出来,直至非常底层的设计工作。然而,在现实中需求是会变化的,有太多不可预见而又无法避免的意外状况。
- 实施。这一阶段就是用来编写代码的。
- 测试。在这个阶段,测试人员运行测试,发现bug,你尽自己所能修复一批bug.
- 部署。首先是“集成”,将多个开发组件捆绑在一起,然后是将代码部署到服务器上,最终交付到客户手里。
- 维护。在维护阶段,你需要修复客户发现的错误,添加新功能,并且保障软件的一切功能都顺利运行。
在软件开发方面,敏捷的出现,确实极大地改变了游戏规则。
敏捷宣言:我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下价值观:
- 个体和互动**高于**流程和工具
- 工作的软件**高于**详尽的文档
- 客户合作**高于**合同谈判
- 响应变化**高于**遵循计划
也就是说,固然右列各项有其价值,但我们更重视左列各项的价值。
敏捷宣言遵循的十二条原则:(这些原则精准地阐释了敏捷的真正意义,甚至超过了宣言本身。)
- 我们最重要的目标是通过持续不断地及早交付有价值的软件使客户满意。
- 欣然面对需求变化,即使在开发后期也一样。善于掌控变化,帮助客户获得竞争优势。
- 频繁地交付可工作的软件,相隔几星期或一两个月,倾向于采取较短的周期。
- 业务人员和开发人员必须相互合作,项目中的每一天都不例外。
- 激发个体的斗志,以他们为核心搭建项目。提供他们所需的环境和支持,相信他们能够达成目标。
- 不论团队内外,传递信息效果最好效率也最高的方式是面对面的交谈。
- 可工作的软件是进度的首要度量标准。
- 敏捷过程倡导可持续开发。发起人、开发者和用户要能够共同维持其步调稳定延续。
- 对技术精益求精,对设计不断完善,将提高敏捷能力。
- 以简洁为本,极力减少不必要工作量。
- 最好的架构、需求和设计出自于自组织的团队。
- 团队定期地反思如何能提高成效,并依此调整团队的行为。
敏捷并不是一种真正的方法论,而是在更抽象的层次上定义了软件开发应该如何完成,就像其他可以被认为属于“敏捷方法”的方法的超集。
瀑布式方法面临的问题:需求变更,或者说,直到项目后期才知道需求有变化。
敏捷就是要承认这个事实并且接受这个事实,构建与这个约束条件和谐相处的软件开发过程,而不是尽量规避它。
现实中,虽然大多数团队都声称自己遵循敏捷的开发方法,他们只是在名义上遵循这些方法,实际所做的其实都是“类敏捷”的开发方法。
基于敏捷,下面是几个常用的开发方法:
- Scrum
- Kanban(看板)
- eXtreme Programming(XP,极限编程)
首先,我们看Scrum方法。
Scrum本身是由Ken Schwaber和Jeff Sutherland在20世纪90年代初同时创建的。在1995年,他们合著了一篇联合论文,合并了他俩各自的方法,定义了Scrum方法。
Scrum是一种形式化、规则化的方法,它定义了软件开发团队中的具体角色、开发软件的工作流,以及在开发每一次迭代(也被称为sprint)中应该召开怎样特定的会议。
1.Scrum中的角色
Scrum方法中有三个主要角色。
首先,产品负责人(Product Owner,PO)充当客户的代言人,他将最终决定工作任务的优先次序,并与业务人员、客户以及其他利益相关人进行沟通。
其次,开发团队不仅编写代码,而且要执行分析、设计、测试以及所有与交付软件相关的其他任务。
最后,Scrum专家(Scrum Master,SM)充当团队的教练,帮助消除任何阻碍团队发展的障碍,与产品负责人沟通,推进Scrum过程。
2.Scrum是如何运转的
Scrum背后的基本思想就是,软件开发被分解成若干个更小的迭代称作Sprint,每一个Sprint由一组锁定在那个时间框架内必须完成的工作组成。
然后,在每个Sprint结束时,其结果增量地交付给客户。
需要为软件开发的所有功能都被合并到一个所谓的产品待办事项清单中。(基本上它与系统的需求类似。)产品待办事项是按优先级别排列的,在每一个Sprint周期内,都会从产品待办事项清单中提取一组待办事项从而创建该Sprint的待办事项清单,以定义在该Sprint过程中工作任务,每一个Sprint通常持续一两个星期。
在每个Sprint开始时,将举行计划会议,把产品待办事项中的一部分工作拉到当前的Sprint中,团队估算出完成这些任务所需的工作量。
从技术上讲,团队应该致力于在Sprint过程中完成列举在Sprint待办事项中的所有工作,但实践中很少会出现这样的情况。(承诺是困难的。)
每天都会有一个叫作Scrum的快速站立式会议,每个人在会上都要给出非常快速的报告。Scrum会议的理念是让每个人都了解进展状况,排除可能会延缓进度的任何障碍。
Scrum会议每天在同一时间同一地点举行,每一名团队成员需要回答三个问题:
- 昨天你做了什么,有帮助团队达成Sprint目标吗?
- 你今天会做哪些帮助团队达成Sprint目标的工作?(这个问题对于寻求个人承诺是非常有效的)
- 是否有任何障碍阻碍你或团队达成Sprint目标?
在Sprint期间,团队合作完成Sprint中的所有待办事项,并且使用燃尽图(Burndown Chart)跟踪团队完成待办事项的进度和速度。燃尽图跟踪剩余的时间、故事点、困难点,以及任何被用于跟踪本Sprint中剩余的工作的表征方法。
当Sprint结束时,在Sprint期间完成的功能被展示给利益相关人,实施评审的工作。
最后,要召开一个回顾性会议,团队需要反思已经完成的这个Sprint,并为如何改进下一个Sprint发表一些想法。
3.Scrum的问题
当Scrum被正确执行时,它是一种极其有效和有价值的软件开发方法。在现实中,Scrum往往并没有被严格地遵循,而且,为了弥补过错,人们也会做出许多让步,甚至给一些人带来了可乘之机。
Scrum团队之所以取得应有的成功,最大的原因就是承诺。导致Scrum不能成功实施的最大杀手就是缺乏承诺,包括团队层面的承诺以及个人层面的承诺。
如果一切都能按照计划按部就班地顺利执行,那么把待办事项拉进Sprint里就是举手之劳,获取承诺也很容易。但要真正做到这一点实际上难度很大。
没有承诺的概念,问责制的标准就会下降,Sprint就失去了其本质意义。
被拉入Sprint的工作任务就失去了可信度。这就像你创建了一个“每天必做事务清单”,然而大多数情况下你都没能完成这个清单。随着时间的推移,这个清单本身将变得毫无意义,你甚至怀疑为什么你要列出这样一份清单。
我们来看看Scrum的变体,暂且称为Scrumbut。
当一个团队说“我们正在实施Scrum”的时候,通常会有长时间的停顿与迟疑,然后他们再加上一个“但是”(but),然后再给出一串长长的例外列表,说明他们的哪些做法没有遵循Scrum过程,这就是Scrumbut。而且,他们一般还会给出各种各样的冠冕堂皇的借口,说明他们为什么要按照自己的方式行事而不是亦步亦趋地追随那个Scrum过程。
Scrumbut最大的问题就是巧妙地躲避了Scrum过程中令人痛苦的步骤,然而正是这些痛苦的步骤,才是Scrum成为有效的重点。打个比方,你在煤气灶上煮东西,你去端锅的时候,把手烫伤了,因为你没有用隔热手套去接触锅的把手。因此你说,我喜欢用炉子做饭,但它太烫手了,以后能不能让我们在炉子上做饭的时候不要使用任何加热的方式。
但遗憾的是,很多实施Scrum的软件开发团队选择的做法是关掉了煤气,然后再去经年累月地探究为什么他们的食物没煮熟。
接下来了解一下看板(Kanban)。看板与Scrum类似,但它是一种定义很松散的方法,它更多的是基于原则而不是基于指导的方法。
看板起源于丰田(Toyota)的生产体系和精益制造。起初,看板是为了在制造业企业内部限制生产工作而创立的,看板会提高效率、降低库存。当应用于软件开发上时,看板方法就主要集中在看板(Kanban Board)上。
看板是一块简单的板子,包含数个列,每一列代表贯穿开发过程的数个工作阶段。看板的基本理念是要把项目中所有正在做的工作可视化,并且对每一次将要完成的工作量总有所限制(称为WIP,Work in Progress,正在处理中的工作),以确定瓶颈、消弭瓶颈。
和Scrum一样,看板也是基于自组织团队的思想。透过公开、可见的看板将工作流程正规化与可视化。看板非常关注通过循环反馈来持续改进的想法。
通常,你可能会看到团队有一些需要完成的待办事项以及工作清单,并且这些工作将被优先处理。然后,团队中的某个人会挑出新的工作,并将其添加到看板上等待完成。随着工作从一个阶段进入另一个阶段,新添加的工作将会全面展开。
最后了解一下极限编程(eXtreme Programming,XP)。
极限编程采纳了当时的许多最佳实践,如单元测试、测试驱动开发、面向对象编程以及“关注优质客户”,并将它们提升到了被一些人称为“极限”的水平。“极限编程”因此而得名。
它的规则性更强,它将软件开发的严谨性与专业精神推向了新的高度。
XP在很大程度上依赖于结对编程的思想,即两个开发者坐在一起,共同完成所有正在创建的代码。XP的目标就是以尽可能简单的方式去设计和实现功能,尽量考虑当前的需求,而不是未来的需求。它的核心思想就是,即使是在更复杂的情况下,代码也可以适时演化,不必试图过早地优化代码或者提供额外的灵活性,因为这种做法通常是以增加复杂度为代价的。
总结:一个特定的方法并不像拥有某种可重复的和可衡量的过程那样重要,因为方法可以不断改进、不断调整。如果你的团队正在实施Scrum并且致力于改进实施Scrum的方法,这是很棒的。但是,如果你的团队从Scrum中汲取一些东西,从看板和XP方法又汲取另一些东西,把它们组合在一起形成自己的过程并且奏效了,这同样也是很棒的。只要有某种过程,关键是已定义并且可重复的过程。可重复的过程比特定的方法更重要。
4.拓展技术技能 ¶
学习一门技术的最好方法不是拿起一本大部头的参考书,一口气从头读到尾,而是需要事半功倍地快速学习、触类旁通地自学。国内技术社区活跃,信息更新快,非常适合这种学习方式。
先确认你想要学习什么,即明确学习的范围。然后搜集学习资源,纵览全局。 聚焦到一个足够小的范围。创建一个系统的而又井然有序的学习计划。 采用“学-做-学”的顺序来学习。通过实践,我们可以自己找到问题、自己解决问题。 最后,把你学到的东西教给别人。把你学到的东西教给谁、怎么教,这些无关紧要。重要的是,你以某种方式重组你头脑中的知识,形成自己的思想,并且拿出来与外界交流,我们学到的东西才可以历久弥坚。在国内技术社区(掘金、CSDN、博客园、知乎、B站)写博客、录视频、回答问题,是“教”的很好方式,也能建立个人品牌。
对大多数的技术技能而言,读读书本文字、看看视频教程这种简单粗糙的方法是不可能学会的,重要的事情说三遍:实践,实践,实践。坚持下去,相信“精诚所至,金石为开”。国内云服务器资源价格相对亲民,为个人实践提供了便利条件。
无论何时,当你尝试要学习一项技术技能时,首先要明确的就是用它将帮助你做什么。如果你对这项技能没有直接的需求,你甚至会质疑“我为什么要学它”。例如,学习Elasticsearch是为了做搜索或日志分析功能,学习RabbitMQ是为了解耦和削峰填谷。
学习过程中需要注意的四个重点:
- 你能用这项技术做什么,否则学习则失焦。
- 如何开始,它是“做”的前奏,能让门槛看起来不是高不可攀。国内很多技术都有“快速开始”或“五分钟入门”的中文教程。
- 二八原则。学习一项技术技能的关键就是识别最有效的20%的内容。一项技术的20%就可以应对80%的工作场景。关注核心概念和常用API,不必求全。
- 阅读那些这项技术技能的专家所撰写的文章。关注国内该技术领域的布道师、知名公司技术博客(如阿里技术、腾讯技术工程等)的文章。
5.是否需要学位 ¶
目前的环境下,没有学位会让你的简历被过滤掉,连被人看到的机会都没有。许多公司,特别是大公司,会根据受教育水平来过滤求职申请。当然,这并不意味着你就不能从这些公司获得工作机会,总有一些例外,但是肯定会难上加难。在国内,学历(尤其是名校背景)的重要性依然显著,是很多大厂的硬性门槛。但对于经验丰富、能力突出的开发者,学历限制会放宽。中小型公司更看重实际技能和项目经验。
在软件开发领域,能力最为重要。与一纸学历证明相比,如果你能写好代码,能解决问题,能证明自己有此能力,你就能走得更远。对于非科班或学历不占优的人,打造一份出色的作品集(GitHub、个人项目、技术博客)是证明能力的关键。
与其他行业相比,软件开发最大的不同就是:该领域总是不断变化。每天都有新的框架和技术问世。在教育机构中培养能适应真实工作环境的软件开发人员几乎是不可能的。等到教材出版、课表排好的时候,很多东西已经改变。现在技术迭代速度尤其快,持续自学能力比一纸文凭更能决定你能走多远。
许多计算机科学课程中包含的算法、操作系统、关系型数据库理论和其他主题都是永恒的。然而,当你坐在办公桌前开始写代码的时候,你极少会用到在学校学到的技能。身为软件开发人员,我们所做的大部分工作,都是如何使用新技术,学会如何用它们完成工作。我们很少需要回溯到计算机科学的本源,然而这并不意味基础的计算机科学教育毫无价值,这能基础知识让你拥有良好的基础,能够让你更深入的理解自己在做什么,以及各种工作原理。国内大厂面试尤其重视这些基础知识的考察,因为它们反映了你的潜力和天花板。
不管你是拥有学位还是拥有经验,都强烈建议你将自己的工作成果总结为作品集。在GitHub/Gitee上创建或者参与一个开源项目。你也可以把自己创建的网站或者应用程序整理出来,带着这些源代码去面试。这是向未来雇主展示能力的好办法,让他了解你具有开发并部署一个完整应用的能力。一个部署在云服务器上、能实际访问的项目,比空谈技术栈更有说服力。