JavaRush /Java 博客 /Random-ZH /喝咖啡休息#64。如何编写干净的代码。为什么对于低延迟系统来说 Java 比 C++ 更好

喝咖啡休息#64。如何编写干净的代码。为什么对于低延迟系统来说 Java 比 C++ 更好

已在 Random-ZH 群组中发布

如何编写干净的代码

来源:Dev.to 编写干净的代码就像写诗。这首诗应该简洁、易懂、易于改变。干净的代码意味着可扩展的组织。这意味着做出改变不会造成混乱。编写此类代码的能力是经验丰富的开发人员的关键素质之一。在几个人推荐我读《Clean Code》这本书后,我终于鼓起勇气读了它。事实证明,这是一本封面完全符合其炒作的书。书中的建议清晰、具体、实用,甚至还带有幽默感。今天我想与大家分享这本书的主要收获。喝咖啡休息#64。 如何编写干净的代码。 为什么对于低延迟系统来说 Java 比 C++ 更好 - 1

1. 代码不仅要能工作,还要可读

软件的大部分成本与长期支持有关。因此,你写的代码必须清楚地表达你的意图。它应该使得加入团队的新开发人员能够轻松理解代码中到底发生了什么以及为什么。作者编写的代码越容易理解,其他开发人员理解它所需的时间就越少。这减少了缺陷和维护成本。 如何实现这一目标?良好的命名+具有单一职责的类和函数+编写测试。

2. 后来意味着永远不会

老实说:有时我们都向自己保证稍后会回来清理代码,但最终我们忘记了这一点。 不要留下不再需要的无用代码片段。它们会让其他开发人员感到困惑并且没有价值。因此,在更改功能时,请务必删除旧代码。如果某个地方出现问题,测试仍然会立即显示出来。 如何实现这一目标?删除代码可能会很可怕,尤其是在大型架构中。所以测试是这里的关键。它们使您可以放心地删除代码。

3.特征要小

编写函数的第一条规则是它们应该很小,最多大约 20 行。函数越小,越专注于一项任务,就越容易为其找到一个好名字。至于函数参数,理想的数量是0。接下来是1、2,但你应该尽量不超过3个参数, 如何实现呢?函数的编写应遵循单一责任、开放/封闭的原则。

4. 代码重复不好

重复是组织良好的系统的敌人。这是额外的工作、额外的风险和额外不必要的复杂性。 该怎么办?确保你的代码是按照 DRY 原则编写的,独立且模块化。

5. 唯一好的评论是你找到了不写的方法。

“没有什么比在正确的地方发表好评论更有用的了。但即使在最好的情况下,评论也是一种不可避免的罪恶。” 注释旨在弥补我们无法用代码表达我们的想法的情况。也就是说,这最初是承认失败。是的,我们必须使用它们,因为我们不能总是通过代码清楚地表达我们的意图,但这并不是值得庆祝的理由。问题是,评论常常撒谎。并不总是,也不是故意的,但太频繁了。注释越旧,离它所描述的代码越远,它就越有可能是不正确的。原因很简单:程序员无法很好地维护代码和所有注释。因此,注释常常与它们引用的代码分离,并成为精度最低的孤立注释。 该怎么办?必须使用描述性命名方法。当你读到变量的名称时,你应该立即明白它是什么。还需要进行测试,以便其他开发人员了解哪些功能最重要。

6. 对象揭示行为,但不揭示数据。

模块不应该知道它所操作的对象的内部结构。对象隐藏其数据并揭示其操作。这意味着对象不应通过访问器方法公开其内部结构。没必要让每个人都看到你的裸体。 该怎么办?变量的范围应尽可能是局部的,以免暴露超出必要的范围。

7. 测试

测试代码与投入生产的代码同样重要。因此,它必须随着项目的发展而改变和成长。 测试使您的代码保持灵活、可维护和可重用。如果没有它们,任何更改都可能会导致错误。测试使您可以清理代码,而不必担心某些内容会损坏。因此,保持测试的纯度非常重要。测试的简洁性确保了它们的可读性。测试是一个用简单语言向其他开发人员解释代码作者意图的机会。因此,我们在每个测试函数中仅测试一个概念。这使得测试具有描述性,更易于阅读,如果失败,也更容易追踪其原因。 如何实现这一目标?必须遵循干净第一测试的原则。测试应该是:
  • 快速地。测试必须快速运行。如果您必须等待太长时间才能运行测试,则不太可能更频繁地运行它。
  • 独立/隔离(Independent)。测试应尽可能相互隔离和独立。
  • 可重复。测试应该在任何环境(开发、登台和生产)中都是可重复的。
  • 自我验证。测试结果必须是布尔值。测试必须要么通过,要么失败。
  • 彻底。我们应该努力通过测试覆盖所有边缘情况、所有安全问题、每个用例(use case)和happy path(对代码最有利的场景)。

8. 处理错误和异常

您抛出的每个异常都应该提供足够的上下文来确定错误的来源和位置。通常,您有任何异常的堆栈跟踪,但堆栈跟踪不会告诉您失败操作的目的。如果可能,请避免在代码中传递 null。如果您想从方法中返回 null,请考虑抛出异常。将错误处理作为一项单独的任务,可以独立于主逻辑进行查看。 如何实现这一目标?创建信息丰富的错误消息并将其与异常一起传递。指定失败的操作和错误类型。

9. 课程

班级规模应该很小。但需要计算的不是代码行数,而是责任。类名是描述其职责的关键。我们的系统应该由许多小类组成,而不是几个大类。每个这样的小类必须封装一个单一的职责。每个类的存在必须只有一个特定的原因,并且每个类必须与其他几个类“合作”以实现系统所需的行为。很少有充分的理由来创建公共变量。削弱封装始终是最后的手段。此外,实例变量应该很少。良好的软件设计允许在无需大量投资或返工的情况下进行更改。缩小变量范围使这项任务变得更容易。 如何实现这一目标?关注点分离是最古老、最重要的设计技术之一。类应该对扩展开放,但对修改关闭。在理想的系统中,我们通过扩展系统而不是更改现有代码来启用新功能。

10. 格式化

每条空线都是一个视觉提示,有助于识别一个新的、独立的概念已经开始。 局部变量必须出现在函数的顶部。 实例变量必须在类的顶部声明。 短线比长线更好。通常限制为 100-120 个字符;不应使其更长。 如何实现这一目标?大多数参数都可以传递给 CI 或文本编辑器中的 linter。使用这些工具使您的代码尽可能干净。

程序开发原则

使用以下技术,您的代码将始终保持干净: 命名变量。选择适当的名称(良好的命名)对于使代码可读并因此可维护至关重要。 “你应该像为你的长子一样负责任地为变量选择一个名字。” 选择好名字对于开发人员来说通常是一个挑战。这需要良好的描述技巧和共同的文化背景。干净的代码是由完全不同的开发人员阅读和改进的代码。变量、函数或类的名称应该回答所有基本问题:这个实体为什么存在、它的用途和用途。如果一个名称需要注释,则意味着它没有充分揭示其所描述内容的本质。较长的名称比较较短的名称更重要,任何可搜索的名称都比常量更好。单字母名称只能用作短方法内的局部变量:名称的长度必须与范围匹配。方法名称必须是动词或动词短语;类名不能是动词。 依赖性应保持在最低限度。依赖你能控制的东西比依赖你无法控制的东西更好。否则这些东西就会控制你。 准确性。每一段代码都应该位于读者期望找到它的地方。代码库的导航应该直观,并且开发人员的意图应该明确。 打扫。不要在代码库中留下无用的代码(旧的且不再使用或创建的“以防万一”)。减少重复并尽早创建简单的抽象。 标准化。编写代码时,您应该遵循为存储库建立的风格和实践。 自律。随着所用技术的发展和新技术的出现,开发人员通常希望更改和改进现有代码中的某些内容。不要太快屈服于炒作:彻底研究新堆栈,并且仅针对特定目的。保持代码库清洁不仅仅是对当前和未来的同事有礼貌。这对于该程序的长期生存至关重要。你的代码越干净,开发人员就越高兴,产品就越好,并且持续时间越长。

为什么对于低延迟系统来说 Java 比 C++ 更好

来源:StackOverflow 作为开发人员,我们都知道有两种方法可以做事:手动、缓慢且烦人,或自动、困难但快速。我可以使用人工智能为我写这篇文章。这可以节省我很多时间——人工智能每秒可以生成数千篇文章,但我的编辑可能会不高兴得知生成第一篇文章需要两年的时间。喝咖啡休息#64。 如何编写干净的代码。 为什么对于低延迟系统来说 Java 比 C++ 更好 - 2开发低延迟的软件系统时也会出现类似的情况。传统观点认为,使用 C++ 以外的任何语言都是疯狂的,因为其他语言都有太多的延迟。但我来这里是为了让您相信相反的、反直觉的、近乎异端的观念:当谈到在软件系统中实现低延迟时,Java 更好。在这篇文章中,我想举一个看重低延迟的软件的具体例子:交易系统。然而,这里提出的论点可以应用于几乎任何需要或期望低延迟的情况。只是针对我有经验的开发领域进行讨论会更容易。事实上,延迟是很难测量的。这一切都取决于你所说的低延迟是什么意思。现在让我们弄清楚这一点。

后天智慧

由于 C++ 更接近硬件,因此大多数开发人员会告诉您用这种语言进行编码具有速度优势。在低延迟情况下,例如高速交易,几毫秒就可以区分出可行的软件和遗留的磁盘空间浪费,C++ 被认为是黄金标准。至少过去是这样。但现实情况是,许多大型银行和经纪商现在都使用用 Java 编写的系统。我的意思是用 Java 原生编写,而不是用 Java 编写然后用 C++ 解释以减少延迟。这些系统甚至正在成为一级投资银行的标准,尽管它们(据称)速度较慢。发生什么了?是的,C++ 在执行代码时可能具有“低延迟”,但在部署新功能甚至寻找可以编写代码的开发人员时绝对不是低延迟。

Java 和 C++ 之间的(真实)差异

当谈到现实系统中 Java 和 C++ 之间的差异时,开发时间问题只是一个开始。为了了解每种语言在这种情况下的真正价值,让我们更深入地研究一下。首先,重要的是要记住在大多数情况下 C++ 比 Java 更快的真正原因:C++ 指针是内存中变量的地址。这意味着该软件可以直接访问各个变量,而不必爬行计算密集型表来查找它们。或者至少可以通过指定它们的位置来解决,因为使用 C++,您通常必须显式管理对象的生命周期和所有权。因此,除非您真的擅长编写代码(这种技能可能需要数十年才能掌握),否则 C++ 将需要数小时(或数周)的调试。任何尝试过调试蒙特卡罗引擎或 PDE 测试工具的人都会告诉您,尝试从根本上调试内存访问可能非常耗时。仅仅一个错误的指针就可以轻松地导致整个系统瘫痪,因此发布用 C++ 编写的新版本确实是一件可怕的事情。当然,这还不是全部。喜欢用 C++ 编程的人会指出 Java 的垃圾收集器遭受非线性延迟峰值的困扰。在使用遗留系统时尤其如此,因此在不破坏客户端系统的情况下发送 Java 代码更新可能会使它们变得如此缓慢以至于无法使用。作为回应,我想指出,在过去十年中,为了减少 Java GC 造成的延迟,我们做了很多工作。LMAX干扰器例如,是一个用 Java 编写的低延迟交易平台,也是作为一个框架构建的,与其运行的硬件具有“机械交互”并且不需要锁定。如果您构建一个使用持续集成和交付 (CI/CD) 流程的系统,则可以进一步缓解问题,因为 CI/CD 允许自动部署经过测试的代码更改。这是因为 CI/CD 提供了一种迭代方法来减少垃圾收集延迟,Java 可以逐步改进并适应特定的硬件环境,而无需在交付之前为不同的硬件规格准备代码的资源密集型过程。由于 IDE 的 Java 支持比 C++ 广泛得多,因此大多数框架(Eclipse、IntelliJ IDEA)都允许您重构 Java。这意味着 IDE 可以优化代码以实现低延迟性能,尽管这种能力在使用 C++ 时仍然受到限制。即使 Java 代码在速度上与 C++ 不太匹配,大多数开发人员仍然发现在 Java 中比在 C++ 中更容易实现可接受的性能。

我们所说的“更快”是什么意思?

事实上,我们有充分的理由怀疑 C++ 是否真的比 Java“更快”,甚至具有“更低的延迟”。我意识到我正陷入一些相当黑暗的水域,许多开发人员会开始质疑我的理智。但请听我说完。让我们想象一下这样的情况:您有两个开发人员 - 一个用 C++ 编写,另一个用 Java 编写,您要求他们从头开始编写一个高速交易平台。因此,用 Java 编写的系统比用 C++ 编写的系统需要更长的时间才能完成交易。然而,Java 中未定义行为的实例比 C++ 少得多。举一个例子,在数组外部建立索引在 Java 和 C++ 中都是一个错误。如果您不小心在 C++ 中执行此操作,则可能会出现段错误,或者(更常见的是)您最终只会得到一些随机数。在 Java 中,越界总是会抛出ArrayIndexOutOfBoundsException错误。这意味着 Java 中的调试要容易得多,因为错误通常会立即被识别出来,并且错误的位置也更容易被追踪。此外,至少根据我的经验,Java 更擅长识别哪些代码不需要运行,哪些对于软件的运行至关重要。当然,您可以花几天时间调整 C++ 代码,使其绝对不包含无关代码,但在现实世界中,每个软件都包含一些臃肿的内容,而 Java 更擅长自动识别它。这意味着在现实世界中,即使按照标准延迟指标,Java 通常也比 C++ 更快。即使情况并非如此,语言之间的延迟差异也常常被其他因素所掩盖,即使在高速交易中,这些因素也不足以产生影响。

Java 对低延迟系统的好处

在我看来,所有这些因素都为使用 Java 编写高速交易平台(以及一般的低延迟系统,稍后会详细介绍)提供了非常令人信服的论据。不过,为了稍微影响一下 C++ 爱好者,让我们看看使用 Java 的一些其他原因:
  • 首先,Java 在软件中引入的任何额外延迟可能会比影响延迟的其他因素(例如互联网问题)少得多。这意味着任何(编写良好的)Java 代码在大多数交易情况下都可以轻松地与 C++ 一样执行。

  • Java 较短的开发时间也意味着,在现实世界中,用 Java 编写的软件可以比 C++ 更快地适应硬件变化(甚至新的交易策略)。

  • 如果您深入研究这一点,您会发现即使优化 Java 软件也比 C++ 中的类似任务更快(当考虑到整个软件时)。

换句话说,您可以很好地编写Java代码来减少延迟。您只需将其编写为 C++,并在开发的每个阶段牢记内存管理即可。不用C++编写的好处是,用Java调试、敏捷开发、适应多种环境更容易、更快。

结论

除非您正在开发低延迟交易系统,否则您可能想知道上述任何内容是否适用于您。除了极少数例外,答案是肯定的。关于如何实现低延迟的争论对于金融界来说既不新鲜也不独特。因此,对于其他情况,可以从中吸取宝贵的教训。特别是,上面关于 Java“更好”的论点是因为它更灵活、更容错、最终开发和维护速度更快,可以应用于软件开发的许多领域。我(个人)更喜欢用 Java 编写低延迟系统的原因与该语言在过去 25 年中如此成功的原因相同。Java 易于编写、编译、调试和学习。这意味着您可以花更少的时间编写代码,而花更多的时间优化代码。在实践中,这会带来更可靠、更快速的交易系统。这对于高速交易来说是最重要的。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION