[翻译]单一职责原则

原文地址:The Single Responsibility Principle

在1972年,David L. Parnas发表了一篇题为《On the Criteria To Be Used in Decomposing Systems into Modules》的经典论文。它被刊登在ACM通讯杂志第12期第15卷上。

在这篇论文中,Parnas采用了一种简单的方法,比较了两种不同的分解逻辑的策略。这篇论文非常值得一读,我强烈建议你好好阅读一下。他的部分结论如下:

我们试图通过这些例子来证明,根据流程图把一个系统分解成模块几乎总是不正确的。相反,我们建议从一个设计很复杂或设计很有可能会变化的地方开始。每个模块都被设计为只会被一种变化因素影响。

Parnas的结论是,在某种程度上,模块的拆分要基于将来可能的变化因素。

两年后,Edsger Dijkstra写了同样堪称经典的一篇论文《 On the role of scientific thought》。在这篇论中他提出了关注点分离(Separation of Concerns)的概念。

二十世纪七八十年代是软件架构思想繁盛时期。结构化编程和设计非常流行。在那段时间,Larry Constantine提出了耦合和内聚的概念,后由Tom DeMarco, Meilir Page-Jones和其他人加以扩充完善。

在九十年代后期,我试图将这些概念合并成一个原则。我把这个原则称为单一职责原则(Single Responsibility Principle)。 (我有这种模糊的感觉,我从Bertrand Meyer那里盗用了的这个原则的名字,但我还没有证实这一点。)

单一职责原则(SRP)指出,每个软件模块应该有且只有一个理由去改变。这听起来很不错,似乎与Parnas想法一致。然而它回避了问题的本质:改变的理由究竟是指什么?这里的理由如何定义?

一些人想知道bug修复是否可以作为改变的理由。另外一些人好奇重构是否是改变的理由。这些问题可以通过指出“改变理由”和“责任”这两个术语之间的联系来回答。

显然代码的职责不是bug修复或者重构。这些应该是程序员的责任,而不是程序的。但如果是这样的话,程序负责什么?或者说:这个程序是谁负责?谁必需对程序的设计负责?

想象一个典型的商业组织。一般情况下,公司有一个首席执行官(CEO),而需要向首席执行官汇报工作的直接责任人有:首席财务官(CFO),首席运营官(COO),首席技术官(CTO)。首席财务官负责控制公司的财务状况。首席运营官负责管理公司的日常运营。首席技术官是负责公司技术基础设施和发展。

现在看看下面JAVA程序段:

Public class Employee {
    public Money calculatePay();
    public void save();
    public String reportHours();
}
  • calculatePay方法根据员工的合同,状态,工作时间等情况计算支付给员工的薪水
  • save方法把员工相关数据存入公司数据库
  • reportHours方法返回员工的工作情况报告,审计人员可以确保员工工作了足够的时间并付给员工相对应的报酬

现在,上面提到的COO,CFO和CTO中的哪一个需要对calculatePay方法的的行为负责?也就是说,如果这个方法出了问题,哪一个会被CEO开除呢?很明显,答案是CFO。发放工资是财务的责任。如果CFO手下的某个员工把计算薪水的规则弄错了,从而导致所有的员工都被发放了双倍的薪水,CFO将难辞其咎,多半会被开除吧。

这里应该还有一个首席官对reportHours的格式和内容负责。他领导审计人员,掌握公司运作情况,报告给CEO。如果出具的报告混乱不堪,错误百出,面临被开除的是谁?没错,就是COO。

最后,如果save方法出了灾难性的行为,哪一个首席官会被开除就很明显了。如果公司的数据库崩溃了,数据丢失,那么CTO将被开除。

因此可以看出,calculatePay方法被修改的需求来自CFO领导的团队。同样的,COO和他领导的团队会对reportHours方法有修改需求,而CTO团队极有可能提出对save方法的修改。

这就是单一职责的关键。它是关于人的。

当你写一个软件模块的时候,你应该确保,当需求变更的时候,需求的来源应该是一个人,更准确的说,应该是对某个业务功能负责的人群。你应该把复杂的系统拆分成独立的模块,使得每一个模块都只满足一个业务功能的需求。

为什么要这样?

因为,我们不希望由于我们为CTO的需求做了一些修改导致COO被开除。最让我们的客户感到不能理解的是出现了一个完全与他们要求的改变无关的程序故障,至少在他们看来是没有任何关联的。如果你在改变calculatePay方法的时候无意中修改了reportHours,那么COO可能会要求你永远都不要去碰calculatePay方法了。

想象一下,你把车开到修理厂,找了一个修理工来修理你的汽车车窗。第二天他告诉你已经修理好了。当你去取车的时候,你发现车窗已经修好了但是车子却打不燃火了。我想你再也不会找这个修理工修车了。

当你改动了客户在意的功能但是客户根本就没叫你去修改的时候,客户就是这个感觉。

这就是我们不能把SQL直接写到JSP中,不把生成HTML的代码和负责数据计算的代码放在一起,业务逻辑不应该知道数据库架构的原因。这也是我们关注分离点(separate concerns)的理由。

单一职责的另一种描述是:

会被同样的原因改变的事情聚集在一起。把会被多种原因改变的事情分离开。

如果你仔细回味上面的描述你就会意识到,这只是另外一种定义内聚和耦合的方式。对于相同原因引起的变化,我们希望提高内聚,而对于会被多种原因改变的事情我们希望降低耦合。

不管怎样,当你脑海中浮现这个法则的时候,请记住变化的原因是。是带来的变化。如果你不想让其他人或者你自己感到困惑,那么请不要把不同的人因为不同的原因关心的代码放在一起。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容