避免条件语句的智慧
今天golang学习网给大家带来了《避免条件语句的智慧》,其中涉及到的知识点包括等等,无论你是小白还是老手,都适合看一看哦~有好的建议也欢迎大家在评论留言,若是看完有所收获,也希望大家能多多点赞支持呀!一起加油学习~

循环复杂度是衡量代码复杂性和混乱程度的指标。
高圈复杂度并不是一件好事,恰恰相反。
简单来说,圈复杂度与程序中可能的执行路径的数量成正比。换句话说,圈复杂度和条件语句的总数(尤其是它们的嵌套)密切相关。
所以今天我们来谈谈条件语句。
反如果
2007年,francesco cirillo发起了一场名为anti-if的运动。
francesco cirillo 是发明番茄工作法的人。我现在正在“番茄钟下”写这篇博文。
我想我们都很快从它的名字就明白了这个活动的意义。有趣的是,该运动的追随者中有不少计算机科学家。
他们的论点坚如磐石——如果语句是邪恶的,会导致程序执行路径呈指数级增长。
简而言之,这就是圈复杂度。它越高,不仅阅读和理解代码就越困难,而且用测试来覆盖它也就越困难。
当然,我们有一种“相反”的指标——代码覆盖率,它显示了测试覆盖了多少代码。但是这个指标以及我们编程语言中用于检查覆盖率的丰富工具是否证明忽略圈复杂度并仅基于“本能”散布 if 语句是合理的?
我觉得不是。
几乎每次我发现自己要将一个 if 嵌套在另一个 if 中时,我都会意识到我正在做一些非常愚蠢的事情,可以用不同的方式重写 - 要么没有嵌套的 if ,要么根本没有 if 。
你确实注意到了“几乎”这个词,对吧?
我并没有立即开始注意到这一点。如果您查看我的 github,您会发现不止一个旧代码示例,它们不仅具有高圈复杂度,而且具有直接的圈复杂度。
是什么帮助我更加意识到这个问题?可能是我一年前学到和接受的经验和一些聪明的事情。这就是我今天要跟大家分享的内容。
破坏 if 语句的两种神圣技术
- padawan,将未知值的每个条件检查移动到该值已知的地方。
- 学徒,改变你的编码逻辑思维模型,让它不再需要条件检查。
1. 让未知为人所知
在我们还不“知道”某事时检查它可能是使用基于“本能”的条件语句的最常见来源。
例如,假设我们需要根据用户的年龄做一些事情,并且我们必须确保年龄有效(在合理范围内)。我们最终可能会得到这样的代码:
from typing import optional
def process_age(age: optional[int]) -> none:
if age is none:
raise valueerror("age cannot be null")
if age < 0 or age > 150:
raise valueerror("age must be between 0 and 150")
我们都见过并且可能写过数百次类似的代码。
我们如何通过遵循所讨论的元原则来消除这些条件检查?
在我们特定的年龄情况下,我们可以应用我最喜欢的方法——摆脱原始的痴迷,转向使用自定义数据类型。
class age:
def __init__(self, value: int) -> none:
if value < 0 or value > 150:
raise valueerror("age must be between 0 and 150")
self.value = value
def get_value(self) -> int:
return self.value
def process_age(age: age) -> none:
# age is guaranteed to be valid, process it directly
万岁,少一个如果!年龄的验证和验证现在始终在“已知年龄的地方”——在单独类的职责和范围内。
如果我们想删除 age 类中的 if ,我们可以走得更远/不同,也许可以使用带有验证器的 pydantic 模型,甚至用断言替换 if — 现在没关系。
有助于摆脱同一元思想中的条件检查的其他技术或机制包括用多态性(或匿名 lambda 函数)替换条件以及分解具有偷偷摸摸的布尔标志的函数等方法。
例如,这段代码(可怕的拳击,对吧?):
class paymentprocessor:
def process_payment(self, payment_type: str, amount: float) -> str:
if payment_type == "credit_card":
return self.process_credit_card_payment(amount)
elif payment_type == "paypal":
return self.process_paypal_payment(amount)
elif payment_type == "bank_transfer":
return self.process_bank_transfer_payment(amount)
else:
raise valueerror("unknown payment type")
def process_credit_card_payment(self, amount: float) -> str:
return f"processed credit card payment of {amount}."
def process_paypal_payment(self, amount: float) -> str:
return f"processed paypal payment of {amount}."
def process_bank_transfer_payment(self, amount: float) -> str:
return f"processed bank transfer payment of {amount}."
如果你用 match/case 替换 if/elif 也没关系——都是同样的垃圾!
很容易将其重写为:
from abc import abc, abstractmethod
class paymentprocessor(abc):
@abstractmethod
def process_payment(self, amount: float) -> str:
pass
class creditcardpaymentprocessor(paymentprocessor):
def process_payment(self, amount: float) -> str:
return f"processed credit card payment of {amount}."
class paypalpaymentprocessor(paymentprocessor):
def process_payment(self, amount: float) -> str:
return f"processed paypal payment of {amount}."
class banktransferpaymentprocessor(paymentprocessor):
def process_payment(self, amount: float) -> str:
return f"processed bank transfer payment of {amount}."
对吗?
将带有布尔标志的函数分解为两个独立函数的示例与时间一样古老,令人痛苦地熟悉,并且令人难以置信地烦人(在我看来)。
def process_transaction(transaction_id: int,
amount: float,
is_internal: bool) -> none:
if is_internal:
# process internal transaction
pass
else:
# process external transaction
pass
无论如何,两个函数会好得多,即使其中 2/3 的代码是相同的!这是其中一种场景,其中与 dry 的权衡是常识的结果,使代码变得更好。
这里最大的区别是,从机械角度来说,在自动驾驶仪上,我们不太可能使用这些方法,除非我们已经内化并养成了通过这一原则进行思考的习惯。
否则,我们会自动陷入 if: if: elif: if...
2. 释放你的思想,尼奥
事实上,第二个技巧才是真正的技巧,而之前的“第一个”技巧只是准备练习,是到位的捷径:)
事实上,实现更简单的代码、降低圈复杂度和减少条件检查的唯一最终方式、方法(无论你怎么称呼它)是改变我们在头脑中建立的用于解决特定问题的心理模型 .
我保证,今天最后一个愚蠢的例子。
考虑一下,我们正在紧急为一些在线商店编写一个后端,用户可以在不注册或使用注册的情况下进行购买。
当然,系统有一个 user 类/实体,完成这样的事情很容易:
def process_order(order_id: int,
user: optional[user]) -> none:
if user is not none:
# process order for a registered user
pass
else:
# process order for a guest user
pass
但是注意到这些废话,由于我们的思维已经转向正确的方向(我相信),我们将回到 user 类的定义位置并重写部分代码,如下所示:
class User:
def __init__(self, name: str) -> None:
self.name = name
def process_order(self, order_id: int) -> None:
pass
class GuestUser(User):
def __init__(self) -> None:
super().__init__(name="Guest")
def process_order(self, order_id: int) -> None:
pass
因此,这一切的本质和美妙之处在于,我们不会用各种模式和编码技术来消除条件语句等,从而使我们的头脑变得混乱。
通过将我们的注意力转移到元级别,转移到更高的抽象级别,而不仅仅是对代码行的推理级别,并遵循我们今天讨论的想法,消除条件检查的正确方法,并且一般来说,更正确的代码将会自然出现.
我们代码中的很多条件检查都是由于被诅咒的 none/null 泄漏到我们的代码中而产生的,所以值得一提的是非常流行的 null 对象模式。
执着于文字,而不是意义
当遵循反如果时,你可能会走上错误的道路,因为执着于文字而不是意义,并盲目地遵循“如果是坏的,如果必须被删除”的想法。
由于条件语句是语义而不是语法元素,因此有无数种方法可以从代码中删除 if 标记,而无需更改我们喜爱的编程语言中的底层逻辑。
我在这里讨论的不是用 match/case 替换 python 中的 elif 链。
逻辑条件源于系统的心理“模型”,并且没有通用方法可以完全“删除”条件。
换句话说,圈复杂度和整体代码复杂度与代码的物理表示(文件中写入的字母和符号)无关。
复杂性来自于形式表达,口头或文字解释特定代码为何以及如何工作。
因此,如果我们更改代码中的某些内容,并且 if 语句更少或根本没有,但相同代码的口头解释保持不变,我们所做的只是更改代码的表示,并且更改本身并没有真正的意义或做出任何改进。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《避免条件语句的智慧》文章吧,也可关注golang学习网公众号了解相关技术文章。
如何在 Java 中正确地关闭资源以避免异常?
- 上一篇
- 如何在 Java 中正确地关闭资源以避免异常?
- 下一篇
- PHP 函数按是否可以被重载如何分类?
-
- 文章 · python教程 | 3小时前 |
- Python如何重命名数据列名?columns教程
- 165浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- 异步Python机器人如何非阻塞运行?
- 216浏览 收藏
-
- 文章 · python教程 | 4小时前 |
- Python排序忽略大小写技巧详解
- 325浏览 收藏
-
- 文章 · python教程 | 4小时前 |
- Python列表引用与复制技巧
- 300浏览 收藏
-
- 文章 · python教程 | 5小时前 | 数据处理 流处理 PythonAPI PyFlink ApacheFlink
- PyFlink是什么?Python与Flink结合解析
- 385浏览 收藏
-
- 文章 · python教程 | 5小时前 | sdk 邮件API requests库 smtplib Python邮件发送
- Python发送邮件API调用方法详解
- 165浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- Pandasmerge_asof快速匹配最近时间数据
- 254浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- 列表推导式与生成器表达式区别解析
- 427浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- Pythonopen函数使用技巧详解
- 149浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- Python合并多个列表的几种方法
- 190浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3193次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3405次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3436次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4543次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3814次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

