优化出来的bug:慎用static

这几天忙的晕头晕脑的,午休取消了,抽烟时间也掐着算,连上厕所的空儿都在想工作那些事儿,没办法,搞IT这行,事儿多的时候,124小时是不够用的,必须一天25小时才行。可日子不按咱的想法走,咱只能顺着日子过!

 

忙的时候一糊涂就容易犯错,这不犯了个菜鸟级别的错嘛,让同事好一顿奚落 :(。事情是这样的,项目中某个算法需要做优化,在Code review的时候发现在初始化时请求数据库比较多,而部分数据又是配置型数据(这里将不频繁变动的数据且称为配置型数据),且数量也不多,于是就想到了使用静态构造来保存这部分数据,以减少数据库请求量。由此在优化的时候将原来的局部变量变成了全局静态变量,且在静态构造函数内构造一次,这样一来问题就出来了,这也怪我太急功近利,因为事儿比较多,也就没留个心眼,结果吃大亏了。

说到这里,看这文章的老鸟们肯定明白了个中缘由(相信也有不少一看题目就能猜到个八九不离十的鸟人们)。闲话先不说,翠花,上代码!

 

    public class StaticBug
    {
        
static Dictionary<int,Bug> BugDictionary = new Dictionary<int,Bug>();
        
static StaticBug()
        {
            InitBugDictionary();
        }        

        
private Bug ErrorGetBug(int bugId)
        {
            
//错误的方法.
            Bug bug 
= null;
            
if (BugDictionary.ContainsKey(bugId))
            {
                bug 
= BugDictionary[bugId];
                
if (bug != null)
                {
                    bug.BugCount
++;//并不希望改变BugDictionary中Bug对象的BugCount属性值.
                }
            }
            
else
            {
                InitBugDictionary();
                
if (BugDictionary.ContainsKey(bugId))
                {
                    bug 
= BugDictionary[bugId];
                    
if (bug != null)
                    {
                        bug.BugCount
++;//并不希望改变BugDictionary中Bug对象的BugCount属性值.
                    }
                }
            }
            
return bug;
        }
    }

    
public class Bug
    {

        
public int BugId{ getset; }
        
public string BugTitle { getset; }
        
public string BugContents { getset; }
        
public int BugCount { getset; } 

        
public static Dictionary<int, Bug> GetBugs()
        {
            
//Do some thing to get bugs.
            
return new Dictionary<int, Bug>();
        }
    }

 

从代码中可以看到对bug变量的错误操作。若不希望改变BugDictionaryBug对象的BugCount属性值,正确的代码应该是:   

        private Bug RightGetBug(int bugId)
        {
            Bug bug 
= null;
            Bug tempBug 
= new Bug();
            
if (BugDictionary.ContainsKey(bugId))
            {
                bug 
= BugDictionary[bugId];
                
if (bug != null)
                {
                    tempBug.BugId 
= bug.BugId;
                    tempBug.BugTitle 
= bug.BugTitle;
                    tempBug.BugContents 
= bug.BugContents;
                    tempBug.BugCount 
= bug.BugCount;
                    tempBug.BugCount
++;
                }
            }
            
else
            {
                InitBugDictionary();
                
if (BugDictionary.ContainsKey(bugId))
                {
                    bug 
= BugDictionary[bugId];
                    
if (bug != null)
                    {
                        tempBug.BugId 
= bug.BugId;
                        tempBug.BugTitle 
= bug.BugTitle;
                        tempBug.BugContents 
= bug.BugContents;
                        tempBug.BugCount 
= bug.BugCount;
                        tempBug.BugCount
++;
                    }
                }
            }
            
return tempBug;
        }

从上面代码可以看出使用了一个临时Bug对象来接收bug的属性值,然后BugCount++,避免了修改BugDictionary

 

相信不少新手在使用static的时候会遇到这个错误,也相信有不少想我这样的老手一不谨慎就造成了这样的错误。造成错误的原因简单,但从3千多行代码中排除bug,谈何容易!因此,各位兄弟姐妹们在使用static变量的时候要谨慎。不只如此,在使用单例模式的时候更要谨慎,相比较起来,单例模式出bug要比我这情况容易排查多了。

 

写此菜鸟型文章,斗胆放在首页上抛砖引玉,希望比我更老的鸟们提点儿珍贵的意见!

 

PS:没想到招来骂声一片!
-----------------
PS2:我还是说说我的本意吧,其实我是不希望对BugDictionary中的元素做任何改变。嗯,没错,归根究底还是引用类型造成的,从这个角度来说跟static没关系。但是从static角度来考量,假如没有使用static,就不会出这问题了。我可以直接取BugDictionary里元素,经过加工后返回。所以,综合来说,是我在使用static时疏忽了不能对BugDictionary进行修改这一点造就了这个错误。我只希望能对其他人有个警醒作用!评论的兄弟们你们说的都没错,但是考虑问题角度不同,给出的观点也是不同。
-----------------
PS3:其实搞.net的都知道.net里总的有2种数据类型:值类型、引用类型,但为什么却还是有不少人频频的遇到"未将对象引用设置到对象实例"的异常呢?这值得我们思考,虽然这是低级错误,但为什么我们总是频繁犯这些低级错误呢?难道这些不值得我们思考么?
posted on 2009-04-16 22:24  Dragon4  阅读(3563)  评论(54编辑  收藏  举报