凡是有经验的程序员都能够意识到应该避免重复的代码和逻辑。
为什么重复的代码和逻辑是隐患呢?
如果从一个类中复制了一段代码到另一个类中,这段代码需要时不时的修改,那么就要花时间去修改所有包含这段逻辑的代码,无形中增加了维护成本和发生bug的几率。这时候就要着手消除和抽取重复的代码。
**消除重复的代码有一个三次法则rule of three:
1.第一次先写了一段代码。
2.第二次在另一个地方写了一段相同的代码。
3.再次在另一个地方写了同样的代码,这个时候就要赶紧去抽象消除这个问题了。
什么样的代码算是重复的?
一个实例:
<?php // example 1
final class Basket
{
private $products;
public function addProduct($product)
{
if (3 == count ( $this ->products)) {
throw new Exception("Max 3 products allowed");
}
$this->products[] =$product;
}
}
final class Shipment
{
private $products ;
public function addProduct( $product )
{
if (3 == count ( $this ->products)) {
throw new Exception( "Max 3 products allowed" );
}
$this ->products[] = $product ;
}
}
这两段代码中都有一个相同的方法addProduct,这两段代码算是重复的吗?违反DRY原则吗?
作为一个领域驱动的实践者,我们可以从业务的角度来分析这一代码,第一段代码似乎是一个用户在购物,但是我们最多允许用户购买三件商品。
在第二段代码的场景中,我们想要给所有用户提供相同的机会并限制用户最大购买数量。
这一分析说明了这两段代码所描述的
领域(Domain)、业务(Business)、知识(Knowledge)、边界(Boundary)、职责(Resposibility)不同,
这两段代码之所以相同完全属于巧合。对这样的代码进行提取和消除重复是错误的。
之前有一些大型的项目遇到一些问题,就是将一些本不应该提取的代码(各种Model、数据访问)抽取到了一个叫做Shared的工程中,这一举动导致开发人员在后期不敢再修改Shared工程中的任何代码,以至于开发人员宁可重新添加一个方法也不敢修改之前的代码。
DRY看似初级人员都要掌握的能力,如果使用不当会造成非常严重的后果。
参考文章:
DRY is about Knowledge
Wikipedia:Don't repeat yourself
网友评论