hrmai

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  40 随笔 :: 0 文章 :: 506 评论 :: 1 引用

2011年6月15日 #

     一个士兵前来报告说:报告前面有一坨屎。长官说:你去把它吃了。

     这个故事我从两个人口中听说过。一个是我以前的总监,他在给我们项目组开动员会的时候说过。另外一个是从我经理口中听过,说我只是提出问题,而没有给出解决方案。

     对于第一场景,当时我们总监的意思是我们项目组需要自己把问题解决了,而不是把问题抛给别人。我觉得这个是对的。

     对于第二个场景,现在已经不会再有了。因为我现在根本就不会提问题了。

     为什么同一句话从不同的人口中说出来会有不同的后果了?原因很简单,有人没有把这句话的意思理解透。其实这句话的意思是说,自己的事情要自己做,不要往上推或者往外推。而这句话对于第二个场景来说有一个很大的问题,就是,我提出问题的时候,我本身是不负责这个功能模块的设计工作的,我本身只是作为一个评审委员(当然,某人不是这样子想的吧)。

      再往深一层想。如果你作为一个管理者你能够容忍一个经常“找茬”的下属不?如果不可以,你又会不会用这句话来教育你的下属了?如果你用了,你的下属会不会因为提意见而不得善终而选择明哲保身了?像现在这样子,明明看到了问题,也不会提出来。

      其实对于第二种场景,就是经济学上的典型的劣币驱逐良币。不好的把好的打败了。错误的把正确打败了。

     作为一个管理者,要容纳各种各样的意见和建议,海纳百川。而作为一个下属,应该把握好提建议的方式,这方面我确实需要加强。

posted @ 2011-06-15 22:39 Leon Mai 阅读(154) 评论(0) 编辑

2011年6月14日 #

     其实想写这篇文章很久了,但是一直都没有动手,今天不一下缺。

     首先介绍一下背景:项目由两种语言来完成java和.net(非面向对象语言的可以掠过下文)。

     今天再次听到两位同事(老员工)说老大要他们在设计文档中画流程图,而且要把整个系统的流程图画出来。心中一楞,看来流程图还真是个害人的东西。

     首先从我自己负责的模块来说吧。我的工作是接别人的工作的,算是维护和改写吧。刚接手的时候不是很明白为什么一个方法会是600+行(一个类也就2-3个方法),想很久也没有想明白,于是在熟悉了流程之后,把流程图画出来,然后把大的方法分解成了小的方法。但是还是一个很大的类。再后来,日子比较清闲也看了一下重构方面的书,于是实验了一下,把大类们都分解成了各个职责明确的小类,(主要用到的方法是提取基类,提取公共方法等方法),于是将几个600+行的大类分解成了10个100-200行的类(当然还有部分方法放到了公共类库中,大约100行代码量吧)。在完成重构后,业务流程发生了一个很大的改变,需要将我负责的模块的业务逻辑进行很大的改动。本来以为这次的改动会让我很难受,孰料我竟然用了3个10行的左右的函数和一个if语句解决了这次更改(当然动手之前想了差不多半天),剩下的工作量都是和界面的搏斗。这是我第一次真切的感受到面向对象的力量。

     其次是从我负责的整个系统的重构工作中看到的情况。以前的系统是由2个同事写的(其中一个以前是php的),但是我看到的代码都是一些500+行的大函数,很多时候我看到的是一个300+行的page_load函数。很多的代码是重复的,就算是在page_load函数里面也有重复的,也是可以提取共用代码的。我一直都想不通。直到后来,可能是看到了某个靓妹,突然脑充血想到自己以前负责鉴权重构的时候的过程,一切都明白了。

      当时的过程是,我老大要求我将整个过程画出来,画得很细,大约有60-80个框的流程图,拧起来就是2~3斤的葡萄了。然后因为这个流程图是在详细设计的时候画的,所以我在写程序的过程中也就大致按照这个流程把整个鉴权过程写到了一个类中,最后我也写了一个600+行的类(唯一的安慰是,没有写一个600+行的函数)。

      于是我得出了一个结论:在OO为主要编程语言的详细设计说明书中不应该出现流程图,取而代之的是时序图(其他的可能没有那么好)。(或者我们对在每一个流程中标志这个流程属于那一个类,好像有点扯蛋哦。。。)当然,你有可能会说在详细设计的时候就是应该这样子做的,如果你们公司的流程是这样的,我想请你写下具体的流程,因为我确实没有经历过这种公司。至于另外一种可能会说,一个类600+行,或者一个功能600+行的代码,是你们在做功能拆分的时候做的不够细,这一点我是承认的,但是功能怎么样分细,用对象的职责还是别的什么方法,也请赐教。

      至于我为什么会有这样的结论了?主要是因为如果你可以画出一个时序图,你总得将一些职责分细,所以总的来说对于一个类承担的职责总会比以前的少了。而且,当你画时序图的时候,你应该会想一下类的构成。所以我们的类的职责就明确了一些,我们的类也就小了,腰也不酸,腿也不痛了。

      但是,是不是流程图就一无是处了?我觉得倒不是,因为对于需求分析和概要设计这些需要对用户或者非技术人员解释的文档,流程图还是很简单明确的,特别是在做需求设计的时候。我们在这里遇到的问题只是因为我们把流程图直接细化copy到了详细设计之中。(可能你是纯化论者,说用例(user case)也很容易跟客户沟通,但是我确实见过不懂用例图,但是流程图还画得很好的客户)

     又或者,这是不是七宗罪中的懒惰。。。。

     欢迎交流意见。

posted @ 2011-06-14 22:43 Leon Mai 阅读(1937) 评论(13) 编辑

2011年5月25日 #

     这两年,互联网上多了很多宠儿,但是大多数都是只做好一件事的新贵。quora、dropbox、微博(非国内的)、groupon等都是。它们都是在大公司的夹缝中找到一个突破点,然后像热带雨林中的小树那样,不停的向上,向上。而国内很多的软件公司都在寻找这样的一个突破点,包括我现在所在的公司也在找这样的一个突破点。但是我发现一个很有趣的现象是,我们的突破点都是在先寻找商业模式,而不是先寻找用户模式。这个是本末倒置还是我太过天真?也就是说我们做的都是被人做过的,被别人证明是赚钱的事情。但是好像又鲜有人赚钱了。是现金流决定了这一切还是眼界,还是别的什么东西。同学们有什么高见,欢迎留言。

暂放首页,以供讨论,管理员觉得不妥,请撤掉。

posted @ 2011-05-25 21:36 Leon Mai 阅读(63) 评论(0) 编辑

2011年5月24日 #

   1、改造还是新建?

       系统本来有A,B,C,D四个页面,其中B是详细页,其他的都是一些概要的页面,大约如下:

image

        A,C,D的模式,HTML大约如下

<ul>

     <li><a href=”B”><img src=”image”/></a></li>

……

</ul>

        而B就是A,C,D链接过去之后的详细页。而且,B本身是可以通过URL直接访问,不一定受限于前面3个页面

       最近产品需要增加一个PV功能,主要的功能是记录从A中过来的访问B页面的次数。

       负责实现的同事决定利用系统本身具有的B页面的记录功能(记录访问B的PV),直接改造原有的记录功能。将A到B的URL中加一个参数以此标记来源为A。而我对这个设计的意见是,他把两个不同的PV揉合在了一起,而且会因为对老数据的不处理而导致以后提数据的误差。我的建议是,原来的B的记录功能保留不变,增加一个A到B的记录功能,也就是在A页面的每一个到B的a中添加一个onclick事件,以此来记录A到B的次数。这样子一来方便以后统计;二来,因为B本身也不仅仅是一个页面而且是一个子系统的入口,如果以后该子系统独立了之后,对于这些PV的改动将不再会影响到一个单独的系统;三来我们不需要通知C,D有这样子的改变,如果以后C,D也有此类需求,重构也只是一个简单的事情。

     2、很多是一个推搪的理由吗?

     这个也是在系统开发中遇到的,还是上面的几个页面。因为产品的几次改版,A、C、D的变动比较大,于是A访问B的URL中少了一个约定的参数MissParam(暂定这个)。于是我在处理这种请求的时候将MissParam统一的改为了null(其实这个处理是因为之前很多有用户邮件中到B的链接都少了这个参数)。今天在系统修改的过程中有一个同事过来跟我说,你这个参数(MissParam)不对,我都没有传给你,你怎么多出了一个null出来(原来URL:B.aspx?tttt=xxxxx,处理后的B.aspx?tttt=xxxxx&MissParam=null)。我当时就说,这个是因为你传的时候没有带这个参数,我统一规整成了null。他又说,你这样子不对呀,你改一下。。。。这类的。然后我就说,这B的访问约定一直都是有的,而且A以前有带MissParam参数,现在没有了,很显然是之前的修改搞丢了,要不你改一下吧。他说了一句,我这边很多,怎么改?我无言。很多真的是个理由吗?

      3、站立会议真的有需要

      不知道为什么,现在开发的时间特别多,每一次一开会就2-3个小时,有时候一开就是一天,开完这个开那个。特别是需求评审,一开起码是一个上午。其实最主要是3个原因。一是会前准备不足,每次开会都说开就开,搞到发起会议的本身对会议内容也没有充分的认识,参见会议的到开发都不知道开什么会,更别提是准备会议了,完全秒杀了墙上的不开无准备的会议的宣传画。二是会上扯蛋的时间比较多,因为项目组中总有一部分人是比较空闲的,所有每次开会这部分人就成了活跃分子(这部分人其实是不确定的),会议中总会有20%左右的时间浪费在这无尽的扯蛋过程中。三是会议室有凳子。于是我想起敏捷里面的站立会议,其实这个真的很必要,记得上次迁移服务器,涉及到那么多的接口,4个部门,我们在会议室中站了半个小时就把迁移的顺序和测试的重点都列出来了,究其原因是因为每一个人都有准备,都知道要做什么,还有就是每个人都站着,没有时间也没有精力扯蛋,开篇直入主题,讨论完,走人,发会议纪要。

      4、了解问题的根源很重要

      在测试服务器上突然之间出现了很多WebHttpException-The-remote-host-closed-the-connection-The-error-code-is-0x80072746。异常信息如下:

System.Web.HttpException: The remote host closed the connection. The error code is 0x80072746.
   at System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.FlushCore(Byte[] status, Byte[] header, Int32 keepConnected, Int32 totalBodySize, Int32 numBodyFragments, IntPtr[] bodyFragments, Int32[] bodyFragmentLengths, Int32 doneWithSession, Int32 finalStatus, Boolean& async)
   at System.Web.Hosting.ISAPIWorkerRequest.FlushCachedResponse(Boolean isFinal)
   at System.Web.Hosting.ISAPIWorkerRequest.FlushResponse(Boolean finalFlush)
   at System.Web.HttpResponse.Flush(Boolean finalFlush)
   at System.Web.HttpResponse.Flush()

。。。。

      于是同事就说,你看每一个异常都指向了HttpResponse.Flush(),这个函数,而且我看过你写的代码,有调用函数Response.Flush(),所以肯定是因为你这里的代码

       Response.Write(some add script tag text,eg:<script href=”ssss” type=”text/javascript”></script>);

       Response.Write(some add script tag text);

       Response.Write(some add script tag text);

       Response.Flush();

       还没有完全输出完全,客户端的js就开始执行了导致的。

       其实如果是一般情况下,我肯定是不予理睬的,可是当时他是当着测试面这样子说的。我于是幽幽的回了一句,这是服务器的异常,而且我输出的是tag,不是js函数。

       很多时候我们很容易根据一点点的线索就直接断定问题就在这里。但是问题真的有这么简单吗?

(PS:我还没有找到问题的根源,有知道的同学告知一声)

       5、自信很重要

       今天比较郁闷,陪同事debug了2个小时。原因是同事的项目调用我写的接口一直不成功,而我本身自己的项目调用没有任何问题。搞了两个小时,终于崩溃了,发现问题好像不像想象的那么简单,于是问同事拿了份代码,在自己的机器上调试,这个时候,神奇的事情发生了,所有的浏览器都可以调用成功,包括同事不可以的IE8.额的神呀,于是把同事叫过来,演示了一下,他承认了他人品有问题。有时候人还真的需要点自信。如果一开始就有信心,叫同事装个FF或者chorme,是不是就可以绕开这个rpIE8了。

posted @ 2011-05-24 23:14 Leon Mai 阅读(857) 评论(1) 编辑

2011年5月14日 #

      其实没有人问过我为什么不写注释,我也没有向别人说过我不写注释的原因。但是最近一直有人在我耳边说,你们这些鸟人为什么都不写注释了。所以我觉得我有必要做一下解释了。

      第一、什么情况下需要注释。如果你面对的受众是一些初学者或者非专业的人员,那么确实需要写注释,这一点在教科书上体现的最多。又或者,你所工作的语言是结构化编程之类的没有很强的层次性(包或者命名空间)和封装(类),那么你需要写注释(C是最好的例子)。最后,如果你写的是算法,或者你的函数中有魔数之类的东西,你需要加注释,比如如果你有一个函数如下,那么你最好写一些注释

public string GetRequestFile(){
    
if(String.IsNullOrEmpty(Request.QueryString["fileName"]))
    
return magicFileName;//你可能需要说明为什么会返回这样一个文件名
     normal procedure....
}

      第二、为什么我不写注释。首先我面对的是专业的人员,大家都是做软件的,没有可能看不懂。其次,现在项目的语言是C#,面向对象的,具有很好的封装性,一个类的代码行数不会很多(因为职责单一)。最后函数和类是自说明的是比较简小的,理解起来也没有什么困难(我写的函数一般不超过10行,如果异常处理多一点也就20行,函数名和类名也符合规范,类一般不超过150行)。

      第三、为什么会要求注释。1、程序写的很不好,函数和类名没有自说明(或者由于语言导致的,比如C)。2、代码阅读人员对业务不熟悉(建议先熟悉业务,因为业务是根本,技术只是实现而已)。3、代码阅读人员能力有限或者自身的经历导致了需要由注释看起。

      而要求我写注释的人属于第三的3。他本身是由PHP转过来的,而且其代码风格是纯粹的面向过程的,写的程序很多注释,但是也很长,经常一个页面下来也就1两个函数搞定,300行是家常便饭。因此他阅读程序养成了一个很不好的习惯的就是总是要全部把程序看完,才可以理清楚这个类是做什么的(类名和函数名对他来说都是浮云,GetRequestFile和GetResponeFile对他应该没有什么区别)。而很多时候我们看代码,第一个就是看类名,其次就是看被调用的函数的名称(公共方法),一般情况下,已经足够判断这个类是做什么的,还有提供的什么功能(如果不行,你可以跟类的作者说,重构一下吧,哥看得苦)。这里就要求我们写代码的时候要像写诗一样去写,就算不行,起码也要做到代码的自解释。因此如果你也是一个拒绝写注释的人,那么你写的代码满足第一和第二吗?

      最后被要求注释的类大概是这样的。

 

class UserAuth{
    public bool UserLoginAsClient(){
          ......
    }
    
public bool UserLoginAsManager(){
          ......
    }
    another private function
}

 

posted @ 2011-05-14 08:21 Leon Mai 阅读(9018) 评论(192) 编辑

2011年3月5日 #

摘要: 最近和同事讨论一个数据库字符串存储html的问题。现在的系统中存储的方式是: <div> <a>fasdfasdfasdf,</a> …… <div> 同事的建议是把它写成一下格式: <div><a>fasdfasdfasdf,</a>……<div> 至于原因是这样可以节省很多存储空间。 我当时就直接说,第一这个表现在数据量不大(行数少),预期以后数据量也不会大。所以就是把格式写成那样子也不会节省多少存储空间,假设最后能节省一个G,加上备份空间,现行方式最多节省,100几十G的空间;而且现在这种方式阅读全文
posted @ 2011-03-05 12:33 Leon Mai 阅读(960) 评论(0) 编辑

2011年1月6日 #

摘要: 其实我用过的,那一天晚上,看着摇摇欲坠的衣架,还有上次换床时留下的两根木头,突发奇想,用菜刀把木头给锯了,然后把衣架给修好了,用了两个小时。(我的菜刀上有一道锯齿状的东西) 其实很多时候我们都是在用不对的工具做对的事情,最后是搞到很辛苦,很不爽。试问,你有没有用剪刀拧过螺丝?用起子敲过钉子?是不是很辛苦。 小时侯觉得这种事情做起来很有成就感,因为确实,用了跟别人不同的方法去做成别人想去做的事情。但是现在你还在用这些方法吗? 作为一个程序员,我们用的最多的工具,应该是编程语言和方法论了(先不算IDE)。而说起方法论,我想说一下设计模式。院子里也有很多人在写设计模式的文章,也有很多人在用设计模式来阅读全文
posted @ 2011-01-06 21:26 Leon Mai 阅读(273) 评论(4) 编辑

摘要: 前段时间做了一个统计系统,但是现在发现统计数据和业务系统耦合度太高,以至于系统在做业务扩展的时候需要顾忌的东西太多。 其实我接触过的很多系统都是这样,那为什么大多数系统都会这样子了?是因为系统刚开始的时候架构设计有问题了?还是我们没有能力去设计一个ETL统计系统了?其实都不是这样子的。真正的问题是系统在演变过程中没有按照既有的数据库设计规则而导致了现在的问题。下面我来模拟一下一个简单系统演变过程。 1、 系统刚开始的时候 由于系统刚开始,也不一定能够得到很多的业务量,投资也不是很大,于是我们按照不要过度设计的原则,只有以下这么几个表。 现在系统可以运行的很好,完全没有问题。 2、 业务第一次阅读全文
posted @ 2011-01-06 21:12 Leon Mai 阅读(1667) 评论(20) 编辑

2010年12月1日 #

摘要: 前今天女友跟我q上说,又要帮客户部署系统,但是客户还是要她在服务器上装IIS,郁闷当中我说了一句,"叫他玩蛋去",更郁闷的是被那个客户看见了...  其实我以前也是做过现场实施的,有些客户的计算机水平确实是可以,我曾经遇到过一些连QQ远程都不会用的信息中心主任.于是悲剧一个接一个,系统部署了一次又一次.由体验,到试用,到正式,到系统改进.一次实施下来起码要部署10次8次系统.但是到你走的时候客户还...阅读全文
posted @ 2010-12-01 03:56 Leon Mai 阅读(2017) 评论(13) 编辑

2010年11月23日 #

摘要: 每一个应用程序到了一定阶段由于这个或者那个原因总是需要进行优化的。其中最主要的原因应该是:数据量的增加。但是我们应该怎么样去优化一个程序了,我们优化的方法又是否正确了。这让我想起了一个故事。  一个操作系统的编写人员把系统中的一个基本函数(调用率为50%)的效率优化了一倍。但是系统性能却没有得到应有的提升。原因在于他优化的函数式nop指令,也就是在系统空闲的时候调用的函数。  这让我想起了前一段时...阅读全文
posted @ 2010-11-23 22:46 Leon Mai 阅读(2186) 评论(6) 编辑