凡是写过一些代码的程序猿都能够意识到应该避免重复的代码和逻辑。我们通过提取方法,提取抽象类等等措施来达到这一目的。我们总能时不时的听到类似这样的话:”把这些公用的类放到shared项目去,别的项目还要使用。。。“,什么算是公用(重复)的代码?是不是公用(重复)的代码就要放到一个叫shared的地方?

为什么说重复的代码和逻辑会带来问题呢?

你从一个类中复制了一段代码到另一个类中,但是这段代码足够的稳定,百年不变,这样的重复会带来问题吗?

也许不会。

如果这段代码需要时不时的修改,那么你就要花时间去修改所有包含这段逻辑的代码,这样无形中增加了维护成本和发生bug的几率。这时候就要着手消除和抽取重复的代码。

对于消除重复的代码有一个三次法则(rule of three):

1.第一次先写了一段代码。

2.第二次在另一个地方写了一段相同的代码,你已经有消除和提取重复代码的冲动了。

3.再次在另一个地方写了同样的代码,你已忍无可忍,现在可以考虑提取和消除重复代码了。

这一法则也适应于对重构时机的把握,过早的重构可能会引入新的问题,三次法则给了你一个重构依据。当然,随着你经验的增长,你可能在第二阶段已经能非常有信心的预料到问题所在。

什么样的代码算是重复的?

DRY is about Knowledge一文中给了这样一个实例:

<?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)不同,这两段代码之所以相同完全属于巧合。对这样的代码进行提取和消除重复是错误的。

我之前待的team维护了一个北美的项目,如果让我指出这一项目最大的设计问题,就是将一些本不应该提取的代码(各种Model、数据访问)抽取到了一个叫做Shared的工程中,这一举动导致开发人员在后期不敢再修改Shared工程中的任何代码,以至于开发人员宁可重新添加一个方法也不敢修改之前的代码。

DRY看似初级人员都要掌握的能力,如果使用不当会造成非常严重的后果,正是因为我维护了这样的项目才有感而发,希望大家引以为戒,当然大家若是有不同的看法可以一起讨论。

DRY(Don't Repeat Yourself )原则的更多相关文章

  1. DRY

    DRY(Don't Repeat Yourself )原则   凡是写过一些代码的程序猿都能够意识到应该避免重复的代码和逻辑.我们通过提取方法,提取抽象类等等措施来达到这一目的.我们总能时不时的听到类 ...

  2. PHP精选数组函数

    编程怎么能少的了数组呢,以下是学习PHP时常用的数组处理函数.在编程中要遵循一个原则就是DRY(Don`t Repeat Yourself)原则,PHP中有大量的函数,都记住这些函数不太现实,但常用的 ...

  3. Django 1.10 中文文档------3.2.2 查询操作making queries

    3.2.2 查询操作 6.15章节包含所有模型相关的API解释. 后面的内容基于如下的一个博客应用模型: from django.db import models class Blog(models. ...

  4. 关于JavaScripting API您不知道的5件事

    现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的.在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个 ...

  5. Instagram的技术架构

    http://blogread.cn/it/article/5497 Instagram 被 Facebook 以10亿美金收购.团队规模:13 人.而在被Facebook收购前的一个月,整个团队才7 ...

  6. 查询操作 -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  7. 《InsideUE4》UObject(六)类型系统代码生成重构-UE4CodeGen_Private

    读的不如写的快 引言 在之前的<InsideUE4>UObject(四)类型系统代码生成和<InsideUE4>UObject(五)类型系统收集章节里,我们介绍了UE4是如何根 ...

  8. 你不知道的JavaScript--Item17 循环与prototype最后的几点小tips

    1.优先使用数组而不是Object类型来表示有顺序的集合 ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 但是在使用for..in循环对Object中的 ...

  9. Django:安装和启动

    最近在学习利用python语言进行web站点开发,使用的框架是Django.这篇博客主要介绍Django的安装和简单使用. 一.Django介绍 Django是一个开源的Web应用框架,由Python ...

随机推荐

  1. PHP AES的加密解密

    AES加密算法 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DE ...

  2. VS2012 集成 IL DASM IL微软中间语言查看器

    第一步: 找到IL DASM的安装位置,默认在C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools 第二步: ...

  3. Ubuntu(Linux系统)虚拟机工具vmtools详细说明

    安装虚拟机工具vmtools大概步骤如下: 个人总结步骤: 第一步:点击虚拟机软件的vm工具栏选项,选择install vmware tools(安装VMware Tools) 第二步:桌面会出现一个 ...

  4. mysql命令行修改字符编码

    1.修改数据库字符编码 mysql> alter database mydb character set utf8 ; 2.创建数据库时,指定数据库的字符编码 mysql> create ...

  5. 【leetcode】Largest Number

    题目简述: Given a list of non negative integers, arrange them such that they form the largest number. Fo ...

  6. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen快速上手

    原文链接:Hello, Android Multiscreen Quickstart. 译文链接:Hello,Android Multiscreen快速上手 本部分介绍利用Xamarin.Androi ...

  7. Arduino uno 引脚说明

    http://openhome.cc/Gossip/Books/mBlockArduino1-3and1-4.html http://swf.com.tw/?p=406

  8. sql字段属性

  9. 学习微信小程序之css9内边距

    padding内边距 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  10. java对象转换成json

    package com.bjs.acrosstime.utils; import java.util.ArrayList; import java.util.Date; import java.uti ...