与软件复杂性的永无止境的战斗

与软件复杂性的永无止境的战斗

什么是复杂性?

最近读完了《软件设计哲学》,第二章探讨了软件复杂性的话题。 

《软件设计哲学》一书实际定义了复杂性:

“复杂性是指与软件系统的结构相关的任何使其难以理解和修改的事物。”

换句话说,复杂性可以有多种形式,并且不一定与性能有任何关系,你的代码可以是高性能的但仍然很复杂

我想在本文中分享本书中的一些关键定义和见解。但首先,让我们想象一个您可能已经经历过的常见情况……

一个简短的恐怖故事

让我们深入探讨一个你们中的许多人可能经历过或将要经历的恐怖故事。

它从一个简单的 CRUD 任务管理应用程序开始。代码干净、模块化且易于维护。开发团队很高兴,系统对于最初的客户来说运行得很好。

当销售团队将系统出售给一家大公司时,问题就开始了,声称它具有日历集成、电子邮件通知和令人惊叹的报告生成器。销售完成后,这些功能必须快速实施。

日历集成: 团队必须与 Google 日历和 Outlook 集成。不同的开发人员实施了解决方案,导致方法不一致。

电子邮件通知:接下来添加了电子邮件通知。一位开发人员使用特定的库,而另一位开发人员创建了自定义解决方案。混合的方法使代码变得混乱。

报告生成器: 对于报告生成器,开发人员使用了各种技术:PDF、Excel 导出和交互式仪表板。缺乏统一的方法使维护成为一场噩梦。

不断增长的复杂性:每个功能都是独立快速开发的,导致功能之间存在依赖关系。开发人员开始创建“快速修复”以使一切正常运行,从而增加了系统的复杂性和耦合性。

软件开发不是凭空发生的;各种内部和外部因素都会对其产生影响。我们都曾经历过或将会经历过这样的情况。

结局的开始

然后问题就开始了:

系统某一部分的变化意外地影响了其他部分。小改动需要修改许多其他文件,使得估计变得困难。月复一月,代码变得越来越难以理解,通常通过反复试验来修复。生产力下降,每个人都害怕维护任务。不可避免地呼吁“我们需要重构。”某些任务只能由特定的开发人员处理(经典)随着时间的推移,曾经编写精美且文档齐全的软件变成了火车残骸。

命名症状

很明显,我们现在拥有一个复杂的系统。

现在让我们“剖析”这种复杂性,以便更容易识别和减轻它。

嗯,“缓解”的意思是:

“减轻严重性、严重性或痛苦;减轻。”

我相信复杂性通常是代码所固有的。有些事情本质上是复杂的。作为开发人员,您的角色不仅仅是创建计算机可以高效执行的代码,还要创建未来的开发人员(包括未来的您)可以使用的代码。

“控制复杂性是计算机编程的本质。”

— 布莱恩·科尼汉

上述书籍的作者指出,复杂性通常以三种方式表现出来,我们将在这里进行探讨。

改变放大

当看似简单的更改需要在许多不同的地方进行修改时,就会发生更改放大。

例如,如果产品负责人请求“优先级”或“完成日期”字段,并且您的实体紧密耦合,那么您需要进行多少更改?

认知负荷

认知负荷是指开发人员完成任务所需的知识量和时间。

想象一下这样的场景:一位新开发人员加入了团队,他被指派修复报告生成器中的错误。为了完成此任务,开发人员需要:

了解不同的日历集成(Google 和 Outlook)。掌握电子邮件通知的不同方法。浏览报告生成器的碎片代码,处理 PDF、Excel 和仪表板。整合这些不同的技术和风格来查找并修复错误。

这是典型的“无法估计”场景,任务可能需要 1 分或 8 分——最好掷 D20 并做出相应的反应。

未知的未知

未知的未知是当你不知道你不知道的事情时。

这是复杂性最糟糕的表现,因为你可能会改变不应该改变的东西,导致一切都崩溃。

示例:开发人员修改了电子邮件发送代码以添加新通知,但没有意识到这会影响依赖于该函数的报告生成器。这给客户带来了重大问题,体现了紧急复杂性的最坏形式。

复杂性的原因

看完恐怖故事和三个主要症状,让我们看看是什么导致了复杂性。

1. 依赖关系

依赖关系在软件中是必不可少的,并且无法完全消除。它们允许系统的不同部分相互作用并一起运行。然而,如果管理不当,依赖关系会显着增加复杂性。

定义:

当代码无法单独理解或修改时,就存在依赖关系,需要考虑或修改相关代码。

依赖项类型:

Direct: 模块A直接依赖模块B。传递性: 模块 A 依赖于模块 B,模块 B 又依赖于模块 C。循环: 模块A、B、C以循环方式相互依赖。

2. 默默无闻

当重要信息不明显时,就会出现模糊性。这可能会使代码库难以理解,从而导致认知负荷增加和未知未知的风险。

定义:

当重要信息不明显时,就会出现模糊性。

晦涩难懂的例子:

不良命名:名称不明确的变量和函数。隐藏的副作用:执行意外操作的方法。全局状态: 过度使用全局变量。深度继承: 行为分布在类层次结构中的多个级别。

请记住:复杂性是渐进的

复杂性很少是由单个“错误”或错误的决定引起的。随着时间的推移,错误的决策和依赖性会“缓慢”地增加复杂性。

因为它是增量的,所以很容易想到,“就这一次,没关系。”但积累起来后,仅修复一两个依赖项并不会产生太大影响。

“软件工程中的一切都是权衡。”
——我不记得作者了

结论

我可以写很多你可能已经在互联网上看到的关于如何避免复杂性的规则、策略和框架:SOLID、设计模式、YAGNI、KISS 等。

但是,您可以将它们统一为一个指导原则(如“务实的程序员”中提到的。): “我正在实现的内容容易更改吗?” 如果答案是否定的,那么您可能会增加复杂性。

确保您的代码易于更改可以简化维护,减少开发人员的认知负担,并使系统更具适应性且不易出错。

谢谢你!

以上就是与软件复杂性的永无止境的战斗的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2672474.html

(0)
上一篇 2025年3月7日 13:26:43
下一篇 2025年3月7日 13:26:48

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 释放 Convexdev 的潜力:彻底改变后端开发

    在不断发展的软件开发领域,创建强大且可扩展的后端系统始终是一个挑战。从管理数据库到处理实时更新,开发人员经常使用多种工具和框架来构建高效的后端。 Convex.dev 是一个旨在简化和增强后端开发的尖端平台。在本文中,我们将探讨 Conve…

    2025年3月7日
    000
  • TypeScript ✔ vs JavaScript ❌:TypeScript 如何胜过 JavaScript

    javascript 多年来一直是 web 开发的基础。它使开发人员能够创建动态和交互式 web 应用程序(显然用于其他目的,但我们将专门讨论 web 开发)。然而,随着应用程序变得越来越复杂,javascript 的局限性变得更加明显。这…

    2025年3月7日
    200
  • Vanilla JS 效果方法

    过去,我经常使用 jquery,我喜欢 jquery 的一点是它通过简单且轻量级的语法提供了许多有用的方法。最常用的 jquery 方法之一是效果方法 – 用于为网站创建动画效果。 例如: 隐藏()/显示()切换()淡入()淡出…

    2025年3月7日
    200
  • 在学习 javascript 的同时编写一个测试函数

    物体无处不在 嗯,您之前可能听说过 javascript 中的对象以及它们对于理解该语言的重要性。 对象因其“key”:“value”模型而使 js 变得非常可读和有用。但我想强调的是,“值”部分不仅接受一个简单的字符串,还接受另一个对象,…

    2025年3月7日
    200
  • React 现代 Web 开发的游戏规则改变者

    介绍 react 是用于构建用户界面的流行 javascript 库,即将在其即将发布的版本 19 中实现巨大飞跃。随着 react 19 的发布,世界各地的开发人员都对新功能和改进感到兴奋,这些新功能和改进有望彻底改变我们构建 web 应…

    2025年3月7日
    200
  • 安全最佳实践

    确保全栈应用程序的安全对于保护用户数据、维护信任和遵守法规至关重要。在本指南中,我们探讨了保护您的应用程序的基本安全最佳实践和技术。 为什么安全很重要 安全漏洞可能会造成严重后果,包括数据盗窃、服务中断和声誉受损。采用强大的安全实践可以降低…

    2025年3月7日
    200
  • 从 Code Monkey 到 DX Champion – 您的一体化开发者体验平台

    在实际编码开始之前,每个开发人员都面临着耗时的设置阶段。作为具有计算机科学背景的开发人员传播者,我介绍了 DronaHQ 如何通过简化设置和改善整体开发人员体验来转变开发流程。 开发人员的困境:从设置到发布 每个开发人员都经历过这样的日子:…

    2025年3月7日
    200
  • npm run dev 报错

    我们在尝试启动 react 应用程序时经常遇到以下错误。 packit-frontend@0.0.0 devvitefile:///home/ariel/desktop/packit/packit-frontend/node_modules…

    2025年3月7日
    200
  • 在 Javascript 中将字符串标题转换为 Slug

    要使用 javascript 将标题转换为 slug 格式,您需要将标题转换为 url 友好的字符串。这通常涉及小写字符串、用连字符替换空格和其他非字母数字字符以及删除任何前导或尾随连字符。以下是有关如何实现此目标的分步指南: 将字符串转换…

    2025年3月7日
    200
  • OOP 中的对象组合和抽象

    对象组合和抽象是 php 面向对象编程 (oop) 中的基本概念。 对象组成: 对象组合是一种对象由一个或多个其他对象组成的技术。这允许: 代码重用维护更方便更加灵活 在 php 中,对象组合是通过使用属性或方法将一个类包含在另一个类中来实…

    2025年3月7日
    200

发表回复

登录后才能评论