关于软件开发,本文认为这是所有管理者都需要知道的10件最重要的事情:
1. 软件不是魔术
软件不是魔术。虽然它看起来像魔术,或者是魔法,但它不是魔法。每一个元素都是由人设计的,都有其数学基础,或者是可以用人类语言解释的过程。
与魔术不同,软件不是凭空变出来的。它需要设计、构建和维护。就像房子有多种系统一起工作(地基、结构、管道、房间、家具等等)那样,软件系统也需要许多层和子系统来创建整个系统。它可以设计得很好,也可以设计得很差,而且快速的设计很少能持久。
如果人们不能用语言来描述它会做什么(包括想要的结果和如何实现),那么计算机也无法做到。“how”被称为算法,这并不神奇。
机器学习和其他人工智能技术也并不神奇。机器学习是基于数据的预测,而不是显式的规则或指令。它一般是用线性代数来做的。如果有100万张已知的香蕉照片和100万张没有香蕉的照片,一个训练有素的机器学习系统看一张新照片,会根据它从之前的照片中学到的知识告诉你它看起来像第一组还是第二组,这不是魔术。使用机器学习根据过去的招聘决定对简历进行排序,即使没有任何故意的偏见,也可能会放大经验主义的招聘历史。
2. 软件永远不会“完成”
软件永远不会“完成”,软件是一个迭代的过程,在其生命周期中包含许多修订和更新。我们的工作是创造一个能认识到这一点的环境。
同样,我们从来没有期望市场营销和客户获取是“完成的”,它们也是迭代过程。在每个迭代中,随着我们不断地为业务交付价值,我们也不断地学习和成长。即使已经做了一些成功的发布,我们从来没有打算“停止”做这些事情。
如果软件可以在一个版本中完成就好了,但这不是现实。需求文档充满了模糊性,软件的第一个版本充满了“哦,那是我写的,但不是我的意思”的场景。最好的软件能激发新的想法和功能需求,看到新的销售管理系统更加高效,就会激发出更高的效率。世界在变化,竞争对手提供了新的功能,人们就有了新的想法。另外,总是有一些bug需要修复:可能是在代码中,也可能是在构建代码的底层软件框架和系统中。某些软件可能是完美的,但可以确信的是,随着时间的推移,人们会发现它所构建的平台存在各种漏洞。
我们的工作就是让一个组织能够认识到这一点。
认识到这一点的方法是建立一个有信心定期发布新版本的组织。当完全自动化测试和其他工程规范就位时,我们就建立了信心。这种信心创造了一种能力,可以避免过长的发布周期,而是每季度、每月甚至每周发布高质量的软件。特定的频率并不重要,但是信心很重要,自信能够带来更快的创新。
3.软件开发是团队作战,没有人能做所有事情
软件开发是团队作战,开发人员既不是产品经理,也不是UX(用户体验)设计师,也不是质量工程师、分析师、安全专家、技术作家或运营工程师。组织需要所有角色。
没有哪个管理者会建议每个销售(sale)人员都做营销(marketing)及PR,否则就解雇销售团队(因为营销人员了解产品,也能做销售)。营销和销售是相关的,但又是不同的。因此,两者之间存在着分工。
同样,开发团队需要独立的人员来收集需求、质量保证和测试、代码编写等等。
一个开发人员可以“做所有事情”的神话,称为“全栈开发人员”或“10x工程师”,这一般只存在于小公司。是的,一个非常小的公司可能一个人同时做营销和销售,但你可能不会加入这样的小公司。
不要用自己的兴趣去挑战别人吃饭的专业。一个小孩“擅长Facebook”并不意味着他或她会成为下一个扎克伯格;一个小孩对工程学很感兴趣并不意味着他或她可以能够使用微积分;一个小孩能够自己做了一个网站并不意味着这个网站每小时可以处理数十亿的金融交易。
4. 设计不是外观,而是工作原理
史蒂夫·乔布斯有句名言:”设计不只是外表和感觉。设计就是工作原理。“ UX设计师不会坐下来决定菜单的颜色,或者决定按钮是圆形还是方形,他们决定工作流和交互是什么。
用户会看到一个有三个选项的屏幕,还是一个屏幕只显示一个选项?这个设计决定需要心理学、对用户的同理心,以及测试、测试、再测试。
UX设计的最大挑战之一是,一旦你熟悉了系统,就失去了预测新用户的能力。设计该系统的人在预测新用户的需求时将自动被取消资格。UX可能很漂亮、优雅,可以与一件艺术品相媲美,但是请UX设计师将背景更改为帆船的图片是没有帮助的。
我们的工作是信任测试数据而不是主观臆测,创建一个环境,在产品发布之前计划进行多次修订,并期望在产品发布之后进行进一步的改进。不要将UX设计人员与图形设计人员混淆。让UX计师设计公司节日贺卡和让技术作家写公司通讯是一样的失礼行为,这些是不同的技能。
5. 安全是每个人的责任
不管知不知道,无论愿不愿意,我们都是从事安全行业的。所有软件都有安全需求和潜在的安全漏洞。开发软件所涉及的系统也有安全需求和漏洞。虽然防火墙和入侵检测等安全的基础设施组件是必要的,但它们还不够:还必须使用内置的安全控制来设计、实现和维护软件平台。安全既是好的技术,也是好的流程。
如果认为我们不是被攻击的目标,那就错了。所有的计算机系统都是被攻击的目标,因为攻击不仅是为了其中的信息,而仅仅是它是一台计算机这样的一个事实。例如,一个没有价值信息的系统是网络攻击目标,因为它可以被用来转发对其他计算机的攻击,或挖掘比特币,或存储他人的盗版视频。
安全不是打开/关闭这样按钮,有许多灰色地带。安全性最好从一开始考虑。事后的亡羊补牢是昂贵的,而且往往是无效的。我们不会先造一艘船,然后再“添加”一种让它漂浮的功能。同样,也无法先构建一个系统,然后按下“具有安全性”按钮就安全了。
安全是关于风险和对风险的容忍度。对两个节点之间的通信进行加密并不能保证它的安全性,但它提高了安全性,只有超级算力才有可能破解密码。在一个领域降低风险对其他领域没有帮助。保护网络并不能防止物理安全问题。一个人撑开一扇门,其他人就能偷走你的备份磁带。
正如吉恩·斯帕福德(Gene Spafford)的一句名言:”唯一真正安全的系统,是一个关了电、浇铸在混凝土里、由全副武装的警卫把守在绝缘房间里的系统——即便如此,我还是心存疑虑。“
遵守NIST CSF(国家标准与技术网络安全框架学会)、PCI DSS(支付卡行业数据安全标准)和SOC 2(服务组织控制报告)等安全标准可以量化风险,如果做得合适,还可以降低风险。这些标准并不能保证绝对安全,绝对安全是不存在的。更重要的是,它们为如何负责任地应对和报告不可避免的安全漏洞提供了指导。诚实、直率、公开是良好的建议。
软件,如果不管它,就像面包一样变得陈旧。我们的工作是平衡安全妄想与现实,并适当预算时间和资源。
6. feature大小并不能预测开发时间
feature大小(用户感知到的)与创建feature所需的时间完全无关。小feature可能需要几天或几年的时间,大feature(用户感知到的)也可能需要几天或几年的时间。
我们的工作是创建并支持一个软件开发过程,该过程接受这个事实,并且不是拍脑袋评估工程量。工作量评估本身可能需要令人惊讶的很长时间。
鼓励通过沟通来解决工作量评估的问题。工程师可能会给出一个令人惊讶的很长时间的工作估算,但是也会提出对需求进行更改,从而大大缩短时间。记住工作量评估要包括测试、培训、部署和意外的假期(例如病假)。
在没有与工程部门协商工作量的情况下,永远不要承诺某个feature。这并不是我们在公司的权力标志,这需要的是一个专业流程,在这个流程中,开发人员的请求得到认真对待,评估工作量,并按时交付(或出于诚实的原因延期)。
7. 伟大来自于成千上万的小进步
伟大来自于在很长一段时间内所做的成千上万,也许是数百万的小进步(变更)。如果变更的效果都被测量是负面的,那么变更将被回滚。
谷歌也不是一天建成的。谷歌的搜索引擎是数百万个人改进的结果。搜索质量小组每周开会一次,工程师们走上讲台,提出他们的修改建议。他们展示了在模拟的环境中会有多大的改进,委员会进行辩论并投票表决。几周后,将对测量结果进行评审,并决定保留或回滚更改。
谷歌搜索是迭代开发战胜“数据大爆炸”思维的胜利。谁都不可能在一开始做出一个好的搜索引擎。只有在好莱坞电影中,一个聪明的极客才会想出一个惊人的新点子,并且第一次就能完美地实现它。在现实世界中,一夜成名需要数年的时间。
无论试图实现的目标是一个为客户提供更好服务的系统,还是一个更高效、错误更少的系统,还是一个运行更顺畅的系统,都是如此。
我们的工作是要求系统的设计能够容易拥抱新的变化,并定义相关的KPI(关键性能指标),这些KPI可以在更改之前和之后方便地进行度量。最重要的是,必须有一个流程来检查结果,并决定保留或回滚变更。回滚不应被视为失败或受到惩罚。从每次回滚中学到的与在每次保留的更改中学到的一样有价值。
托马斯·爱迪生声称在发明灯泡的过程中测试了1000根灯丝。当一位记者问他:”失败1000次是什么感受?“他回答说:”我没有失败1000次。灯泡是一项有1000个步骤的发明。”
8. 技术债很讨厌,但不可避免
技术债务是将来需要做的工作,因为我们现在选择了一个更简单的解决方案,而不是使用一个需要更长时间的更好解决方案。任何合理规模的软件项目都有技术债务。技术债务让所有的进步都变得更慢,越忽视它,它就越像滚雪球一样越滚越大。
有金融背景的管理者听到“债务”时,会认为这是一种未来会有回报的投资。技术债务恰恰相反,它是有毒和痛苦的,并且是一个定时炸弹。
1972年,Fram为它的滤油器做了一个电视广告,在广告中,一位汽车机械师解释说,一位顾客为了节省4美元而不更换滤油器,后来,这位顾客不得不花200美元更换一个昂贵的主轴承。汽车机械师总结说:“你可以现在付给我钱,也可以以后付。”
有一个软件项目,其中有一个子系统与供应商通信。最初系统只与一个供应商通信,所以非常简单。然后又接了一个,然后另一个。有些功能必须实现三次,每个供应商一次,这是不可持续的。当要求支持第四个供应商时,开发人员表示反对。是的,他们可以在大约一个月的时间里把它移植上去,但是软件架构开始吱吱作响,就像飓风中的老房子一样。这些权宜之计积累了大量的技术债务。
开发人员的建议是花两个月的时间重构供应商架构,使其成为一个插件系统。然后,新的供应商可以在一周内而不是一个月内支持接入。
管理者们并不高兴。为什么下一个供应商需要两个多月的时间来支持,而之前的供应商是在一个月内支持的呢?花两个月的时间来偿还技术债务将使未来的支持更快,代码更稳定,并使添加新feature更容易。很难衡量确切的好处。
“你可以现在付给我,也可以以后再付给我"。
我们的工作是分期偿还技术债务。失控的技术债务降低了添加其他feature的能力,并导致软件系统不稳定。偿还技术债务应该与业务目标挂钩,类似于非功能需求。
9. 软件不会自己运行(软件需要运维)
虽然供应商和开发人员可能会试图告诉你不同的情况,但是软件并不会自己运行。任何基于软件的系统(特别是网站和web应用程序)都需要运维人员和运维流程。否则,软件就像一本合上的书,必须有人打开它,管理它,以及照顾它的需求。
运维比软件开发本身更重要。代码只写一次,但运行可能会是数百万次。因此,粗略地衡量一下,运维的重要性是否要高出几百万倍呢?
我们的工作就是期望运维成为任何软件系统的一部分。它必须像其他任何项目一样被计划、预算、管理和有效地运行。
运维功能(通常称为非功能需求)对用户是不可见的,除非作为二级需求。数据备份是非功能需求中一个很好的例子。没有用户请求数据备份,但是,用户确实要求恢复已删除的数据。遗憾的是,没有备份就没有恢复。恢复是功能需求,备份是一种运维(非功能)需求。
让软件服务易于维护或高效运行的功能需求从来不会被用户提出来。然而,他们确实享受着一个低成本、高可靠的系统所带来的好处。客户会离开那些不靠谱的网站,再也不会回来。
持续改进的需求不仅包括新功能需求,还应该包括新的非功能性需求。因此,我们的工作不仅是为客户提出的功能需求分配资源,还要为运维需求分配资源。在两种相互竞争的需求之间取得平衡是困难的。
但是,一个成功的产品是业务需求和运维需求的权衡结果。
10. 复杂的系统需要DevOps才能良好运行
复杂的系统最好通过DevOps进行改进。DevOps有很多定义,但是DevOps通常看作是通过快速迭代加速交付价值(feature、bug修复、流程改进等等)。要做到这一点,每个相关人员都必须参与。也就是说,他们必须跨职能团队进行协作。DevOps这个名字来自于移除开发人员和运维(IT)之间的隔阂,这对于实现快速的发布是绝对必要的。然而,优秀的DevOps环境将其扩展到跨所有职能团队的端到端工作。
DevOps被误解为开发人员来做运维。这种“构建它,运行它”的策略是跨职能团队工作(消除隔阂)的一种方法,但它不是唯一的方法。
一个复杂的系统需要三件事:良好的流程、所有相关人员的良好沟通以及尝试新事物的能力。
结论
软件正在吞噬世界。本文总结了软件以及软件工程的10个箴言,希望管理者及相关从业者理解其重要性并从中受益。
原文:https://queue.acm.org/detail.cfm?id=3325792
作者:Thomas A. Limoncelli