编码原则 之 Once and Only Once
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.
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.
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.
编码原则 之 Once and Only Once的更多相关文章
- S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则
注:以下图片均来自<如何向妻子解释OOD>译文链接:http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html < ...
- 编码原则实例------c++程序设计原理与实践(进阶篇)
编码原则: 一般原则 预处理原则 命名和布局原则 类原则 函数和表达式原则 硬实时原则 关键系统原则 (硬实时原则.关键系统原则仅用于硬实时和关键系统程序设计) (严格原则都用一个大写字母R及其编号标 ...
- Web前端安全之安全编码原则
随着Web和移动应用等的快速发展,越来越多的Web安全问题逐渐显示出来.一个网站或一个移动应用,如果没有做好相关的安全防范工作,不仅会造成用户信息.服务器或数据库信息的泄露,更可能会造成用户财产的损失 ...
- Python写业务逻辑的几个编码原则
作为一个写业务逻辑的boy,我需要专注的就是把业务逻辑写好.写业务逻辑并不复杂,就是把编程最基础的东西使用好,有变量.循环.流程控制.函数.数据库等. 但是写出的逻辑要通俗易懂.易于理解,避免炫技.晦 ...
- Web开发者不可不知的15条编码原则
HTML已经走过了近20的发展历程.从HTML4到XHTML,再到最近十分火热的HTML5,它几乎见证了整个互联网的发展.但是,即便到现在,有很多基础的概念和原则依然需要开发者高度注意.下面,向大家介 ...
- zg项目 应用系统编码原则
一.编码说明: 1.系统编码采用三码为原则,通常两码简称之. 1>.子系统或类型 2>.系统小分类 3>.系统大分类 如 IPMS领域业务群: DA 应用软件发展管理系统 DE公用副 ...
- Web 开发者不可不知的15条编码原则
HTML 已经走过了近20的发展历程.从HTML4到XHTML,再到最近十分火热的HTML5,它几乎见证了整个互联网的发展.但是,即便到现在,有很多基础的概念和原则依然需要开发者高度注意.下面,向大家 ...
- 中文字符utf-8编码原则
UTF-8是一种变长字节编码方式.对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0:如果是 多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字 ...
- 编码原则:必须使用的 TODO
结构 // TODO:JS ParentId 不要使用硬编码. var parentId = record.get('ParentId'); var parentNode = me.getStore( ...
- dubbo作者讲编码原则
刚看到梁飞谈到dubbo为保证代码质量开发人员必须要注意的,其实也是开发人员应该做的. 1. 防止空指针和下标越界 这是我最不喜欢看到的异常,尤其在核心框架中,我更愿看到信息详细的参数不合法异常, 这 ...
随机推荐
- DOS特殊字符转义方法
http://www.robvanderwoude.com/escapechars.php 期望得到的字符 转义后字符 说明 % %% May not always be required in do ...
- sed memo 2
配置文件注释过滤 示例文件 [user_00@txyun test]$ cat sed_test # comment aaaaaaaaaaa bbbb #comment cccc dddd fffo ...
- xamarin.Android开发前的配置
vs2019开发 入门教程 https://docs.microsoft.com/zh-cn/xamarin/android/get-started/installation/android-emul ...
- git上clone需要ssh时
在命令行中输入ssh-keygen -t rsa -C "your_email@example.com" 然后使用编辑器打开id_rsa.pub文件,复制里面的ssh
- Mac vs code 快捷键
control + shift + L 选中所有匹配的所有单词,光标选中
- 转-->>mysql的bin log
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日 ...
- centos7 安装oracle 11g数据库
1.新建oracle用户 groupadd oracle useradd -g oracle oracle .修改操作系统核心参数 在Root用户下执行以下步骤: 1)修改用户的SHELL的限制,修改 ...
- 聊聊call、apply、bind的故事
说到call.apply.bind,前端的胖友可是不陌生.以下就从几个方面分别聊聊它们. 是什么?(what?) 实际上它们真正的样子是这样的: Function.prototype.call(thi ...
- linux软AP--hostapd+dhcpd
linux软AP--hostapd+dhcpd 2018年05月08日 ⁄ 综合 ⁄ 共 4908字 ⁄ 字号 小 中 大 ⁄ 评论关闭 随着手机.笔记本等无线设备的增多,公司里的家用三个无线路由器已 ...
- Nginx处理请求的11个阶段(agentzh的Nginx 教程学习记录)
Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read.server-rewrite.find-config.rewrite.post-rewrite.preacc ...