百度空间 | 百度首页 
 
查看文章
 
设计之痛——定性思维
2009年04月03日 星期五 09:55

设计模式在技术繁杂的今天仍然是被讨论的很多.从以前的那种盲从到现在的理性,设计模式逐渐得到了它应该得到的地位.现在看来谈设计模式就不可能不提到反模式以及重构。

设计是演化出来的。不是一蹴而就的完成的。我们的思维很习惯做假设,我们作假设倒是没有什么错误,但是我们似乎也习惯忽略我们的假设。举一个我自己的作项目遇到的例子。我们习惯了用System.IO.Directory.GetFiles()方法来找存在此目录的文件。现在的客户要做的功能是分享你所得到文件,并通过网络发送到另一台机器上。我们get到了所有文件,并且实现的很好。很顺利的把文件发送到了另一台机器上。OK,你认为我们做了什么假设,我们犯了什么错误。如果你没有看出来那你的客户会很严厉很生气的告诉你当他打开后缀名为.lnk的文件的时候,操作系统很友好的告诉他“The item "***" thit this shortcut refers to has been changed or moved, so this shortcut will no longer work proerly.”并且原来的系统让他给format了,文件对客户来说是他的命根子。这不是要来亲命了么!!跟他们讲理去,你说lnk文件很特殊是windows操作系统为防止文件的重复拷贝做得一个文件关联,类似于C语言的指针.....。教训是惨痛的。回想一下我们犯的错误,我们假设了所有的文件都是正常的文件,但是这个前提是不成立的。

立即去解决我们设计的问题,不,等等,我们应该还要想想是不是之前的去重构我们的代码有没有问题。经过我深思,我发现.lnk的文件不只是指向一个文件还可以指向一个网页。bug么?对,设计的bug。慢慢的重构吧。别着急,一定别着急,bug在很多情况下是你修复bug造成的。

我准备写一系列的文章来说明我们常见的设计bug。你可以猜到它不会很具体,因为在设计方面我们更喜欢的是通用性。我决定让这个问题很通用,让这个问题的例子很具体。

今天先写一个很常见的设计问题,我自己给起个名字吧,属性关联的设计。具体描述如下:“一个类中的两个属性相互影响,一个的改变导致另一个的改变”,当我们遇到这样的问题是,首先观察我们真的需要这两个属性么?如果能通过一个就表现出来了,那么还是砍掉一个吧。如果发现确实不能砍掉,那我们应该设计成其中的一个是只读(只get不是set)的吧。设置只读的那个属性的原则是属性的被动项,也就是经常被另一个属性改变的那个。

来个例子:还是文件分析系统。因为通过我们的软件我们能获得到客户机器上的目录,但是我们不想让别人知道这个文件具体在那个盘符下。我们做了如下的设计

public class VirualCatalog
{
public string TruePath{get;set;}
public string VirualPath{get;set;}
}

接下来的问题来了,我们想通过改其中的一个另一个也跟着改变。于是我们又做了如下的工作:

    public class VirualCatalog
    {
        private string m_TruePath;
        public string TruePath
        {
            get { return m_TruePath; }
            set
            {
                m_TruePath = value;
                OnTruePathChenged();
            }
        }

        private void OnTruePathChenged()
        {
            //cheng m_VirualPath and change local folder or file
        }

        private string m_VirualPath;
        public string VirualPath
        {
            get { return m_VirualPath; }
            set
            {
                m_VirualPath = value;
                OnVirualPathChenged();
            }
        }

        private void OnVirualPathChenged()
        {
            //Cheng m_TruePath
        }
    }

问题出现了。你发现当你移动文件目录的时候,子目录没有被通知到。于是你递归的开始设置,很不巧你先设置了VirualPath,导致了你OnTruePathChenged()方法没有被执行,(当然这里也违反了一种设计,属性职能过多,我们先不去讨论),这样导致了真实目录没有被完全的移动。导致了错误的设计是最明显的设计错误,我们也许会碰到类似的问题。

我们砍掉

           set
            {
                m_TruePath = value;
                OnTruePathChenged();
            }
那么我们改变真实路径的方法 OnTruePathChenged();独立出来吧,别忘了换个名字就可以了。

欢迎大家对我的设计提出异议。


类别:Patterns In Practice | 添加到搜藏 | 浏览() | 评论 (3)
 
最近读者:
 
网友评论:
1
2009年04月03日 星期五 13:32 | 回复
 
2
2009年04月03日 星期五 16:18 | 回复
回复lvxiaolin1220:拽吧!
 
3
2009年04月03日 星期五 16:58 | 回复
回复CH似水年华:没看懂!所以拽不拽我说了不算!
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu