`
hdy007
  • 浏览: 30986 次
最近访客 更多访客>>
文章分类
社区版块
存档分类

代码复用的规则(上)

阅读更多

    代码复用是绝大多数程序员所期望的,也是OO的目标之一。总结我多年的编码经验,为了使代码能够最大程度上复用,应该特别注意以下几个方面。

  对接口编程

  "对接口编程"是面向对象设计(OOD)的第一个基本原则。它的含义是:使用接口和同类型的组件通讯,即,对于所有完成相同功能的组件,应该抽象出一个接口,它们都实现该接口。具体到JAVA中,可以是接口(interface),或者是抽象类(abstract class),所有完成相同功能的组件都实现该接口,或者从该抽象类继承。我们的客户代码只应该和该接口通讯,这样,当我们需要用其它组件完成任务时,只需要替换该接口的实现,而我们代码的其它部分不需要改变!
  当现有的组件不能满足要求时,我们可以创建新的组件,实现该接口,或者,直接对现有的组件进行扩展,由子类去完成扩展的功能。

  优先使用对象组合,而不是类继承

  "优先使用对象组合,而不是类继承"是面向对象设计的第二个原则。并不是说继承不重要,而是因为每个学习OOP的人都知道OO的基本特性之一就是继承,以至于继承已经被滥用了,而对象组合技术往往被忽视了。下面分析继承和组合的优缺点:

  类继承允许你根据其他类的实现来定义一个类的实现。这种通过生成子类的复用通常被称为白箱复用(white-box reuse)。术语"白箱"是相对可视性而言:在继承方式中,父类的内部细节对子类可见。

  对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组合对象来获得。对象组合要求对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为被组合的对象的内部细节是不可见的。对象只以"黑箱"的形式出现。

  继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便地改变父类的实现。但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

  对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。由于组合要求对象具有良好定义的接口,而且,对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。

  优先使用对象组合有助于你保持每个类被封装,并且只集中完成单个任务。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物(这正是滥用继承的后果)。另一方面,基于对象组合的设计会有更多的对象(但只有较少的类),且系统的行为将依赖于对象间的关系而不是被定义在某个类中。

  注意:理想情况下,我们不用为获得复用而去创建新的组件,只需要使用对象组合技术,通过组装已有的组件就能获得需要的功能。但是事实很少如此,因为可用的组件集合并不丰富。使用继承的复用使得创建新的组件要比组装已有的组件来得容易。这样,继承和对象组合常一起使用。然而,正如前面所说,千万不要滥用继承而忽视了对象组合技术。

  相关的设计模式有: Bridge、Composite、Decorator、Observer、Strategy等。

  下面的例子演示了这个规则,它的前提是:我们对同一个数据结构,需要以任意的格式输出。

  第一个例子,我们使用基于继承的框架,可以看到,它很难维护和扩展。

abstract class AbstractExampleDocument
{
    // skip some code ...
    public void output(Example structure)
        {
            if( null != structure )
                {
                this.format( structure );
                }
        }
    protected void format(Example structure);
}

  第二个例子,我们使用基于对象组合技术的框架,每个对象的任务都清楚的分离开来,我们可以替换、扩展格式类,而不用考虑其它的任何事情。

class DefaultExampleDocument
{
  // skip some code ...
  public void output(Example structure)
  {
     ExampleFormatter formatter =
       (ExampleFormatter) manager.lookup(Roles.FORMATTER);
     if( null != structure )
     {
       formatter.format(structure);
     }
  }
}

  这里,用到了类似于"抽象工厂"的组件创建模式,它将组件的创建过程交给manager来完成;ExampleFormatter是所有格式的抽象父类;

  将可变的部分和不可变的部分分离

  "将可变的部分和不可变的部分分离"是面向对象设计的第三个原则。如果使用继承的复用技术,我们可以在抽象基类中定义好不可变的部分,而由其子类去具体实现可变的部分,不可变的部分不需要重复定义,而且便于维护。如果使用对象组合的复用技术,我们可以定义好不可变的部分,而可变的部分可以由不同的组件实现,根据需要,在运行时动态配置。这样,我们就有更多的时间关注可变的部分。

  对于对象组合技术而言,每个组件只完成相对较小的功能,相互之间耦合比较松散,复用率较高,通过组合,就能获得新的功能。

  减少方法的长度

  通常,我们的方法应该只有尽量少的几行,太长的方法会难以理解,而且,如果方法太长,则应该重新设计。对此,可以总结为以下原则:

  ☆ 三十秒原则:如果另一个程序员无法在三十秒之内了解你的函数做了什么(What),如何做(How)以及为什么要这样做(Why),那就说明你的代码是难以维护的,必须得到提高;
  ☆ 一屏原则:如果一个函数的代码长度超过一个屏幕,那么或许这个函数太长了,应该拆分成更小的子函数;
  ☆ 一行代码尽量简短,并且保证一行代码只做一件事:那种看似技巧性的冗长代码只会增加代码维护的难度。



分享到:
评论

相关推荐

    第5章 函数和代码复用.pdf

    ### 第5章 函数和代码复用 #### 知识点概述 本章节主要围绕着函数的概念、定义、使用以及代码复用的方式展开讨论。针对Delphi环境下的Python语言程序设计,深入剖析了如何利用函数实现更高效、灵活的编程实践。 #...

    面向Linux的内核级代码复用攻击检测技术.pdf

    【摘要分析】 本文主要探讨了针对Linux操作...综上所述,这篇文章提出了一个有效的内核级代码复用攻击检测技术,利用控制流完整性、编译器插桩和Hypervisor层的验证,实现了对内核安全的强化,同时兼顾了系统的性能。

    qt,c++告警规则 demo仅供参考,代码复用

    qt,c++告警规则 demo仅供参考,代码复用

    代码分析策略规则说明

    自.NET Framework 2.0起,可以使用`System.EventHandler<TEventArgs>`泛型委托,以避免为每个特定事件创建新的委托类型,提高了代码的复用性和灵活性。 5. **CA1004:泛型方法应提供类型参数推理** 泛型方法应该...

    第5周函数和代码复用.docx

    在Python编程中,函数和代码复用是核心概念,它们有助于编写简洁、高效且易于维护的代码。以下是根据提供的文件内容解析出的相关知识点: 1. **递归函数**: - 递归函数是一种在其定义中调用自己的函数。 - **基...

    Yii2扩展开发与代码复用:以资源包为例

    Yii2扩展开发与代码复用是当前流行的PHP开发框架Yii2的一个重要实践领域,特别是在资源包的开发和复用方面,本文将深入探讨如何利用资源包来管理和维护前端资源,以及如何通过扩展的形式实现代码的复用。 在Yii2...

    PHP 实现代码复用的一个方法 traits新特性_.docx

    在 PHP 语言中,代码复用是一个重要的编程原则,它有助于提高代码的效率和可维护性。自 PHP 5.4.0 版本起,PHP 引入了一种新的代码复用机制,称为 Traits。Traits 是一种为了解决单继承限制而设计的特性,它允许...

    rulz可复用的JUnit规则

    【标题】"rulz可复用的JUnit规则" 是一个专门为Java开发人员设计的测试框架扩展,它提供了丰富的JUnit规则库,使得单元测试更加灵活和可维护。JUnit是Java领域广泛使用的自动化测试框架,而rulz则进一步提升了其功能...

    测验5: 函数和代码复用 (第5周)

    本测验主要围绕函数和代码复用的主题展开,涵盖了一些基本的函数使用规则和递归的概念。 1. **函数的作用**: - **复用代码**:函数的主要优点之一就是可以避免重复代码,提升开发效率。 - **降低编程复杂度**:...

    stm32 GPIO复用表

    在实际应用中,通常通过STM32CubeMX这类工具或直接在代码中设置寄存器来配置这些复用功能,以达到设计要求。正确使用这些高级特性,可以在硬件资源有限的情况下,扩展微控制器的应用范围,提高系统的灵活性和性能。

    中粮我买网代码规范

    这部分强调代码复用的原则和方法,提高开发效率并减少重复代码。 - **DRY原则**:代码复用应尽量避免重复。 - **SHY原则**:指的是在代码复用中要慎用继承。 - **可变与不可变分离**:分离程序中的可变和不可变部分...

    书写和存储可复用的Fortran90Style代码准则.docx

    ### 书写和存储可复用的Fortran90Style代码准则 #### 1. 引言 本准则旨在为欧洲气象组织提供一个统一的Fortran 90编程框架,以促进不同组织间代码的交流与复用。通过建立一套标准化的文档规范与代码编写准则,不仅...

    精品网不规则焦点图广告代码.rar

    9. **模块化编程**:可能采用了模块化设计,如ES6的import/export,便于代码管理和复用。 10. **错误处理**:适当的错误检测和处理,确保代码的健壮性。 学习并理解这个代码,对于提升前端开发者在动态效果和用户...

    中国电信面向5G前传的无源彩光粗波分复用设备技术要求.pdf

    在缩略语和术语方面,标准中详细界定了面向5G前传的无源彩光粗波分复用设备的组成部分和光模块的应用代码,包括网络位置、设备管理、光模块分类以及应用代码的详细描述。 技术要求部分,包括了极限要求、推荐工作...

    轻量,快速,稳定,可编排的组件式规则引擎/流程引擎 拥有全新设计的DSL规则表达式 组件复用,同步/异步编排,动态编排

    总的来说,liteFlow作为一个全面的规则引擎和流程引擎,集成了众多高级特性,如DSL规则表达式、组件复用、同步/异步编排、动态编排等,旨在帮助开发者构建灵活、高效且易于维护的业务流程。在程序开发领域,尤其是...

    基于构件的软件复用技术研究与应用实践实用文档doc.doc

    代码复用是最基础的层次,通过直接使用或修改已有的源代码或目标代码。设计复用涉及复用设计模式和模板,减少了对实现环境的依赖。分析复用则更进一步,复用的是对问题域的理解和解决方案,抽象程度更高。 复用技术...

    计算机源代码编写规范(VB编码规范).rar

    以上只是VB编码规范的一部分要点,实践中还会涉及更多细节,如代码复用、异常处理策略、代码审查等。遵循这些规范,可以使VB代码更易于理解,更健壮,同时也为团队合作提供了统一的标准。通过不断学习和实践,开发者...

    Angularjs 创建可复用组件实例代码

    在AngularJS中,创建可复用组件是一种提升代码效率和可维护性的重要方式。本教程将以创建一个名为“rn-stepper”的自定义步长选择Directive为例,深入讲解如何实现AngularJS中的可复用组件。 首先,理解AngularJS的...

Global site tag (gtag.js) - Google Analytics