它闻起来是因为可能有很多情况可以对其进行编辑或改进。
大多数这些气味只是一些可能出错的暗示。因此,它们本身不需要固定......(不过你应该调查一下。)
您可以在这里找到所有以前的代码味道(第一部分 - XXIX)
让我们继续...
评论是代码的味道。吸气剂是另一种代码味道。你猜怎么了?
TL;DR:不要使用吸气剂。不要评论吸气剂
几十年前,我们习惯于对每一种方法进行评论。即使是微不足道的。
评论应该只描述一个关键的设计决策。
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; } }
我们可以检测一个方法是否是一个 getter 并且有注释。
该功能需要一个评论,这是一个偶然的吸气剂,评论与设计决策有关
不要评论吸气剂。
它们没有增加任何实际价值并使您的代码膨胀。
Reimond de Zuñiga 在 Unsplash 上拍摄的照片
代码应该非常有表现力以避免大多数评论。会有一些例外,但我们应该将评论视为“表达失败”,直到被证明是错误的。
罗伯特·马丁
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() { } }
大多数 linters 计算方法并警告我们。
拆分类和协议是支持小型和可重用对象的好习惯。
Marcin Simonides在Unsplash上拍摄的照片
没有代码太大、扭曲或复杂到维护不能使它变得更糟的程度。
杰拉尔德·M·温伯格
我们为未来的自己购买债务。现在是回报时间。
TL;DR:不要在代码中留下 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; } }
我们可以计算 TODO。
我们可以计算 TODO。
大多数 linter 都会这样做。
我们需要减少它们的政策。
如果我们使用 TDD,我们会立即编写缺失的代码。
在这种情况下,TODO 仅在进行深度优先开发以记住开放访问路径时才有效。
Eden Constantino在Unsplash上拍摄的照片
完成项目的前 90% 后,您必须完成其他 90%。
迈克尔·亚伯拉什
我们的代码更加健壮和易读。但是我们将 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
这是一个语言功能。
我们可以检测并删除它。
许多开发人员觉得用 null 处理污染代码是安全的。
事实上,这比根本不处理 NULL 更安全。
Nullish Values 、 Truthy 和 Falsy 也是代码味道。
我们需要瞄准更高的目标并编写更简洁的代码。
好处:从您的代码中删除所有空值。
坏处:使用可选链接。
丑陋的:根本不处理空值。
Code Smell 69 - Big Bang(JavaScript 可笑的转换)
照片由engin akyurt在Unsplash上拍摄
与怪物战斗的人可能会小心,以免自己成为怪物。如果你长时间凝视深渊,深渊也会凝视你。
尼采
每个开发人员都平等地比较属性。他们错了。
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. }
我们可以使用语法树检测属性比较。
与许多其他气味一样,原始类型也有很好的用途。
我们需要将责任放在一个地方。
比较就是其中之一。
如果我们的一些业务规则发生变化,我们需要改变一个单点。
Piret Ilver在Unsplash上拍摄的照片
行为是软件最重要的事情。这是用户所依赖的。当我们添加行为时用户会喜欢它(前提是这是他们真正想要的),但如果我们更改或删除他们依赖的行为(引入错误),他们就会停止信任我们。
迈克尔羽毛
下一篇:另外 5 种代码味道。