• [Objectoriented] 相依性


    前言 :

    写程序的时候都会听到说,要降低程序之间的相依性。

    程序之间的「相依性」,可以用下面简单的范例来理解。FunctionA里面使用了FunctionB,当FunctionB功能变更的时候,FunctionA就必须跟着做修改。这也就是说,「FunctionA相依FunctionB」。

    static void FunctionA()
    {
        FunctionB();
    }
    
    static void FunctionB()
    {
    
    }
    

    以上面这个范例看起来,相依性不会是很大的问题,改就是了。但是当我们把问题放大,假设系统里有1000个Function。Function之间互相相依。当要更改1个Function内容并且维持整个系统正确运作,就必须要去检查其他999个Function是否需要跟着修改。这样的修改会是一场灾难,也是造成很多软件系统,改这边坏那边的主要原因。所以减少相依性,是提高程序代码质量很重要的一个环节。

    在「结构化导向程序设计」Function与Function之间的相依性,可以透过追踪程序代码的方式来识别。但到了「面向对象程序设计」的环境下,虽然说也是可以使用追踪程序代码的方式,来识别对象之间的相依性。但却会受到继承、接口等等面向对象特性的影响,让识别对象之间相依性的这件工作变得非常复杂。

    本篇使用UML类别图里的「关系」当作工具,阐述该如何透过UML类别图里的「关系」,来辅助开发人员识别面向对象程序的对象相依性。

    说明 :

    识别对象相依性一个简单的方法,就是「当两个类别A与B,分别存在不同的项目内。大幅修改了B之后,A如果需要跟着重新编译,那就是A相依B」。我们依照这个原则,来检视UML类别图里所定义的各种关系:

    关联关系(Association)

    using Association.ProjectB;
    
    namespace Association.ProjectA
    {
        public class ClassA
        {
            private readonly ClassB _b;
    
            public ClassA(ClassB b)
            {
                _b = b;
            }
    
            public ClassB B { get { return _b; } }
        }
    }
    
    namespace Association.ProjectB
    {
        public class ClassB
        {
    
        }
    }
    

    上图与范例程序是UML类别图里定义的关联关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更ClassB的时候,ClassA需要跟着重新编译。所以ClassA相依于ClassB。

    依赖关系(Dependency)

    using Dependency.ProjectB;
    
    namespace Dependency.ProjectA
    {
        public class ClassA
        {
            public void MethodXXX(ClassB b)
            {
                // TODO
            }
        }
    }
    
    namespace Dependency.ProjectB
    {
        public class ClassB
        {
    
        }
    }
    

    上图与范例程序是UML里定义的依赖关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更ClassB的时候,ClassA需要跟着重新编译。所以ClassA相依于ClassB。

    概括关系(Generalization)

    using Generalization.ProjectB;
    
    namespace Generalization.ProjectA
    {
        public class ClassA : ClassB
        {
            public ClassA()
                : base()
            {
    
            }
        }
    }
    
    namespace Generalization.ProjectB
    {
        public class ClassB
        {
    
        }
    }
    

    上图与范例程序是UML里定义的概括关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更ClassB的时候,ClassA需要跟着重新编译。所以ClassA相依于ClassB。

    实现关系(Realization)

    using Realization.ProjectB;
    
    namespace Realization.ProjectA
    {
        public class ClassA : IntefaceB
        {
    
        }
    }
    
    namespace Realization.ProjectB
    {
        public interface IntefaceB
        {
    
        }
    }
    

    上图与范例程序是UML里定义的实现关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更IntefaceB的时候,ClassA需要跟着重新编译。所以ClassA相依于IntefaceB。

    聚合关系(Aggregate)

    using Aggregate.ProjectB;
    
    namespace Aggregate.ProjectA
    {
        public class ClassA
        {
            private readonly ItemB[] _itemBCollection;
    
            public ClassA()
            {
                _itemBCollection = new ItemB[2];
                _itemBCollection[0] = new ItemB();
                _itemBCollection[1] = new ItemB();
            }
    
            public ItemB[] ItemBCollection { get { return _itemBCollection; } }
        }
    }
    
    namespace Aggregate.ProjectB
    {
        public class ItemB
        {
    
        }
    }
    

    上图与范例程序是UML里定义的聚合关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更ItemB的时候,ClassA需要跟着重新编译。所以ClassA相依于ItemB。
    *聚合关系语意较为复杂,范例程序只是简单示意。

    组成关系(Composition)

    using Composition.ProjectB;
    
    namespace Composition.ProjectA
    {
        public class ClassA
        {
            private readonly ItemB[] _itemBCollection;
    
            public ClassA(ItemB[] itemBCollection)
            {
                _itemBCollection = itemBCollection;
            }
    
            public ItemB[] ItemBCollection { get { return _itemBCollection; } }
        }
    }
    
    namespace Composition.ProjectB
    {
        public class ItemB
        {
    
        }
    }
    

    上图与范例程序是UML里定义的组成关系,代表图形与范例程序。依照原则去检视程序代码可以看出,当变更ItemB的时候,ClassA需要跟着重新编译。所以ClassA相依于ItemB。
    *组成关系语意较为复杂,范例程序只是简单示意。

    后记 :

    本篇的文章描述了,如何透过UML类别图里的「关系」,来辅助开发人员识别面向对象程序的对象相依性。当将对象依照职责分类成为独立Package的时候,对象之间的相依性也需要考虑进去,避免在Package之间有相依性杂乱的问题。当发现相依性杂乱时,则可以透过IoC、Facade等等手法来整理相依性。透过不断的整理相依性,就能慢慢提高程序代码的品质。

    参考数据 :

    维基百科 - 类别图

  • 相关阅读:
    Windows 2008 R2 安装 Windows phone 7 开发环境
    win 7,win2008 无法给新建用户完全权限
    基于Ajax的Asp.Net 简易在线聊天室
    phpwind ecshop 用户整合
    UVALive 3942 Remember the Word(字典树+DP)
    UVA 11732 strcmp() Anyone? (压缩版字典树)
    UVA 11992 Fast Matrix Operations(线段树:区间修改)
    hdu 2222 Keywords Search(AC自动机模版题)
    动态规划基础练习笔记
    递归与分治策略基础练习笔记
  • 原文地址:https://www.cnblogs.com/clark159/p/2428046.html
Copyright © 2020-2023  润新知