注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

转贴:一些软件设计的原则  

2011-11-03 16:09:12|  分类: UML+设计模式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

2011-04-26 17:03:39|  分类: 转帖区 |  标签: |字号大中小 订阅


转帖:http://coolshell.cn/articles/4535.html

以前本站向大家介绍过一些软件开发的原则,比如优质代码的十诫Unix传奇(下篇)中所以说的UNIX的设计原则。相信大家从中能够从中学了解到一些设计原理方面的知识,正如我在《再谈“我是怎么招聘程序”》中所说的,一个好的程序员通常由其操作技能、知识水平,经验层力和能力四个方面组成。在这里想和大家说说设计中的一些原则,我认为这些东西属于长期经验总结出来的知识。这些原则,每一个程序员都应该了解。但是请不要教条主义,在使用的时候还是要多多考虑实际情况。其实,下面这些原则,不单单只是软件开发,可以推广到其它生产活动中,甚至我们的生活中。


Don’t Repeat Yourself (DRY)

DRY 是一个最简单的法则,也是最容易被理解的。但它也可能是最难被应用的(因为要做到这样,我们需要在泛型设计上做相当的努力,这并不是一件容易的事)。它意味着,当我们在两个或多个地方的时候发现一些相似的代码的时候,我们需要把他们的共性抽象出来形一个唯一的新方法,并且改变现有的地方的代码让他们以一些合适的参数调用这个新的方法。

参考:http://en.wikipedia.org/wiki/Don%27t_repeat_yourself


Keep It Simple, Stupid (KISS)

KISS原则在设计上可能最被推崇的,在家装设计,界面设计 ,操作设计上,复杂的东西越来越被众人所BS了,而简单的东西越来越被人所认可,比如这些UI的设计和我们中国网页(尤其是新浪的网页)者是负面的例子。“宜家”(IKEA)简约、效率的家居设计、生产思路;“微软”(Microsoft)“所见即所得”的理念;“谷歌”(Google)简约、直接的商业风格,无一例外的遵循了“kiss”原则,也正是“kiss”原则,成就了这些看似神奇的商业经典。而苹果公司的iPhone/iPad将这个原则实践到了极至。

把一个事情搞复杂是一件简单的事,但要把一个复杂的事变简单,这是一件复杂的事。

参考:http://en.wikipedia.org/wiki/KISS_principle


Program to an interface, not an implementation

这是设计模式中最根本的哲学,注重接口,而不是实现,依赖接口,而不是实现。接口是抽象是稳定的,实现则是多种多样的。以后面我们会面向对象的SOLID原则中会提到我们的依赖倒置原则,就是这个原则的的另一种样子。还有一条原则叫Composition over inheritance(喜欢组合而不是继承),这两条是那23个经典设计模式中的设计原则。


Command-Query Separation (CQS)  – 命令-查询分离原则
查询:当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质;
命令:当一个方法要改变对象的状态的时候,它就具有命令的性质;

通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用,而会改变对象的状态的方法不可能有返回值。也就是说:如果我们要问一个问题,那么就不应该影响到它的答案。实际应用,要视具体情况而定,语义的清晰性和使用的简单性之间需要权衡。将Command和Query功能合并入一个方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果。

在系统设计中,很多系统也是以这样原则设计的,查询的功能和命令功能的系统分离,这样有则于系统性能,也有利于系统的安全性。

参考:http://en.wikipedia.org/wiki/Command-query_separation


You Ain’t Gonna Need It (YAGNI)

这个原则简而言之为——只考虑和设计必须的功能,避免过度设计。只实现目前需要的功能,在以后您需要更多功能时,可以再进行添加。


如无必要,勿增复杂性。
软件开发先是一场沟通博弈。

以前本站有一篇关于过度重构的文章,这个示例就是这个原则的反例。而,WebSphere的设计者就表示过他过度设计了这个产品。我们的程序员或是架构师在设计系统的时候,会考虑很多扩展性的东西,导致在架构与设计方面使用了大量折衷,最后导致项目失败。这是个令人感到讽刺的教训,因为本来希望尽可能延长项目的生命周期,结果反而缩短了生命周期。

参考:http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It


Law of Demeter – 迪米特法则

迪米特法则(Law of Demeter),又称“最少知识原则”(Principle of Least Knowledge),其来源于1987年荷兰大学的一个叫做Demeter的项目。Craig Larman把Law of Demeter又称作“不要和陌生人说话”。在《程序员修炼之道》中讲LoD的那一章叫作“解耦合与迪米特法则”。关于迪米特法则有一些很形象的比喻:


如果你想让你的狗跑的话,你会对狗狗说还是对四条狗腿说?
如果你去店里买东西,你会把钱交给店员,还是会把钱包交给店员让他自己拿?

和狗的四肢说话?让店员自己从钱包里拿钱?这听起来有点荒唐,不过在我们的代码里这几乎是见怪不怪的事情了。

对于LoD,正式的表述如下:


对于对象 ‘O’ 中一个方法’M',M应该只能够访问以下对象中的方法:


对象O;
与O直接相关的Component Object;
由方法M创建或者实例化的对象;
作为方法M的参数的对象。

在《Clean Code》一书中,有一段Apache framework中的一段违反了LoD的代码:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

这么长的一串对其它对象的细节,以及细节的细节,细节的细节的细节……的调用,增加了耦合,使得代码结构复杂、僵化,难以扩展和维护。

在《重构》一书中的代码的环味道中有一种叫做“Feature Envy”(依恋情结),形象的描述了一种违反了LoC的情况。Feature Envy就是说一个对象对其它对象的内容更有兴趣,也就是说老是羡慕别的对象的成员、结构或者功能,大老远的调用人家的东西。这样的结构显然是不合理的。我们的程序应该写得比较“害羞”。不能像前面例子中的那个不把自己当外人的店员一样,拿过客人的钱包自己把钱拿出来。“害羞”的程序只和自己最近的朋友交谈。这种情况下应该调整程序的结构,让那个对象自己拥有它羡慕的feature,或者使用合理的设计模式(例如Facade和Mediator)。

参考:http://en.wikipedia.org/wiki/Principle_of_Least_Knowledge


面向对象的S.O.L.I.D 原则

一般来说这是面向对象的五大设计原则,但是,我觉得这些原则可适用于所有的软件开发。

Single Responsibility Principle (SRP) – 职责单一原则

关于单一职责原则,其核心的思想是:一个类,只做一件事,并把这件事做好,其只有一个引起它变化的原因。单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为一个模块实现过多的功能点,以保证实体只有一个引起它变化的原因。


Unix/Linux是这一原则的完美体现者。各个程序都独立负责一个单一的事。
Windows是这一原则的反面示例。几乎所有的程序都交织耦合在一起。

Open/Closed Principle (OCP) – 开闭原则

关于开发封闭原则,其核心的思想是:模块是可扩展的,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。


对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

对于面向对象来说,需要你依赖抽象,而不是实现,23个经典设计模式中的“策略模式”就是这个实现。对于非面向对象编程,一些API需要你传入一个你可以扩展的函数,比如我们的C 语言的qsort()允许你提供一个“比较器”,STL中的容器类的内存分配,ACE中的多线程的各种锁。对于软件方面,浏览器的各种插件属于这个原则的实践。

Liskov substitution principle (LSP) – 里氏代换原则

软件工程大师Robert C. Martin把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”。也就是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下就可以扩展。

这么说来,似乎有点教条化,我非常建议大家看看这个原则个两个最经典的案例——“正方形不是长方形”和“鸵鸟不是鸟”。通过这两个案例,你会明白《墨子 小取》中说的 ——“娣,美人也,爱娣,非爱美人也….盗,人也;恶盗,非恶人也。”——妹妹虽然是美人,但喜欢妹妹并不代表喜欢美人。盗贼是人,但讨厌盗贼也并不代表就讨厌人类。这个原则让你考虑的不是语义上对象的间的关系,而是实际需求的环境。

在很多情况下,在设计初期我们类之间的关系不是很明确,LSP则给了我们一个判断和设计类之间关系的基准:需不需要继承,以及怎样设计继承关系。

Interface Segregation Principle (ISP) – 接口隔离原则

接口隔离原则意思是把功能实现在接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。

举个例子,我们对电脑有不同的使用方式,比如:写作,通讯,看电影,打游戏,上网,编程,计算,数据等,如果我们把这些功能都声明在电脑的抽类里面,那么,我们的上网本,PC机,服务器,笔记本的实现类都要实现所有的这些接口,这就显得太复杂了。所以,我们可以把其这些功能接口隔离开来,比如:工作学习接口,编程开发接口,上网娱乐接口,计算和数据服务接口,这样,我们的不同功能的电脑就可以有所选择地继承这些接口。

这个原则可以提升我们“搭积木式”的软件开发。对于设计来说,Java中的各种Event Listener和Adapter,对于软件开发来说,不同的用户权限有不同的功能,不同的版本有不同的功能,都是这个原则的应用。

Dependency Inversion Principle (DIP) – 依赖倒置原则

高层模块不应该依赖于低层模块的实现,而是依赖于高层抽象。

举个例子,墙面的开关不应该依赖于电灯的开关实现,而是应该依赖于一个抽象的开关的标准接口,这样,当我们扩展程序的时候,我们的开关同样可以控制其它不同的灯,甚至不同的电器。也就是说,电灯和其它电器继承并实现我们的标准开关接口,而我们的开关产商就可不需要关于其要控制什么样的设备,只需要关心那个标准的开关标准。这就是依赖倒置原则。

这就好像浏览器并不依赖于后面的web服务器,其只依赖于HTTP协议。这个原则实在是太重要了,社会的分工化,标准化都是这个设计原则的体现。

参考:http://en.wikipedia.org/wiki/Solid_(object-oriented_design)


Common Closure Principle(CCP)– 共同封闭原则

一个包中所有的类应该对同一种类型的变化关闭。一个变化影响一个包,便影响了包中所有的类。一个更简短的说法是:一起修改的类,应该组合在一起(同一个包里)。如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里(修改关闭),而不是遍布在很多包里。CCP原则就是把因为某个同样的原因而需要修改的所有类组合进一个包里。如果2个类从物理上或者从概念上联系得非常紧密,它们通常一起发生改变,那么它们应该属于同一个包。

CCP延伸了开闭原则(OCP)的“关闭”概念,当因为某个原因需要修改时,把需要修改的范围限制在一个最小范围内的包里。

参考:http://c2.com/cgi/wiki?CommonClosurePrinciple


Common Reuse Principle (CRP) – 共同重用原则

包的所有类被一起重用。如果你重用了其中的一个类,就重用全部。换个说法是,没有被一起重用的类不应该被组合在一起。CRP原则帮助我们决定哪些类应该被放到同一个包里。依赖一个包就是依赖这个包所包含的一切。当一个包发生了改变,并发布新的版本,使用这个包的所有用户都必须在新的包环境下验证他们的工作,即使被他们使用的部分没有发生任何改变。因为如果包中包含有未被使用的类,即使用户不关心该类是否改变,但用户还是不得不升级该包并对原来的功能加以重新测试。

CCP则让系统的维护者受益。CCP让包尽可能大(CCP原则加入功能相关的类),CRP则让包尽可能小(CRP原则剔除不使用的类)。它们的出发点不一样,但不相互冲突。

参考:http://c2.com/cgi/wiki?CommonReusePrinciple


Hollywood Principle – 好莱坞原则

好莱坞原则就是一句话——“don’t call us, we’ll call you.”。意思是,好莱坞的经纪人们不希望你去联系他们,而是他们会在需要的时候来联系你。也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:


不创建对象,而是描述创建对象的方式。
在代码中,对象与服务没有直接联系,而是容器负责将这些联系在一起。

控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

好莱坞原则就是IoC(Inversion of Control)或DI(Dependency Injection )的基础原则。这个原则很像依赖倒置原则,依赖接口,而不是实例,但是这个原则要解决的是怎么把这个实例传入调用类中?你可能把其声明成成员,你可以通过构造函数,你可以通过函数参数。但是 IoC可以让你通过配置文件,一个由Service Container 读取的配置文件来产生实际配置的类。但是程序也有可能变得不易读了,程序的性能也有可能还会下降。

参考:


http://en.wikipedia.org/wiki/Hollywood_Principle
http://en.wikipedia.org/wiki/Inversion_of_Control
High Cohesion & Low/Loose coupling & – 高内聚, 低耦合

这个原则是UNIX操作系统设计的经典原则,把模块间的耦合降到最低,而努力让一个模块做到精益求精。


内聚:一个模块内各个元素彼此结合的紧密程度
耦合:一个软件结构内不同模块之间互连程度的度量

内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。

参考:


http://en.wikipedia.org/wiki/Coupling_(computer_science)
http://en.wikipedia.org/wiki/Cohesion_(computer_science)
Convention over Configuration(CoC)– 惯例优于配置原则

简单点说,就是将一些公认的配置方式和信息作为内部缺省的规则来使用。例如,Hibernate的映射文件,如果约定字段名和类属性一致的话,基本上就可以不要这个配置文件了。你的应用只需要指定不convention的信息即可,从而减少了大量convention而又不得不花时间和精力啰里啰嗦的东东。配置文件很多时候相当的影响开发效率。

Rails 中很少有配置文件(但不是没有,数据库连接就是一个配置文件),Rails 的fans号称期开发效率是 java 开发的 10 倍,估计就是这个原因。Maven也使用了CoC原则,当你执行mvn -compile命令的时候,不需要指源文件放在什么地方,而编译以后的class文件放置在什么地方也没有指定,这就是CoC原则。

参考:http://en.wikipedia.org/wiki/Convention_over_Configuration


Separation of Concerns (SoC) – 关注点分离

SoC 是计算机科学中最重要的努力目标之一。这个原则,就是在软件开发中,通过各种手段,将问题的各个关注点分开。如果一个问题能分解为独立且较小的问题,就是相对较易解决的。问题太过于复杂,要解决问题需要关注的点太多,而程序员的能力是有限的,不能同时关注于问题的各个方面。正如程序员的记忆力相对于计算机知识来说那么有限一样,程序员解决问题的能力相对于要解决的问题的复杂性也是一样的非常有限。在我们分析问题的时候,如果我们把薙P园 of Demeter)r =独此的敲从邢抟谎d扑悴簧c式。 get="_blank" rel="nofollow" href="http://c =中,甚至魏我en.wikipedia.org/wiki/Convention_over_C我记礒NT上则恳INDE/c =中在《,ow" 际需论了1年程序在《 玻隙籇原则钟肟鱿啊V" >彩焙蛑贫啵惶字" 鏔旁谑者都遵守它,就说,没有副则有被服务

R的口,而程序的使程序郑在这自己和别人湮募以蹋没 EE0 倍,估" 鸵寞以蹋每个mvn 者le="TEXT有限" 信享和耍CC在度 硎鋈缇托衝ven工遵求或雹镙丝钉运责渊有限mvn 镙丝钉就行nv序员锩解决镙帽构造函℅oo机知反正镙帽和镙丝钉按标历性则定可能得稍蹋死嘞地把限。力铣些不关样狂差况习被服务emet: 于复r 读被样狂程序制什么em;"是一旁谑r 读运性和拭新测开。r 读义社何:内="T愦位蚨嘌窈涂鱿啊R訲EXT旁谑者锩解心性之屠:http://c2.com/cgi/wiksulong.meA> s/9A>
s/9A>

方疏计 与os供应商”达经寻契约”而得序的旧暇涂
如构┯ι倘魏沃炙车目剐裕ㄒ蝗蹈鲈/els他有权期望疏计已经付款(权利ENT:yle="疏计任何付款(一鹊个原/els有权得到抗性(权利ENT:yle="契约双的澄何禄有那了皆blan契约tyl行Ш犀蝗蹈呤欠稍谖驷到墓δ努力目标之一。这个原则,就是在软件开蛘叽痈。。你第限。益求; 肷于祝好像浏累意巍T妊樯于祝ㄊ杓苹Ф逦嗽谖┯ι态对ɡ鸈

http://en.wikipedia.org/wikiDesign_by_候蟬r瞔t=">


Separation of ConcernDesign_by_候蟬r瞔t>

礟 stylei匦階>
在很旱m;"种//Ω弥苯变。因,PC机A、B、C形经环路调用T:是一务器,逼鹬类抽程序饩褪黄龇变。因D并发

http:/ Principle (CRP)Acyclic>礟 stylei匦A>


礟 stylei匦A>

给鸵鸟黄龇概糜操还是想le="解>软肌薄2弧E夷癫鄃是“k一下,ref="http://c2.com/cgi/wiki?CommonClooT-Iτ么方,看上去都自佳声明成氮用好闰制自记一的代但营 IoCτ么方,又得好又得精序员形不hr;&精。验中一个(我以应该幸黄龇理" 美帏又的过sor://BR>如筫 Cont先粗浅与设表岬呢知道τ么方,T:yle="发效;" 弊怕Ω檬焙在实在一起。这样,我鄄熳约踔鞅鹑:虺绦蛑R媲蟮在一起≠回过头用端回谷莞希开么方,,通信le="l杏谛┏绦蛑K实在一起考攀懒⒇去 pri一下,yle="Goto第原则就3蚕翟呐δ勘曛弧U飧鲈颍褪窃谌砑彝ㄐ臫EXTA rean菩,于些方,而欢迎乓鸟种锁,ref="http://c2.com/cgi/wiki?CommonClo(萷;<完r://BR>如 bcm"0" div id="$ 评论这张ss="bct fcssss="bct fc蘢iv cla 篺ollow" ze:12px;textr fc06"> ptcs="sta7:03:39ss="bct fcss"订阅ss="bct fcht"blogsep"="http:/蘢iv cla="http:/"TEXT-INDENTptcs="sta;穝s="bct fcss63.oftepublishtohareBtr fc06"> toL格riclspan> 墓 iki/You_Ain%27t_px;color:#ff0000div id="$iv> 蘢iv cla="http:/ss="bct fc"TEXTfont-size:12px;textr fc06"> ptcs="sta7:03:39ss="bct fcss"订阅ss="bct fcht"blogsep"="http:/蘢iv cla ss="bct fc"TEXT11 nbw-bloglefttbar">&nb ht"5 fc11 nbw-="hss=barofollow" ="_blan3fter 3fter.com/align:1-03;;穝s="bct fcssht"订阅阅读("订阅< &nc">span> ss="bct fcv>ht"订阅评论("订阅< htss="bct fcv>5 fcfont-si="_blan4w.lo 4w.lo;穝s="bct fcssht"5 fc11 nbw-分享 rdif;穝s="bct fcsshtht"订阅 p1-03 ne""ne"-l。Cr>&nc">span> ss="bct fcv>htht"5 fc11 nbw-r2" title="分享到LOFTER" class="shareitm lofter f-bkicons">&nbsiclspan> &niclspan> &nbsiclspan> &iclspan>

layer fc06">

用微信  “1fc0ss="bc"5 fc11 nbw-p>将文章分享到朋友圈。

 
ayer fc06">

用易信  “12">ss="bc"5 fc11 nbw-p>将文章分享到朋友圈。

 
="ht"即cfont-size:12px;textr ss="bc="http:/="ht"in: n以替籹=px;tyl" nem;s="hirdId" valu;s=fks_nbsp;7nbsp|&nb6小&nb> | 75hre模式"40l="n20/a> 7&nbs" /穝s="bct fcssss="ht"in: n以替籹=px;tyl" nem;s=fromnovalu;s=BLOGPOST" /穝s="bct fcssss="ht"in: n以替籹=px;tyl" nem;s=lspannovalu;s=c07 fw0 fs0">转帖区 |  标签: |字号大中小 订;&t;/A> |e="TEnbsp3;7108nbsp3&242t;e="TEoo"_blan7108k" rel="7108k掷鄉low7108k"href="7108k"h3low"7108k謑shell7108k"n/art&242t; iki/You&242t;de"ank&242t; comp&242t;ented_de&242t; 84065&242t;OLOR: r="Unix传奇(下&242t; >1687;)" target;&t;/A>和;&t;Prlspan>&242t;ofoll7108k" href7108k謍ttp://7108koolshel7108k"cn/art&242t; iki/You&242t;de"ank&242t; comp&242t;ented_de&242t; 84065&242t;OLOR: r="Unix传奇家从中能&242t; >中学了解到一些;&t;/A>原理方面的知识,正如我在《DRY 是一个最简单的法则,;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;应用的(因为要做到这样,我们需要在泛型设计上做相当的努力,这并不是一件容易的事)。它意味着,当我们在两个或多个地方的时候发现一些相似的代码的时候,我们需要把他们的共性抽象出来形一个唯一的新方法,并且改变现有的地方的代码让他们以一些合适的参数调用这个新的方法。

参考:KISS原则在设计上可能最被;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;粕希丛拥亩髟嚼丛奖恢谌怂鵅S了,而简单的东西越来越被人所认可,比如

参考:&242t; font-s&242t; rel="nofollow" href="http://en.wikipedia.org&242t; comp&242t;ented_de&242t; 84065&242t;OLOR: rn & Low/Loose coupementation
&242t; >w" hrefn & Low/Loose coupementation
&&t;/A>;&t;/P>;&t;BR>TEXT-INDENT: 2em;" >这是设计模式中最根本的哲;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;该幸益求憧梢口是抽象是稳定的,实现则是多种多样的。以后面我们会面向对象的SOLID原则中会提到我们的依赖倒置原则,就是这个原则的的另一种样子。还有一条原则叫Composition over inheritance(喜欢组合而不是继承),这两条是那23个经典设计模式中的设计原则。


Command-Query Separation (CQS)  – 命令-查询;&t;/P>;&t;BR>rinc查询:当一个方法返回一个值7108nbsp3;7108nbsp3蚴桥置则,它就具有查;&t;BR>统的

通常,一个方法可能是纯的C;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;两者的混合体。在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用,而会改变对象的状态的方法不可能有返回值。也就是说:如果我们要问一个问题,那么就不应该影响到它的答案。实际应用,要视具鷈t=况而定,语义的清晰性和使用的简单性之间需要权衡。将Command和Query功能合并入一个方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果。

在系统设计中,很多系统也;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;能的系统分离,这样有则于系统性能,也有利于系统的安全性。

参考:这个原则简而言之为——只;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;开。方,需要的功能,在以后您需要更多功能时,可以再进行添加。


如无必要,勿增复杂性。
软件开发先是一场沟通博弈。<;&t;/P>;&t;BR>style="TEXT-INDENT: 2em;&t;BR>s: 2mvn 居幸黄赜
。我们的程序员或是架构师在设&242t; >统的时候,会考虑很多扩展性;&t;/A>己当外人的店员与设计方面使用了大量折衷,最后导致项目失败。这是个令人感到讽刺的教训,因为本来希望尽可能延长项目的生命周期,结果反而缩短了生命周期。

参考:


如果你想让你的狗跑的话,你会对狗狗说还是对四条狗腿说?;&t;/P>;&t;BR>还是サ昀锫蚨鳎慊岚亚桓暝保故腔岚亚桓暝;&t;BR>还是サ?

和狗的四肢说话?让店员自;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;在我们的代码里这几乎是见怪不怪的事情了。

对于LoD,正式的表述如下:;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;增的对于对象 ‘O’ 中一个;&t;/P>;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;增的 styR>对象O;
与O直接相关的Component Object;
由方法;&t;/P>;&t;BR> sty;&t;BR>螅
作为方法M的参数的对象。<;&t;BR>

final String outputDir = ;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;AbsolutePath();

这么长的一串对其它对象的;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;典的陈过用,增加了耦合,使得代码结构复杂、僵化,难以扩展和维护。

在《重构》一书中的代码的;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;登榻幔蜗蟮拿枋隽艘恢治シ戳薒oC的情况。Feature Envy就是说一个对象对其它对象的内容更有兴趣,也就是说老是羡慕别的对象的成员、结构或者功能,大老远的调用人家的东西。这样的结构显然是不合理的。我们的程序应该写得比较“害羞”。不能像前面例子中的那个不把自己当外人限。了开样,拿过客人的钱包自己把钱拿出来。“害羞”的程序只和自己最近的朋友交谈。这种情况下应该调整程序的结构,让那个对象自己拥有它羡慕的feature,或者使用合理的设计模式(例如Facade和Mediator)。

参考:

Single Responsibility Pri;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;

关于7108nbsp3蚴堑ヒ滑其核心;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;事做好,其只有一个引起它变化的原因。单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为一个模块实现过多的功能点,以保证实体只有一个引起它变化的原因。


Unix/Linux是这一原则的完美体现者。各个程序都独立负责一;&t;/P>;&t;BR>事。
Windows是这一原则的反面示例。几乎所有的程序都交织耦合在一;&t;BR>BR>

Open/Closed Principle (OC;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;XT-INDENT: 2em;" >关于开发7108nbsp3蚴仟修改的;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;事做mvn Ω枚酝展是开放的,而对修改是封闭的。


对扩展开放,意味着有新的需求或变化时,可以对现有代码进;&t;/P>;&t;BR>以适应新的情况。
对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而;&t;BR>以梅浅行任何修改。

对于面向对象来说,需要你;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;增的“策略模这个原各个个实现。对于非面向对象编程,一些API需要你传入一个你可以扩展的函数,比如我们的C 语言的qsort()允许你提供一个“比较器”,STL中的容器类的内存分配,ACE中的多线程的各种锁。对于软件方面,浏览器的各种插件属于这个原则的实践。

Liskov substitution princ;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;

软件7108nbsp3蚴 for their b;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;Subtypes must be substitutable for their base types”。也就是,子类必须能够替换成它们的基类。即:子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。另外,不应该在代码中出现if/else之类对子类类型进行判断的条件。里氏替换原则LSP是使代码符合开闭原则的一个重要保证。正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下就可以扩展。

这么说来,似乎有点教条化;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;典的案例——“正方形不是长方形”和“鸵鸟不是鸟”。通过这两个案例,你会明白《墨子 小取》中说的 ——“娣,美人也,爱娣,非爱美人也….盗,人也;恶盗,非恶人也。”——妹妹虽然是美人,但喜欢妹妹并不代表喜欢美人。盗贼是人,但讨厌盗贼也并不代表就讨厌人类。这个原则让你考虑的不是语义上对象的间的关系,而是实际需求的环境。

在很多情况下,在设计初期;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;颐且桓雠卸虾蜕杓评嘀涔叵档幕迹盒璨恍枰坛校约霸跹杓萍坛泄叵怠

Interface Segregation Pri;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;

接口7108nbsp3蚴墙涌谇把功能;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;接口前压δ苁单一的总接口要好。

举个例子,我们对电脑有不;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;一个抽象的鷈t=,编程,计算,数据等,如果我们把这些功能都声明在电脑的抽类里面,那么,我们的上网本,PC机,服务器,笔记本的实现类都要实现所有的这些接口,这就显得太复杂了。所以,我们可以把其这些功能接口隔离开来,比如:工作学习接口,编程开发接口,上网娱乐接口,计算和数据服务接我们这样,我类中?同功能的电脑就可以有所选择地继承这些接口。

这个原则可以提升我们“搭;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;开。方,产生 Listener和Adapter,对于软件开发来说,不同的用户权限有不同的功能,不同的版本有不同的功能,都是这个原则的应用。

Dependency Inversion Prin;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;>礟 style="TEXT-INDENT: 2em;" >高层7108nbsp3蚴侨饔胣 over i;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;

举个例子,墙面的开关不应;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;一个抽象的开关的标准接口,这样,当我们扩展程序的时候,我们的开关同样可以控制其它不同的灯,甚至不同的电器。也就是说,电灯和其它电器继承并实现我们的标准开关接口,而我们的开关产商就可不需要关于其要控制什么样的设备,只需要关心那个标准的开关标准。这就是依赖倒置原则。

这就好像浏览器并不依赖于;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;飧鲈蚴翟谑翘匾耍缁岬姆止せ曜蓟际钦飧錾杓圃虻奶逑帧

参考:一个包中所有的类应该对同;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;亿便影响了包中所有的类。一个更简短的说法是:一起修改的类,应该组合在一起(同一个包里)。如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里(修改关闭),而不是遍布在很多包里。CCP原则就是把因为某个同样的原因而需要修改的所有类组合进一个包里。如果2个类从物理上或者从概念上联系得非常紧密,它们通常一起发生改变,那么它们应该属于同一个包。

CCP延伸了开闭原则(OCP);&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;时,把需要修改的范围限制在一个最小范围内的包里。

参考:包的7108nbsp3蚴腔起重用。如;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;个说法是,没有被一起重用的类不应该被组合在一起。CRP原则帮助我们决定哪些类应该被放到同一个包里。依赖一个包就是依赖这个包所包含的一切。当一个包发生了改变,并发布新的版本,使用这个包的所有用户都必须在新的包环境下验证他们的工作,即使被他们使用的部分没有发生任何改变。因为如果包中包含有未被使用的类,即使用户不关心该类是否改变,但用户还是不得不升级该包并对原来的功能加以重新测试。

CCP则让系统的维护者受益。;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;睦啵珻RP则让包尽可能小(CRP原则剔除不使用的类)。它们的出发点不一样,但不相互冲突。

参考:

简单的来讲,就是由容器控;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;序代码直接操控。这也就是所谓“控制反转”的概念所在:


不创建对象,而是描述创建对象的方式。
在代码中,对;&t;/P>;&t;BR>挥兄苯恿担侨萜鞲涸鸾庑┝翟;&t;BR>。

控制权由应用代码中转到了;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;P>

好莱坞原则就是IoC(Invers;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;ction )的0 倍原则。这个原则很像依赖倒置原则,依赖接口,而不是实例,但是这个原则要解决的是怎么把这个实例传入调用类中?你可能把其声明成成员,你可以通过构造函数,你可以通过函数参数。但是 IoC可以让你通过配置文件,一个由Service Container 读取的配置文件来产生实际配置的类。但是黄龇也有可能变得不易读了,程序的性能也有可能还会下降。

参考:




这个原7108X蚴荱NIX操作系统设;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;开。方,一个模块做到精益求精。


内聚:一个模块内各个元素彼此结合的紧密程度
耦合:;&t;/P>;&t;BR>峁鼓诓煌?橹浠チ潭鹊亩攘

内聚意味着重用和独立,耦;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;

参考:


&242t;OLOR: rgb(41,112,166); TEXT-Ddia.org/wiki/Cohesion_(comp&242t; font-s&242t; rel="nofollow" href="http://en.wikipedia.org&242t; comp&242t;ented_de&242t; 84065&242t;OLOR: rn & Low/Loose coupdia.org/w_(computer_science)简单点说,就是将一些公认;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;用。例如,Hibernate的映射文件,如果约定字段名和类属性一致的话,基本上就可以不要这个配置文件了。你的应用只需要指定不convention的信息即可,从而减少了大量convention而又不得不花时间和精力啰里啰嗦的东东。配置文件很多时候相当的影响开发效率。

Rails 中很少有配置文件(;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;),Rails 的fans号称期开发效率是 java 开发的 10 倍,估计就是这个原因。Maven也使用了CoC原则,当你执行mvn -compile命令的时候,不需要指源文件放在什么地方,而编译以后的class文件放置在什么地方也没有指定,这就是CoC原则。

参考:SoC 是7108nbsp3蚴腔中最重要;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;发中,通过各种手段,将问题的各个关注点分开。如果一个问题能分解为独立且较小的问题,就是相对较易解决的。问题太过于复杂,要解决问题需要关注的点太多,而程序员的能力是有限的,不能同时关注于问题的各个方面。正如程序员的记忆力相对于计算机知识来说那么有限一样,程序员面决问题的能力相对于要解决的问题的复杂性也是一样的非常有限。在我们分析问题的时候,如果我们把薙P园 of Demeter)r =独此的敲从邢抟谎d扑悴簧c式。 get="_blank" rel="nofollow" href="http://c =中,甚至魏我en;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;我记礒NT上则恳INDE/c =中在《,ow" 际需论了1年程序在《 玻隙籇原则钟肟鱿啊V" >彩焙蛑贫啵惶字" 鏔旁谑者都遵守它,就说,没有副则有被服务

R的口,而程序的使程序郑在这自己和别人湮募以蹋没 EE0 倍,估" 鸵寞以蹋每个mvn 者le="TEXT有限" 信享和耍CC在度 硎鋈缇托衝ven工遵求或雹镙丝钉运责渊有限mvn 镙丝钉就行nv序员锩解决镙帽构造函℅oo机知反正镙帽和镙丝钉按标历性则定可能得稍蹋死嘞地把限。力铣些不关样狂差况习被服务emet: 于复r 读被样狂程序制什么em;"是一旁谑r 读运性和拭新测开。r 读义社何:内="T愦位蚨嘌窈涂鱿啊R訲EXT旁谑者锩解心性之屠: s/9A&242t; >OLOR: rsulong.meA> s/9A&&t;/A>;&t;/P>;&t;BR>Design by褚览档left(Db是7108nbsp3蚴瞧踉际揭媲;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;Db实目呕脑訲: 2到精组合潭蹲胖ofol合作码结ˉ一鹊 与oso逦艘补吠人捣挚滞人荡

方疏计 与os供应商”达经寻契约”而得序的旧暇涂;&t;/P>;&t;BR>供应商任何种锁某的抗性(一鹊个原/els他有权期望疏计已经付款(权利ENT:y;&t;BR>疏计任何付款(一鹊个原/els有权得到抗性(权利ENT:y;&t;BR>契约双的澄何禄有那了皆blan契约tyl行Ш犀蝗蹈呤欠稍谖驷到墓;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;蛘叽痈。。你第限。益求; 肷于祝好像浏累意巍T妊樯于祝ㄊ杓苹Ф逦嗽谖┯ι态对ɡ鸈

礟 stylei匦階>
在很旱m;"种//Ω弥苯变。因,PC机A、B、C形经环路调用T:是一务器,逼鹬类抽程序饩褪黄龇变。因D并发

礟 stylei匦A>
礟 stylei匦A>
给鸵鸟黄龇概糜操还是想le="解>软肌薄2弧E夷癫鄃是“k一下,;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;oT-Iτ么方,看上去都自佳声明成氮用好闰制自记一的代但营 IoCτ么方,又得好又得精序员形不hr;&精。验中一个(我以应该幸黄龇理" 美帏又的过sor:;&t;/P>;&t;BR>e Cont先粗浅与设表岬呢知道τ么方,T:y;&t;BR>发效;" 弊怕Ω檬焙在实在;&t;BR>在这样,我鄄熳约踔鞅鹑:虺绦蛑R媲蟮在;&t;BR>再回过头用端回谷莞希开么方,,通信le="l杏谛┏绦蛑K实在;&t;BR>考攀懒⒇去 pri一下,y;&t;BR>Goto第7108nbsp33蚕翟;&t;BR> ;&t;分类: <&242t; title="转&&242t; ;gt;我通信TEXTA rean菩,于些方,而欢迎乓鸟种锁,;&t;/P> ;&t;分类: <&242t; title="转&&242t; ;gt;(萷;<完r:;&t;/P>;&t;BR>;&t;W件>" /穝s="bct fcssss="ht"in: n以替籹=px;tyl" nem;s=sourcenovalu;s=还东国" /穝s="bct fcssss="ht"in: n以替籹=px;tyl" nem;s=sourceUrlnovalu;s=OLOR: rfpcfjf.blog/163Commoblog/static/55rel793掷啵lshe91272" /穝s="bct fcssss="ht"in: n以替籹=px;tyl" nem;s=tagnovalu;s=" /穝s="bct fcssss=" htht"div cla="http:/="ht"5 fc11 nbw-穜ight rightoper鈈ar"rightoper鈈ar-某">ss="bc="http:/=""订阅喜欢"blogsep"assssssssssss"订阅
推荐"blogsep"assssssssss"订阅ssassssssssssss"订阅&nbass订阅< icn0 icn0-7221-0w-tgl1 nes-icn0fix div id="$ <"订阅 icn0 icn0-621 n0w-tgl01-es-icn0fix div id="$ <"订阅&nc">设 <| 3ssassssssssss"blogsep"ssssssssssssssss"订阅转载"blogsep"ssssssssssss"div cla="http:/=""div cla="http:/"div cla="http"div cla="http"5 fc11 nbw-snl">ss="bc="ht"TEXTfont-size:12px;textr fc06"> ppx;c bdwb bds2 bdc0 rdcleno "div cla="httpht"5 fc ssssssssssss

&nc fs0">历史上的今天ssassssss

&nc fs0">最近读者ssassssss

&nc fs0">热度ssassssssht"a"spasstead k"ll.cn/"#="iki/You_Ain%27t_px;cfocustetrue">ssassssssss"5 fc "div claassssssss"ifrem; mbusinwidth="0no"busin="_bla="0no <1mx;_ifrem;" font-s"ze:12px;text;" width="590no="_bla="(&#" frem;border="0noscrol g="no" allowtran订詒encytetrue">ssassss"div claassssssassss"5 fc <1ofter.com kad" font-s"ze:12px;text;padd g:0 6px 0 5px;;穝sassssss"5 fcfont-s"="_blan40px; e-="_blan40px;"busin:15px 0 15px 0;border:1px solid #d5d5d5;background:#ffffe1;.com-align:1-03;;穝sassssssss"订阅&nc fs0">评论ssassssss"5 fc11 nbw-ztagn>"div claassss"div claassss"5 fc11 nbw-ppx;cno &n3n>"div classss"div classs"div class"div cla"div cla"5 fc11 nbw-ppx;c n0-init;穝sss".comkiea nem;s=js;穝sssss"his.p={ m:2,ss="bct fcv>="htb:2,ss="bct fcv>="htharePermalink:'',ss="bct fcv>="htid:'fks_nbsp;7nbsp|&nb6小&nb> | 75hre模式"40l="n20/a> 7&nbs',ss="bct fcv>="htblogTitle:'c07 fw0 fs0">="htblogAbstract:' 3"BR\>ss"分类: <\" title="转&\" \>掷啵21306;" rel="nofnbsp3;nbsp3匾猣.b 转帖区 |  标签: |字号大中小 ow">订s| 3 3l.cns5.htmlOLOR: r="Unix传奇rel="nofosss"分类: <\" title="转&\" \>30340;&#代码的十#\"&o2"_blank" rel="o2"鄉low#99721;&og#65311#ols0040#3n/art\" iki/You\"de"ank\" comp\"nofol ow\" 84065\"OLOR: r="Unix传奇(下\" \>1687;)" target和',ss="bct fcv>="htblogTag:'',ss="bct fcv>="htblogUrl:'blog/static/55rel793掷啵lshe91272',ss="bct fcv>="htisPublished:1,ss="bct fcv>="htisss=:false,ss="bct fcv>="httype:0,ss="bct fcv>="htmodifyTime:0,ss="bct fcv>="htpublishTime:13掷997752972,ss="bct fcv>="htpermalink:'blog/static/55rel793掷啵lshe91272',ss="bct fcv>="htcincyltdiac0:0,ss="bct fcv>="htmainrincylediac0:0,ss="bct fcv>="htrecincylddiac0:0,ss="bct fcv>="htbsrk:-(&#,ss="bct fcv>="htpublisherId:0,ss="bct fcv>="htrecinBlogHome:false,ss="bct fcv>="htcurrentRecinBlog:false,ss="bct fcv>="htattachcylesFileIds:[],ss="bct fcv>="htvote:{},ss="bct fcv>="htgroupInfo:{},ss="bct fcv>="htfriendstatus:'none',ss="bct fcv>="htfol owstatus:'unFol ow',ss="bct fcv>="htpubSucc:'',ss="bct fcv>="htvisitorTEXvince:'',ss="bct fcv>="htvisitorCity:'',ss="bct fcv>="htvisitorNewUser:false,ss="bct fcv>="htpostAddInfo:{},ss="bct fcv>="htmset:'000',ss="bct fcv>="htm候:'',ss="bct fcv>="htsrk:-(&#,ss="bct fcv>="htremindgoodnightblog:false,ss="bct fcv>="htisBlackVisitor:false,ss="bct fcv>="htisShowYodaoAd:false,ss="bct fcv>="hthost ="hthm候:'1',ss="bct fcv>="htselfRecinBlogdiac0:'0',ss="bct fcv>="hthareer_s gle:'"ifrem; width="140no="_bla="560nofont-s"overflow:px;tyl;" src 'ss="bct fcv>="}ss=" n0w-fce n0w-f40n穝sssss="&n3 noulnoiki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.visitorNem;}/n穝sssss="{if x.visitorNem;==visitor.userNem;}ss="bct ${x.visitorNicknem;|escape}ssssss="<5 fc11 nbw-cwd vnem;s"hi;cn穝sssss=" {if x.moveFrom=='wap'}ss=" ="ss=""订阅"来自网易手机博客n"spasstean> wapI候; 3"d订阅sssss="sss{elseif x.moveFrom=='iphone'}ss=" ="ss=""订阅"来自iPhone疏计端n"spasstean> iphoneI候; 3"d订阅sssss="sss{elseif x.moveFrom=='查裷oid'}ss=" ="ss=""订阅"来自A檠roid疏计端n"spasstean> 查裷oidI候; 3"d订阅sssss="sss{elseif x.moveFrom=='mobile'}ss=" ="ss=""订阅"来自网易短信写博n"spasstean> wapI候; 3"d订阅sssss="sss{dif}ss=" ="="&n3 m2a" oiki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.visitorNem;}/n穝sssss="sss=${fn(x.visitorNicknem;,8)|escape}ss="bct ="ssssss="
ssssss&n3 m2a" 84065"OLOR: rblog.163Commo${a.userNem;}/n${fn(a.nicknem;,8)|escape}ssssss<5 fc11 nbw-i蟬ror>&n5">${a.self "div claass<5 fc11 nbw-mbgas="sta omkgn>ss="bct ="<5 fc11 nbw-mbgai; 3"d5 f>ss="bct ="&n3 omkg m2a" 84065"#="iki/You_Ain%27tssssss="ss="bc{dif}ss="ss="".comkiea nem;s=jseno ss="bc{list a as x}ss=" {if !!x}ss=" "li"spasste"hi;cn&n3 m2a" 84065"${furl()}${x.permalink}/?m鈙tBlog">${fn(x.lspan,26)|escape}"dli>ss="bc{dif}ss=" {/list}ss="ss="".comkiea nem;s=jseno ss="bc&n6">推荐过这篇日志的人:

ss="bc<5 f>ss="bcs={list a as x}ss=" {if !!x}ss=" ss<5 fc11 nbw-an> n0w-fce n0w-f40n穝sssss="ss&n3 noulnoiki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.recincylderNem;}/n穝sssss="ss${x.recincylderNicknem;|escape}ssssss="ss<5 fc11 nbw-cwd "hi;cn穝sssss=" ss&n3 m2a" iki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.recincylderNem;}/n穝sssss="sss=s=${fn(x.recincylderNicknem;,6)|escape}ss="bct ="ssssssss="ssss="bcssss="bcs={dif}ss=" s={dlist}ss="ssss="bc{if !!b&&b.length>0}ss="

&n6">他们还推荐了:

ss="bc
    ss="bc{list b as y}ss=" ="{if !!y}ss=" ="ss"订阅&n3 m2a" iki/You"de"ank" 8ref ${y.recincyldBlogTitle|escape}"dli>ss="bcs={dif}ss=" {/list}ss="ss
ss="bc{dif}ss="ss="".comkiea nem;s=jseno ss="bc"订阅&n7">转载记录:ss="bc{list d as x}ss=" ss"订阅>&n7 m2a" 84065"${x.referBlogUrl}">${x.referBlogTitle|escape}"d订阅ss="bcs=ss<5 f spasstetbr p1-03n>"订阅>&n7 m2a" 84065"${x.referHomePage}">${x.referUserNem;|escape}"d订阅ss="bcs=ss="bc{dlist}ss="ssss="ss="".comkiea nem;s=jseno ss="bc{list a as x}ss=" {if !!x}ss=" "li"spasste"hi;cn&n3 m2a" 84065"http://blog.163Commo${x.userNem;}/${x.permalink}/?recincyldBlognoiitle="${x.iitle|;cfault:""|escape}">${x.iitle|;cfault:""|escape}"dli>ss="bc{dif}ss="s={dlist}ss="ss="".comkiea nem;s=jseno ss="bc{list a as x}ss=" {if !!x}ss=" "li"spasste"hi;cn&n3 m2a" 84065"http://blog.163Commo${x.userNem;}/${x.permalink}/?personalRecinBlog"oiitle="${x.iitle|;cfault:""|escape}">${x.iitle|;cfault:""|escape}"dli>ss="bc{dif}ss="s={dlist}ss="ss="".comkiea nem;s=jseno ss="bc{list a as x}ss=" {if !!x}ss=" "li"spasste"hi;cn&n3 m2a" iki/You"de"ank" 8ref <${x.blogUrl|;cfault:""|escape}?recincyldReadernoiitle="${x.blogTile|;cfault:""|escape}">${x.blogTile|;cfault:""|escape}"dli>ss="bc{dif}ss="s={dlist}ss="ss="".comkiea nem;s=jseno ss="bcs={list a as x}ss=" {if x_index>4}{bieak}{dif}ss="bct {if !!x}ss=" s=s=&nbasss="bct s=s=${fn1(x.iitle,60)|escape}"订阅 spasste>&n7">${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}ss="bcs={dif}ss=" s={dlist}ss="ssss="ss="".comkiea nem;s=jseno &n3 m2a" 84065"${furl()}${x.permalink}/">${fn(x.lspan,26)|escape}"dli>ss="bc{dif}ss=" {/list}ss="ss="".comkiea nem;s=jseno icn0 icn0-620n 3"/订阅穝s="bc=s=<5 f spasstep1-03 "hi;cn"d5 f>ss="bcs{dif}ss="s= {if !!(blogDetail.ncomBlogPermalink)}ss=" ="s"订阅 icn0 icn0-619n 3"/订阅穝s="bc=s=<5 f spasstepright "hi;cn"d5 f>ss="bcs{dif}ss="ss="".comkiea nem;s=jseno ss="bc{list a as x}ss=" {if !!x}ss=" "5 f spasstehoiItem an> n0w-fce n0w-f40n穝sssss="&n3 noulnoiki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.publisherUsernem;}/n穝sssss="{if x.publisherUsernem;==visitor.userNem;}ss="bct ${x.publisherNicknem;|escape}ssssss="<5 fc11 nbw-cwd vnem;s"hi;cn穝sssss=" &n3 m2a" liki/You"de"ank" 8x;cfocustetrue"ll.cn/"http://blog.163Commo${x.publisherUsernem;}/n穝sssss="s=s=${fn(x.publisherNicknem;,8)|escape}ss="bct ="ssssss="
sss=s=ss="bc{dif}ss="s={dlist}ss="ss="".comkiea nem;s=jseno ss="bcs=s=====<5 f spasstettlbar">&n6 bdwb bdc0 bds0n吠仔挛ss="bcs=s=====<5 f spasste某蘳clen>sss=s=s=====s=====ss assssssss"img frc <${imgsize(head es.imgsrc,240,150,true)}">ss assssssss"订阅 spassteicovern>"d订阅穝s assssssss"订阅 spassteinfon>"订阅ss s=====s=
    ss s=====s=s={if ;cf ed('某蘳list')&&某蘳list.length>0}ss=" s=====s=s=====s={list 某蘳list as x}ss=" sss=====s=s====={if x_index>7}{bieak}{dif}ss s=====s=s===&n5">"订阅 doen>·"dli>ss s=====s=s==={dlist}ss="s=====s=s=====s={dif}ss s=====s=
ss s=====s=<5 f spasstedownload163某蘳">ss s=====s=s===ss s=====s=ss="bcs=s=====ss="ss="".comkiea nem;s=txeno "div clas===

&n7 fs0 ltt p8x;c7:03:n>被推荐日志"dul>ss="bc

&n7 fs0 ltt p8x;c7:03:n>最新日志"dul>ss="bc

&n7 fs0 ltt p8x;c7:03:n>该作者的其他文章"dul>ss="bc

&n7 fs0 ltt p8x;c7:03:n>博主推荐"dul>ss="bc

&n7 fs0 ltt p8x;c7:03:n>随机阅读"dul>ss="bc

&n7 fs0 ltt p8x;c7:03:n>首页推荐"dul>ss="bc<5 f spasstemoren>"a"iki/You"de"ank" spasste>&n3 m2a" 84065"OLOR: rblog<163Comm">更多>>ss="==
ss="==<5 f "d5 f穝ss=s=<5 f "d5 f穝ss=ss="".comkiea nem;s=txeno "div clas===<5 f spasstebdwt bds2 bdc0 ppx;cno sss=s=s=<5 f spasstecasen>"d5 f穝ss=s===<5 f spassteclearfix d"d5 f穝ss=s="d5 f穝ss=ss="".comkiea nem;s=jst" ss="bct s"订阅 icn0 icn0-57"> 3"/订阅穝ss===="d5 f穝s =<5 f spassteztag ppx;cn>"d5 f穝ss=ss="".comkiea nem;s=jst" ss="bc{list a as x}ss=" {if !!x}ss=" ==
  • ss="bc==&nbas${x.nickNem;|escape} 3 3投票给ss="bct s {var">irst_op="T = true;}ss=" ="s={list x.voteDetailList as voteToOp="T}ss=" ="s=s==={if voteToOp="T==1}ss="bct s s====={if >irst_op="T==false},{dif} 3 3“${b[voteToOp="T_index]}” 3 3ss="bct s s==={dif}ss="s=s==={dlist}ss="sss==={if (x.role!="-1;) },“我是${c[x.role]}” 3 3{dif}ss="s=s=== 3 3 3 3"订阅&n7"> 3 3 3 3${fn1(x.voteTime)}ssvar"wumiiPermaLink = ss