随笔-43  评论-307  文章-11  trackbacks-4

很久之前见过一个面试题,就是看一段代码并且发现里面的问题,那段代码是这样的:
public String XXXXXX(String input)
{
    StringBuilder sb = new StringBuilder(input);
    // 这里是一堆很复杂的操作sb的语句
    return input;
}
明眼人一下就看出来了,这简直就是忽悠小孩子玩的。
但是,在我现在的项目中,却真有人犯类似的错误,真是个很严重的问题,它直接造成了系统性能上的问题。
先说一下背景:
在对数据库操作之前,我们需要对用户的输入进行规范,其中包括需要把用户输入的内容进行截取,去掉前后的全角空格。
同样的,从数据库检索出来的数据,也要进行同样的操作。
这当然需要写入到共同方法里面,这就是我发现问题的代码段:
for (cntT = 0; cntT < str.Length; cntT++)
{
    if ((" ".Equals(str.Substring(cntT, 1))))
    {
        strWork = str.Substring(cntT + 1, str.Length - cntT - 1);
        continue;
    }
    else
    {
        strWork = str.Substring(cntT, str.Length - cntT);
        break;
    }
}
这是去掉前面的全角空格,先撇开这段代码是否有BUG,您发现里面存在的性能问题了吗?
不要告诉我应该用StringBuilder,它真正的问题是根本就不应该在循环里面进行截取。
循环里面只要计数就可以了,在循环之后进行截取,这样就避免了很多字符串操作,难道不是更好。
所以我说,基础很好总要,这个基础,既包括编程语言的基础,但是我们更需要注意的是编程思想、思维方式的基础。
不要把简单的问题复杂化,也不要把复杂的问题简单化,写出那样的代码,我也只能说编码人员根本就没有进行思考,就去写代码了。
很多人抱怨面试的时候,让你做面试题,而且都是很基础的题。
但是,您静下心来想一下,那些问题您都是十分清楚吗?
您可以不用翻书查资料就能准确的回答吗?
如果您办不到的话,我建议您还是先回家复习一下功课吧。
不要连这些基础东西都没搞明白,就跟我大谈特谈什么高深的设计模式、最新技术什么的。
不要告诉我说没有必要,那些基础的东西可以在很短的时间内掌握,而且平时应用也不会用到.......

我觉得,切忌:浮沙之上筑高台。
(心情不爽,特发此文。)

posted on 2007-12-09 19:26 Game_over 阅读(2437) 评论(33)  编辑 收藏

评论:
#1楼  2007-12-09 19:34 | JesseZhao      
支持你以下
  回复  引用  查看    
#2楼  2007-12-09 19:38 | 静水≈深流      
有道理
  回复  引用  查看    
#3楼  2007-12-09 19:39 | gakaki [未注册用户]
这很常见啊
工作忙 急的时候就会忘记

连重构的时间都没有 还要你自己花下班时间重构的项目你有没见过
一天做4个CRUD操作界面 就用ADO.NET
你怎么个重构法

所以教育的方法很重要 引导 怒 根本解决不了问题

  回复  引用    
#4楼  2007-12-09 21:17 | 重典      
有理
  回复  引用  查看    
#5楼  2007-12-09 21:20 | Yok      
为何不用TrimStart()和TrimEnd()?
  回复  引用  查看    
#6楼  2007-12-09 21:28 | Stanley.Luo      
既然是“去掉前后”,为什么要搞这么麻烦?

用:
str = str.Trim(" ".ToCharArray());
不可以了吗?
  回复  引用  查看    
#7楼  2007-12-09 21:32 | birdshome      
虽然代码比较ugly,但这里不会是系统的瓶颈。当然严格的说,是个潜在的瓶颈,比如来个数据有1w个前导空格。。。
  回复  引用  查看    
#8楼  2007-12-09 21:41 | kiler      
那段代码看了几分钟,没看懂,放弃了,不过这个算不上很严重的问题,也很难造成了系统性能上的问题,除非像birdshome说的在一次操作中执行1W次。

  回复  引用  查看    
#9楼  2007-12-09 21:47 | llj098 [未注册用户]
有道理~
  回复  引用    
#10楼  2007-12-09 21:56 | 蛙蛙池塘      
我也看了半天才看懂,给大家看看.net自己的trimstart方法
public string TrimStart(params char[] trimChars)
{
if ((trimChars == null) || (trimChars.Length == 0))
{
trimChars = WhitespaceChars;
}
return this.TrimHelper(trimChars, 0);
}
--------------
private string TrimHelper(char[] trimChars, int trimType)
{
int num = this.Length - 1;
int startIndex = 0;
if (trimType != 1)
{
startIndex = 0;
while (startIndex < this.Length)
{
int index = 0;
char ch = this[startIndex];
index = 0;
while (index < trimChars.Length)
{
if (trimChars[index] == ch)
{
break;
}
index++;
}
if (index == trimChars.Length)
{
break;
}
startIndex++;
}
}
if (trimType != 0)
{
num = this.Length - 1;
while (num >= startIndex)
{
int num4 = 0;
char ch2 = this[num];
num4 = 0;
while (num4 < trimChars.Length)
{
if (trimChars[num4] == ch2)
{
break;
}
num4++;
}
if (num4 == trimChars.Length)
{
break;
}
num--;
}
}
int length = (num - startIndex) + 1;
if (length == this.Length)
{
return this;
}
if (length == 0)
{
return Empty;
}
return this.InternalSubString(startIndex, length, false);
}

--------------
private unsafe string InternalSubString(int startIndex, int length, bool fAlwaysCopy)
{
if (((startIndex == 0) && (length == this.Length)) && !fAlwaysCopy)
{
return this;
}
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar)
{
fixed (char* chRef2 = &this.m_firstChar)
{
wstrcpy(chRef, chRef2 + startIndex, length);
}
}
return str;
}

  回复  引用  查看    
#11楼 [楼主] 2007-12-09 22:56 | Game_over      
--引用--------------------------------------------------
Stanley.Luo: 既然是“去掉前后”,为什么要搞这么麻烦?

用:
str = str.Trim(&quot; &quot;.ToCharArray());
不可以了吗?
--------------------------------------------------------

啊,Thank you。多谢提醒,都忘了啊。
  回复  引用  查看    
#12楼  2007-12-10 00:28 | Nathan2008      
我觉得性能上无关大碍的话,可以这么写啊,没关系啊

就像if语句

有的人觉得
if ...
...
else
...
这样写是菜鸟

但我不觉得是习惯问题

要是这么死扣的话,扣的东西多了
  回复  引用  查看    
#13楼  2007-12-10 09:49 | 丁一      
感触很深,
最近一起合作的人就是这样,
真不知道该不该再继续合作了..
像楼主发的这段效率低的代码还算是能看出写代码人的意图,
而我们这位写的代码根本看不出他要"干什么"..
而且整天抱怨公司里待遇多么不公平,
说实话,
我从心底里鄙视这种"冒充"是搞程序的人..

他的一段代码:
if(i == 0)
{
// 一段代码..
}
if(i == 1)
{
// 一段代码..
}
if(i == 5)
{
// 一段代码..
}



  回复  引用  查看    
#14楼  2007-12-10 10:35 | TinsunChan [未注册用户]
很多面试题目都是很基础的
而这些基础
很多人在学习的时候 都一眼带过
那时候觉得这很简单 看一下就明白了
而其实是不知道其所以然...


切忌:浮沙之上筑高台

这个主题不错 切忌 切记!
  回复  引用    
#15楼  2007-12-10 10:49 | 哦买噶的 [未注册用户]
偶怎么就没看出,下面这段有什么性能问题:

楼主给偶解释下哈,谢谢了哟

学习 学习
public String XXXXXX(String input)
{
StringBuilder sb = new StringBuilder(input);
// 这里是一堆很复杂的操作sb的语句
return input;
}


  回复  引用    
#16楼  2007-12-10 11:05 | jillzhang      
呵呵,不同的阶段会有不同的理解,如果你总是畏首畏尾的写代码的话,永远只能是一个小心谨慎的程序员而已,写代码完全没必要那么讲究,太讲究只能造成项目停滞不前。遇到问题,解决问题就可以了。开发之前或者过程中,一些性能问题,只要能在自己的经验范围内尽量别出格,就是很好的了。记住几个小技巧就这么也不行,那么写也不行。大错特错的做法!
  回复  引用  查看    
#17楼  2007-12-10 11:06 | Enzo      
基础重要,也要注意简单方法的应用,像牛顿说的“我是站在巨人的肩上”,我们要善于运用前人成果,当然也不能仅仅止步于前人的成果
  回复  引用  查看    
#18楼  2007-12-10 11:07 | jillzhang      
而且,坚持这种做法的时间越长,技术水平停止不前的时间也就越长,深有体会。当然楼主的执着精神和细致,的确也是一种好品质。
  回复  引用  查看    
#19楼  2007-12-10 12:57 | 壁虎      
@哦买噶的
--引用--------------------------------------------------
哦买噶的: 偶怎么就没看出,下面这段有什么性能问题:

楼主给偶解释下哈,谢谢了哟

学习 学习
public String XXXXXX(String input)
{
StringBuilder sb = new StringBuilder(input);
// 这里是一堆很复杂的操作sb的语句
return input;
}


--------------------------------------------------------
对sb做的再多操作,都是无效的。
不过这个可能不能定义为性能问题。应该是说程序问题,在项目中编写时,代码书写人可能是想return sb.ToString()。
  回复  引用  查看    
#20楼  2007-12-10 13:11 | Yoshow      
我看了半天 看懂第一段代码 搞笑的面试题

第二段就看不大懂 想干嘛
  回复  引用  查看    
#21楼  2007-12-10 13:18 | 怪怪      
....

我承认, 那个return input我没看出来...
  回复  引用  查看    
#22楼  2007-12-10 15:04 | oyeah [未注册用户]
@壁虎 @怪怪


哦,那个return input我也没看出来...


哦买噶等

肯定也没看出来

但是开始看楼主说性能

于是乎以为是sb哪儿出错了

原来是这个低级错我啊

实在是汗啊









  回复  引用    
#23楼  2007-12-10 15:27 | guohao [未注册用户]
汗一个。我居然没看出来 哈哈 。。。。。
  回复  引用    
#24楼  2007-12-10 16:11 | zhchang [未注册用户]
只能做代码规范检查,然后重构
  回复  引用    
#25楼  2007-12-10 16:29 | hoodlum1980      
去掉前导空格那段代码,不仅写的笨拙,可读性也差。

  回复  引用  查看    
#26楼  2007-12-10 20:49 | 恶灵旧都      
翻书查资料找到解决方法也是不错的。

记得哪个高人说过“只要能迅速找到解决方法,不管是什么方式 ”
  回复  引用  查看    
#27楼  2007-12-11 10:15 | lllever [未注册用户]
呵呵,不同的阶段会有不同的理解,如果你总是畏首畏尾的写代码的话,永远只能是一个小心谨慎的程序员而已,写代码完全没必要那么讲究,太讲究只能造成项目停滞不前。遇到问题,解决问题就可以了。开发之前或者过程中,一些性能问题,只要能在自己的经验范围内尽量别出格,就是很好的了。记住几个小技巧就这么也不行,那么写也不行。大错特错的做法!

  回复  引用    
#28楼  2007-12-11 13:54 | wywhb [未注册用户]
前面列举的示例与后来的代码跟结论之间完全没有关系,不知道楼主怎么想问题的。第一段代码可以算是手误,把返回写错了;第二段代码与性能关系也不是很大,然后,楼主就得出了性能问题的结论,是在是看不懂啊。如果不是后来别人的解释,真是不明白楼主想表达的意思。
虽然题目很好,但跟内容不怎么贴切啊,主旨不就是告诉大家,注意基础知识嘛,你这么一写,大家反倒迷糊。
  回复  引用    
#29楼  2007-12-11 14:44 | 阿第三方 [未注册用户]
用户输入规范根本不是一个截取空格这么简单的事情。
设计很多复杂的判断,且如果是一个通用组件,还要考虑很多特殊情况。
还有怎么针对复杂的规范输入,你不知道有个东西叫正则表达式吗。
  回复  引用    
#30楼  2007-12-14 14:54 | 啊 [未注册用户]
太汗了,那个return 竟然没看,我还以为批判stringbuilder 呢。
  回复  引用    
#31楼  2007-12-16 04:35 | 工 [未注册用户]
不是候捷的话吗,嘿嘿
  回复  引用    
#32楼  2007-12-16 04:36 | 45 [未注册用户]
@工
嗯,就是他的话
  回复  引用    
#33楼  2007-12-16 04:37 | 工 [未注册用户]
不错!!!
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-09 22:20 编辑过


相关链接: