为什么我说低代码是“行业毒瘤”?

本文探讨了低代码平台的兴起及其在行业中的争议。ThoughtWorks中国区CTO徐昊认为,以降低程序员门槛为目的的低代码平台可能导致代码质量下降,维护困难,且对行业传递错误信号。低代码平台通常分为脚本化、个人工作流自动化和入门级编程工具三类,但最后一类被认为是行业毒瘤,因为它暗示程序员价值不高。尽管低代码市场增长迅速,但其实际效用和长期影响仍待观察。

转载自https://www.infoq.cn/article/q2mFOAtreDZETqMplw0M

使用低代码平台写出来的代码既难以维护,又难以测试,同时它还给行业传递了非常不好的信号,“程序员的价值是不值钱的”,最终造成的结果就是一些不具备编程专业技能的人,使用极不趁手、效率低下的工具来做写代码的工作。这是非常危险的,这类低代码工具就是行业毒瘤!

近段时间,低代码在市场中获得了前所未有的热度,很多投资机构都做了相关的分析与预测。Gartner 预测:到 2025 年,70% 的新应用将由低代码 / 无代码技术完成开发。那么,低代码真的是新风口吗?它真的可以提升效率吗?

带着这些问题,InfoQ 采访了 ThoughtWorks 中国区 CTO 徐昊,他表示低代码不是一个新概念,现在也不是低代码第一次引发业界讨论,以降低程序员门槛为目的的低代码从底层逻辑上就是不通的,这类低代码不是风口,而是行业毒瘤。

低代码并不是新概念,每隔几年就会重新流行

什么是低代码呢?2014 年,Forrester Research 研究机构正式提出了低代码的定义,即利用很少或几乎不需要写代码就可以快速开发应用,并可以快速配置和部署的一种技术和工具。通俗一点理解,在程序员实现功能的过程中,只使用了很少的代码,或者是通过拼接的方式来完成,比如我们在 Excel 中输入公式,完成相应计算,这也可以算是低代码的一种。

在徐昊看来,低代码并不是一个新概念,每隔几年低代码就会卷土重来,在业界引发热议。

伴随着计算机产生的历史,“程序员”有一个圣杯性的使命——让计算机彻底工具化。不要只是让专业人员来操控计算机,要让一些没有编程训练、不是计算机专业的人也可以使用计算机完成相应的工作。

顺着计算机发展历史去看低代码,我们会发现每个阶段的低代码定义都是不一样的。

最开始,我们是使用机器码来编程的,FORTRAN 编程语言出现之后,我们就可以使用高级编程语言去编程,不用再操控机器。那么,与操控机器对比,FORTRAN 中的数学表达式就是“低代码”。

经过一段时间的发展,编程开始围绕数据来展开,那么,业务人员能不能不用写代码就生成自己的数据报表呢?这时,SQL 就出现了,当年它也被认为是“低代码”。

根据历史规律,这类“低代码”总是在出现之后再慢慢演变成程序员的一个工具。

这次,低代码能够流行的一个背景是微服务的发展。微服务的理念是把企业中复杂度高的应用拆解成多个微服务,然后通过更简单、更低成本的方式把已存在的微服务串联起来,形成新的功能。那么,企业在进行微服务改造的时候,心中存的念想就是可以降低新功能研发和创新的成本。当企业的微服务改造都基本完成之后,通过“低代码”的开发模式将它们串联成新功能,似乎是合理的选择。

以降低程序员门槛为目的的低代码是最没用的

低代码领域目前没有特别明确的类别划分依据,各家研究机构和企业都有自己的划分标准。在徐昊看来,低代码可以粗粒度地分为三类。

第一类低代码是我们常说的脚本化,类似于在 Excel 中使用宏,通常是围绕一个特定的产品或生态去形成脚本化的环境。以 Salesforce 为例,每家公司的销售流程都会有差异,即使是再优秀的 SaaS 服务或产品都只能覆盖 80% 以上的功能,剩下一些需求还是要定制化。而这些定制化的需求往往是轻量级的,因此,SaaS 或 PaaS 平台通过低代码工具就可以实现这些需求。

其实,脚本化在行业中已经存在很多了,基本上所有做产品的公司都有脚本化的需求,主体功能不变,通过一个轻量的脚本语言在上面去做定制化需求。最典型的例子 JavaScript,JavaScript 出现时的平台产品是浏览器,通过一个脚本语言去完成浏览器上的一些额外功能,但是现在很少有人会把使用 JavaScript 叫做低代码。从某种程度上来讲,这类低代码产品最终会演变成程序员的工作,甚至引发新一类程序员的出现,而它本身则从低代码退化成为真正的代码。

第二类是我们希望看到的低代码,但是可能没有商业前景。目前企业内部仍然存在大量的人工操作和流程。这些操作或流程可能都有特殊之处,如果把它们自动化,就可以把大量的人力从繁琐的工作中解放出来。

但是企业很难关注这些流程,再加上想要自动化这些工作是很难的。不过我们会发现,在行业中出现了很多针对个人工作流的自动化工具,比如苹果的 automator, 昙花一现的 IFTTT,甚至更早的 yahoo pipes。这种简单的个人流程自动化低代码,通常是根据屏幕上发生的事情来触发,或者根据绘制的简单流程完成业务自动化的操作。

服务于个人生产力的低代码,既不会对行业造成影响,同时又有很明确的市场需求,但由于不赚钱,进入这个领域的人非常少。

第三类是现在常见的以降低程序员门槛为目的,想要说服企业使用便宜的人力成本去干活的低代码平台。在它们的宣传语中甚至会强调自己不只是低代码,而是无代码。

这类低代码其实就是之前出现过的使用表单去绘制工作流,然后在工作流程的每个节点上配上表、企业流程和 OA。

徐昊表示:“这类代码其实是最没有用的,它给行业传达了非常不好的信号——程序员的价值是不值钱的,它尝试说服企业的理由永远是程序员那么贵,使用我的工具,就可以使用更便宜的程序员了。事实上,这些能够实现的功能非常有限,甚至会导致很严重的结果,让一些不具备专业技能的人,使用极不趁手、效率低下的工具,来干写代码的工作。这是非常危险的,这样写出来的代码既难以维护,又难以测试,这一类的工具低代码平台是行业毒瘤。”

为什么我说低代码是行业毒瘤?

徐昊认为以降低程序员门槛为目的的低代码是行业毒瘤,但有意思的是,这类低代码平台在资本上是最受追捧的,因为它能讲出很美好的故事。原本企业需要花很多费用来雇佣程序员,而使用低代码工具就可以节约这部分成本。但仔细思考,就会发现这个故事的内在逻辑是有问题的。问题出在哪里呢?

第一,低代码平台预设的使用人群永远是初级、入门的人

以图形化工作流为例,当你完全不会写代码时,通过拖拽工作流这种直观的方式可以实现相关代码。但开发者会成长,不会永远处在同样的位置,而低代码平台预设的使用群体永远是初级、入门的人。

以面向幼儿编程的编程语言 Scratch 为例,它将代码结构表达为图形化的模块,通过图形化的拖拽拼搭代码。在这种情况下,即使是不识字的小朋友也可以通过拖拽去实现相关功能。但是小朋友不会永远不识字,当他成长之后,就会发现打字的效率是要远高于拖拽。

第二,低代码平台暗藏巨大的变革成本

根据徐昊的观察,目前绝大多数低代码厂商提供的产品都尝试覆盖完整的软件生命周期。企业购买之后,开发者在平台上按照平台的规则来编程。所以,低代码平台看似售卖的是开发工具,实际上卖的是一种工作模式,企业研发团队需要改变原本的工作模式。这种变革的成本是非常巨大的。

据徐昊所知,某厂商的研发部想要上线一个低代码平台来提升研发效能,但是上线之后,发现团队没有办法使用低代码平台来接管整个业务,再加上上线时间很紧张,所以权衡之后,他们又采购了另一个低代码平台,想要联合两个平台来解决问题,但现实是直到现在,他们还在尝试如何将低代码平台成功应用到企业业务中。

第三,风口不代表长期发展,低代码其实是个伪需求

在投资市场中,低代码似乎已经成为了一个新风口,很多研究机构都对低代码的未来做了分析和预测。Infolob 研究显示,低代码应用程序保持着 40% 的年复合增长率,预计到 2022 年,低代码应用程序市场总规模将达 212 亿美元。研究机构 Gartner 则预测,2024 年应用软件开发活动当中的 65% 将通过低代码方式完成,同时 75% 的大型企业将使用至少四种低代码开发工具进行应用开发。

那么,被资本市场看好是否意味着低代码的未来值得期待呢?

徐昊表示:“风口和长期发展并不能完全划等号。资本市场的投资策略往往是宁可错投、不可错过,而作为行业从业者,我是从基础逻辑来判断一项技术的未来,即它对行业长期发展是否有帮助。”

“低代码的出现确实是有市场机遇的,现在程序员缺口很大,大家都在 996,加班干活,所以我们需要一个提升效能的工具。但你仔细思考,对于很多企业来说,这其实是个伪需求,低代码的定位不是帮助从业者提升效能,而帮助小白来入门行业。软件从业者的效率会低于一个没有入门的人吗?显然不可能,所以与其关注低代码,不如关注针对程序员本身是否有工具可以帮助他,能否将他的流程进行有效的自动化。”

<think>嗯,用户想实现模数为10^9+7的多项式乘法,用编程语言怎么做呢?首先,我得回忆一下常见的多项式乘法方法。通常,快速傅里叶变换(FFT)和数论变换(NTT)是常用的方法。不过,用户提到的模数是10^9+7,这个数可能不适合直接用NTT,因为NTT需要模数满足某些条件,比如必须是形如k*2^m +1的素数,而10^9+7虽然是个大素数,但可能不满足这个形式。让我先确认一下10^9+7是否符合NTT的条件。 计算一下,10^9+7等于1000000007。现在检查它是否是形如k*2^m +1。假设存在这样的k和m,那么k*2^m =1000000006。分解这个数,看看是否能分解出一个较大的2的幂次。比如,1000000006除以2得到500000003,这显然是一个奇数,所以最大的2的幂是2^1。所以k=500000003,m=1。但这样的话,NTT要求较大的m,比如至少20左右才能处理较长的多项式,显然这里m=1不够,所以无法使用NTT。因此,用户的问题不能用标准的NTT来处理,必须考虑其他方法,比如拆系数FFT(MTT)或者三模数NTT。 接下来,我需要回忆这两种方法的原理。拆系数FFT是将大系数的多项式分解成较小的系数,进行FFT后再合并,这样可以避免精度问题。而三模数NTT则是使用三个适合NTT的模数分别计算,最后通过中国剩余定理合并结果。不过,用户提到的模数是10^9+7,可能需要较大的模数组合,这里可能需要选择三个满足条件的模数,然后合并结果。 现在,根据用户提供的引用,引用[1]和[2]提到当模数不满足FFT精度要求时,需要使用拆系数FFT(MTT)。引用[4]提到拆系数FFT分为4次和7次FFT的方法,其中7次更精确但更慢,4次更快但精度可能不够。对于模数10^9+7,系数相乘可能会超过double的精度,所以需要拆系数。 具体步骤应该是将每个系数拆成高位和低位,比如A(x)=A1(x)*M + A2(x),B(x)=B1(x)*M + B2(x),其中M是一个合适的数,比如2^15,这样拆分后的系数较小,FFT时不会溢出。然后进行四次FFT计算,分别计算A1B1, A1B2, A2B1, A2B2,再组合起来,最后取模。 另外,三模数NTT的方法需要找到三个模数,它们的乘积大于可能的最大结果,然后分别用这三个模数做NTT,得到结果后用中国剩余定理合并,最后再对10^9+7取模。这种方法需要这三个模数都满足NTT的条件,比如每个模数都是形如k*2^m +1的素数,并且它们的乘积足够大。 例如,常用的三模数组合是:469762049(原根3,长度支持2^26),998244353(原根3,支持2^23),1004535809(原根3,支持2^21)。这三个模数的乘积大约是4.7e+28,而两个多项式系数相乘后的最大值是(1e9)^2 * n,假设n是多项式的次数,比如n=1e5,那么最大系数是1e23,所以这三个模数的乘积足够大,可以覆盖。 因此,用户的问题有两种可能的解决方案:拆系数FFT或者三模数NTT。现在需要比较这两种方法的优缺点。拆系数FFT的精度依赖于浮点运算,可能存在精度问题,尤其是当系数很大时。而三模数NTT需要更多的计算步骤,但结果准确,因为NTT是精确的。 接下来,用户可能需要具体的实现步骤。比如,对于三模数NTT,首先分别对三个模数做NTT,计算每个模数下的卷积,然后用中国剩余定理将三个结果合并,最后对10^9+7取模。这需要实现NTT的函数,以及中国剩余定理的部分。 而对于拆系数FFT,需要将每个系数拆分为高位和低位,分别进行FFT,然后组合结果,处理进位,最后取模。这需要处理复数运算,并注意精度问题。 现在,用户可能需要代码示例。例如,对于三模数NTT,可以给出三个模数的NTT实现,然后合并结果。对于拆系数FFT,可能需要使用库中的FFT函数,并进行系数拆分。 需要注意的是,编程实现时,选择哪种方法取决于具体需求。如果对精度要求极高,且模数允许,三模数NTT可能更可靠。而拆系数FFT可能在实现上更复杂,尤其是处理浮点误差。 综上所述,用户的实现步骤可能包括:选择合适的方法(拆系数FFT或三模数NTT),实现相应的算法,处理模数,合并结果。接下来,我需要将这个过程整理成结构化的回答,并生成相关问题。</think>### 实现模数$10^9+7$的多项式乘法算法 #### 方法选择分析 模数$10^9+7$无法直接使用常规NTT,因为其不满足$k \cdot 2^m +1$形式[^3]。需选择以下两种方法之一: 1. **拆系数FFT(MTT)**:将系数分解为高位和低位,通过多次FFT降低精度压力[^2][^4] 2. **三模数NTT**:使用三个符合NTT条件的模数分别计算,通过中国剩余定理合并结果 #### 方案一:拆系数FFT(4次FFT优化版) ##### 实现步骤 1. **系数拆分**:设$M=2^{15}$,将多项式$A(x)$拆分为: $$A(x) = A_1(x) \cdot M + A_2(x)$$ 其中$A_1(x)$存储高位,$A_2(x)$存储低位 2. **并行FFT计算**: ```python def multiply_mod(a, b, mod=10**9+7): M = 1 << 15 # 拆分系数 a1 = [x // M for x in a] a2 = [x % M for x in a] b1 = [x // M for x in b] b2 = [x % M for x in b] # 计算四个卷积 c11 = convolve(a1, b1) # 需要实现FFT卷积 c12 = convolve(a1, b2) c21 = convolve(a2, b1) c22 = convolve(a2, b2) # 合并结果 result = [] for i in range(len(c11)): val = (c11[i] * M * M % mod + (c12[i] + c21[i]) * M % mod + c22[i]) % mod result.append(val) return result ``` 3. **精度控制**:需使用`long double`类型存储FFT计算结果,且多项式长度不超过$10^5$ #### 方案二:三模数NTT ##### 实现步骤 1. **选择三个NTT友好模数**: - $m_1=469762049$(支持长度$2^{26}$) - $m_2=998244353$(支持长度$2^{23}$) - $m_3=1004535809$(支持长度$2^{21}$) 2. **分别计算NTT结果**: ```python def ntt_multiply(a, b, mod): # 实现NTT卷积的具体代码 ... c1 = ntt_multiply(a, b, m1) c2 = ntt_multiply(a, b, m2) c3 = ntt_multiply(a, b, m3) ``` 3. **中国剩余定理合并**: $$x \equiv c_1 \mod m_1$$ $$x \equiv c_2 \mod m_2$$ $$x \equiv c_3 \mod m_3$$ 使用扩展欧几里得算法合并三个同余式 4. **最终取模**: $$result = x \mod (10^9+7)$$ #### 性能对比 | 方法 | 时间复杂度 | 精度保证 | 实现难度 | |---------------|------------|----------|----------| | 拆系数FFT | $O(n \log n)$ | 依赖浮点精度 | 中等 | | 三模数NTT | $O(n \log n)$ | 绝对精确 | 较高 | [^1]: 当系数超过$10^{16}$时,double类型将无法精确表示 [^2]: 拆系数FFT通过分解系数控制数值范围 : NTT需要特定形式的模数支持 [^4]: 7次FFT方案精度更高但更耗时
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值