You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
25 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# “一问一答”第3期 | 18个软件开发常见问题解决策略
你好,我是宝玉。我们专栏已经完成了架构设计和开发这两个模块的学习。这两个模块都是和技术有很大关系,也是很多人关心的内容。
希望你通过对架构设计内容的学习,能控制好软件项目中技术复杂的问题。遇到技术选型,能心中有数,通过一个科学的过程去完成选型;对于项目中的技术债务,能及早识别,及早应对。
通过对开发模块的学习,可以帮助你在项目中搭建持续集成环境,推行自动化测试,改进基于源代码管理工具的开发流程。借助工具和流程,让你项目的开发质量更上一个台阶。
本篇继续分享同学们的精彩留言,这些问答和同学们的分享都是对专栏内容的最好补充,希望可以帮助你更好地学习和理解软件工程知识。
## 一问一答
No.1
**一路向北:**每次看这些架构的思想方法的时候,总是和实际的应用没能很好的结合起来,原因是不是架构设计的实践不够?或者是对各种实现的分析和思考太少?
**宝玉:**我觉得不仅要有架构实践,还要有不同场景的实践。
举个例子来说,你平时做企业应用架构,没什么流量,没多少数据,复杂的地方都在业务逻辑,这时候你去看那些讲大数据、讲高并发的文章,很难带入到场景去。
还有就是一些架构,不自己搭一遍是很难了解其中的优缺点的,这也是另一个原因。
可以考虑有机会自己尝试,把看到的一些好的架构用一个原型程序搭一遍,造一点数据出来,用工具压测一下,这样会更有感觉。
和实际应用想结合的问题,一方面说明你现有的架构可能并没有什么大问题,没有那么迫切的需求要改造;另一方面可能还是因为缺少实践经验,心里没底,不知道真用上了有没有用。
No.2
**小伟:**比较规范的文档有哪些,他们功能分别是什么?
**宝玉:**对于瀑布模型,每个阶段结束后,都有相应的验收文档,而敏捷开发则没有那么多硬性的要求,而是根据项目需要,写必要的文档。
有些团队对于测试阶段,会有测试用例文档、测试验收报告,发布前还会有部署文档、维护手册,但现在这类文档基本上被测试工具、部署脚本替代了,也没有什么存在必要。
我觉得项目中必要的文档,主要包括这几类:
1. 设计类文档
这类文档主要用来说明、讨论需求设计、架构设计,可以用来了解、讨论和评审,以及记录后续结果。
2. 说明类文档
这类文档用来对规范、API、配置、操作等做说明便于规范和统一。
3. 报告类文档
对事情结果的报告和说明,比如说验收报告、故障报告、调研等。
而这些文档的价值,在于帮助成员了解设计、参与讨论,记录项目成果,减少沟通成本。重要的不是文档多丰富,而是这些文档有没有价值,你能不能及时通过这些文档得到想要的答案。
所以你也可以对照一下你的项目中,现在的文档有哪些地方是可以简化的,哪些地方是要增强的。
比如说,概要设计/接口设计/详细设计是不是可以适当合并减轻文档工作PRD是不是够详细会不会引起歧义不容易理解要不要增加原型设计文档辅助
No.3
**邢爱明:**项目团队的开发人员,基本都是从外包公司临时找的,水平参差不齐,稳定性差,因此技术选型更多考虑技术的普及度的和是否容易学习掌握,从这方面看基本不太可能选择比较小众、但在特定领域很高效的技术。
加上是企业内部管理的系统数据量和用户数量可控因此存在技术瓶颈的可能性很小综合下来看最好的选择就是最成熟和通用的技术比如说选择java技术栈web开发的ssm框架等但这样长远看团队和个人的技术能力很难提升请问老师在这方面有什么建议
**宝玉:**我觉得团队的技术提升和项目的技术选型要分开,不要总想着两个都兼顾,优先保证好项目稳定、低成本运行。
技术提升这种事,需要让一部分人先成长起来,然后带动其他人。我自己工作之外会做一些业余项目,然后在这些项目中体验新的技术,体会其中优缺点,然后再逐步应用到工作的项目中,传授给同事们。
我也鼓励其他同事这么做,去做一点自己的项目。但工作中的项目,我是很保守的。
No.4
**alva\_xu**对于开源技术方面,老师有没有什么经验来指导选型?
**宝玉:**开源技术选型,我的经验一般是这样的。
1. 先找朋友推荐,少走一点弯路。
2. 没有推荐的话,就去网上搜索,找几个满足需求的备选。
3. 对比以下几个指标:
* 代码质量、有无测试;
* 文档健全度;
* 看Issue处理情况、最后更新时间无人维护的项目后续恐怕有问题都没法解决
* 看Star数量通过Google和StackOverflow看使用情况。
4.自己按照说明试试看。
No.5
**alva\_xu**有没有什么大的原则可以指导技术选型?比如技术成熟度等?
**宝玉:**我认为在满足设计目标的前提下,大的原则还是在于项目约束,尤其是成本和时间,然后就是看技术可行性和风险是不是可控,其他看团队风格,有的偏保守有的追新。
比如说我自己的原则:
1. 成熟的好过新酷的;
2. 流行的好过小众的;
3. 团队熟悉的好过陌生的;
4. 简单的好过复杂的;
5. 开源的好过商业的(有时候也视情况而定)。
No.6
**Charles**有着正常职位或头衔的架构师,对一个全新的项目理解产品需求后进行架构设计,一般会产出哪些“东西”,来满足后续的架构讲解和项目开发过程中的沟通?
**宝玉:**互联网产品特点是用户多,企业产品特点是业务复杂,所以架构的侧重点不一样。
架构师在架构设计后产出首先是架构设计文档让大家理解架构。然后还要写架构开发的文档比如如何基于这个架构开发功能模块有哪些公共API可以调用怎么样是最佳实践要遵守哪些规范等。
再要帮助搭脚手架和基础模块或示例项目,也就是要搭建一个最基础的可运行项目,通过这个项目,大家可以直观地理解你的架构是怎么落地的,通过基础模块或者示例项目,可以知道如何基于框架开发,后面就也可以照葫芦画瓢照着实现。
还有就是在开发过程中,要答疑、解决架构中存在的问题,对架构做优化,还要做代码审查,对于不符合架构规范的地方要指出和修正。
No.7
**Dora**互联网架构要考虑互联网很快的迭代速度所以对于扩展等特别注意。企业架构内部IT系统相对稳定对比互联网架构更简单
**宝玉:**挺好的分析。帮你补充几点:互联网架构不仅迭代会快一些,用户规模通常更大,但业务也会单一些;企业应用通常业务比较复杂,尤其是和行业会有一些结合,但是用户规模要小很多。这些特点,都会影响架构设计的选择。
No.8
**WL**老师能不能具体讲讲重构有哪些原则和要注意的地方,感觉一直得不到要领。
**宝玉:**重构的要领我觉得两点。
第一:你要先写一部分自动化测试代码,保证重构后这些测试代码能帮助你检测出来问题;
第二:在重构模块的时候,老的代码先保留,写新的代码,然后指向新代码,或者用特定开关控制新旧代码的指向(这样上线后可以自己先测试,有问题也可以及时关闭),然后让自动化测试通过,再部署测试,新代码没问题了,删除旧代码。
No.9
**bearlu**有没有事情管理的工具?因为如果不记录下来,一会儿就忘记了。
**宝玉:**留言区McCree同学推荐了滴答清单。我个人的话一般就用系统自带的记事本记一下或者贴一个便签纸在显示器。如果时间跨度长我就记到Calendars上加上提醒。工作中的任务我则会创建成Ticket。
No.10
**W.T**现在还有一种说法:提倡基于主分支开发,效率更高;而不是您提到的每人基于自己的分支开发完再合并回主分支。您怎么看待这个问题?
**宝玉:**我认为对于软件工程来说,很多问题,并不是只有唯一解,即使是最佳实践,也得看适用的场景和团队。
无论是基于主干还是分支开发,有两点需要注意的:
1. 就是一定要有一个稳定的分支可以随时发布的那种至于是叫master还是叫release并不重要。
2. 合并之前要有代码审查和自动化测试配合CI
上面两点才是核心。
No.11
**hua168**如果一个项目有5个开发做持续集成怎么保证不乱比如开发A刚刚修复的bug1开发B把自己修复的bug2上传之前的代码bug1没修复怎么办如果采用分支怎么合并如果是直接更新master分支那A不是白做了
**宝玉:**要注意是“合并”而不是“覆盖”。比如说bug1涉及file1和file3的修改那么开发A合并的时候只合并file1和file3。
等到开发B修复了bug2修改了file1和file2file2直接合并file1需要手动去修复合并冲突才能合并。
每个人开发之前都会从master获取最新版本合并的时候如果出现冲突要先解决冲突才能合并进去。这些其实应该自己去动手试试会体会更深刻。
No.12
**dancer**在微服务架构中一个服务在测试环境的交付验证往往还依赖于其他相关服务的新版本导致新的feature很难独立的交付。对于这种情况有什么好的方法吗
**宝玉:**我觉得对于大部分时候,微服务之间应该是独立的,而不是依赖过于紧密,如果每一个新功能都会这样,那架构设计一定是有问题的,需要重新思考服务划分的合理性。
但你需要有更多上线或者场景我才能针对性提出一些意见。对于有一些确实需要跨服务合作的大Feature这样也是正常的就是需要一起协作实现商量好通信协议分头开发再联调。
No.13
**Gao**老师所讲排查生产问题的案例,首先回滚版本,再看日志。这会引发更多的系统功能不可用吧,两个版本之间的功能差异尚不清楚就直接回滚,系统风险是否被进一步扩大?
**宝玉:**这个确实要具体情况具体看,因为我日常的系统上线,都会有回滚方案,回滚也是自动化的很方便。有些跟数据库相关的,如果数据库结构发生变化又产生了新数据,确实没法直接回滚。
No.14
**kirogiyi**团队成员的能力和素质参差不齐,如何有效的去组织和管理项目的自动化测试,自动化集成?
**宝玉:**首先你要先搭建好自动化测试环境让自动化测试代码能跑起来最好要和CI持续集成工具整合在一起每次提交代码CI都会跑自动测试然后能看到运行结果。
然后把自动化测试作为开发流程的一部分比如说要代码审查和自动化测试通过后才能合并代码。这部分工作如果和CI集成会容易很多。
再有就是要培训比如遇到不会写的开始先带着他写几个确保他学会了自己能写然后下次代码审查的时候看到缺了就要求补上还不会就继续教来不及写的就创建个Ticket跟踪起来。
简单来说,就是代码审查+CI+培训。
No.15
**探索无止境:**各种类型的测试覆盖率你们一般采用什么指标?个人感觉在理想的情况下最好是做到百分百覆盖率。
**宝玉:**100%覆盖,这个我觉得可以作为一种理想追求,但是没必要追求极致,还是要在进度和质量之间有个平衡比较好,毕竟进度也很重要。
另外对于前端业务,我更重视集成测试的覆盖,对于主要业务场景集成测试覆盖到位后,单元测试也就有比较多的覆盖,相对性价比更高,然后再逐步补充单元测试的覆盖率。
No.16
**起而行:**持续集成怎么理解呢?我看知乎上说,有的团队成员在一天内多次进行编译,发布或自动化测试。
**宝玉:**狭义的持续集成不包括发布,主要指集成,持续的(每次提交代码变更都触发,频繁地提交)对代码进行集成(合并到主干),但集成前要确保自动化测试通过。广义的持续集成还包括部署,也就是集成后自动部署测试环境(持续交付)或者生产环境(持续部署)。
No.17
**小小:**请问下有没有介绍开发如何写好测试不错的书?
**宝玉:**推荐《how we test software at microsoft》中文版《微软的软件测试之道》。不过没有书其实你也可以找到很多资料的。比如我平时写前端程序那么我会去GitHub或者Google通过关键字、语言找跟我项目类似的开源项目然后看其中有没有自动化测试写得好的。
找到了(例如reactstrap、electron-react-boilerplate、kitematic)就照葫芦画瓢好了,因为都是真实项目,所以特别简单有效,建议你也可以试试。
另外耐心一点,你也可以看到很多关于测试知识分享的技术文章,多看一看也有收获。
No.18
**hua168**代码审核是纯手工做的吗?没有好的工具?
**宝玉:**代码审查可以参考GitHub上一些开源项目的PR Review通常网页上可以清楚地标记出代码修改针对代码行可以写Review的评论这就已经很方便了。
其他工具主要是Lint检查代码规范、语法错误等这个一般在CI里面就集成了。
## 精选留言
陈珙
在没有特殊要求的情况下,项目中更加倾向选择更为熟悉的技术,因为我们需要对项目的质量与交付时间负责,可以做到可控的。而新技术有着新的设计思想与强大的功能,同时也伴随着无法预知的“坑”。在后续产品迭代的时间里,有针对性的升级或者选择更换同类技术里更优的。
相关阅读: [22 | 如何为项目做好技术选型?](http://time.geekbang.org/column/article/90957)
Y024
Appfuse一个 Web 开发基础平台)的作者 Matt Raible 曾总结了选择 [Web 框架的 20 条标准](http://static.raibledesigns.com/repository/presentations/Comparing_JVM_Web_Frameworks_February2014.pdf)。
同时,他也整理了一份表格,你可以根据自己的权重进行调整,产生自己的[分析](http://docs.google.com/spreadsheets/d/12l0sZNVSnwxcxs3CtcjeaCcI8rXjTrrldfTBZn7grD8/pub?hl=en&output=html#)。
但是现实情况,大家可能更遵循的是“经济适用原则”,比如:很多人提到的,负责人会啥就用啥,或者大公司者业界流行什么就用什么。
有位大佬说过“这个世界是你认为有很多选择其实只是幻觉大多数人只有很少的选项。技术研讨会搞一个选型hadoop + mysql + xx 时髦技术。架构师唾沫四溅吹一下午,结果老老实实上 Oracle 单例。”
相关阅读: [22 | 如何为项目做好技术选型?](http://time.geekbang.org/column/article/90957)
kirogiyi
架构师是一个概念性职位没有明确的界定需要具备的能力和素质也是千差万别每个开发人员心目中的架构师画像也都不一样神秘的IT牛人高级的保姆无休的恶魔…
在我看来,一名优秀的架构师应该具备良好的技术思维、产品思维和项目管理思维。技术思维是基础,评估技术难度、分析技术复杂度、准确把握技术方向,这些都是架构师在设计架构时面临的技术决策。
产品思维是骨架,在产品思维上构建起来的整体全面的产品意识,可以对业务、功能、模块进行明确的抽象、分治、迭代等等。
项目管理思维是方向,无论是敏捷管理模型还是瀑布管理模型,都需要在不同的时间、不同的环境条件下去关注金三角理论的取舍所带来的影响,降低技术以外对项目带来的局限性。
不过,架构师也不是想象中的那么神秘。开发人员和架构师的差别,最主要是层次和格局上的差别,导致最终产生了不同的结果而已。
试想两个能力相同的开发人员一个的目标是每年涨工资80%开发人员他会去努力多做事拓展技术的深度一个的目标是CTO20%开发人员),他会去努力多做事,多思考,多学习,多交流,尽力做到面面俱到。几年以后的结果就不言而喻,至少坚定的目标能够推动过程的发展。
相关阅读:[23 | 架构师:不想当架构师的程序员不是好程序员](http://time.geekbang.org/column/article/91312)
alva\_xu :
讲到架构我想先得谈一下康威定律。康威在1967年曾说过
> Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.
通俗地说,就是组织形式等同于系统设计。所以系统架构设计的进化,是和组织形式的变化结合的。
从ITIL来说BIAbusiness IT alignment是IT的核心所以充分认识组织的业务模式和运营方式才能让架构师设计出适合于企业的系统架构架构设计的最高境界就是适合企业业务的运营。
从单体架构到微服务架构从前后端分离到中台都是架构适应业务功能与非功能需求的体现。所以架构师首先必须要有业务思维、产品思维。TOGAF把企业架构分成业务架构、应用架构、数据架构、技术架构四个子域我觉得相当全面。
从程序员开始,如果能培养好老师讲的架构师能力模型中的四个思维和三个能力,我们可以给自己规划出一个架构师的成长路径,从单个业务应用开始,然后扩展到一个业务领域,最终到达企业架构师,甚至成为跨企业应用架构师的境界。
相关阅读:[23 | 架构师:不想当架构师的程序员不是好程序员](http://time.geekbang.org/column/article/91312)
纯洁的憎恶:
技术债务不全坏,与金融债务一样,需要具体问题具体分析。轻率&有意的债务要避免。谨慎&有意的债务有收益。
轻率&无意的债务要警惕。谨慎&无意的债务要改变。识别债务防患于未然。根据成本收益分析,决定重写(一次性还款)、维持(只还利息)还是重构(分期付款)。
相关阅读:[24 | 技术债务:是继续修修补补凑合着用,还是推翻重来?](http://time.geekbang.org/column/article/91729)
kirogiyi
在研发过程中,产生技术债务的时候,稍微有点技术功底的人,或多或少都会有感觉的。
比如:有重复代码的时候,会意识到好像已经写过了;函数命名的时候,会意识到好像有个相似的名称已经命名过;函数行数过多的时候,自己心里会感觉不舒服等等。
更有甚者,你去整理这些问题还会被同事标上“强迫症”患者的称号,还是放弃吧。技术债务就这样在外部和内部双重压力下自然而然的产生了。
那么如何产生有利的技术债务呢?我觉得应该从公司制度、研发流程、个人素质培养三方面入手。
公司制度实际上是为领导层准备的,领导层以身作则去影响下面的员工,员工就没有冒犯的理由,比如合理的奖惩制度,要做到公平合理,一视同仁;
研发流程主要是让团队成员知道自己什么时候该做什么事情,如何去按照指定的约束去做好自己的事情,除此之外,还应该给予明确的成长上升空间;
员工素质的培养则需要从一个人的职业素质,技能优化,团队协作方面着手,让他们拥有积极努力的心态参与到工作中去,这基本上就能解决最基础的技术债务问题(领导决策错误产生的技术债务另当别论)。
在我遇到过的技术债务中,主要由领导决策、产品业务逻辑、技术最初选型、技术更新换代、团队综合素质中的一种或几种导致。对此,我只能说个人能力达到什么层次就应该去解决什么层次的技术债务,不能去推诿和落井下石,在你手中的技术债务就应该当成自己欠下的技术债务来解决,这样才能持续性的做好自己分内和分外的事情,工作起来才能得心应手。
相关阅读:[24 | 技术债务:是继续修修补补凑合着用,还是推翻重来?](http://time.geekbang.org/column/article/91729)
kirogiyi
我觉得高效,意味着自律,自律的好坏是可以通过你散发出来的气息让周围的人感受到的,比如:说话有没有条理,做事拖不拖延等等。
生活自律,你会发现每一分每一秒都充满了希望和力量,用积极乐观的心态去完成每一件事,知道自己上一步做好什么,下一步才能做好什么。
工作也是一样要想高效完成任务需要利用前辈们总结的思想和方法去长期实际应用在使用的过程中就会体现出你的高效不能说我知道单元测试我知道CI…很少有人讲我一直在用。
如果我们注意观察,会看到身边的同事,有的很少加班(活蹦乱跳),有的经常加班(蔫头耷脑),做了一样的事情用了不一样的时间,此时就能真正的体会到高效做事的魅力了。
我不提倡加班的原因就在于此,但那是针对高效人士的,低效人士不加班,老板是不会答应的。而一般对自己的时间把握比较好的人,在估算工作时间或工作量的时候,都比较果断,不会支支吾吾,还会主动给出具体时间点和阶段性成果,让人觉得这才是真正做事的人应该有的态度。
我的看法是,积极、主动、自律是高效人士的必备素质。
相关阅读: [25 | 有哪些方法可以提高开发效率?](http://time.geekbang.org/column/article/92266)
nigel
就学习能力而言,“祭海先河,尤务本原之学”,重要的是对基础知识的掌握。就像侯捷先生说的“基础的东西不易变,不易变的可重用”。
相关阅读:[27 | 软件工程师的核心竞争力是什么?(上)](http://time.geekbang.org/column/article/93062)
\_CountingStars
之前看到过一个关于 code review 的观点:在让别人 review 你的代码的之前,你要确保你的代码没有基础的问题,比如单元测试要通过,不能有代码风格问题,首先你要确保你的代码是能正常工作并解决需求的。当然这些基本都可以通过自动化来操作,比如提交 PR 的时候,自动化的检查代码风格,运行单元测试。保证邀请别人 review 你代码的时候,不要为这些小事费精力,提高 review 效率和积极性。
相关阅读:[30 | 用好源代码管理工具,让你的协作更高效](http://time.geekbang.org/column/article/93757)
bearlu
其实我觉得用什么源代码管理工具都没关系,最重要是要了解工具,形成流程,按流程走,然后纠正流程。
相关阅读:[30 | 用好源代码管理工具,让你的协作更高效](http://time.geekbang.org/column/article/93757)
## 思辨时刻
Charles
三四线城市技术选型前期主要考虑当地市场什么人才比较充足比如后端PHP人多那就PHP学习成本也低几人团队协作起来也不是大问题而且前期扩充人员也比较好招人另外前期应该也不会在语言层面出现性能问题。
然后数据库基本就选MySQL够熟悉够成熟。前端的话web、小程序、ios、android之类的都统一MVVM思想进行前后端分离开发这样各个用户端都可以统一API提升效率这个也会从产品角度思考。
如果产品经理就只是需要一个PC网站而且短期也没升级计划就选择传统的后端渲染web页面方案。可能会站在目前项目或经历过的项目经验去思考问题期待老师回复指正。
宝玉:
我觉得你的选型思路在项目发展阶段包括没有很大规模之前都是没有问题的。选最熟悉的、流行的往往也是风险比较低的。包括如果就是一个PC站也不做SPA单页应用也没有必要前后端分离。还是看是不是能低成本满足好项目需求和业务发展。
有一点补充的就是前端除了MVVM像React的Flux和Redux的架构模式也是一种很好的架构模式但在非Rect/Vue的项目中应用不多。
相关阅读:[22 | 如何为项目做好技术选型?](http://time.geekbang.org/column/article/90957)
好,今天的加餐就到这里,非常感谢同学们的用心留言,希望大家都能持续思考与总结,不断精进!
感谢阅读,如果你觉得这篇文章对你有一些启发,也欢迎把它分享给你的朋友。