当前位置:首页 > 科技  > 软件

程序的“通用性”和“过度设计”困境

来源: 责编: 时间:2024-06-24 09:13:17 224观看
导读在软件工程的实际操作中,我常常遇到这样一种现象:本可以用简单代码解决的问题,却因为设计者过分关注“通用性”、“可维护性”和“可扩展性”而变得不必要地复杂,难以理解。他们的思维方式是这样的:“这段代码未来可能会在

2l128资讯网——每日最新资讯28at.com

在软件工程的实际操作中,我常常遇到这样一种现象:本可以用简单代码解决的问题,却因为设计者过分关注“通用性”、“可维护性”和“可扩展性”而变得不必要地复杂,难以理解。2l128资讯网——每日最新资讯28at.com

他们的思维方式是这样的:“这段代码未来可能会在更多场景中使用,所以我现在应该考虑它的可扩展性。”结果,他们在代码中加入了各种“框架结构”,以便在未来有新需求时,无需修改就能在新的地方使用。2l128资讯网——每日最新资讯28at.com

“通用性”的价值与误区

作者并不否认“通用性”的价值,我的一些程序也具有很高的通用性。然而,很多人所谓的“通用性”实际上适得其反,这种现象通常被称为 “过度设计” 。关于过度设计,有一个有趣的故事:2l128资讯网——每日最新资讯28at.com

传说在上世纪60年代美国和俄罗斯的“太空竞赛”期间,NASA 遇到了一个严重的技术问题:宇航员需要一支能在外太空真空环境中书写的笔。最终,NASA 花费了150万美元开发了这样一支笔。不幸的是,这种笔在市场上并不畅销。2l128资讯网——每日最新资讯28at.com

俄罗斯人也面临同样的问题,他们则用了铅笔。2l128资讯网——每日最新资讯28at.com

虽然这个故事是虚构的,但它具备了伊索寓言的力量。现在让我们看看软件行业,可能会发现:2l128资讯网——每日最新资讯28at.com

代码需要“重用”的场合比您想象的要少得多2l128资讯网——每日最新资讯28at.com

许多人在写程序时,连“当前异常”都处理不好,却关注“未来的需求”。他们总是想象别人会重用这段代码。然而,实际上,由于设计过于复杂,理解这些设计所需的心智努力已经超过了从头开始的成本。因此,大多数人根本不会使用他们的代码,而是重新写一个。有些人最终会发现自己甚至看不下去之前写的代码,更愿意删除它并重新开始,而不是谈论重用。2l128资讯网——每日最新资讯28at.com

我们用一个简单的例子来说明这一点。假设我们需要写一个简单的程序来计算两个整数的和:2l128资讯网——每日最新资讯28at.com

def add(a, b):    return a + bresult = add(3, 5)print(result)  # 输出 8

这个函数非常直观,可以很好地满足当前需求。然而,一些程序员可能会考虑未来可能需要更多的计算能力,因此设计了一个复杂的框架:2l128资讯网——每日最新资讯28at.com

class Operation:    def execute(self, a, b):        raise NotImplementedErrorclass AddOperation(Operation):    def execute(self, a, b):        return a + bclass OperationFactory:    @staticmethod    def get_operation(op_type):        if op_type == 'add':            return AddOperation()        # 可以添加更多操作类型。        raise ValueError("不支持的操作类型")operation = OperationFactory.get_operation('add')result = operation.execute(3, 5)print(result)  # 输出 8

虽然这个设计提供了可扩展性,但在当前只需计算两个整数和的场景中,这个设计无疑增加了代码的复杂性和理解成本。2l128资讯网——每日最新资讯28at.com

实际修改代码所需的工作量比你想象的少

还有一种情况是,这些设计为“共享”而写的代码在很多地方并没有被使用,因此即使你完全手动修改它们,也不会花费很多时间。现在,随着 IDE 技术的发展和各种高级重构工具的出现,批量代码修改不再特别麻烦。过去需要在逻辑层面设计可维护性,现在只需在 IDE 中点击几下就能轻松完成。因此,在考虑设计框架之前,你还应该考虑这些因素。2l128资讯网——每日最新资讯28at.com

例如,在上面提到的复杂设计中,如果我们需要修改加法操作,我们需要修改多个类和文件。在这种情况下,我们可能会发现简单的函数实现更容易维护和修改。2l128资讯网——每日最新资讯28at.com

“考虑”通用性并不意味着你已经准确“掌握”了通用性

许多人考虑通用性,但他们并不准确地看到未来可能需要修改的部分,因此他们的设计往往错失重点。当新需求出现时,发现最初认为可能变化的部分并没有变化,而那些认为不变的部分却发生了变化。2l128资讯网——每日最新资讯28at.com

能够准确预测未来需求并从代码中抽象出真正通用的框架是非常困难的任务。它不仅需要编程技能,还需要强大的观察现实世界事物的能力。许多人设计的框架只是复制他人的经验,无法适应实际需求。Java 世界中的许多设计模式就是由这些半吊子的人创造的。2l128资讯网——每日最新资讯28at.com

例如,假设我们需要添加一个新的操作,如减法。如果我们没有准确掌握哪些部分需要通用设计,我们可能会发现现有框架不适用于新需求:2l128资讯网——每日最新资讯28at.com

class SubtractOperation(Operation):    def execute(self, a, b):        return a - boperation = OperationFactory.get_operation('subtract')result = operation.execute(10, 3)print(result)  # 输出 7

在这里,我们需要修改 OperationFactory 类以支持减法操作。这表明,虽然我们考虑了通用性,但我们没有准确掌握未来的需求,导致框架的灵活性有限。2l128资讯网——每日最新资讯28at.com

初始设计的复杂性

如果在初始设计中过早地考虑未来需求,可能会导致不必要的复杂性和问题。因此,这种对未来变化的考虑阻碍了进展。原本如果我们专注于解决当前问题,可以取得很好的结果。然而,由于“通用性”带来的复杂性,设计者每次都要多费一些心思,无法创建优雅的程序。2l128资讯网——每日最新资讯28at.com

例如,在上面提到的复杂设计中,如果我们只需要一个简单的加法操作,复杂的框架反而使初始设计变得臃肿且难以理解:2l128资讯网——每日最新资讯28at.com

class Operation:    def execute(self, a, b):        raise NotImplementedErrorclass AddOperation(Operation):    def execute(self, a, b):        return a + bclass OperationFactory:    @staticmethod    def get_operation(op_type):        if op_type == 'add':            return AddOperation()        raise ValueError("不支持的操作类型")# 初始设计的复杂性。operation = OperationFactory.get_operation('add')result = operation.execute(3, 5)print(result)  # 输出 8

相比之下,只需执行一个简单的函数即可。2l128资讯网——每日最新资讯28at.com

def add(a, b):    return a + bresult = add(3, 5)print(result)  # 输出 8

理解和维护框架代码的开销

如果你设计了一个框架式的代码,每个程序员都需要理解这个框架的构建,才能在这个框架下编写代码,这带来了学习成本。一旦发现这个框架有设计问题,依赖它的代码可能需要修改,这带来了修改成本。因此,在设计中加入“通用性”的初衷是为了节省未来的修改成本,但可能会增加当前的开发和维护成本。2l128资讯网——每日最新资讯28at.com

例如,在复杂的框架设计中,添加新操作类型需要理解多个类及其关系:2l128资讯网——每日最新资讯28at.com

class MultiplyOperation(Operation):    def execute(self, a, b):        return a * b# 理解和维护的成本。operation = OperationFactory.get_operation('multiply')result = operation.execute(3, 5)print(result)  # 输出 15

而在简单的函数实现中,添加新功能相对简单:2l128资讯网——每日最新资讯28at.com

def multiply(a, b):    return a * bresult = multiply(3, 5)print(result)  # 输出 15

结论

在软件工程中,设计的“通用性”确实是一个重要的考虑因素,但我们必须谨慎。过度设计和过度工程不仅不会提高代码的可维护性,反而会增加开发和维护成本。在实际项目中,我们应该根据当前需求采用最简单直接的解决方案,而不是为了未来的可能性增加当前的复杂性。2l128资讯网——每日最新资讯28at.com

总的来说,简洁直观的代码往往比复杂的框架更能满足实际需求。我们应在设计中保持平衡,避免过度工程,专注于解决当前问题,同时为未来扩展留有余地。2l128资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-95919-0.html程序的“通用性”和“过度设计”困境

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++ vs Rust vs Go 性能比较

下一篇: 字节面试:说说零拷贝技术实现原理?

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • K60至尊版狂暴引擎2.0加持:超177万跑分斩获性能第一

    Redmi的后性能时代战略发布会今天下午如期举办,在本次发布会上,Redmi公布了多项关于和联发科的深度合作,以及新机K60 Ultra在软件和硬件方面的特性,例如:“K60 至尊版,双芯旗舰
  • 2023 年的 Node.js 生态系统

    随着技术的不断演进和创新,Node.js 在 2023 年达到了一个新的高度。Node.js 拥有一个庞大的生态系统,可以帮助开发人员更快地实现复杂的应用。本文就来看看 Node.js 最新的生
  • Flowable工作流引擎的科普与实践

    一.引言当我们在日常工作和业务中需要进行各种审批流程时,可能会面临一系列技术和业务上的挑战。手动处理这些审批流程可能会导致开发成本的增加以及业务复杂度的上升。在这
  • 深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析

    在 Elasticsearch 中,function_score 可以让我们在查询的同时对搜索结果进行自定义评分。function_score 提供了一系列的参数和函数让我们可以根据需求灵活地进行设置。近期
  • 这款新兴工具平台,让你的电脑效率翻倍

    随着信息技术的发展,我们获取信息的渠道越来越多,但是处理信息的效率却成为一个瓶颈。于是各种工具应运而生,都在争相解决我们的工作效率问题。今天我要给大家介绍一款效率
  • 虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 一条抖音4亿人围观 ! 这家MCN比无忧传媒还野

    作者:Hiu 来源:互联网品牌官01 擦边少女空降热搜,幕后推手曝光被网友誉为“纯欲天花板”的女网红井川里予,近期因为一组哥特风照片登上热搜,引发了一场互联网世界关于
Top