paint-brush
如何找到代码中有问题的部分 [第 XXXII 部分]经过@mcsee
806 讀數
806 讀數

如何找到代码中有问题的部分 [第 XXXII 部分]

经过 Maximiliano Contieri9m2023/03/08
Read on Terminal Reader

太長; 讀書

它闻起来是因为可能有很多情况可以对其进行编辑或改进。大多数这些气味只是一些可能出错的暗示。因此,它们本身不需要修复……(不过您应该研究一下。) 以前的代码味道您可以在这里找到所有以前的代码味道(第 i 部分 - XXXI)。
featured image - 如何找到代码中有问题的部分 [第 XXXII 部分]
Maximiliano Contieri HackerNoon profile picture

它闻起来是因为可能有很多情况可以对其进行编辑或改进。


大多数这些气味只是一些可能出错的暗示。因此,它们本身不需要固定......(不过你应该调查一下。)

以前的代码味道

您可以在此处找到所有以前的代码味道(第一部分 - XXXI)。


让我们继续...


代码味道 156 - 隐式 Else

我们在第一个编程日学习 if/else。然后我们忘记其他的。


TL;DR:要明确。即使有其他人。

问题

解决方案

  1. 写出明确的 else

语境

如果我们提前返回 IF 语句,我们可以省略 else 部分。


之后,我们删除 IF并使用多态性。


那就是我们错过真实案例的时候。

示例代码

错误的

function carBrandImplicit(model) { if (model === 'A4') { return 'audi'; } return 'Mercedes-Benz'; }

正确的

function carBrandExplicit(model) { if (model === 'A4') { return 'audi'; } if (model === 'AMG') { return 'Mercedes-Benz'; } // Fail Fast throw new Exception('Model not found); }

检测

  • [x]自动


我们可以检查语法树并解析它们并警告遗漏其他内容。


我们也可以重写它们并进行变异测试。

标签

  • 条件句

结论

这种气味带来了很多公众的争论和仇恨


我们必须交换意见并重视每一个利弊。

关系

Code Smell 102 - 箭头代码

Code Smell 36 - Switch/case/else if/else/if 语句

更多信息

停止使用隐式 Else

何时使用隐式 Else

快速失败

如何永远摆脱烦人的 IF

学分

Elena MozhviloUnsplash上拍摄的照片


软件团队最大的问题是确保每个人都了解其他人在做什么。


马丁福勒


Code Smell 157 - 余额为 0

今天,我希望钱包里有一笔付款。余额为0,我慌了。


TL;DR:Null 不是 0。错误不是 0。只有 0 是 0。

问题

解决方案

  1. 明确区分零和错误。

语境

我读了很多关于安全问题的文章。


特别是在加密货币上。


上周,我读到了一个加密黑客线程


当我的钱包显示余额为 0 时,我惊慌失措。


这只是一种用户体验的味道。


区块链无法访问💩

示例代码

错误的

""" Below code is automatically generated by code-davinci-002 on GTP3 Codex 1. check balance with blockchain 2. If blockchain is unreachable show 0 as the balance """ import requests import json def get_balance(address): url = "https://blockchain.info/q/addressbalance/" + address response = requests.get(url) if response.status_code == 200: return response.text else: return 0

正确的

""" Below code is automatically generated by code-davinci-002 on GTP3 Codex 1. check balance with blockchain 2. If blockchain is unreachable throw an error """ import requests import json def get_balance(address): url = "https://blockchain.info/q/addressbalance/" + address response = requests.get(url) if response.status_code == 200: return response.text else: raise BlockchainNotReachableError("Error reaching blockchain")

检测

  • [x]手册


这是一种设计气味。


当抛出异常返回代码并用 0 屏蔽时,我们可以找到模式。

标签

  • 用户体验

结论

始终遵循最小惊讶原则作为指导。

关系

Code Smell 12 - 空

Code Smell 139 - 用户界面中的业务代码

Code Smell 73 - 预期情况的异常

Code Smell 72 - 返回代码

更多信息

无效:十亿美元的错误

信用

Jasmin SesslerUnsplash上拍摄的照片

免责声明

代码味道只是我的意见


我对 Null 的真正批评是,它不必要地再次带来了必须选择是在不检查的情况下快速运行程序还是在检查的情况下缓慢运行程序的所有痛苦。


托尼·霍尔(Null Inventor)


软件工程名言


Code Smell 158 - 变量不可变


您为变量赋值并使用它,但从不更改它。


TL;DR:声明可变性。

问题

  • 可读性
  • 尊重双射可变性。
  • 潜在的性能和内存问题。

解决方案

  1. 变量更改为常量并明确其范围。

重构

重构003——提取常量

重构008——将变量转换为常量

语境

我们总是从领域中学习。


有时我们猜测一个值可以随MAPPER改变。


后来,我们知道它不会改变。


因此,我们需要将其提升为常量。


这也将避免Magic Constants

示例代码

错误的

<?php function configureUser() { $password = '123456'; // Setting a password on a variable is another vulnerability // And Code Smell $user = new User($password); // Notice Variable doesn't change }

正确的

<?php define("USER_PASSWORD", '123456') function configureUser() { $user = new User(USER_PASSWORD); } // or function configureUser() { $user = new User(userPassword()); } function userPassword() : string { return '123456'; } // Case is an oversimplification as usual

检测

  • [x]自动


许多 linter 检查变量是否只有一个赋值。


我们还可以执行变异测试,并尝试修改变量以查看测试是否失败。

标签

  • 可变性

结论

我们必须在变量作用域清晰时挑战自我并重构,并且我们更多地了解它的属性和可变性

关系

Code Smell 116 - 使用“var”声明的变量

Code Smell 127 - 可变常量

Code Smell 107——变量重用

Code Smell 02 - 常量和幻数

更多信息

变种人的邪恶力量

免责声明

代码味道只是我的意见

学分

Noah BuscherUnsplash上拍摄的照片


一个有效的复杂系统总是被发现是从一个有效的简单系统演变而来的。


约翰高尔


代码气味 159 - mixEd_cASeI

严肃的开发是由许多不同的人完成的。我们必须开始同意。


TL;DR:不要混合不同的大小写转换

问题

  • 可读性
  • 可维护性

解决方案

  1. 选择案例标准


  2. 坚持下去

语境

当不同的人一起开发软件时,他们可能会有个人差异或文化差异。

有些人更喜欢camelCase 🐫,其他人更喜欢snake_case 🐍,MACRO_CASE🗣️, 等等


代码应该简单易读。

示例代码

错误的

{ "id": 2, "userId": 666, "accountNumber": "12345-12345-12345", "UPDATED_AT": "2022-01-07T02:23:41.305Z", "created_at": "2019-01-07T02:23:41.305Z", "deleted at": "2022-01-07T02:23:41.305Z" }

正确的

{ "id": 2, "userId": 666, "accountNumber": "12345-12345-12345", "updatedAt": "2022-01-07T02:23:41.305Z", "createdAt": "2019-01-07T02:23:41.305Z", "deletedAt": "2022-01-07T02:23:41.305Z" // This doesn't mean THIS standard is the right one }

检测

  • [x]自动

我们可以告诉我们的 linters 我们公司广泛的命名标准并执行它们。


每当新人到达组织时,自动化测试应该礼貌地要求他/她/..更改代码。

例外情况

每当我们需要与超出我们范围的代码进行交互时,我们应该使用客户的标准,而不是我们的标准。

标签

  • 命名

结论

处理标准很容易。


我们需要强制执行它们。

关系

Code Smell 48 - 没有标准的代码

更多信息

名字到底是什么 - 第一部分 The Quest

所有命名约定

免责声明

代码味道只是我的意见

学分

Wolfgang HasselmannUnsplash上拍摄的照片


如果你有太多特殊情况,那你就做错了。


克雷格·泽鲁尼


代码味道 160 - 无效 ID = 9999

Maxint 是一个非常适合无效 ID 的数字。我们永远达不到。


TL;DR:不要将真实 ID 与无效 ID 结合使用。事实上:避免 ID。

问题


  • 您可能比您想象的更快到达无效 ID。


  • 也不要对无效 ID 使用null


  • 从调用者到函数的耦合标志。

解决方案

  1. 使用特殊对象对特殊情况进行建模。


  2. 避免使用 9999、-1 和 0,因为它们是有效的域对象和实现耦合。


  3. 引入空对象

语境

在计算的早期,数据类型是严格的。


然后我们发明了十亿美元的错误


然后我们长大了,用多态的特殊值对特殊场景进行建模。

示例代码

错误的

#include "stdio.h" #include "stdlib.h" #include "stdbool.h" #define INVALID_VALUE 999 int main(void) { int id = get_value(); if (id==INVALID_VALUE) { return EXIT_FAILURE; // id is a flag and also a valid domain value } return id; } int get_value() { // something bad happened return INVALID_VALUE; } // returns EXIT_FAILURE (1)

正确的

#include "stdio.h" #include "stdlib.h" #include "stdbool.h" // No INVALID_VALUE defined int main(void) { int id; id = get_value(); if (!id) { return EXIT_FAILURE; // Sadly, C Programming Language has no exceptions } return id; } get_value() { // something bad happened return false; } // returns EXIT_FAILURE (1)

检测

  • [x]半自动


我们可以检查代码中的特殊常量和特殊值。

标签

  • 无效的

结论

我们应该使用数字来关联外部标识符。


如果不存在外部标识符,则它不是数字。

关系

Code Smell 120 - 顺序 ID

Code Smell 12 - 空

更多信息

无效:十亿美元的错误

Y2K22 - 让我们尴尬的错误

免责声明

代码味道只是我的意见

学分

Markus SpiskeUnsplash上拍摄的照片


虫子潜伏在角落里,聚集在边界处。


鲍里斯·贝泽


即将推出 5 种代码味道……