- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
程序设计开闭原则
出处:/en-us/magazine/cc546578.aspx
引言
本文是新开设的MSDN软件设计基础专栏的第一篇文章。我的目的是以不局限于某种特定工具或者某个(软件工程)周期方法(lifecycle methodology)的方式来讨论设计的模式和原则。换言之,我计划讨论一些可以引导你使用任何技术,或者在任何项目中更好地进行设计的基础知识。
我喜欢以讨论开闭原则和其他由 Robert C.Martin 在其著作《敏捷软件开发,原则,模式和实践》中所倡导的相关主题作为开始。不要因为在标题中出现“敏捷”一词就把书合上了,因为这本书实际上完全是关于如何竭力进行优良软件设计的。
问下你自己:有多少次你是从零开始去写一个全新的应用程序?又有多少次你是通过将新功能添加到现有代码库(codebase)中来作为开始?恐怕大多数的情况下,你是花费了更多的时间将新功能添加到现有代码库中吧。
然后再问自己另一个问题:写全新的代码容易还是对现有代码进行修改容易?通常对我来说写全新的方法和类要比深入旧代码中,找出我想要修改的部分容易得多。修改旧有代码增添了破坏已有功能的风险。对于新代码来说,你通常只需要测试下新实现的功能就可以了。而当你修改旧有代码时,你不得不既要测试你更改的部分,还要进行一系列的兼容测试,以保证你没有破坏任何的旧有代码。
所以,你通常基于现有的代码库进行工作,可是写全新的代码又比修改旧的代码容易得多。你难道不想像写全新代码一样多产、轻松地去对现有的代码库进行扩展么?这就是开闭原则一展身手的地方了。我来解释一下开闭原则,它的意思是:软件实体应该对于扩展是开放的,而对于修改是关闭的。
从字面上看这好像是矛盾的,实际并非如此。它的全部含义就是你应该这样去构建一个应用程序:可以在对现有代码做最小修改的同时添加新的功能。我曾经认为开闭原则仅仅是意味着使用插件(plugins),但并不是这么简单。
你应该避免一个小小的改动就波及了你应用程序中的多个类。这样会使程序更加脆弱,更倾向于产生向下兼容的问题,并使扩展付出更高的代价。为了隔离变化,你会想要以一种一旦写好了就再也不需要修改的方式去写类和方法。
然而你如何构建代码以实现隔离变化呢?我想说的第一步就是遵循单一责任原则。
单一责任原则
在遵循开闭原则的过程中,我期望能够写出一个类或者方法,在以后我回过头读它的时候,会很舒服地看到它能完成它的工作并且我也不需要再修改它。你永远也达不到真正的开闭天堂,但是通过严格地遵循与之相关的单一责任原则:一个类应该有并且只有一个更改的理由,你可以非常靠近地接近它。
写那些永远也不需要进行修改的类的最简单方法就是写一些只能做一件事情的类。通过这种方式,一个类只有在它所确切负责的那件事更改时它才需要更改。代码1演示了没有遵循单一责任原则的一个例子。我真的怀疑你正在像这样设计一个系统,但是最好记得为什么我们不应该这样去构建代码。
代码1. 这个类负责了太多的事
public class OrderProcessingModule {? public void Process(OrderStatusMessage orderStatusMessage) {??? // 从配置文件中读取连接字符串??? string connectionString = ????? ConfigurationManager.ConnectionStrings[Main].ConnectionString;??? Order order = null;??? using (SqlConnection connection = ????? new SqlConnection(connectionString)) {????? // 从数据库中获取一些数据????? order = fetchData(orderStatusMessage, connection);??? }??? // 向来自于OrderStatusMessage的订单提交变更??? updateTheOrder(order);??? // 国际订单有一些特定的规则??? if (order.IsInternational) {????? processInternationalOrder(order);??? }??? // 对于大批量订单我们需要特别处理??? else if (order.LineItems.Count 10) {????? processLargeDomesticOrder(order);??? }??? // 小的国内订单也需要区别处理??? else {????? processRegularDomesticOrder
文档评论(0)