开发编码篇
- 一、软件工程师的核心竞争力
- 1、学习能力
- 2、解决问题的能力
- (1)发现问题
- (2)分析问题
- (1)解决问题
- 3、影响力
- 4、总结
- 二、如何提升软件工程师的核心竞争力
- 1、如何提升学习能力
- 2、如何提高解决问题的能力
- 3、如何提升影响力
- 三、自动化测试
- 1、为什么自动化测试能保障质量
- 2、有哪些类型的自动化测试
- (1)小型测试
- (2)中型测试
- (3)大型测试
- 3、区分测试类型的依据是什么
- 4、怎么写好自动化测试代码
- 5、如何为你的项目实施自动化测试
- (1)选择好自动化测试框架
- (2)在持续集成环境上跑你的自动化测试
- (3)新项目和老项目的不同策略
- 四、源码管理工具
- 1、如何选择合适的源代码管理系统
- 2、如何用好源代码管理工具
- 3、该选择什么样的开发流程
一、软件工程师的核心竞争力
我觉得软件工程师的核心竞争力,不是单一能力的体现,而是几种能力和价值的合集。学习能力、解决问题能力和影响力构成了软件工程师的核心竞争力。
1、学习能力
对于软件工程师来说,最基本的要求是技术和代码。如果你看招聘网站上招聘软件工程师的要求,都需要能掌握一门或者多门编程语言,会熟练使用工具、框架。
因为现在技术更新迭代很快,现在你熟悉的语言或者框架,可能过几年就没有太大的市场了,需要学习新的技术。
因此编程语言、框架、工具,这些都不是软件工程师的核心竞争力,能快速学习掌握编程语言、框架、工具的学习能力才是软件工程师最基础的核心竞争力。
2、解决问题的能力
技术学了是要用才能产生价值的。学的好不代表用的好,所以解决问题的能力很重要。举例就是 Leetcode 上刷题分很高的同学,让他去实现一个需求,代码可能还是会写的一团糟。
我们先看看软件工程师的日常工作,有哪些主要工作以及需要什么样的能力去解决:
- 实现功能需求——需要先分析需求,然后抽象设计,最后实现;
- 修复 Bug——改 Bug 最大的挑战其实是重现问题,也就是发现问题,然后再分析问题,最后解决问题;
- 重构代码、优化性能——对代码重构,优化性能,最难的地方其实在于发现代码问题在哪,发现性能的瓶颈,后面再去寻找解决方案,最后再解决。
也就是说,软件工程师这些日常开发工作的核心还是在发现问题、分析问题和解决问题,这里统称为解决问题的能力。
(1)发现问题
对于一个抽奖系统需求,新手程序员看到的是如何实现功能,而有经验的程序员,会发现可能存在的安全隐患,把可能的安全问题消除掉。这就是发现问题的能力体现。
(2)分析问题
软件工程师经常遇到的一个问题就是生产环境发生故障,新手程序员通过分析也能把问题修复,但修复完了就觉得没事了。而有经验的程序员,会在恢复后还会进一步分析故障产生的深层次原因,以及以后可以怎么预防类似的故障再次发生。
分析问题,不仅是分析表面的问题,还需要去分析问题深层次的原因,以及思考预防同类问题的机制。
(1)解决问题
在发现问题和分析问题后,解决问题相对会容易一些。但有时候明明知道问题在哪,但不知道怎么解决也是很苦恼的事情。
有些问题可以通过搜索来解决,还有的问题通过搜索解决不了的,需要去寻求其他组或者外部专业人士的帮助。就算是问问题这种小事,一样都能体现程序员的水平。
比如有程序员去请教别人问题,但是都没人回复的,并不是没有人愿意帮忙他,而是他基本的问题没有描述清楚,从他的问题很难知道表达的意思和要解决的问题。
这样的发现问题、分析问题和解决问题的能力,就是软件工程师的进阶核心竞争力。
3、影响力
影响力不是一朝一夕能形成的,但却是一个软件工程师最核心的价值体现。
你需要通过一点点技术成长的积累,需要通过一个个成功项目的积累,需要通过一篇篇技术文章分享的积累,需要通过一次次帮助其他人成长的积累。而一旦形成足够的影响力,就会变成软件工程师职场发展最牢固的护城河。
4、总结
所以综合来说,软件工程师最核心的竞争力其实分三层:
- 最底层、最基础的就是学习能力,通过学习能力,快速学习掌握新技术;
- 中间一层就是解决问题的能力,充分利用学到的技术,去发现问题、分析问题和解决问题;
- 最上一层就是影响力,是核心竞争力的综合体现。
学习能力、解决问题能力和影响力一起构成了软件工程师的核心竞争力,就像下面这个金字塔图一样,我称之为软件工程师竞争力金字塔。
但必须要注意,这三层缺一不可,你不能光去追求影响力而不踏踏实实学习和做事,也不能光去做事而不学习。必须要踏实地、一层层地打好基础,这样才能让你的竞争力是持久的,而不是昙花一现。
软件工程师竞争力金字塔的意义
如果你是软件工程师,了解了软件工程师竞争力金字塔,你就可以自下而上,更有针对性地培养、提高软件工程师的核心竞争力。
不是把自己绑死在一门技术或者一个框架上,而是训练自己的学习能力,让自己可以拥有快速学习掌握新技术的能力。
如果你是要招聘优秀的软件工程师,了解了软件工程师竞争力金字塔,你可以自上而下,更容易筛选出来优秀的软件工程师。
首先你可以通过内部推荐,优先找那些口碑好,做事情认真靠谱的软件工程师。然后你可以考察他解决问题的能力。
二、如何提升软件工程师的核心竞争力
1、如何提升学习能力
-
首先需要在一个技术领域深耕
每个人精力其实很有限的,一开始专注在一个技术领域容易在短时间取得成绩,同时也相当于建立起了最初的知识体系。只有一个领域的知识你真正吃透,才能有效地共享到其他领域,构成一个知识领域的森林。
要在某一个领域的技术达到一定深度,通常需要三年以上的时间。当你熬过这个阶段,在一个技术领域取得了一定成就,不仅会收获你的知识树,还能收获技术上的自信,让你有信心在其他技术领域也同样取得成就。 -
然后往相近的领域逐步横向拓展
当在一个技术领域达到一定深度后,可以开始横向扩展。最好是往相近的领域扩展,因为这样你之前的知识有很多是可以共享的,容易快速取得成绩。
2、如何提高解决问题的能力
- 第一步:明确问题
这一步也要透过现象看本质,去明确问题背后是不是还有其他问题。 - 第二步:拆分和定位问题
一个复杂的问题,只有经过拆分,才好找到本质的问题。 - 第三步:提出解决方案并总结
发现并分析完问题后,找到解决方案是容易的,但很有必要总结一下。总结要做的就是两点:- 下次有这种问题怎么解决,是不是可以做的更好?
- 这种问题是不是可以预防?如果可以,应该怎么做?
如果每次解决完问题,你还能提出一个预防问题发生的方案,一定会让大家印象深刻的。
3、如何提升影响力
刻意地去提升自己的影响力,是很多软件工程师忽略去做的事情。但影响力,却是程序员核心竞争力的最顶层,也是一个软件工程师能力的综合体现。
-
在某个领域做出了足够牛的成绩
有些程序员能在某一个技术领域做到一定深度,做出了常人难以达到的成绩,比如说 PHP 开发组核心成员的鸟哥惠新宸,写 Vue 框架的尤雨溪,前端的 Winter。做到他们这样,基本上就不用担心影响力的问题了。
要取得这样的成绩,要实力、要机缘、还要坚持。 -
做事情超出预期
在软件项目中,你作为一个程序员,每个人都会对你有预期。如果你做事情的结果能超出预期,就会让人对你刮目相看,进而会形成口碑。 -
帮助其他人就是在帮助自己
帮助别人、教别人收获最大的恰恰是自己。程序员的经验,很大部分来自于解决问题时积累的经验。你自己在工作中遇到的问题其实是很有限的,但如果帮助其他人解决问题,相当于增加了你解决问题的样本,这些样本能帮助放大你的工作经验。帮助其他人,还是形成影响力最简单有效的途径。 -
分享就是学习和打造影响力
建议大家可以通过分享,在教中学。其实,在分享形式上也可以更多样化,除了写博客还有很多其他方式,比如公司内部的讲座就是很好的分享途径。每一次分享都会帮助我学习巩固很多知识点,也是在帮我打造自己的影响力。
三、自动化测试
1、为什么自动化测试能保障质量
自动化测试是一种使用软件工具和脚本来执行测试任务的测试方法。它使用自动化工具来模拟用户的行为,自动化执行测试用例,比较实际结果与预期结果,并生成测试报告。
自动化测试有一个手工测试没有的优势,那就是可以直接绕过界面,对程序内部的类、函数进行直接测试,如果有一定量的自动化测试代码覆盖,相对来说软件质量是更有保障的。
而且,一旦实现了自动化,每测试一次的成本其实大幅降低了的,几百个测试用例可能几分钟就跑完了。尤其是每次修改完代码,合并到主干之前,把这几百个测试用例跑一遍,可以有效地预防“修复一个 Bug 而产生新 Bug”的情况发生。
但现阶段,自动化测试还是不能完全代替手工测试的,有些测试,自动化测试成本比手工测试成本要高,比如说测试界面布局、颜色等,还是需要一定量的手工测试配合。
2、有哪些类型的自动化测试
在对自动化测试类型的定义方面,Google 将自动化测试分成了三大类:小型测试、中型测试和大型测试,Google是根据数据做出决策来分类,而不仅仅是依靠直觉或无法衡量和评估的内容。
(1)小型测试
小型测试是为了验证一个代码单元的功能,例如针对一个函数或者一个类的测试。我们平时说的单元测试就是一个典型的小型测试。
小型测试的运行,不需要依赖外部。如果有外部服务(比如文件操作、网络服务、数据库等),必须使用一个模拟的外部服务。比如上面例子中我们就使用了 FakeUserDA 这个模拟的数据库访问类,实际上它不会访问真实的数据库。这样可以保证小型测试在很短时间内就可以完成。
(2)中型测试
中型测试是验证两个或多个模块应用之间的交互,通常也叫集成测试。
对于中型测试,可以使用外部服务,可以模拟也可以使用真实的服务。中型测试要不要使用模拟的服务,有个简单的标准,就是看能不能在单机情况下完成集成测试,如果可以就不需要模拟,如果不能,则要模拟避免外部依赖。
(3)大型测试
大型测试则是从较高的层次运行,把系统作为一个整体验证。会验证系统的一个或者所有子系统,从前端一直到后端数据存储。大型测试也叫系统测试或者端对端测试。
对于大型测试,通常会直接使用外部服务。
3、区分测试类型的依据是什么
Google 针对这几种测试类型列了一张表,根据数据给出了明确区分:
结合上面的表格其实就很好区分了:
- 小型测试,没有外部服务的依赖,都是要模拟的;
- 中型测试,所有的测试几乎都不需要依赖其他服务器的资源,如果有涉及其他机器的服务,则本地模拟,这样本机就可以完成测试;
- 大型测试,几乎不模拟,直接访问相关的外部服务。
越是小型测试,执行速度越快,越是大型测试,执行速度越慢。另外越是大型测试,写起来的成本也相应的会更高,所以一般项目中,小型测试最多,中型测试次之,大型测试最少。
4、怎么写好自动化测试代码
很多人认为写自动化测试很复杂,其实测试代码其实写起来不难,包含四部分内容即可:
- 准备,例如创建实例,创建模拟对象;
- 执行要测试的方法,传入要测试的参数;
- 断言就是检查结果对不对,如果不对测试会失败;
- 对数据进行清理,这样不影响下一次测试。
以上是针对写一个自动化测试的代码结构。对于同一个功能,通常需要写几个自动化测试才完整。
一个完整的自动化测试要包括三个部分的测试:
- 验证功能是不是正确
- 覆盖边界条件
- 异常和错误处理
5、如何为你的项目实施自动化测试
(1)选择好自动化测试框架
不同的语言,不同的平台,测试的框架都不一样。通过搜索引擎根据 “你的语言 + 自动测试框架” 的关键字,就能找到很多的结果。
(2)在持续集成环境上跑你的自动化测试
让自动化测试在持续集成上运行非常重要,只有这样才能最大化地发挥自动化测试的作用。
因为持续集成,会强制测试通过才能合并代码,在合并代码之前就能知道测试是不是都通过了,可以帮助程序员获得最直观的反馈,知道哪里可能存在问题,这样才能真正做到防患于未然,把 Bug 杀死在摇篮里。
下图描述的就是自动测试配合持续集成的一个标准流程:
- 在提交代码前,先本地跑一遍单元测试,这个过程很快的,失败了需要继续修改;
- 单元测试成功后就可以提交到源代码管理中心,提交后持续集成服务会自动运行完整的自动化测试,不仅包括小型测试,还有中型测试;
- 通过所有的测试后,就可以合并到主分支,如果失败,需要本地修改后再次提交,直到通过所有的测试为止。
(3)新项目和老项目的不同策略
如果是新项目,那么可以在一开始就保持一定的自动化测试代码的覆盖率,你甚至还可以试试测试驱动(TDD)的开发模式,也就是先写测试代码,再写实现代码,保证测试通过,最后对代码进行重构。
如果是老项目,短期内要让自动化测试代码有覆盖是有难度的,可以先把主要的功能场景的中型测试写起来,这样可以保证这些主要功能不会轻易出问题。后面在维护的过程中:
- 增加新功能的时候,同步对新功能增加自动化测试代码;
- 修复 Bug 的时候,针对 Bug 补写自动化测试代码。
这样一点一点,把自动化测试代码覆盖率加上去。
四、源码管理工具
源代码管理工具在软件项目中已经是标准配置了,几乎每个软件项目都会应用到,可以说是最基础的项目开发工具。选择也很多,可以自己搭建源代码管理服务,也可以直接用网上托管的服务,例如 Github、Gitlab、BitBucket 等。
1、如何选择合适的源代码管理系统
- 自己搭建的好处就是可以有更多的控制,但是需要有自己的服务器,自己搭建环境,还要后续的维护。
- 用网上的托管平台,可以减少运维成本,功能也很强大,但对平台有一定的依赖。
建议是如果项目规模不大,隐私要求不高,完全没必要自己搭建,可以直接选择网上的托管平台。这样可以节约很多时间成本,而且还可以方便和一些第三方服务,例如持续集成等进行整合。
如果希望对源代码管理有更多控制,也能接受运行维护上的投入,就可以选择自己搭建。
自己搭建源代码管理系统
- Git:Git 本身是开源免费的,所以每个人都可以搭建自己的 Git Server。
- Gitlab:Git 自带的 Server 默认是没有 Web 界面进行管理的,只能用命令行操作交互,这在操作上有很多不便利性,尤其是不方便做代码审查,
所以可以安装GitLab 的社区版本,开源免费的,有 Web 操作界面,可以像 GitHub 一样提交 Pull Request,并且和 CI (持续集成)系统例如 GitLab CI、Jenkins 都有很好的集成。 - Gerrit:是由 Google 开发的,用于管理 Google Android 项目源代码的一个系统。它支持 Git 和代码评审。
网上的代码托管平台
- GitHub:现在已经是全球最流行的代码托管平台,功能强大,和第三方服务集成非常好。
GitHub的 Web UI 非常强,尤其是代码浏览和审查,在网站上就可以提交 Pull Request 和进行代码审查。不过 GitHub 不提供 CI 服务,需要和第三方 CI 服务集成。 - Gitlab:Gitlab的网上托管服务很多地方和 GitHub 都很类似,但是价格更便宜,也内置了 CI 的支持。
- Coding:是国内一个不错的代码托管平台,5 人以下的私有库免费,内置了 CI 支持,同时还有项目管理工具支持。
其他的服务还有像:码云、阿里云 Code、百度效率云、腾讯 Git 代码托管、华为云 CodeHub……
2、如何用好源代码管理工具
用好源代码管理工具,有三个简单可行的原则:
- 要频繁的提交
频繁提交,不意味着提交不完整的内容,而是将要提交的内容分拆,并且保证完整性。频繁地提交,也让团队成员可以及时同步最新代码,不至于在最后合并时,产生有大量的合并冲突。 - 每次提交后要跑自动化测试
如果测试不通过就不能合并,要对问题进行甄别和修复,确保提交的代码质量是没问题的。 - 提交的代码要有人审查
代码审查是自动化测试之外,一种非常行之有效的提高质量的手段,通过代码审查,可以发现代码中潜在的问题。
3、该选择什么样的开发流程
现在基于源代码管理有三种主要的开发流程:
- Git flow
- Github flow
- Gitlab flow
GitHub 开发流程:
GitHub 开发流程的关键在于两点:
- 有一个稳定的分支,例如 master;
- 每次创建新功能或者修复 Bug,必须创建一个分支。最后通过代码审查和自动化测试后,才能合并回稳定分支。
具体看看基于 Github flow 是如何开发的:
-
创建一个分支
分支是 Git 中的核心概念,整个 GitHub 流程都是基于分支展开的,master 分支是要一直保持稳定的,不能直接在 master 上开发。 -
提交更新
可以按照前面建议的原则,频繁的提交更新。注意每次提交的时候,要加上说明性的信息,让其他人明确知道你这次提交的内容是什么,如果开发过程中,发现错误了,还可以随时回滚之前的更改。 -
创建一个 Pull Request
在开发完成后,创建一个 Pull Request(合并请求,简称 PR),创建 PR 时,通常要附上描述性的信息,关联上相应的 Ticket 连接,让其他人知道你这个 PR 要完成什么任务。创建好 PR 后,其他人就可以直观的看到你所有的修改。 -
讨论和代码审查
团队的其他人就可以对 PR 中的代码修改进行评论,根据代码审查的结果,你可能要做一些修改,那么只要继续提交更新到这个分支就可以了,提交更新后,PR 就会自动更新,其他人可以基于你的更新进一步的讨论和审查,直到通过代码审查。 -
部署测试
把分支的修改进行测试。理论上来说,需要将修改的内容部署到测试环境测试,但这样效率太低了,所以通常的做法是借助持续集成工具,在每次提交代码后,就运行自动化测试代码,自动化测试代码全部通过后,就可以认为质量是可靠的。
这也意味着你需要让项目中的自动化测试代码保持一定的测试覆盖率,否则质量还是难以保障的。 -
合并
合并后,之前的分支就可以删除,但你之前所有的提交记录在 master 都可以看到,所以完全不用担心丢失历史版本记录。