函数式编程减少漏洞的新方法

EETOP 2023-03-27 12:09
你可能认为软件产品生命周期中耗时最长、费用最高的阶段是系统的初期开发阶段,因为所有美妙的功能都是在这一阶段构想出来的。而事实上,最困难的部分是后期的维护阶段。在这个阶段,程序员将为自己在开发过程中走的捷径付出代价。那么,程序员为什么要走捷径?可能性有很多:也许他们没有意识到自己在“投机取巧”;只有代码被许多用户部署并执行时,隐藏的漏洞才会暴露出来;开发人员时间紧,也可能导致缺陷;此外,产品上市时间的压力几乎肯定会让软件包含更多的错误。

大多数公司维护代码的难题导致了第二个问题:脆弱性。添加到代码中的每个新功能都会增加代码的复杂性,从而增加程序中断的机会。软件变得越来越复杂,开发人员因为害怕出现程序中断,如非绝对必要,都尽量避免改动软件,这是很普遍的现象。在许多公司中,整个开发团队的工作不是为了做任何新的开发,而只是为了保持现有系统的运行。你可能会说,这就像是软件版本的红皇后效应,奋力奔跑只是为了停在原地。

这种现状令人遗憾。然而,软件行业目前的发展趋势就是复杂度越来越高、产品开发时间越来越长、运行系统的脆弱性越来越高。公司一般只能投入更多人力来解决这些问题:更多的开发人员、更多的测试人员、更多的技术人员在发现系统漏洞时及时干预。

当然,一定有更好的方法。越来越多的开发人员认为这一问题的答案可能是函数式编程,我便是其中的一员。本文中,我描述了什么是函数式编程,使用函数式编程为什么会有帮助,以及我为何如此热衷于函数式编程。

为更好地理解函数式编程的基本原理,我们先回顾半个多世纪前发生的事情。20世纪60年代后期,为了提高代码质量,减少所需的开发时间,一种编程范式应运而生,称为结构化编程。

各种语言的出现促进了结构化编程的发展,为了更好地支持结构化编程,一些已有的语言被修改。结构化编程语言最显著的特征之一,是消除了一个长期存在的特征:GOTO语句。

GOTO语句用于程序执行的重新定向。程序流不是按顺序执行下一条语句,而是重定向至其他某个语句,即GOTO行中指定的语句,通常需满足某些条件。

取消GOTO语句是基于程序员在使用GOTO的过程中学到的教训——它让程序非常难以理解。带有GOTO语句的程序通常被称为“意大利面代码”,因为指令序列执行可能就像一碗意大利面,难以单链跟随。

开发人员无法理解自己的代码是如何工作的,或者为什么代码有时不工作,这是一个复杂的问题。那个时代的软件专家认为,GOTO语句造成了不必要的复杂性,因此必须消除这些GOTO语句。

这在当时是颇为激进的想法,许多程序员拒绝消除自己一直依赖的语句。相关争论持续了十多年,最终,GOTO不存在了,今天也没人主张它再次回归。这是因为在高级编程语言中消除GOTO语句大大降低了复杂度,提高了生产软件的可靠性。这是通过对程序员的限制实现的,其结果是程序员更容易推理自己编写的代码。

尽管软件行业已经从现代高级语言中消除了GOTO语句,但软件的复杂度和脆弱性仍在继续上升。如果想看看还能修改哪些编程语言以避开一些常见的陷阱,你会很奇怪地发现,软件设计师往往能在硬件同行那里找到灵感。

在设计计算机硬件时,电阻不能共用,比如键盘和显示器电路就不能共用电阻。但程序员在软件中却一直在做这种共用,也就是全局状态共享:变量不由某一个进程所有,而可由任意数量的进程进行更改,甚至可以同时更改。

现在,想象一下,你每次使用微波炉时,洗碗机的循环设置会从一般程序变为瓶罐清洗程序。当然,这在现实世界中并不会发生,但在软件中,这样的情况却一直出现。程序员编写调用一个函数的代码,期望执行单个任务。但是许多函数都有副作用,会改变共享的全局状态,从而导致意想不到的后果。

在硬件中,这种情况不会发生,因为物理定律限制了这种可能性。当然,硬件工程师也可能会搞砸,但不像软件那样有太多的可能,且有好有坏。

另一个潜藏在软件“沼泽”中的复杂怪物被称为空引用,即引用内存中某个位置根本不指向任何内容。一旦尝试使用此引用,就会出现错误。因此,程序员必须牢记,在尝试读取或更改引用的内容前,需检查该引用是否为空。

当今几乎所有流行的语言都存在这一缺陷。先驱计算机科学家托尼•霍尔(Tony Hoare)早在1965年就在ALGOL语言中引入了空引用,空引用后来被纳入许多其他语言。霍尔解释说,自己这样做“仅仅是因为它很容易实施”,但今天他认为这是一个“数十亿美元的错误”。因为当程序员期望的是有效引用而实际上是空引用时,便会导致无数错误。

软件开发人员需要非常自律,才能避免此类陷阱,但有时他们没有采取足够的预防措施。结构化编程的架构师知道GOTO语句确实是陷阱,未给开发人员留下任何逃避的借口。为保证无GOTO语句的代码获得预期的清晰度改善,他们知道必须在结构化编程语言中完全消除GOTO语句。

历史证明,删除危险特征可大大提高代码的质量。今天,许多危险的习惯做法损害了软件的鲁棒性和可维护性。几乎所有现代编程语言均有某种形式的空引用、全局状态共享和带有副作用的函数,这些要比GOTO语句糟糕得多。

如何消除这些缺陷?事实证明,答案已经存在几十年:纯函数式编程语言。

第一个流行的纯函数式语言称为Haskell,创建于1990年。因此,软件开发领域如今依旧面临的棘手问题早在20世纪90年代中期便已有了解决方案。遗憾的是,当时的硬件通常不够强大,无法使用该解决方案。但今天的处理器已经能够轻松管理Haskell和其他纯函数式语言的需求。

事实上,基于纯函数的软件特别适合现代多核CPU。这是因为纯函数仅靠输入参数运行,因而不同函数间不可能存在交互。这使我们可以对编译器进行优化,生成在多个内核上高效、轻松运行的代码。

顾名思义,纯函数式编程意味着开发人员只能编写纯函数,既然是纯函数,便不会产生副作用。这种限制提高了稳定性,打开了编译器优化的大门,最终生成的代码更容易推理。

但若是函数需要知道或操作某个系统的状态,又该如何?这种情况下,状态会由一长串“组合函数”进行传递——一个函数将其输出传递给下一个函数作为输入。将状态自一个函数传递至另一个函数,每个函数都可以访问该状态,且不会出现另一个并发程序线程对该状态进行修改——这是在太多程序中发现的常见且代价高昂的脆弱性。

函数式编程亦可解决霍尔的“十亿美元错误”:空引用。解决的方法是不允许值为空。另外,有一种结构通常称为Maybe(或某些语言中的Option)。Maybe的值可以是Nothing或Just。使用Maybe结构,开发人员不得不始终考虑这两种情况。在这件事上他们别无选择,每一次遇到Maybe时都必须处理Nothing的情况。这样做可以消除空引用可能造成的许多错误。

函数式编程还要求数据不可变,这意味着一旦将变量设置为某个值,该值就永远不变。变量更像是数学中的变量。

例如,要计算方程y= x2 + 2x - 11,需要为x选择一个值,并且在计算y的过程中,x都不会取不同的值。因此,计算x2时使用的x值与计算2 x时所用的x值是相同的。在大多数编程语言中没有这样的限制。可以使用一个值计算x2,然后在计算2 x之前更改x的值。不允许开发人员将赋值更改(变异),他们可以使用与中学代数课相同的推理过程。

与大多数语言不同,函数式编程语言深深植根于数学。这种逻辑极为严密的数学血统正是函数式语言最大的优势。

为何是这样?因为人们研究数学的历史已有数千年之久。它牢不可破。而大多数编程范式(如面向对象的编程)背后的历史最多只有60年,相比之下显得粗糙且不成熟。

不妨通过一个例子来说明编程与数学相比有多“草率”。通常情况下,我们会告诉编程新手在第一次遇到语句x = x + 1时忘记自己在数学课上学的东西。在数学中,这个方程为零解。但在当今的大多数编程语言中,x = x + 1不是一个等式。它是一个语句,命令计算机读取x的值,将其加1后,放回名为x的变量中。

在函数式编程中,没有语句,只有表达式。我们在用函数式语言编写代码时可以使用在中学学到的数学思维。

由于函数的纯粹性,我们可以使用代数替换来推理代码,从而帮助降低代码复杂性,就像回到代数课上,降低方程复杂性一样。在非函数式语言(命令式语言)中,则并无同等机制来推理代码是如何工作的。

纯函数式编程删除了编程语言中的危险特征,解决了我们行业中的许多大问题,开发人员也不容易出现“搬起石头砸自己的脚”的问题。这些限制起初可能看来很极端,我可以肯定地说,20世纪60年代开发人员对消除GOTO也有相同感。但事实是,使用函数式语言既不失自由,功能又强大,以至于当今几乎所有最流行的语言都包含了函数功能,尽管它们本质上仍然是命令式语言。

这种混和编程方法的最大问题在于它仍然允许开发人员忽略语言的函数性质。如果50年前保留GOTO作为一个选项,我们可能至今仍面临着“意大利面代码”的困境。

要获得纯函数式编程语言的全部好处,就不能妥协。需要使用从一开始就符合这些原则设计的语言。只有这样,才能获得本文阐述的许多益处。

但函数式编程并非易事,要有所付出。学习使用此类函数范式编程几乎就像从头再学编程一样。许多情况下,开发人员必须学习那些学校里不曾教过的数学知识。所需的数学并不难,但是新知识,而且对于数学恐惧症人群来说很可怕。

更重要的是,开发人员需要学习一种新的思维方式。因为不熟悉,起初这会让人感到有负担。但随着时间的推移,新的思维方式习惯成自然,与旧的思维方式相比,最终减少了认知成本,效率也就会大幅提升。

但实现到函数式编程的转变会很困难。我自己几年前的经历就很能说明问题。

我当时决定学习Haskell,并且要在业务要求的时间线内完成。在我40年的职业生涯中,这是最为艰难的学习经历,在很大程度上是因为缺少明确的资源来帮助开发人员实现到函数式编程的过渡。事实上,在过去30年里,没有人非常综合地写过函数式编程。

我只能到处拼拼凑凑。我个人的经验证明这样做的效率极低。我花了3个月时间,没日没夜、周末无休,时时刻刻都在学习Haskell。最后,我用它写的代码比用其他的都好。

在决定公司改用函数式语言时,我不想让公司的开发人员经历同样的噩梦。因此,我开始着手设计一个供开发人员使用的课程,并在此基础上编写一本书,帮助开发人员过渡到函数式编程。在书中,我指导读者熟练掌握一种名为PureScript的函数式语言,它吸收了Haskell的所有优点,并改进了Haskell的许多缺点。此外,它能够在浏览器和后台服务器上运行,成为满足当今许多软件需求的绝佳解决方案。

这些学习资源只能起到帮助作用,要广泛实现这种转变,软件型企业必须对其最大的资产——开发人员——进行更多投资。我在自己的公司Panoramic Software担任首席技术官,公司进行了此项投资,所有新工作都用PureScript或Haskell完成。

3年前我们开始采用函数式语言时,使用的是另一种名为Elm的纯函数式语言,因为它是一种更简单的语言。(我们全然不知最终能够超越它。)我们花了近一年的时间才开始有所收获。但自从我们渡过难关之后,一路顺畅无比。我们没有产生运行错误,过去在前端用JavaScript、在后端用Java时,运行错误非常常见。这一改进让团队能够把更多的时间花在为系统添加新功能上。现在,我们几乎不需要花时间调试生产问题。

但是,对于相对较少有人使用的语言来说,仍然存在挑战,例如缺少在线帮助、文档和示例代码。也很难聘请具有相关语言经验的开发人员。正因如此,我们公司的招聘人员专门寻找函数式程序员。如果雇用的人没有函数式编程背景,我们会在最初的几个月里让他们接受培训,以便跟上进度。

我的公司很小,它向政府机构提供软件,帮助退伍军人获取美国退伍军人事务部的福利。这项工作非常有意义,但它并非赚大钱的领域。由于利润微薄,我们必须使用所有的可用工具,用更少的开发人员做更多的事。函数式编程正是我们所需要的。

像我们这样平淡无奇的企业,通常很难吸引开发人员。但我们现在能够雇用顶级人才,因为他们想从事函数式代码库工作。我们在这一领域所处的领先地位,让我们可以获得我们这种规模的公司梦寐以求的人才。

我预计,采用纯函数式语言将提高整个软件行业的质量和可靠性,同时大大减少浪费在查找漏洞上的时间,函数式编程基本不产生漏洞。这不是什么魔法,但有时它很神奇,每当被迫使用非函数式代码库时,我都会想起有它多好。

整个软件行业正在为范式转变作准备,其中一个迹象便是函数功能正出现在越来越多的主流编程语言中。软件行业需要做更多的工作才能完全实现过渡,但这样做的好处显而易见,毫无疑问,这也是未来的发展方向。

文章来源于悦智网,作者Charles Scalfani


创新大讲堂芯片就业课推荐

本课程75折返场进行中,随时取消

EETOP EETOP半导体社区-国内知名的半导体行业媒体、半导体论坛、IC论坛、集成电路论坛、电子工程师博客、工程师BBS。
评论
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 75浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 69浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 60浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 108浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 84浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 60浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 88浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 43浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 63浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 60浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 93浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 56浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦