组件化开发

原创 2015年07月07日 21:08:15

组件化开发概述

软件系统开发面临的困境与突破尝试
  1. 软件代码难以读懂和维护,业务逻辑分散在多个代码模块中
  2. 软件系统面对着的需求不断变化,再次开发一个新的软件成本高
  • 因此,我们应该“重用”,而不是每次都“从头开始”
  • 大量的软件系统中都存在着功能重复的情况,因而开发可重用的软件组件是可行的。


组件(Component):
  • 是指可以用于重用、开发和部署的软件模块。
组件化开发(CBD:Component-based Development)
  • 以可重用的组件为基础“装配出”解决需求软件的过程。

组件实现的功能:
  • 组件的功能是通过其接口(是宏观意义的接口,指向外界提供的功能)来表达;
  • 组件只是黑盒,外界只能通过接口来访问,外界只关系通过接口可以实现的功能,并不关心组件的技术细节;
  • 组件具有独立性和可组合性。

  • 因此,创建可以当“积木”组合的软件组件是组件化开发的核心工作之一。

组件设计的基本原则
  1. 组件设计首先是组件接口的设计,这个组件该干什么事情,每个组件都应有一个明确的职责,只做好一件事,体现为一个明确的组件接口;
  2. 组件的具体实现技术。
  • 组件需按职责进行设计!!
  • 为实现复用而设计
    • 允许围绕该组件的应用自由改变而无需改变组件自身,除非组件自己的功能需求改变,即只会改变其内部的技术实现,而不会改变其对外接口。
  • 仔细考虑组件功能集合的大小
    • 组件的粒度是用于衡量组件所提供的功能集的大小、所封装的代码量多少等与“规模”相关的特性。
    1. 小组件(如一个只允许输入邮编的文本框);
    2. 大组件:一个预先构造的应用软件包(如一个用于生成复杂报表的组件,用于文档处理的office软件包)。
    • 粒度大小与灵活性通常成反比,与易用性成正比!

组件化软件开发的“三板斧”(套路):
  1. 重用已有组件;
  2. 开发部分新组件;
  3. 组合新旧组件搭建出新系统。

组件化软件的开发方式:


组件化开发全过程

实例:两数相加程序:从“天下一统”到“借鸡生蛋”


  • 原始版本

  • 原始需求:输入框接收用户输入,“=”按钮计算结果。
    • “=”按钮事件:
        private void btnAdd_Click(object sender, EventArgs e)
        {
            try
            {
                int num1 = Convert.ToInt32(txtNumber1.Text);
                int num2 = Convert.ToInt32(txtNumber2.Text);
                lblResult.Text = (num1+num2).ToString();
            }
            catch ( Exception ex)
            {
                lblResult.Text = ex.Message;
            }
        }


  • 需求二:在输入数字时,能直接看到结果而无需点击“=”按钮。
    1. 为输入框添加 TextChanged 事件,并将原本按钮的事件复制到两个输入框的 TextChanged 事件中:
        private void txtNumber1_TextChanged( object sender, EventArgs e)
        {
            try
            {
                int num1 = Convert.ToInt32(txtNumber1.Text);
                int num2 = Convert.ToInt32(txtNumber2.Text);
                lblResult.Text = (num1 + num2).ToString();
            }
            catch ( Exception ex)
            {
                lblResult.Text = ex.Message;
            }
        }
  • 需求三:将雷同的用于相加的方法提取用于复用。
    1. 选中代码,右键菜单>重构>提取方法Add()
  • 需求四:将窗口的数据输入与数据处理分离。
    1. 新增数据处理类MathOpt,并把权限改成public;
    2. 增加纯粹用于数据处理的方法Add;
    3. 在原来的类frmAdd中,实例化MathOpt类:private MathOpt calculator = new MathOpt();
    4. 在Add方法中将 lblResult.Text = (num1 + num2).ToString();  替换为 lblResult.Text=calculator.Add(num1, num2).ToString(); ;
    • 好处:Add方法中只与界面相关,并不涉及数据的处理
  • 需求五:(迈向组件化开发的重要一步)
    1. 将数据处理的代码做成程序集
      1. 添加新类库MathLibrary:
      2. 将MathOpt类复制到MathLibrary类库中,并修改命名空间使其匹配,并将多余的类删除;
      3. 编译;
      4. 在需要该类库的项目添加MathLibrary的引用。

小结:
  1. 不要不功能代码直接写到事件响应代码中,而是用调用函数的方式(减少代码重复);
  2. 尽可能少地编写重复代码,将重复的代码编写成组件以复用;
  3. 事件界面代码与功能代码分离;
  4. 尽量复用二进制形式的程序集,而不是复用源代码,即不该直接拷贝代码,而是引用已经编译好的类库。


.NET组件化开发技术

程序集(Assembly)
  • .NET Framework中基本的软件模块,它可以包容不限数目的类型,其常见的载体为一个或多个DLL文件,也可以是一个可独立执行的EXE文件。
  • 程序集和命名空间是多对多的关系。一个命名空间可以包含多个程序集,一个程序集也可以分布在多个命名空间中。
  • 一个项目如果需要使用特定程序集中的类型,需要添加对此程序集的“引用(Reference)”。

程序集的内部结构

  • 程序集大致分为两种:
    • 单文件程序集(占绝大多数)
    • 多文件程序集,多用于国际化程序设计时,根据实际情况组合程序集实现国际化多语言。
  • 程序集主要组成部分:元数据、IL代码、资源。
    • IL代码:有.NET编译器编译生成,将编程语言代码转换为IL代码,是程序集实现功能的主体。
    • 程序集元数据:程序集的公用信息。
    • 类型数据:该程序集定义了哪些类、接口、方法、属性、字段、事件等信息
  • 使用ildsam可以查看程序集元数据。

组件设计的“对外接口最小化”原则
  • 一个程序集中,可以放置任意多个类,但仅有需要为程序集外界使用的类,才设置为“公有(public)”,以实现程序集的信息封装。
  • 而公有类,需要使公有成员“越少越好”,这样的类才易于使用和维护。

组件间的“依赖性”
  • 含义:包容于某组件内部的类,需要调用另一个组件中的类以实现功能。
  • 这是由于类之间的依赖导致的。
  • 在设计各组件接口时,尽量避免和减少组件之间的耦合性。

解决方案示例:

  • UseDLL依赖于MyDLL和MyDLL2,UseDLLC、MyDLL和MyDLL2又依赖于.NET的基础组件System。
  • 在实际开发中,两个程序集之间的依赖关系应该要是“单向”的,不能是双向的,这是系统架构的关键点。
  • 具有相同的抽象级别的对个组件组成一个“层”,各个层之间的依赖关系也应是“单向”的。
  • 把多个组件分层,组件间建立“单向”的依赖关系,这种方式就称为“组件化的多层架构”,是当前软件系统最常见、最主流的软件架构。

避免出现组件循环依赖的情况,这样在编译时就会出错


  • 要消除这种循环依赖,应在设计时就避免;
  • 可以使用在组件间移动类的方式,消除组件间的循环依赖

组件的版本
  • 一个大型系统,需要注意其版本要一致。
  • 这里的版本是指:
    1. 组件运行时要求的软件系统平台的版本;
    2. 组件自身的版本。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Web应用的组件化开发

基本思路 1. 为什么要做组件化?   无论前端也好,后端也好,都是整个软件体系的一部分。软件产品也是产品,它的研发过程也必然是有其目的。绝大多数软件产品是追逐利润...

Android 开发:由模块化到组件化(一)

当你看到这的时候,想必心理一阵恶寒:模块化?组件化?到底是什么鬼?有啥区别. 有这种感觉才是对的,模块化和组件化本质思想是一样的,都是"大化小",两者的目的都是为了重用和解耦,只是叫法不一样.如果非要...

Android组件化方案

随着APP版本不断的迭代,新功能的不断增加,业务也会变的越来越复杂,APP业务模块的数量有可能还会继续增加,而且每个模块的代码也变的越来越多,这样发展下去单一工程下的APP架构势必会影响开发效率,增加...

.NET 委托与事件

“委托”基础 含义: 委托(Delegate):是.NET Framework对C#和VB.NET等面向对象编程语言特性的一个重要扩充。是.NET中的一些重要技术,如事...

kick boll

测试下能用chrome 写木有

在对象生命周期内只执行一次的Block

在对象生命周期内只执行一次的Block众所周知,要想代码执行一次,可以使用 dispatch_once 函数。有时候我们不想辣么绝。。

C# 泛型generic的简单理解

根据MSDN的一段话:泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性。泛型为.NET框架引入了类型参数(type parameters)的概念。类型参数使得设计类和方法时...

Sublime 为指定操作设置快捷键

Sublime 为指定操作设置快捷键Sublime 作为一款优秀的文本编辑器,不仅有华丽丽的界面,还支持丰富的扩展,尤其是自定义。似乎一切都可以改成自己心仪的样子。但我在修改快捷键时遇到了难题。

Android的组件化开发

  • 2016-12-02 17:18
  • 4.08MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)