代码味道是经典之作。
它闻起来是因为可能有很多情况可以对其进行编辑或改进。
大多数这些气味只是一些可能出错的暗示。因此,它们本身不需要固定......(不过你应该调查一下。)
以前的代码味道
您可以在这里找到所有以前的代码味道(第一部分 - XXIX)
让我们继续...
Code Smell 146 - 吸气评论
评论是代码的味道。吸气剂是另一种代码味道。你猜怎么了?
TL;DR:不要使用吸气剂。不要评论吸气剂
问题
- 评论滥用者
- 可读性
- 吸气剂
解决方案
- 删除 getter 注释
- 去除吸气剂
语境
几十年前,我们习惯于对每一种方法进行评论。即使是微不足道的。
评论应该只描述一个关键的设计决策。
示例代码
错误的
pragma solidity >=0.5.0 <0.9.0; contract Property { int private price; function getPrice() public view returns(int) { /* returns the Price */ return price; } }
正确的
pragma solidity >=0.5.0 <0.9.0; contract Property { int private _price; function price() public view returns(int) { return _price; } }
检测
- [x]半自动
我们可以检测一个方法是否是一个 getter 并且有注释。
例外情况
该功能需要一个评论,这是一个偶然的吸气剂,评论与设计决策有关
标签
- 注释
结论
不要评论吸气剂。
它们没有增加任何实际价值并使您的代码膨胀。
关系
学分
Reimond de Zuñiga 在 Unsplash 上拍摄的照片
代码应该非常有表现力以避免大多数评论。会有一些例外,但我们应该将评论视为“表达失败”,直到被证明是错误的。
罗伯特·马丁
Code Smell 147 - 方法太多
Util 类非常适合收集协议。
TL;DR:不要在你的类中添加意外协议
问题
- 可读性
- 单一职责违规
- 内聚力差
- 高耦合
- 可重用性低
解决方案
- 打破你的课堂
- 提取类
重构
语境
我们倾向于将协议放在我们找到的第一个类中。
那不是问题。
我们只需要重构。
示例代码
错误的
public class MyHelperClass { public void print() { } public void format() { } // ... many methods more // ... even more methods public void persist() { } public void solveFermiParadox() { } }
正确的
public class Printer { public void print() { } } public class DateToStringFormatter { public void format() { } } public class Database { public void persist() { } } public class RadioTelescope { public void solveFermiParadox() { } }
检测
- [x]自动
大多数 linters 计算方法并警告我们。
关系
更多信息
标签
- 凝聚
- 膨胀裤
结论
拆分类和协议是支持小型和可重用对象的好习惯。
学分
Marcin Simonides在Unsplash上拍摄的照片
没有代码太大、扭曲或复杂到维护不能使它变得更糟的程度。
杰拉尔德·M·温伯格
Code Smell 148 - 待办事项
我们为未来的自己购买债务。现在是回报时间。
TL;DR:不要在代码中留下 TODO。修复它们!
问题
- 技术债务
- 可读性
- 信心不足
解决方案
- 修复你的 TODO
语境
我们在代码中遇到 TODO。我们算他们。
我们很少解决它。
我们开始欠下技术债务。
然后我们偿还债务+利息。
几个月后,我们支付的利息比原来的债务还多。
示例代码
错误的
public class Door { private Boolean isOpened; public Door(boolean isOpened) { this.isOpened = isOpened; } public void openDoor() { this.isOpened = true; } public void closeDoor() { // TODO: Implement close door and cover it } }
正确的
public class Door { private Boolean isOpened; public Door(boolean isOpened) { this.isOpened = isOpened; } public void openDoor() { this.isOpened = true; } public void closeDoor() { this.isOpened = false; } }
检测
- [x]自动
我们可以计算 TODO。
标签
- 技术债务
结论
我们可以计算 TODO。
大多数 linter 都会这样做。
我们需要减少它们的政策。
如果我们使用 TDD,我们会立即编写缺失的代码。
在这种情况下,TODO 仅在进行深度优先开发以记住开放访问路径时才有效。
更多信息
学分
Eden Constantino在Unsplash上拍摄的照片
完成项目的前 90% 后,您必须完成其他 90%。
迈克尔·亚伯拉什
Code Smell 149 - 可选链接
我们的代码更加健壮和易读。但是我们将 NULL 隐藏在地毯下。
TL;DR:避免空值和未定义。如果你避免使用它们,你将永远不需要 Optionals。
问题
- 空值
- 如果污染
解决方案
- 删除空值
- 处理未定义
语境
Optional Chaining 、Optionals、Coalescence 和许多其他解决方案帮助我们处理臭名昭著的 null。
一旦我们的代码成熟、健壮且没有空值,就没有必要使用它们。
示例代码
错误的
const user = { name: 'Hacker' }; if (user?.credentials?.notExpired) { user.login(); } user.functionDefinedOrNot?.(); // Seems compact but it is hacky and has lots // of potential NULLs and Undefined
正确的
function login() {} const user = { name: 'Hacker', credentials: { expired: false } }; if (!user.credentials.expired) { login(); } // Also compact // User is a real user or a polymorphic NullUser // Credentials are always defined. // Can be an instance of InvalidCredentials // Assuming we eliminated nulls from our code if (user.functionDefinedOrNot !== undefined) { functionDefinedOrNot(); } // This is also wrong. // Explicit undefined checks are yet another code smell
检测
- [x]自动
这是一个语言功能。
我们可以检测并删除它。
标签
- 无效的
结论
许多开发人员觉得用 null 处理污染代码是安全的。
事实上,这比根本不处理 NULL 更安全。
Nullish Values 、 Truthy 和 Falsy 也是代码味道。
我们需要瞄准更高的目标并编写更简洁的代码。
好处:从您的代码中删除所有空值。
坏处:使用可选链接。
丑陋的:根本不处理空值。
关系
Code Smell 69 - Big Bang(JavaScript 可笑的转换)
更多信息
学分
照片由engin akyurt在Unsplash上拍摄
与怪物战斗的人可能会小心,以免自己成为怪物。如果你长时间凝视深渊,深渊也会凝视你。
尼采
Code Smell 150 - 相等比较
每个开发人员都平等地比较属性。他们错了。
TL;DR:不要导出和比较,只是比较。
问题
- 封装中断
- 代码重复
- 信息隐藏违规
- 违反拟人化
解决方案
- 在单一方法中隐藏比较
语境
我们的代码中大量使用了属性比较。
我们需要关注行为和责任。
与其他对象进行比较是对象的职责。不是我们自己的。
过早的优化器会告诉我们这是性能较低的。
我们应该要求他们提供真实的证据,并对比更易于维护的解决方案。
示例代码
错误的
if (address.street == 'Broad Street') { if (location.street == 'Bourbon St') { // 15000 usages in a big system // Comparisons are case sensitive
正确的
if (address.isAtStreet('Broad Street') { } // ... if (location.isAtStreet('Bourbon St') { } // 15000 usages in a big system function isAtStreet(street) { // We can change Comparisons to // case sensitive in just one place. }
检测
- [x]半自动
我们可以使用语法树检测属性比较。
与许多其他气味一样,原始类型也有很好的用途。
标签
- 封装
结论
我们需要将责任放在一个地方。
比较就是其中之一。
如果我们的一些业务规则发生变化,我们需要改变一个单点。
关系
学分
Piret Ilver在Unsplash上拍摄的照片
行为是软件最重要的事情。这是用户所依赖的。当我们添加行为时用户会喜欢它(前提是这是他们真正想要的),但如果我们更改或删除他们依赖的行为(引入错误),他们就会停止信任我们。
迈克尔羽毛
下一篇:另外 5 种代码味道。