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 ...
随机推荐
- Centos7学习之静态IP设置方法介绍
1.编辑 ifcfg-eth0 文件,vim 最小化安装时没有被安装,需要自行安装不描述. # vim /etc/sysconfig/network-scripts/ifcfg-eth0 2.修改 ...
- 剑指Offer-【面试题02:实现Singleton 模式——七种实现方式】
题目:设计一个类,我们只能生成该类的一个实例 package com.cxz.demo02; /** * Created by CXZ on 2016/9/13. */ public class Si ...
- Windows平台手动卸载Oracle Server【完整+干净】
使用Oracle自带的Universal Installer卸载存在问题: 不干净,不完全,还有一些注册表残留,会影响到后来的安装. 所以,推荐使用手工卸载Oracle. 1.[win+R]-> ...
- sizeof(转载)
原文地址:http://blog.sina.com.cn/s/blog_5da08c340100bmwu.html 转载至:http://www.cnblogs.com/wangkangluo1/ar ...
- Winform窗体用对象数组做一个小项目
首先我我们看一下需求:我们要做的是显示员工信息,实现项目经理给员工评分的功能! 首先项目经理是评分的人所以没有用,因为我们自己写,评分的就是我们自己.所以我们要做的是先在vs也就是我们的环境里建一个项 ...
- 解决ScrollView 嵌套 GridView 单行显示问题
简单重写GridView package com.hh.beauter.my_ui; import android.content.Context; import android.util.Attri ...
- python 爬虫(二)
python 爬虫 Advanced HTML Parsing 1. 通过属性查找标签:基本上在每一个网站上都有stylesheets,针对于不同的标签会有不同的css类于之向对应在我们看到的标签可能 ...
- SqlServer查询表中各列名称、表中列数
查询表名为tb_menu的所有列名 select name from syscolumns where id=object_id('tb_menu') 查询表名为tb_menu的所有列名个数 ...
- 帝国CMS如何自动生成sitemap.xml网站地图文件
登录网站的后台http://你的域名/e/admin/ 进入后台栏目 =>增加自定义页面 =>选择直接页面,页面名称为:网站地图,文件名修改为 ../../sitemap.xml 内容填 ...
- T-SQL Recipes之Common Function
在我们写SQL的时候,经常会用到许多内置方法,简化了我们许多代码,也提高了效率,这篇主要总结一些常用的方法. ISNULL VS COALESCE VS NULLIF 在SQL中,NULL值是比较特殊 ...