所有人都不知道怎么写代码

在莫斯科Python Conf ++的前夕,我们与We Do Services公司的CTO Nikita Sobolev谈了关于在编程语言开发过程中管理代码复杂性的全球性问题。 以及为什么随着时间的流逝,情况只会变得更糟。 另外,他们问为什么他需要创建自己的短绒棉。




-告诉我们一些关于您自己和您的工作的话。

我是“我们做服务”的技术总监。 在谈到公司名称时,我通常会问一个问题:“您怎么看,我们在做什么?”。 实际上,我们专注于Web开发:面向企业客户的前端和后端。 我们根据自己的方法进行工作,并且随着公司的发展而不断改进-可重复软件开发流程(RSDP)。

-在莫斯科Python Conf ++上,您将进行讨论,包括您自己的短毛绒。 您的工作与审核和代码复杂性管理有何关系?

总的来说,我们有两个主要领域:开发本身及其周围的一切:咨询,制定需求,尤其是审计,在此期间,我可以看到许多其他人的代码。 代码完全不同:现在正在开发的代码和遗留的代码(没人会修复); 以及客户专家编写的代码,以及他们在旁边订购的代码。 在所有版本的代码中都有很多问题:相同和不同。

-您将专门针对Python开发人员。 Python在管理代码复杂性方面是否具有任何功能?

当然可以!

首先,至少在阅读代码时,由于缺少附加上下文,所有具有动态类型的语言都会在很大程度上遭受不合理的复杂性的困扰。 并且允许您更多的污垢。

其次,Python正在积极开发。 它在标准库中具有新的语法元素,新概念和模块,可以打破以前的所有内容。

-Python中的所有内容有多糟糕? 毕竟,还有其他积极开发的语言,例如JavaScript,经常因此而受到批评。 JavaScript更好吗?

不行 我什至要说,就复杂性而言,Python在其他语言方面是相当不错的。 JavaScript确实很糟糕,原因很简单:在JS项目代码中,与语言本身不相关的几个实体立即混合在一起-用于构建项目的第三方插件和库。 例如,如果您使用Webpack,则可以编写函数import(),以异步方式加载模块。 事实证明,收集器会将其某些内容塞入您的编程语言中,最后通常不清楚发生了什么。

当语言从安装Babel或其插件而改变时,管理复杂性是困难的。 为了理解它们的工作原理,您需要遵循语言标准,特定的实现方式等。

在Python中,情况要好得多。 语言正在相当系统地发展,这种发展具有可理解的里程碑。 在其中,您不能在配置中用两行来根本地更改语法。 而且这仍然是一个后端,我们已经习惯了对后端提出更高的要求。 但是,我认为,Python中有许多新变化打破了以往的局面,带来了可疑的收益。

-也就是说,随着语言的发展,一切都会变得更糟吗?

如果您还记得AsyncIO的出现-本质上是Python中的第二种语言-当然,其复杂性已经大大提高了。 实际上,现在有两种具有相似语法的完全独立的编程语言:Python和Python + AsyncIO。 也就是说,作为一个实体的Python变得更加复杂了两倍,因为它有两个根据不同规则工作的独立后代。

这些是不同的编程语言的观点并不流行。 但是,当您要求反对者(例如,从同步代码运行异步函数)时,它们将失败。 图书馆也完全不同。 想要使用同步库来处理数据库-请。 而您想要异步-不是。

但是在五年前编写的Python中,什么都没有真正改变,反之亦然,出现了简化代码的工具,例如注释和类型检查。

-复杂性管理是否会影响这样的事实,即在编程中现在有很多人的技术基础薄弱?

当然可以 对于这类人,他们甚至想出了一种特殊的编程语言。 叫做Go。 我不是在开玩笑 确实,创建Go语言的目标是尝试吸引无法学习C ++编写代码的Google学生和实习生。 Python在性能上不适合他们,他们需要其他东西,而Google提出了Go。 事实证明,因为它非常简单,所以很多人已经准备好写它了。 但是,以何种代价实现了这种简单性? 它们不是给我们普通的编程语言,而是给我们截断的版本-实际上,在设计上没有复杂的概念。 没有泛型,没有异常等。 这种方法有很多支持者。

但是还有其他开发人员,对他们来说,问题是有些语言之间没有平衡:您可以简单地做简单的事情,而根本不能做复杂的事情。 或至少通过痛苦-您必须使用工具来做某事。 在我看来,这是管理复杂性的问题。

-他人代码的典型问题是什么?

通常,它们分为两部分。

首先是与以下事实有关的问题:人们无法就将条件逗号放在何处达成共识。 您阅读一个代码,在一个地方看到逗号,切换到另一文件-在另一个地方看到逗号。 这使感觉变得复杂,就好像在读一本书以粗体显示在另一处并以斜体显示时一样。 这分散了内容的注意力,因为大脑必须认识到这是书写同一事物的另一种方式。

纠正语法时,您开始关注语义,因为人们在概念上的写法有所不同。 不幸的是,无法在这个水平上达成共识-不可能达成共识,我们将以这种方式解决此类问题,但这就是事实。 最初不可能涵盖所有情况。 此过程发生在对立即任务的代码审查中:当向开发人员解释为什么无法做出决定时。 如果应用代码审查的实践并且审查者很好,他们将切断解决方案曲线,并且代码中没有问题。 但是通常我们会在没有建立此类流程的地方进行审核。 语义和体系结构的问题更难解决,因为有时甚至很难自己制定和定义它们。

-实际情况如何?

例如,人们可以在模板,视图或模型中解决相同的问题。 而且,没有普遍接受的理解应该确切地解决该任务的位置:没有专门适用于该项目的文档或模式(例如,在这里我们使用粗模型,并将所有逻辑放入其中,但是在这里我们使用薄模型;好的或坏的,现在没关系,但我们同意。)

“您认为这些问题甚至存在的主要原因是什么?”

所有人都不知道如何编写代码。

本文的解读如下:问题是我们是人。 通常,对于我们来说,编写结构化和逻辑性的内容非常困难。 在这里,我们还有两种不同类型的收件人。 首先,这是将读取此代码的人,其次,这是必须执行该代码的机器。 机器的代码应根据性能,内存消耗和CPU时间的标准来创建,人的代码应基于可读性,清晰度等原则。 这是两个相反的任务。 实际上,一个人甚至不能完全解决其中的一个,却被迫同时解决两个矛盾的任务。

“但是使用不同的编程模式本质上是一项工程搜索吗?” 真的不好吗?

当然,工程研究是重要且必要的。 但是他也必须是可控的。 在执行每个此类任务之前,有必要设定明确的标准和限制:根据花费的时间,业务需求,工程实践和工具。

我更有可能观察到创造性的搜索。 没有这种限制,也可以验证所获得的结果。 与当代艺术一样,质量无法衡量。

几乎所有要求我们进行审计的客户都遇到一种典型的情况:有人对他们做了一些事情,他们雇用了开发人员以某种方式开发解决方案,但他来了,伸出了双手:“我不知道在这里,让我们重写所有内容。” 重写会很好吗? 不会的。 当您决定重写时,您将采取完全相同的步骤:将任务委托给另一个犯其他错误的开发人员,但最终一切都完全相同。

-是否需要其他方法?

是的 在审核过程中,我们尝试找出导致代码问题的原因:为什么没有人采取并将模块充气到难以滚动的地步,以及为什么最初做出了错误的决定。 而且,我们正在尝试在给定的范围内自动执行或简化正确的决策。

我将在报告中介绍一些内容。 每个人都知道代码是由行组成的-这是它可以组成的最简单的实体。 每行可以写成

x = 1

也许像

x = Math.median(forecast_data) if forecast_data else compute_probability(default_model)

这两行之间有很大的不同,因为您容易理解第一行,而第二行集中了很多逻辑。 必须与解释程序并行在头中执行它。 因此,您需要通过控制一行代码来开始控制代码的编写方式。 更进一步,这条线变成了更复杂的概念-函数,类,模块等。 但是您接受的规则必须是一个。

结果,我们不禁止完成许多事情。 因为管理是关于禁止的。

-您在别人的代码中遇到过有趣的事情吗?

当然可以 我什至还有一个收集此类代码示例的存储库

我看到的最可怕的示例告诉我,在一百次迭代的循环中,您可以定义一个函数。 老实说,当我看着它的时候,我的翻译器坏了。 我猜了,但不知道有可能。

在某些情况下,我们在代码中看到了很多有趣的注释。 有人抱怨生活,关于工作,有人写道:“我知道我在写废话,但是顾客强迫我这么做。” 但是,客户通常不会强迫您编写错误的代码。 他们要求解决他们的问题,您在那里写什么代码,他们不在乎。

-Linter,代码审查-不保存?

我有两个答案。 是的,他们有。 不,他们不保存。 如果您严格遵守带衬里的灯笼(为您做很多粗活的人:检查函数的复杂性,代码语义等)所提供的规则和规定,那么它会有所帮助。 此项目必须被阻止。 有时您不能只是运行短绒棉絮来查看结果。 如果您违反了这些规则,则根本不应该在生产环境中发布代码。

但实际上-它们无法保存。 因为那些使用它的项目很少。

顺便说一句,他们经常问我:该如何介绍? 我的回答是:很简单,您在CI中放置一行-检查我的代码-如果它崩溃了,就实现了。 它只是重构所有内容。 幸运的是,现在有了自动格式化程序和逐个文件重构代码的功能。 接下来的问题是传统的:如何向企业解释这很重要?

-这个问题有什么一般答案吗?

对于每种情况,答案都是不同的,因此在一般情况下很难表述(您需要考虑一下……)。 但是通常处理此问题的公司来自技术方面。 即 技术人员问我们,因为那些知道如何谈论业务的人以及对技术了解的人都知道如何在特定情况下向业务解释这一点。 有了这样的问题说明,这非常简单。 当你来的时候,一切都已经很糟了,每个人都明白这一点。 与企业的对话开始是这样的:“您可能认为您的程序员坐在那里什么都不做?” 并且企业点头。 你说那不是重点。 程序员是极好的人,他们试图解决您的问题。 但是,如果没有用于项目管理的集成方法,一切都会陷入混乱,这是正常的。

我们建议提出规则以避免某些问题。 我们考虑引入不同部件的成本,然后从尚无此类部件的事实来评估实际(完成)的损失。 例如,如果您使用特定的方法和工具,程序员已经修复了一个月不存在的错误,或者一个在30秒内可以发现的错误。 这些数字令人信服。

-最后,这是一个管理问题吗?

当然可以 我坚信程序员想要编写好的代码。 但是有很多障碍。 有人因为经验不足而不知道如何做。 有人失去了动力,因为每个人都不在乎。 有人不知道什么是好的代码,原因就是创造性的投掷。 他们向某人施加压力-他想要并且可以写作,但他们告诉他应该是明天。 他不但没有与企业建立合作伙伴关系,而且没有解释为什么明天不会发生这种情况(或者如果发生这种情况,那么就必须再统治三天),他还是这样做。 这种伙伴关系对企业本身很有趣。 他还需要使其长期工作并且维护成本低廉。

也就是说,所有问题都在这里得到解决:没有不可解决的矛盾。

-有一种代码样式-PEP8。它无助于快速了解什么是好的?

就逗号而言,它会有所帮助。 但是,如果您将逗号放在正确的位置,而其他所有内容都不好,那又有什么意义呢?

-缺少一些知名的高级物品?

从理论上讲,有一些最佳的工程实践。 但是它们要么未知,要么被忽略。 当您问为什么开发人员不遵循这种做法时,他说他听说这是一个很好的话题,但是代码就是这样工作的。 当代码停止工作时,您问他是否理解相应的最佳实践来自何处以及为什么要遵循它? 不,我不明白。 他认为自己只是误会了。

很难向一个人解释犯错是正常的。 每个人都是错误的,我们都是人类。 但是,只是发明了最佳的工程实践,以使您免于犯错误或使您免于后果。 即 与企业中一样,它是一种安全工具。 它不是用鲜血写的,而是用了很多时间和金钱。

通常,我们无法实现的全局任务是使代码审查自动化,以便Python本身(如果我们在谈论我们的案例)知道如何编写代码。 这应该是一个不仅提供机会,而且为开发人员提供限制的工具。

-为什么还要开发短绒呢? 是否可以使用(或开发)现有的?

实际上,我们这样做。 我们的linter实际上是Flake8的插件。 我们只是将其定位为成熟的工具,而不仅仅是插件。

为什么选择Flake8,而不选择Pylint? 皮林特做了​​很多皮棉不应该做的事情。 例如,尽管类型检查器必须处理类型,但是它实现了大量的类型检查。 另外,它会产生大量错误,而实际上并非如此。 而且我不喜欢他的文档,而且我担心他自己实现的ast。 难以配置。 通过启用配置,您使人们做出错误的选择。 因此,我们的任务是制作一个无法配置的工具。 所以你说了-仅此而已。

-哪些指南构成了该短毛绒的基础? 还是只是您自己的经历?

现在,它基于我们多年来在代码审查中一直为自己制定的规则。 一些规则是从其他linter移植而来的:ESLint,Pylint,SonarQube,Credo。 认知复杂性的出色工作取得了很多成果 。 总是回头看米勒的钱包。 单独的规则-这是我的愿景,它是在评估了大量其他人的代码之后出现的。 也就是说,在此阶段它是一个“大杂烩”。

-您将在Moscow Python Conf ++上谈论什么?

首先,关于复杂性管理 。 本主题是所有开发人员都可以理解和理解的。 我们将研究不同的度量标准,以及将复杂度从最简单的组件代码(行)转移到最复杂的模块的方法。 然后,我们将讨论暂存部分,在此我将介绍我对如何用Python编写或不应该用Python编写的看法,并要求用户对自己喜欢的东西和不喜欢的东西进行投票。 对于许多开发人员而言,限制(执行A但不执行B)是对他们创作空间的一种尝试,因此他们对此反应非常猛烈。 在这里,您可以开始一个有趣的讨论。

-报告的重点是谁?

我认为这些仍是成熟的开发人员,因为新手程序员尚未形成明确的意见。 尽管让他们倾听并大声说话很有趣。 他们绝对是我们的用户。



, , Moscow Python Conf++ . . , .

Source: https://habr.com/ru/post/zh-CN424393/


All Articles