编写“快速而肮脏”的脚本来测试某物或在项目的最早阶段进行测试并不少见。此外,旧版项目通常包含不优化的代码。
直到该项目成为一场维护噩梦之前,这没什么大不了的。为了防止这样的不良结果,团队可以定期安排重构会议。
但是,这可能很难开始,因此以下是使用PHP的一些示例,但是以下许多技巧可以应用于其他编程语言。
代码太长
这个标志可能是最容易发现的标志之一。
如果类具有太多的方法,变量和/或其方法的线太多,则通常是一个警告信号。
更新现有方法而不是创建新类可能很诱人,但通常会膨胀代码。此外,您可能会破坏坚实的原则,做太多的事情,而代码可以组成较小的对象。
根据原始代码,这种操作可能很难实现,但是这通常是有益的。它甚至可能允许捕获未发现的错误和以前错过的逻辑问题,因为代码太复杂了。
维护者的另一个良好副作用可能是:
- 总体上更好的可读性
- 更少要记住的东西(在维护多个项目时很有帮助)
- 不必要的评论较少(用适当命名的方法替代)
- 少重复
死亡代码
另一个明显的符号是死亡代码。
找到未使用的变量和方法(有时甚至是整个类)并不少见。在这种情况下,只需放下它们即可。
尽管它可能并不像看起来那么容易,因此请在继续之前仔细检查所有潜在用法:
- 使用您喜欢的IDE
- 使用静态分析,但要注意的是不是调试工具(它不能执行代码)
- 使用辩论者
重复
重复的代码非常频繁。干燥原理(不重复自己)建议合并相同或相似的方法以简化维护。
巨大的免责声明:在某些情况下,该操作产生的问题比解决的问题更多。为了干燥,不惜一切代价集中代码并不那么聪明,甚至可以引入讨厌的回归。
在继续操作之前,请确保要合并的方法尚未处理太多情况。同样,将小方法重构为一个很大的论点是一种不良习惯,这可能意味着两种方法并不相似。
更实用的例子
先前的观点是必不可少的,但相当通用。让我们研究代码。
n.b。:我们假设我们在示例中使用的许多字段(例如$total
)在
无用的中介方法
让我们考虑以下课程:
public function getFactor() {
return ($this->isFirstPart()) ? 1 : 3;
}
public function isFirstPart() {
return $this->total < 2;
}
典型的重构将合并这两种方法:
public function getFactor() {
return ($this->total < 2) ? 1 : 3;
}
当然,这并不意味着您在所有情况下都应该这样做。实际上,只要您不在代码中乘以它们,isFirstPart()
之类的方法可能会很好。如果有太多类似的帮助者,您会严重损害可读性。
在进行继续之前,只需确保在其他地方没有使用isFirstPart()
。
长条件
逻辑问题一直在发生。重构可以帮助发现错误的条件,但是即使一切正常,您也可以显着提高可读性。
if ($total > 19 || $discount < 30 || $category === "premium" || $coupon === "summer2014") {
// some code
}
上面的代码可以包装到函数中:
public function isEligible() {
return $product->total > 19 || $product->discount < 30 || $user->category === "premium" || $product->coupon === "summer2014"
}
// to be used like that:
if ($user->isEligible()) {
// some code
}
当然,这是一个绝对不是最终重构的快速示例,但这个想法是要保持简短,可读且易于使用(并重复使用)。
不要那么负面!
不要重构带有否定陈述的条件如下:
if ($user->isNotEligible()) {
// some code
}
上面是不好的。为什么?
您如何处理符合条件的用户?
if (!$user->isNotEligible()) {
// some code
}
它感觉不正确。原因很简单:它的可读性较低,因此,请使用正面格式:
if ($user->isEligible()) {
// some code
}
// or the other case
if (!$user->isEligible()) {
// some code
}
开关与多态性:经典战斗
class Universe {
protected $segment;
public function handleTheUniverse() {
switch ($this->segment) {
case "alphaone":
echo "Alpha Alpha One, buddy";
break;
case "beta3":
echo "Welcome to Beta III";
break;
case "ulysse31":
echo "Hello, Ulysse 31";
break;
}
}
}
在还有其他方法可以缓解维护的方法的同时,找到上述代码很常见。例如:
abstract class Universe {
abstract function getSegment();
}
class AlphaOne extends Universe {
public function getSegment() {
echo "Alpha Alpha One, buddy";
}
}
class Beta3 extends Universe {
public function getSegment() {
echo "Welcome to Beta III";
}
}
class Ulysse31 extends Universe {
public function getSegment() {
echo "Hello, Ulysse 31";
}
}
这有点违反直觉,因为我们用延伸相同抽象的小儿童班代替了集中的switch
。
目前,好处可能并不明显,您甚至可能会说switch
案看起来很方便。但是,假设您必须基于$segment
进行更复杂的操作,您将迅速膨胀代码。
对于任何新的“变体”,替代方法允许您在另一个文件中创建一个儿童类而无需修改现有代码。
确实,重构现有开关可能具有挑战性,但通常值得。
包起来
重构是一个涉及多个参数的棘手操作。没有通用规则,您可以盲目应用,但是您的PHP代码可能需要它。
这些技术可以大大提高可读性和维护。您甚至可以发现隐藏的错误和逻辑问题。
,尽管您可以在代码评论中与队友讨论涉及大量代码的“大重构”,这是最好的。即使需要这样的深层更改,并且表明初始方法不是最好的方法,但这个想法也不是打破业务。
摄