DRY(Don't Repeat Yourself )原则
凡是写过一些代码的程序猿都能够意识到应该避免重复的代码和逻辑。我们通过提取方法,提取抽象类等等措施来达到这一目的。我们总能时不时的听到类似这样的话:”把这些公用的类放到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 )原则的更多相关文章
- DRY
DRY(Don't Repeat Yourself )原则 凡是写过一些代码的程序猿都能够意识到应该避免重复的代码和逻辑.我们通过提取方法,提取抽象类等等措施来达到这一目的.我们总能时不时的听到类 ...
- PHP精选数组函数
编程怎么能少的了数组呢,以下是学习PHP时常用的数组处理函数.在编程中要遵循一个原则就是DRY(Don`t Repeat Yourself)原则,PHP中有大量的函数,都记住这些函数不太现实,但常用的 ...
- Django 1.10 中文文档------3.2.2 查询操作making queries
3.2.2 查询操作 6.15章节包含所有模型相关的API解释. 后面的内容基于如下的一个博客应用模型: from django.db import models class Blog(models. ...
- 关于JavaScripting API您不知道的5件事
现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的.在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个 ...
- Instagram的技术架构
http://blogread.cn/it/article/5497 Instagram 被 Facebook 以10亿美金收购.团队规模:13 人.而在被Facebook收购前的一个月,整个团队才7 ...
- 查询操作 -- Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- 《InsideUE4》UObject(六)类型系统代码生成重构-UE4CodeGen_Private
读的不如写的快 引言 在之前的<InsideUE4>UObject(四)类型系统代码生成和<InsideUE4>UObject(五)类型系统收集章节里,我们介绍了UE4是如何根 ...
- 你不知道的JavaScript--Item17 循环与prototype最后的几点小tips
1.优先使用数组而不是Object类型来表示有顺序的集合 ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 但是在使用for..in循环对Object中的 ...
- Django:安装和启动
最近在学习利用python语言进行web站点开发,使用的框架是Django.这篇博客主要介绍Django的安装和简单使用. 一.Django介绍 Django是一个开源的Web应用框架,由Python ...
随机推荐
- 爬虫requests模块 2
会话对象¶ 会话对象让你能够跨请求保持某些参数.它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 urllib3 的 connection pooling 功能.所 ...
- Andriod学习笔记3:Mac 平台下搭建 CLion 集成开发环境
1. 安装Xcode 通过App store或者下载安装Xcode. 安装完成之后,最好启动一下Xcode,否则可能会报"Error:The C compiler "/usr/bi ...
- axure的一些注意事项
1. 不要轻易用中继器的 载入时 事件, 感觉存在bug 2. 元件在显示和隐藏的动画过程中,不要去取他的x,y值,有几率会取成0,也不要去获取它的尺寸,只有在动画完成后才能获得 3. 装着一个中继器 ...
- jQuery中事件绑定到bind、live、delegate、on方法的探究
1. 给页面上的某个元素绑定事件,最初采用下面的方式实现: $(‘selector’).click(function(){ //code }); 缺点: 不能同时绑定多个事件,不能绑定动态的元素. 后 ...
- ListView 的优化
listView 的宽高设为固定, 或match_parent,这样在加载布局是, 几面装下几个item 就首先加载几个 减少对象的创建 //减少对象的创建 if (convertView == nu ...
- Map排序
HashMap: 最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度.HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 ...
- 【原】iOS学习之NSDate在项目中的一些类目扩展
在项目中,我们可能会面对各种各样的对于时间的需求,在这里提供几种可能会用到的需求代码 1.与今天的时间做比较,返回日期差值 代码: - (NSInteger)compareWithToday { NS ...
- 【BZOJ3156】防御准备 斜率优化DP
裸题,注意:基本的判断(求Min还是Max),因为是顺着做的,且最后一个a[i]一定要取到,所以是f[n]. DP:f[i]=min(f[j]+(i-j-1)*(i-j)/2+a[i]) 依旧设x&g ...
- Swift的关键字
在声明中使用关键字 let :声明一个常量 var :声明一个变量 class :声明一个类 static :静态的 deinit :反初始化方法?析构方法 init :构造方法?初始化方法 en ...
- C#窗体中读取修改xml文件
由于之前没有操作过xml文件,尤其是在窗体中操作xml,脑子一直转不动,而且很抵制去做这个功能,终于还是突破了自己通过查询资料完成了这个功能,在此记录一下自己的成果. 功能说明:程序中存在的xml文件 ...