软件开发之要义:DRY-——不要重复你自己

21CTO学院导读:不重复自己(Do not Repeat Yourself)是软件开发之要义,它的目标就是避免代码重复。

8-code-deck.jpg

 
不要重复自己,是软件开发的基本原则,它的目标是避免重复的代码发生。
 
每行代码在系统必须有单一,明确,权威的表现。
 
很多时间,你发现自己一遍又一遍编写同样的代码时,本文告诉你更实际好用的方法。
 
 
案例:不要重复自己
 
先看一个代码例子,来看它是否可以再改进,重构它以避免代码重复。
 
以下是一个Rport类,功能很简单,接收一些数据,通过控制台格式化打印一些信息。
 
代码如下:

class Report{



public function show(array $data){



echo "Report: " . ucwords(strtolower($data["name"])) . "/n";

echo "Product: " . ucwords(strtolower($data["product"])) . "/n";

echo "Start date: " . date("Y/m/d", $data["startDate"]) . "/n";

echo "End date: " . date("Y/m/d", $data["endDate"]) . "/n";

echo "Total: " . $data["total"] . "/n";

echo "Average x day: " . floor($data["total"] / 365) . "/n";

echo "Average x week: " . floor($data["total"] / 52) . "/n";



}

}

 
可以改进此代码吗?稍等一下,有报表的新需求,把内容保存到文件里。这很容易,我们对它进行一些复制粘贴,做一些小更改,几分钟就可能搞定。
 
代码如下:

class Report {



public function show(array $data) {



echo "Report: " . ucwords(strtolower($data["name"])) . "/n";

echo "Product: " . ucwords(strtolower($data["product"])) . "/n";

echo "Start date: " . date("Y/m/d", $data["startDate"]) . "/n";

echo "End date: " . date("Y/m/d", $data["endDate"]) . "/n";

echo "Total: " . $data["total"] . "/n";

echo "Average x day: " . floor($data["total"] / 365) . "/n";

echo "Average x week: " . floor($data["total"] / 52) . "/n";

echo "Average x month: " . floor($data["total"] / 12) . "/n";



}



public function saveToFile(array $data) {



$report = '';

$report .= "Report: " . ucwords(strtolower($data["name"])) . "/n";

$report .= "Product: " . ucwords(strtolower($data["product"])) . "/n";

$report .= "Start date: " . date("Y/m/d", $data["startDate"]) . "/n";

$report .= "End date: " . date("Y/m/d", $data["endDate"]) . "/n";

$report .= "Total: " . $data["total"] . "/n";

$report .= "Average x day: " . floor($data["total"] / 365) . "/n";

$report .= "Average x week: " . floor($data["total"] / 52) . "/n";

$report .= "Average x month: " . floor($data["total"] / 12) . "/n";

file_put_contents("./report.txt", $report);



}

}

 
等一下,我们真的完成了?当然,需求确实已经满足,但从技术角度,它似乎有些问题。可以看到很多重复项,虽然代码只有几行,至少写了两次写入文件。显然,这与DRY特性相反。
 
接下来,我们做一些重构。这两个方法的内容大致内容相同,唯一不同的是最终输出。我们来将主干内容提取到新方法中。这样,我们就有一个单一的功能,在一个地方创建报表,其它方法只负责如何处理即可。

class Report
{

public function show(array $data)
{

echo $this->createReport($data);

}



public function saveToFile(array $data)
{

file_put_contents("./report.txt", $this->createReport($data));

}



private function createReport(array $data): string
{

$report = '';

$report .= "Report: " . ucwords(strtolower($data["name"])) . "/n";

$report .= "Product: " . ucwords(strtolower($data["product"])) . "/n";

$report .= "Start date: " . date("Y/m/d", $data["startDate"]) . "/n";

$report .= "End date: " . date("Y/m/d", $data["endDate"]) . "/n";

$report .= "Total: " . $data["total"] . "/n";

$report .= "Average x day: " . floor($data["total"] / 365) . "/n";

$report .= "Average x week: " . floor($data["total"] / 52) . "/n";

$report .= "Average x month: " . floor($data["total"] / 12) . "/n";

return $report;

}

}

 
这样看起来好多了,还有一些小的重复项需要修复。

$report .= "Report: " . ucwords(strtolower($data["name"])) . "/n";

$report .= "Product: " . ucwords(strtolower($data["product"])) . "/n";

把这些转换提取到新方法,甚至可以提取到自己的单元测试库中。

private function normalizeName($name): string
{

return ucwords(strtolower($name));

}

另外还一个重复,日期格式:

$report .= "Start date: " . date("Y/m/d", $data["startDate"]) . "/n";

$report .= "End date: " . date("Y/m/d", $data["endDate"]) . "/n";

将它合并提取为:

private function formatDate($date): string
{

return date("Y/m/d", $date);

}

还有一个,计算平均数。

$report .= "Average x day: " . floor($data["total"] / 365) . "/n";

$report .= "Average x week: " . floor($data["total"] / 52) . "/n";

$report .= "Average x month: " . floor($data["total"] / 12) . "/n";




它们之间的计算结果并不完全一样,但是,我们可以合并成一个函数:

private function calculateAverage(array $data, $period): string
{

return floor($data["total"] / $period);

}

最后,重构的Report类是这个样子的:

class Report
{

public function show(array $data)
{

echo $this->createReport($data);

}



public function saveToFile(array $data)
{

file_put_contents("./report.txt", $this->createReport($data));

}



private function createReport(array $data)
{

$report = '';

$report .= "Report: " . $this->normalizeName($data["name"]) . "/n";

$report .= "Product: " . $this->normalizeName($data["product"]) . "/n";

$report .= "Start date: " . $this->formatDate($data["startDate"]) . "/n";

$report .= "End date: " . $this->formatDate($data["endDate"]) . "/n";

$report .= "Total: " . $data["total"] . "/n";

$report .= "Average x day: " . $this->calculateAverage($data, 365) . "/n";

$report .= "Average x week: " . $this->calculateAverage($data, 52) . "/n";

$report .= "Average x month: " . $this->calculateAverage($data, 12) . "/n";

return $report;

}



private function formatDate($date): string
{

return date("Y/m/d", $date);

}





private function calculateAverage(array $data, $period): string
{

return floor($data["total"] / $period);

}





private function normalizeName($name): string
{



return ucwords(strtolower($name));

}

}

DRY是编码过程中,开发基础结构以及部署的终结点,开发者应该努力做到这一点,从而全面改善代码环境,让其更具可读性和可管理性。

     

    作者:正明
    来源:21CTO学院

    原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/258246.html

    (0)
    上一篇 2022年5月20日
    下一篇 2022年5月20日

    相关推荐

    发表回复

    登录后才能评论