原文

The Once and Only Once principle can be thought of as a subset of the Don’t Repeat Yourself principle, and is one of the most fundamental principles of software development.

Duplication of behavior is one of the most common sources of bugs in software systems, since it becomes increasingly likely that changes to behavior defined in one location may not be propagated to all locations where this behavior is defined.

Eliminating the duplication caused by not following the Once and Only Once principle is one of the primary reasons for refactoring and is also at the core of many design patterns.

原文2

One of the main goals (if not the main goal) when ReFactoringcode.

Each and every declaration of behavior should appear OnceAndOnlyOnce.

Conceptually analogous to normalization in the RelationalModel. See also DontRepeatYourself.

Code wants to be simple.

If you are aware of CodeSmells, and duplicate code is one of the strongest, and you react accordingly, your systems will get simpler.

When I began working in this style, I had to give up the idea that I had the perfect vision of the system to which the system had to conform.

Instead, I had to accept that I was only the vehicle for the system expressing its own desire for simplicity.

My vision could shape initial direction, and my attention to the desires of the code could affect how quickly and how well the system found its desired shape,

but the system is riding me much more than I am riding the system. -- KentBeck, feeling mystical, see MysticalProgramming

Beware of introducing unnecessary coupling (CouplingAndCohesion) when refactoring for OnceAndOnlyOnce.

Refactoring is the moving of units of functionality from one place to another in your program. Refactoring has as a primary objective getting each piece of functionality to exist in exactly one place in the software. -- RonJeffries

It's not OAOO, and this comment probably ought to be somewhere else, but doesn't refactoring also cover replacing one piece of code with another, simpler piece of code that has the same external "appearance" and function?

Yes - good point. Note Ron's subtle use of "a primary objective" instead of "the primary objective". I personally use two "first tier" refactoring rules - OnceAndOnlyOnce and SeparateTheWhatFromTheHow (my name - the common name is ComposedMethod)

OnceAndOnlyOnce is a profound concept, but difficult to apply. I've spent my entire professional life (25 years) learning how to apply it to programs. This page [many versions ago] ... was rewritten to make OnceAndOnlyOnce seem like a simple rule to apply, instead of a prime principle. OnceAndOnlyOnce is NOT easy! And it was wrong to refactor this page so that all hints of tension and disagreement are removed from it.

OnceAndOnlyOnce is not a pattern. A pattern is something you can teach someone to do in a fairly short amount of time. A day, usually. Perhaps a few weeks.

But learning how to refactor classes to form a TemplateMethod does not help you see how to use XML to represent your user interfaces (a recent OnceAndOnlyOnce technique applied to Squeak), or how to make a good virtual machine. These are patterns; OnceAndOnlyOnce is not a pattern. OnceAndOnlyOnce is a principle. -- RalphJohnson

Well said. OnceAndOnlyOnce is not just a simple rule, but one of the core goals of all software design. It's why functions were invented. Remember that your program could have been written as a single long function using only ifs, whiles, and try/catch blocks for flow control, and primitives for all the data. Consider what that would look like. For "hello world", it's the default.

I once saw Beck declare two patches of almost completely different code to be "duplication", change them so that they WERE duplication, and then remove the newly inserted duplication to come up with something obviously better. -- RonJeffries, from the XpMailingList

or, the long version...

I recall once seeing Beck look at two loops that were quite dissimilar: they had different for structures, and different contents, which is pretty much nothing duplicated except the word "for", and the fact that they were looping - differently - over the same collection.

He changed the second loop to loop the same way the first one did. This required changing the body of the loop to skip over the items toward the end of the collection, since the previous version only did the front of the collection.

Now the for statements were the same. "Well, gotta eliminate that duplication, he said, and moved the second body into the first loop and deleted the second loop entirely.

Now he had two kinds of similar processing going on in the one loop. He found some kind of duplication in there, extracted a method, did a couple of other things, and voila! the code was much better.

That first step - creating duplication - was startling. -- RonJeffries, from the XpMailingList

It isn't so startling. That technique is necessary for the more powerful space optimizations of program code: you reduce everything as much as possible, then you find two subgraphs that are similar, you add conditional nodes to them until they're identical (and inject the proper conditions), then you combine them. Repeat until the apparent gains aren't worth the resource cost to acquire them. Beck is just doing it by hand.

It is also frequently used to allow consistent idiomatic expressions to emerge. This allows bugs to be detected via inspection for all cases where the idiom was not followed properly. This is more than superficial coding standards. For example: a loop guard of < n or <=n will behave differently if n starts at 0 vs starting at 1. It is best to pick one idiom and stick with it. I suspect the duplication here was semantic in nature and culling it out allowed a reuse opportunity to emerge.

-- MarcGrundfest

It isn't so startling. That technique is necessary for the more powerful space optimizations of program code: you reduce everything as much as possible, then you find two subgraphs that are similar, you add conditional nodes to them until they're identical (and inject the proper conditions), then you combine them. Repeat until the apparent gains aren't worth the resource cost to acquire them. Beck is just doing it by hand.

It is also frequently used to allow consistent idiomatic expressions to emerge. This allows bugs to be detected via inspection for all cases where the idiom was not followed properly. This is more than superficial coding standards. For example: a loop guard of < n or <=n will behave differently if n starts at 0 vs starting at 1. It is best to pick one idiom and stick with it. I suspect the duplication here was semantic in nature and culling it out allowed a reuse opportunity to emerge.

-- MarcGrundfest

编码原则 之 Once and Only Once的更多相关文章

  1. S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则

    注:以下图片均来自<如何向妻子解释OOD>译文链接:http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html      < ...

  2. 编码原则实例------c++程序设计原理与实践(进阶篇)

    编码原则: 一般原则 预处理原则 命名和布局原则 类原则 函数和表达式原则 硬实时原则 关键系统原则 (硬实时原则.关键系统原则仅用于硬实时和关键系统程序设计) (严格原则都用一个大写字母R及其编号标 ...

  3. Web前端安全之安全编码原则

    随着Web和移动应用等的快速发展,越来越多的Web安全问题逐渐显示出来.一个网站或一个移动应用,如果没有做好相关的安全防范工作,不仅会造成用户信息.服务器或数据库信息的泄露,更可能会造成用户财产的损失 ...

  4. Python写业务逻辑的几个编码原则

    作为一个写业务逻辑的boy,我需要专注的就是把业务逻辑写好.写业务逻辑并不复杂,就是把编程最基础的东西使用好,有变量.循环.流程控制.函数.数据库等. 但是写出的逻辑要通俗易懂.易于理解,避免炫技.晦 ...

  5. Web开发者不可不知的15条编码原则

    HTML已经走过了近20的发展历程.从HTML4到XHTML,再到最近十分火热的HTML5,它几乎见证了整个互联网的发展.但是,即便到现在,有很多基础的概念和原则依然需要开发者高度注意.下面,向大家介 ...

  6. zg项目 应用系统编码原则

    一.编码说明: 1.系统编码采用三码为原则,通常两码简称之. 1>.子系统或类型 2>.系统小分类 3>.系统大分类 如 IPMS领域业务群: DA 应用软件发展管理系统 DE公用副 ...

  7. Web 开发者不可不知的15条编码原则

    HTML 已经走过了近20的发展历程.从HTML4到XHTML,再到最近十分火热的HTML5,它几乎见证了整个互联网的发展.但是,即便到现在,有很多基础的概念和原则依然需要开发者高度注意.下面,向大家 ...

  8. 中文字符utf-8编码原则

    UTF-8是一种变长字节编码方式.对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0:如果是 多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字 ...

  9. 编码原则:必须使用的 TODO

    结构 // TODO:JS ParentId 不要使用硬编码. var parentId = record.get('ParentId'); var parentNode = me.getStore( ...

  10. dubbo作者讲编码原则

    刚看到梁飞谈到dubbo为保证代码质量开发人员必须要注意的,其实也是开发人员应该做的. 1. 防止空指针和下标越界 这是我最不喜欢看到的异常,尤其在核心框架中,我更愿看到信息详细的参数不合法异常, 这 ...

随机推荐

  1. 用vue怎么写点击保存之后的返回的代码?

    点击完保存调用接口之后,如果使用  this.$router.go(-1); 返回到编辑页面,数据不会有更新,使用 this.$router.replace({ name: '信息展示', param ...

  2. 好的UI管理后台

    1,https://www.v2ex.com/t/513539 - https://github.com/a54552239/projectManage

  3. opencart3修改产品页模板没有效果的原因排查

    这几天在opencart 3模板时发生了一个很奇怪的事情,ytkah明明已经将product.twig模板修改了,但是前端产品页就是没有变化,后台刷新缓存了也不起左右.后面想着把模板重命名成produ ...

  4. Python3学习之路~7.3 反射

    python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,该四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删除成员. ...

  5. nginx中的超时设置,请求超时、响应等待超时等

    nginx比较强大,可以针对单个域名请求做出单个连接超时的配置. 比如些动态解释和静态解释可以根据业务的需求配置 proxy_connect_timeout :后端服务器连接的超时时间_发起握手等候响 ...

  6. Java中数组的几个常用算法:插入算法,删除算法,冒泡排序算法

    前言: 在Java中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...

  7. Unity 属性雷达图

    using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(MeshFilter),typeof(Mes ...

  8. Git使用和Vue项目

    1.创建git排除文件,.gitignore 2.READEME.md 和 LICENSE开源协议 git init  创建仓库 , git status 查看文件状态 红色文件表示未提交. git ...

  9. 单点登录(SSO)详解

    背景 在企业发展初期,企业使用的系统很少,通常一个或者两个,每个系统都有自己的登录模块,运营人员每天用自己的账号登录,很方便.但随着企业的发展,用到的系统随之增多,运营人员在操作不同的系统时,需要多次 ...

  10. cnpm安装失败

    解决办法: 先:npm config set registry "http://registry.npmjs.org/" 再:npm install -g cnpm