<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_hrmai</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/37501/rss</id><updated>2011-06-15T14:39:12Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/37501/rss"/><entry><id>http://www.cnblogs.com/hrmai/archive/2011/06/15/2082182.html</id><title type="text">这坨屎真不该吃！</title><summary type="text">一个士兵前来报告说：报告前面有一坨屎。长官说：你去把它吃了。 这个故事我从两个人口中听说过。一个是我以前的总监，他在给我们项目组开动员会的时候说过。另外一个是从我经理口中听过，说我只是提出问题，而没有给出解决方案。 对于第一场景，当时我们总监的意思是我们项目组需要自己把问题解决了，而不是把问题抛给别人。我觉得这个是对的。 对于第二个场景，现在已经不会再有了。因为我现在根本就不会提问题了。 为什么...</summary><published>2011-06-15T14:39:00Z</published><updated>2011-06-15T14:39:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/06/15/2082182.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/06/15/2082182.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一个士兵前来报告说：报告前面有一坨屎。长官说：你去把它吃了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个故事我从两个人口中听说过。一个是我以前的总监，他在给我们项目组开动员会的时候说过。另外一个是从我经理口中听过，说我只是提出问题，而没有给出解决方案。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于第一场景，当时我们总监的意思是我们项目组需要自己把问题解决了，而不是把问题抛给别人。我觉得这个是对的。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于第二个场景，现在已经不会再有了。因为我现在根本就不会提问题了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为什么同一句话从不同的人口中说出来会有不同的后果了？原因很简单，有人没有把这句话的意思理解透。其实这句话的意思是说，自己的事情要自己做，不要往上推或者往外推。而这句话对于第二个场景来说有一个很大的问题，就是，我提出问题的时候，我本身是不负责这个功能模块的设计工作的，我本身只是作为一个评审委员（当然，某人不是这样子想的吧）。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 再往深一层想。如果你作为一个管理者你能够容忍一个经常“找茬”的下属不？如果不可以，你又会不会用这句话来教育你的下属了？如果你用了，你的下属会不会因为提意见而不得善终而选择明哲保身了？像现在这样子，明明看到了问题，也不会提出来。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实对于第二种场景，就是经济学上的典型的劣币驱逐良币。不好的把好的打败了。错误的把正确打败了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 作为一个管理者，要容纳各种各样的意见和建议，海纳百川。而作为一个下属，应该把握好提建议的方式，这方面我确实需要加强。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/2082182.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/06/15/2082182.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/06/14/2081030.html</id><title type="text">流程图OO杀手？</title><summary type="text">其实想写这篇文章很久了，但是一直都没有动手，今天不一下缺。 首先介绍一下背景：项目由两种语言来完成java和.net（非面向对象语言的可以掠过下文）。 今天再次听到两位同事（老员工）说老大要他们在设计文档中画流程图，而且要把整个系统的流程图画出来。心中一楞，看来流程图还真是个害人的东西。 首先从我自己负责的模块来说吧。我的工作是接别人的工作的，算是维护和改写吧。刚接手的时候不是很明白为什么一个方...</summary><published>2011-06-14T14:43:00Z</published><updated>2011-06-14T14:43:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/06/14/2081030.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/06/14/2081030.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实想写这篇文章很久了，但是一直都没有动手，今天不一下缺。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先介绍一下背景：项目由两种语言来完成java和.net（非面向对象语言的可以掠过下文）。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 今天再次听到两位同事（老员工）说老大要他们在设计文档中画流程图，而且要把整个系统的流程图画出来。心中一楞，看来流程图还真是个害人的东西。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先从我自己负责的模块来说吧。我的工作是接别人的工作的，算是维护和改写吧。刚接手的时候不是很明白为什么一个方法会是600+行（一个类也就2-3个方法），想很久也没有想明白，于是在熟悉了流程之后，把流程图画出来，然后把大的方法分解成了小的方法。但是还是一个很大的类。再后来，日子比较清闲也看了一下重构方面的书，于是实验了一下，把大类们都分解成了各个职责明确的小类，（主要用到的方法是提取基类，提取公共方法等方法），于是将几个600+行的大类分解成了10个100-200行的类（当然还有部分方法放到了公共类库中，大约100行代码量吧）。在完成重构后，业务流程发生了一个很大的改变，需要将我负责的模块的业务逻辑进行很大的改动。本来以为这次的改动会让我很难受，孰料我竟然用了3个10行的左右的函数和一个if语句解决了这次更改（当然动手之前想了差不多半天），剩下的工作量都是和界面的搏斗。这是我第一次真切的感受到面向对象的力量。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其次是从我负责的整个系统的重构工作中看到的情况。以前的系统是由2个同事写的(其中一个以前是php的），但是我看到的代码都是一些500+行的大函数，很多时候我看到的是一个300+行的page_load函数。很多的代码是重复的，就算是在page_load函数里面也有重复的，也是可以提取共用代码的。我一直都想不通。直到后来，可能是看到了某个靓妹，突然脑充血想到自己以前负责鉴权重构的时候的过程，一切都明白了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当时的过程是，我老大要求我将整个过程画出来，画得很细，大约有60-80个框的流程图，拧起来就是2～3斤的葡萄了。然后因为这个流程图是在详细设计的时候画的，所以我在写程序的过程中也就大致按照这个流程把整个鉴权过程写到了一个类中，最后我也写了一个600+行的类（唯一的安慰是，没有写一个600+行的函数）。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于是我得出了一个结论：在OO为主要编程语言的详细设计说明书中不应该出现流程图，取而代之的是时序图（其他的可能没有那么好）。（或者我们对在每一个流程中标志这个流程属于那一个类，好像有点扯蛋哦。。。）当然，你有可能会说在详细设计的时候就是应该这样子做的，如果你们公司的流程是这样的，我想请你写下具体的流程，因为我确实没有经历过这种公司。至于另外一种可能会说，一个类600+行，或者一个功能600+行的代码，是你们在做功能拆分的时候做的不够细，这一点我是承认的，但是功能怎么样分细，用对象的职责还是别的什么方法，也请赐教。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 至于我为什么会有这样的结论了？主要是因为如果你可以画出一个时序图，你总得将一些职责分细，所以总的来说对于一个类承担的职责总会比以前的少了。而且，当你画时序图的时候，你应该会想一下类的构成。所以我们的类的职责就明确了一些，我们的类也就小了，腰也不酸，腿也不痛了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但是，是不是流程图就一无是处了？我觉得倒不是，因为对于需求分析和概要设计这些需要对用户或者非技术人员解释的文档，流程图还是很简单明确的，特别是在做需求设计的时候。我们在这里遇到的问题只是因为我们把流程图直接细化copy到了详细设计之中。（可能你是纯化论者，说用例（user case）也很容易跟客户沟通，但是我确实见过不懂用例图，但是流程图还画得很好的客户）&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 又或者，这是不是七宗罪中的懒惰。。。。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 欢迎交流意见。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/2081030.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/06/14/2081030.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/05/25/2057381.html</id><title type="text">一个突破点，向上，向上</title><summary type="text">这两年，互联网上多了很多宠儿，但是大多数都是只做好一件事的新贵。quora、dropbox、微博（非国内的）、groupon等都是。它们都是在大公司的夹缝中找到一个突破点，然后像热带雨林中的小树那样，不停的向上，向上。而国内很多的软件公司都在寻找这样的一个突破点，包括我现在所在的公司也在找这样的一个突破点。但是我发现一个很有趣的现象是，我们的突破点都是在先寻找商业模式，而不是先寻找用户模式。这个...</summary><published>2011-05-25T13:36:00Z</published><updated>2011-05-25T13:36:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/05/25/2057381.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/05/25/2057381.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这两年，互联网上多了很多宠儿，但是大多数都是只做好一件事的新贵。quora、dropbox、微博（非国内的）、groupon等都是。它们都是在大公司的夹缝中找到一个突破点，然后像热带雨林中的小树那样，不停的向上，向上。而国内很多的软件公司都在寻找这样的一个突破点，包括我现在所在的公司也在找这样的一个突破点。但是我发现一个很有趣的现象是，我们的突破点都是在先寻找商业模式，而不是先寻找用户模式。这个是本末倒置还是我太过天真？也就是说我们做的都是被人做过的，被别人证明是赚钱的事情。但是好像又鲜有人赚钱了。是现金流决定了这一切还是眼界，还是别的什么东西。同学们有什么高见，欢迎留言。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;暂放首页，以供讨论，管理员觉得不妥，请撤掉。&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/2057381.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/05/25/2057381.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/05/24/2056086.html</id><title type="text">杂谈</title><summary type="text">1、改造还是新建？ 系统本来有A，B，C,D四个页面，其中B是详细页，其他的都是一些概要的页面，大约如下： A，C,D的模式，HTML大约如下 &lt;ul&gt; &lt;li&gt;&lt;a href=”B”&gt;&lt;img src=”image”/&gt;&lt;/a&gt;&lt;/li&gt; …… &lt;/ul&gt; 而B就是A，C，D链接过去之后的详细页。而且，B本身是可以通过URL直接访问，不一定受限于前面3个页面 最近产品需要增加一个PV功能，主要...</summary><published>2011-05-24T15:14:00Z</published><updated>2011-05-24T15:14:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/05/24/2056086.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/05/24/2056086.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp; 1、改造还是新建？ &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 系统本来有A，B，C,D四个页面，其中B是详细页，其他的都是一些概要的页面，大约如下： &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201105/201105242314234831.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hrmai/201105/201105242314242256.png" width="244" height="98"&gt;&lt;/a&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A，C,D的模式，HTML大约如下 &lt;p&gt;&amp;lt;ul&amp;gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;li&amp;gt;&amp;lt;a href=”B”&amp;gt;&amp;lt;img src=”image”/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt; &lt;p&gt;…… &lt;p&gt;&amp;lt;/ul&amp;gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 而B就是A，C，D链接过去之后的详细页。而且，B本身是可以通过URL直接访问，不一定受限于前面3个页面 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最近产品需要增加一个PV功能，主要的功能是记录从A中过来的访问B页面的次数。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 负责实现的同事决定利用系统本身具有的B页面的记录功能（记录访问B的PV)，直接改造原有的记录功能。将A到B的URL中加一个参数以此标记来源为A。而我对这个设计的意见是，他把两个不同的PV揉合在了一起，而且会因为对老数据的不处理而导致以后提数据的误差。我的建议是，原来的B的记录功能保留不变，增加一个A到B的记录功能，也就是在A页面的每一个到B的a中添加一个onclick事件，以此来记录A到B的次数。这样子一来方便以后统计；二来，因为B本身也不仅仅是一个页面而且是一个子系统的入口，如果以后该子系统独立了之后，对于这些PV的改动将不再会影响到一个单独的系统；三来我们不需要通知C，D有这样子的改变，如果以后C，D也有此类需求，重构也只是一个简单的事情。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、很多是一个推搪的理由吗？ &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个也是在系统开发中遇到的，还是上面的几个页面。因为产品的几次改版，A、C、D的变动比较大，于是A访问B的URL中少了一个约定的参数MissParam（暂定这个）。于是我在处理这种请求的时候将MissParam统一的改为了null（其实这个处理是因为之前很多有用户邮件中到B的链接都少了这个参数）。今天在系统修改的过程中有一个同事过来跟我说，你这个参数（MissParam）不对，我都没有传给你，你怎么多出了一个null出来（原来URL：B.aspx?tttt=xxxxx，处理后的B.aspx?tttt=xxxxx&amp;amp;MissParam=null)。我当时就说，这个是因为你传的时候没有带这个参数，我统一规整成了null。他又说，你这样子不对呀，你改一下。。。。这类的。然后我就说，这B的访问约定一直都是有的，而且A以前有带MissParam参数，现在没有了，很显然是之前的修改搞丢了，要不你改一下吧。他说了一句，我这边很多，怎么改？我无言。很多真的是个理由吗？ &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、站立会议真的有需要 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不知道为什么，现在开发的时间特别多，每一次一开会就2-3个小时，有时候一开就是一天，开完这个开那个。特别是需求评审，一开起码是一个上午。其实最主要是3个原因。一是会前准备不足，每次开会都说开就开，搞到发起会议的本身对会议内容也没有充分的认识，参见会议的到开发都不知道开什么会，更别提是准备会议了，完全秒杀了墙上的不开无准备的会议的宣传画。二是会上扯蛋的时间比较多，因为项目组中总有一部分人是比较空闲的，所有每次开会这部分人就成了活跃分子（这部分人其实是不确定的），会议中总会有20%左右的时间浪费在这无尽的扯蛋过程中。三是会议室有凳子。于是我想起敏捷里面的站立会议，其实这个真的很必要，记得上次迁移服务器，涉及到那么多的接口，4个部门，我们在会议室中站了半个小时就把迁移的顺序和测试的重点都列出来了，究其原因是因为每一个人都有准备，都知道要做什么，还有就是每个人都站着，没有时间也没有精力扯蛋，开篇直入主题，讨论完，走人，发会议纪要。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4、了解问题的根源很重要 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在测试服务器上突然之间出现了很多WebHttpException-The-remote-host-closed-the-connection-The-error-code-is-0x80072746。异常信息如下： &lt;p&gt;System.Web.HttpException: The remote host closed the connection. The error code is 0x80072746.&lt;br&gt;&amp;nbsp;&amp;nbsp; 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&amp;amp; async)&lt;br&gt;&amp;nbsp;&amp;nbsp; at System.Web.Hosting.ISAPIWorkerRequest.FlushCachedResponse(Boolean isFinal)&lt;br&gt;&amp;nbsp;&amp;nbsp; at System.Web.Hosting.ISAPIWorkerRequest.FlushResponse(Boolean finalFlush)&lt;br&gt;&amp;nbsp;&amp;nbsp; at System.Web.HttpResponse.Flush(Boolean finalFlush)&lt;br&gt;&amp;nbsp;&amp;nbsp; at System.Web.HttpResponse.Flush() &lt;p&gt;。。。。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于是同事就说，你看每一个异常都指向了HttpResponse.Flush()，这个函数，而且我看过你写的代码，有调用函数Response.Flush()，所以肯定是因为你这里的代码 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write(some add script tag text，eg：&amp;lt;script href=”ssss” type=”text/javascript”&amp;gt;&amp;lt;/script&amp;gt;); &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write(some add script tag text); &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write(some add script tag text); &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Flush(); &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 还没有完全输出完全，客户端的js就开始执行了导致的。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实如果是一般情况下，我肯定是不予理睬的，可是当时他是当着测试面这样子说的。我于是幽幽的回了一句，这是服务器的异常，而且我输出的是tag，不是js函数。 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 很多时候我们很容易根据一点点的线索就直接断定问题就在这里。但是问题真的有这么简单吗？ &lt;p&gt;&lt;strong&gt; （PS：我还没有找到问题的根源，有知道的同学告知一声）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5、自信很重要 &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 今天比较郁闷，陪同事debug了2个小时。原因是同事的项目调用我写的接口一直不成功，而我本身自己的项目调用没有任何问题。搞了两个小时，终于崩溃了，发现问题好像不像想象的那么简单，于是问同事拿了份代码，在自己的机器上调试，这个时候，神奇的事情发生了，所有的浏览器都可以调用成功，包括同事不可以的IE8.额的神呀，于是把同事叫过来，演示了一下，他承认了他人品有问题。有时候人还真的需要点自信。如果一开始就有信心，叫同事装个FF或者chorme，是不是就可以绕开这个rpIE8了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/2056086.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/05/24/2056086.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/05/14/2046043.html</id><title type="text">我为什么拒绝写注释</title><summary type="text">其实没有人问过我为什么不写注释，我也没有向别人说过我不写注释的原因。但是最近一直有人在我耳边说，你们这些鸟人为什么都不写注释了。所以我觉得我有必要做一下解释了。 第一、什么情况下需要注释。如果你面对的受众是一些初学者或者非专业的人员，那么确实需要写注释，这一点在教科书上体现的最多。又或者，你所工作的语言是结构化编程之类的没有很强的层次性（包或者命名空间）和封装（类），那么你需要写注释(C是最好的例子）。最后，如果你写的是算法，或者你的函数中有魔数之类的东西，你需要加注释，比如如果你有一个函数如下，那么你最好写一些注释publicstringGetRequestFile(){if(String.</summary><published>2011-05-14T00:21:00Z</published><updated>2011-05-14T00:21:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/05/14/2046043.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/05/14/2046043.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实没有人问过我为什么不写注释，我也没有向别人说过我不写注释的原因。但是最近一直有人在我耳边说，你们这些鸟人为什么都不写注释了。所以我觉得我有必要做一下解释了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第一、什么情况下需要注释。如果你面对的受众是一些初学者或者非专业的人员，那么确实需要写注释，这一点在教科书上体现的最多。又或者，你所工作的语言是结构化编程之类的没有很强的层次性（包或者命名空间）和封装（类），那么你需要写注释(C是最好的例子）。最后，如果你写的是算法，或者你的函数中有魔数之类的东西，你需要加注释，比如如果你有一个函数如下，那么你最好写一些注释&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;GetRequestFile(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;(String.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;fileName&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;]))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;magicFileName;&lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;你可能需要说明为什么会返回这样一个文件名&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;normal&amp;nbsp;procedure....&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第二、为什么我不写注释。首先我面对的是专业的人员，大家都是做软件的，没有可能看不懂。其次，现在项目的语言是C#，面向对象的，具有很好的封装性，一个类的代码行数不会很多（因为职责单一）。最后函数和类是自说明的是比较简小的，理解起来也没有什么困难（我写的函数一般不超过10行，如果异常处理多一点也就20行，函数名和类名也符合规范，类一般不超过150行）。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第三、为什么会要求注释。1、程序写的很不好，函数和类名没有自说明（或者由于语言导致的，比如C）。2、代码阅读人员对业务不熟悉（建议先熟悉业务，因为业务是根本，技术只是实现而已）。3、代码阅读人员能力有限或者自身的经历导致了需要由注释看起。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;而要求我写注释的人属于第三的3。他本身是由PHP转过来的，而且其代码风格是纯粹的面向过程的，写的程序很多注释，但是也很长，经常一个页面下来也就1两个函数搞定，300行是家常便饭。因此他阅读程序养成了一个很不好的习惯的就是总是要全部把程序看完，才可以理清楚这个类是做什么的（类名和函数名对他来说都是浮云，GetRequestFile和GetResponeFile对他应该没有什么区别）。而很多时候我们看代码，第一个就是看类名，其次就是看被调用的函数的名称（公共方法），一般情况下，已经足够判断这个类是做什么的，还有提供的什么功能（如果不行，你可以跟类的作者说，重构一下吧，哥看得苦）。这里就要求我们写代码的时候要像写诗一样去写&lt;img alt="" src="http://www.cnblogs.com/Emoticons/QQ/14.gif" /&gt;，就算不行，起码也要做到代码的自解释。因此如果你也是一个拒绝写注释的人，那么你写的代码满足第一和第二吗？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后被要求注释的类大概是这样的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;UserAuth{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff"&gt;public&amp;nbsp;bool &lt;/span&gt;UserLoginAsClient(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;font color="#0000ff"&gt;bool &lt;/font&gt;UserLoginAsManager(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; another private function&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/2046043.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/05/14/2046043.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/03/05/1971512.html</id><title type="text">与时俱进</title><summary type="text">最近和同事讨论一个数据库字符串存储html的问题。现在的系统中存储的方式是： &lt;div&gt; &lt;a&gt;fasdfasdfasdf,&lt;/a&gt; …… &lt;div&gt; 同事的建议是把它写成一下格式： &lt;div&gt;&lt;a&gt;fasdfasdfasdf,&lt;/a&gt;……&lt;div&gt; 至于原因是这样可以节省很多存储空间。 我当时就直接说，第一这个表现在数据量不大（行数少），预期以后数据量也不会大。所以就是把格式写成那样子也不会节省多少存储空间，假设最后能节省一个G，加上备份空间，现行方式最多节省，100几十G的空间；而且现在这种方式</summary><published>2011-03-05T04:33:00Z</published><updated>2011-03-05T04:33:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/03/05/1971512.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/03/05/1971512.html"/><content type="html">&lt;p&gt;最近和同事讨论一个数据库字符串存储html的问题。现在的系统中存储的方式是：&lt;/p&gt; &lt;p&gt;&amp;lt;div&amp;gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;a&amp;gt;fasdfasdfasdf,&amp;lt;/a&amp;gt;&lt;/p&gt; &lt;p&gt;&amp;#8230;&amp;#8230;&lt;/p&gt; &lt;p&gt;&amp;lt;div&amp;gt;&lt;/p&gt; &lt;p&gt;同事的建议是把它写成一下格式：&lt;/p&gt; &lt;p&gt;&amp;lt;div&amp;gt;&amp;lt;a&amp;gt;fasdfasdfasdf,&amp;lt;/a&amp;gt;&amp;#8230;&amp;#8230;&amp;lt;div&amp;gt;&lt;/p&gt; &lt;p&gt;至于原因是这样可以节省很多存储空间。&lt;/p&gt; &lt;p&gt;我当时就直接说，第一这个表现在数据量不大（行数少），预期以后数据量也不会大。所以就是把格式写成那样子也不会节省多少存储空间，假设最后能节省一个G，加上备份空间，现行方式最多节省，100几十G的空间；而且现在这种方式很方便debug，你一看就知道这个html节有没有那些地方是少了东西的，标签没关闭之类的。&lt;/p&gt; &lt;p&gt;其实我还遇到过很多有这种想法的事情。比如，在系统写入数据库慢的情况下，有人会提出先写文件，再回写到数据库；又比如，程序写在一起会跑的快一点。&lt;/p&gt; &lt;p&gt;先看第一个。我个人从来不建议写文件，因为，很多人包括我自己，都没办法达到这种水平。为什么了？因为如果用文件代替数据库那么你需要解决的问题有：1、文件的独占问题（程序一定要独占文件）2、文件并发写问题（没有并发写，我想这个肯定很悲剧）3、事物突然中断问题。等等。那么怎么解决系统写入数据库慢的问题了？批量提交。可以使用的方式有消息队列、本地存储（memcache）、nosql数据库作为中间库等。&lt;/p&gt; &lt;p&gt;后面那一个我就不说了。&lt;/p&gt; &lt;p&gt;但是纵观上面的说法是不是曾经都是对的了？是的，但是现在已经不对了，所以我们很多时候需要跟上时代，与时俱进。可以不懂具体的技术，但是总要知道具体的技术。&lt;/p&gt; &lt;img src="http://www.cnblogs.com/hrmai/aggbug/1971512.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/03/05/1971512.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/01/06/1929170.html</id><title type="text">你用过菜刀锯木头吗？</title><summary type="text">其实我用过的，那一天晚上，看着摇摇欲坠的衣架，还有上次换床时留下的两根木头，突发奇想，用菜刀把木头给锯了，然后把衣架给修好了，用了两个小时。（我的菜刀上有一道锯齿状的东西） 其实很多时候我们都是在用不对的工具做对的事情，最后是搞到很辛苦，很不爽。试问，你有没有用剪刀拧过螺丝？用起子敲过钉子？是不是很辛苦。 小时侯觉得这种事情做起来很有成就感，因为确实，用了跟别人不同的方法去做成别人想去做的事情。但是现在你还在用这些方法吗？ 作为一个程序员，我们用的最多的工具，应该是编程语言和方法论了（先不算IDE）。而说起方法论，我想说一下设计模式。院子里也有很多人在写设计模式的文章，也有很多人在用设计模式来</summary><published>2011-01-06T13:26:00Z</published><updated>2011-01-06T13:26:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929170.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929170.html"/><content type="html">&lt;p&gt;其实我用过的，那一天晚上，看着摇摇欲坠的衣架，还有上次换床时留下的两根木头，突发奇想，用菜刀把木头给锯了，然后把衣架给修好了，用了两个小时。（我的菜刀上有一道锯齿状的东西） &lt;p&gt;其实很多时候我们都是在用不对的工具做对的事情，最后是搞到很辛苦，很不爽。试问，你有没有用剪刀拧过螺丝？用起子敲过钉子？是不是很辛苦。 &lt;p&gt;小时侯觉得这种事情做起来很有成就感，因为确实，用了跟别人不同的方法去做成别人想去做的事情。但是现在你还在用这些方法吗？ &lt;p&gt;作为一个程序员，我们用的最多的工具，应该是编程语言和方法论了（先不算IDE）。而说起方法论，我想说一下设计模式。院子里也有很多人在写设计模式的文章，也有很多人在用设计模式来完成工作，也包括我。但是一般情况下我不用设计模式，我宁愿让类看起来自然易懂一点。为什么了？因为，很多时候我们用设计模式的时候我们是分不清楚各种各样的设计模式所代表的工具类型的。比如，单例，他主要的作用是要来维持实例的状态的全局性；facase，主要是封装系统内部的实现，像windows的HAL层，让每一个做驱动开发的，直接使用函数就可以了；适配器，主要是为了让两孔的插头可以插进三孔的插孔。 &lt;p&gt;其实这些设计模式他们本身被提取出来的时候所肩负的职责你懂吗？如果不懂，会发生什么事情了？曾经有人说过，单例可以节省内存，首先不说任何问题，如果你真的要节省内存，那么，我建议将所有的函数和属性静态化，我想这是最节省内存的方法了。 &lt;p&gt;说起起子，其实我们可以看到各种各样的起子，但是如果就按适合的类型，来分类，那么大概可以分成，十字和一字，还有就是起子头的大小。于是就有一些很有设计模式头脑的人用了一个模板模式来把起子重构了一把，最后结果就是，一个起子柄可以安装多个标准的起子头，如图： &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062126063772.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062126065134.jpg" width="154" height="189"&gt;&lt;/a&gt; &lt;p&gt;于是有人发挥想象的空间：为什么不把一个锤子附加在起子的柄上了，这样就可以两用了，一头是起子，一头是锤子（有点像单例既省内存又维护状态）。这个可以有吗？这个真的不可以有。为什么了，因为如果加了一个锤子，你会发现你用起子的时候，手柄不好用，用锤子的时候，你会发现柄太小，震的手疼。 &lt;p&gt;这里就引申到了我个人觉得软件里面最重要的一个东西，职责，responsibility。为什么说这个东西重要，是因为，无论是生活中的工具还是软件开发中的设计模式与类，如果承担的职责过多且职责之间没有想象之处，那么这个东西是有问题的。就好象带锤子的起子，它是起子还是锤子了？一个类之所以不应该承担太多的职责，就是因为会变成带起子的锤子。而一个函数不应该有太多的职责，是因为你把起子铸在类锤子里面，仍希望既能当锤子用又能当起子用。类应该是一个多头的起子，他可以承担多个相同的职责，方法应该是起子中的一个头，命名空间应该是一个工具箱，既有锤子又有起子，可能还有能当菜刀用的锯子（这是扯淡的，当我没说）。 &lt;p&gt;最后，如果你不知道下面的代码有什么问题，那么还是不要用设计模式了，这个时候是手柄是菜刀的起子了。 &lt;p&gt;public class Test &lt;p&gt;{ &lt;p&gt;private Test() &lt;p&gt;{ &lt;p&gt;} &lt;p&gt;private static Test instanse; &lt;p&gt;private static List&amp;lt;int&amp;gt; status = new List&amp;lt;int&amp;gt;(); &lt;p&gt;public Test Instance &lt;p&gt;{ &lt;p&gt;get &lt;p&gt;{ &lt;p&gt;status.Clear(); &lt;p&gt;return instanse; &lt;p&gt;} &lt;p&gt;} &lt;p&gt;}     &lt;img src="http://www.cnblogs.com/hrmai/aggbug/1929170.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929170.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2011/01/06/1929156.html</id><title type="text">ETL，你的系统可以吗？</title><summary type="text">前段时间做了一个统计系统，但是现在发现统计数据和业务系统耦合度太高，以至于系统在做业务扩展的时候需要顾忌的东西太多。 其实我接触过的很多系统都是这样，那为什么大多数系统都会这样子了？是因为系统刚开始的时候架构设计有问题了？还是我们没有能力去设计一个ETL统计系统了？其实都不是这样子的。真正的问题是系统在演变过程中没有按照既有的数据库设计规则而导致了现在的问题。下面我来模拟一下一个简单系统演变过程。 1、 系统刚开始的时候 由于系统刚开始，也不一定能够得到很多的业务量，投资也不是很大，于是我们按照不要过度设计的原则，只有以下这么几个表。 现在系统可以运行的很好，完全没有问题。 2、 业务第一次</summary><published>2011-01-06T13:12:00Z</published><updated>2011-01-06T13:12:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929156.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929156.html"/><content type="html">&lt;p&gt;前段时间做了一个统计系统，但是现在发现统计数据和业务系统耦合度太高，以至于系统在做业务扩展的时候需要顾忌的东西太多。 &lt;p&gt;其实我接触过的很多系统都是这样，那为什么大多数系统都会这样子了？是因为系统刚开始的时候架构设计有问题了？还是我们没有能力去设计一个ETL统计系统了？其实都不是这样子的。真正的问题是系统在演变过程中没有按照既有的数据库设计规则而导致了现在的问题。下面我来模拟一下一个简单系统演变过程。 &lt;p&gt;1、 系统刚开始的时候 &lt;p&gt;由于系统刚开始，也不一定能够得到很多的业务量，投资也不是很大，于是我们按照不要过度设计的原则，只有以下这么几个表。 &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112221234.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112225105.gif" width="480" height="134"&gt;&lt;/a&gt; &lt;p&gt;现在系统可以运行的很好，完全没有问题。 &lt;p&gt;2、 业务第一次扩展 &lt;p&gt;随着业务的进一步发展，系统进行了第一的扩展，主要是要求系统可以对一次订购可以进行分状态提交，也就是说订购是多个状态的，比如：下单、确认、支付。其实就是类似于淘宝的一个购买过程。于是我们进行了第一次系统扩展过程。 &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/20110106211223612.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112238071.gif" width="480" height="148"&gt;&lt;/a&gt; &lt;p&gt;我们在Order表中加入了一个记录订单状态的Status状态，然后用户每一次提交改变订单状态的时候我们都将status置位为对应的状态。 &lt;p&gt;至今，我们的系统还可以运行下去，一切还好。 &lt;p&gt;3、 业务第二次扩展 &lt;p&gt;业务进一步发展，我们的系统得到了进一步的发展，现在我们需要回馈新老客户，我们将系统中的业务打包起来形成一个套餐包，然后给予一定的优惠。类似于移动的套餐，比如动感地带的音乐套餐等。现在我们给Produce表加了一个字段，如下图： &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112231941.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112241036.gif" width="480" height="150"&gt;&lt;/a&gt; &lt;p&gt;PDetail中存储了这个产品中包含的子产品ID。这个时候系统还可以继续运行。而且除了套餐包麻烦一点之外，其他所有的都还好。 &lt;p&gt;4、 统计系统 &lt;p&gt;现在管理层需要报表，而且，由于系统数据的膨胀，我们不可能只用简单的操纵原始数据来获得系统需要的统计数据。我们开始设置一个ETL的统计系统。 &lt;p&gt;我们先从最简单的要求开始，提供指定日期的营业额，周报，日报等。 &lt;p&gt;这个时候我们会发现，按照3的系统来说，如果要用ETL来提取这个数据，我们是没办法做得到的（假设，订购状态的改变时长可以无限），除非我们每天都对Order表进行一个全表的扫描，然后和抽取出来的数据进行一个对比。可是，我们现在已经是一个很大的数据量，我们的系统可能已经不可以在每天晚上的空闲时间完成这个数据抽取工作。 &lt;p&gt;可是，我们在整个系统改造过程中都没有发现问题呀。难道这可以怪我们吗？ &lt;p&gt;（有人可能会说我们其实可以在客户购买的过程中将统计数据插入统计中。这里有以下的问题，第一，如果系统有多个购买渠道，或者增加多个订购渠道，那么你将会遇到我在开篇的时候说的情况；第二，如果有多个统计要求，那么插入统计表的过程就会很有问题。） &lt;p&gt;5、 解决之道 &lt;p&gt;其实这里的解决之道比较复杂。为什么了，因为系统已经积聚了很多历史数据，所以，如果从长久来看，我们应该调整系统的结构，然后解决遗留数据。我们将会看到以下的数据结构： &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112246859.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112257349.gif" width="580" height="357"&gt;&lt;/a&gt; &lt;p&gt;我们这样做的原因是因为我们满足第三范式，而且，我们会使统计数据的ETL来的非常简单。比如，我们只要每天在一个固定的时间将当天的数据抽取到统计表中，那么我们就可以解决ETL中的全表扫描问题了。 &lt;p&gt;那么历史数据怎么办了？其实历史数据历来都是一个问题，但是我觉得，其实我们可以将历史数据简化成一个两部提交的购买过程，下单，支付；下单，否决支付。 &lt;p&gt;6、 3中的设计存在的问题 &lt;p&gt;其实这个设计没什么问题，真的没有。但是在一种情况下会有一个很大的问题。假设我们的系统就是一个移动的业务系统，那么这个设计就会有很大的问题，为什么了？因为产品代表的是业务，是一种长期订购的业务。这种设计在系统扣费的时候不会有任何问题，但是这种设计在系统控制用户状态的时候会有问题。比如：我订购的是音乐套餐，19元，130条短信,如果短信超出了就要扣钱。如果我每一次发短信，系统都需要关联Produce表一次，那么我想这个系统的效率就会有很大的问题。我个人觉得应该将系统调节成以下的结构： &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112253936.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://images.cnblogs.com/cnblogs_com/hrmai/201101/201101062112262790.gif" width="580" height="324"&gt;&lt;/a&gt; &lt;p&gt;（CustomerProduce表只记录没有子节点的产品） &lt;p&gt;这样子我们每次控制客户的业务状态的时候我们就可以得到很好的效率。 &lt;p&gt;其实我们从这次模拟中会看到，很多系统我们参与的时候会发现很烂，然后就骂开始时的设计人员，程序员，骂之前的人，殊不知，其实我们很多时候就是在做着被自己骂的人。一个系统之所以由一个好的系统变成一个不好的系统，是由于在每一次变更中慢慢的变的不那么的规范，变的不愿意去更改之前的业务逻辑，于是我们的系统慢慢的变得由一个具有很高的可扩展性的系统，变成了一个可以满足业务且仅满足业务的系统。 &lt;p&gt;今天你是不是也在做着同样的事情了？  &lt;img src="http://www.cnblogs.com/hrmai/aggbug/1929156.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2011/01/06/1929156.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2010/12/01/1892598.html</id><title type="text">玩蛋的客户</title><summary type="text">前今天女友跟我q上说,又要帮客户部署系统,但是客户还是要她在服务器上装IIS,郁闷当中我说了一句,"叫他玩蛋去",更郁闷的是被那个客户看见了...其实我以前也是做过现场实施的,有些客户的计算机水平确实是可以,我曾经遇到过一些连QQ远程都不会用的信息中心主任.于是悲剧一个接一个,系统部署了一次又一次.由体验,到试用,到正式,到系统改进.一次实施下来起码要部署10次8次系统.但是到你走的时候客户还...</summary><published>2010-11-30T19:56:00Z</published><updated>2010-11-30T19:56:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2010/12/01/1892598.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2010/12/01/1892598.html"/><content type="html">&lt;p&gt;前今天女友跟我q上说,又要帮客户部署系统,但是客户还是要她在服务器上装IIS,郁闷当中我说了一句,"叫他玩蛋去",更郁闷的是被那个客户看见了...&lt;/p&gt;&lt;p&gt;其实我以前也是做过现场实施的,有些客户的计算机水平确实是可以,我曾经遇到过一些连QQ远程都不会用的信息中心主任.于是悲剧一个接一个,系统部署了一次又一次.由体验,到试用,到正式,到系统改进.一次实施下来起码要部署10次8次系统.但是到你走的时候客户还是不会部署自己的系统.&lt;/p&gt;&lt;p&gt;其实这种情况我们可以采取以下方法来解决:&lt;/p&gt;&lt;p&gt;1.给客户部署文档.这个部署文档要由一开始第一次部署之前就要给到客户手上.因为这样客户在第一次部署的时候对系统的部署就有了一个直观的了解了.&lt;/p&gt;&lt;p&gt;2.每一次部署都要有客户在场.做到这一点,一般的客户在部署3次之后基本上就可以自己动手部署一套系统了.前提是你不要一脚踢,要适当的给客户锻炼的机会.&lt;/p&gt;&lt;p&gt;3.如果可以最好提供部署视频.&lt;/p&gt;&lt;p&gt;4.最后一次部署最好由客户自己实施.这里有一点需要注意的是,客户所做的一定要适度的在客户领导面前加以赞许.&lt;/p&gt;&lt;p&gt;可能有人说写文档的时候我都可以部署好了,但是其实这样做的好处有两个:&lt;/p&gt;&lt;p&gt;1.减轻了自己的负担,其实写一个部署文档也就那么3-5个小时,绝对会比每一次都自己部署一次要来得容易的多.&lt;/p&gt;&lt;p&gt;2.增加了客户的系统认同感.因为客户在这个系统上付出了心血,自然也就减少了,客户对系统的那种事不关己的心态,毕竟每一个人都是希望把事情做好的.这对之后的实施会有很大的帮助.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/1892598.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2010/12/01/1892598.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hrmai/archive/2010/11/23/1885970.html</id><title type="text">优化程序的一点建议</title><summary type="text">每一个应用程序到了一定阶段由于这个或者那个原因总是需要进行优化的。其中最主要的原因应该是：数据量的增加。但是我们应该怎么样去优化一个程序了，我们优化的方法又是否正确了。这让我想起了一个故事。一个操作系统的编写人员把系统中的一个基本函数（调用率为50%）的效率优化了一倍。但是系统性能却没有得到应有的提升。原因在于他优化的函数式nop指令，也就是在系统空闲的时候调用的函数。这让我想起了前一段时...</summary><published>2010-11-23T14:46:00Z</published><updated>2010-11-23T14:46:00Z</updated><author><name>Leon Mai</name><uri>http://www.cnblogs.com/hrmai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hrmai/archive/2010/11/23/1885970.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hrmai/archive/2010/11/23/1885970.html"/><content type="html">&lt;p&gt;每一个应用程序到了一定阶段由于这个或者那个原因总是需要进行优化的。其中最主要的原因应该是：数据量的增加。但是我们应该怎么样去优化一个程序了，我们优化的方法又是否正确了。这让我想起了一个故事。&lt;/p&gt;&lt;p&gt;一个操作系统的编写人员把系统中的一个基本函数（调用率为50%）的效率优化了一倍。但是系统性能却没有得到应有的提升。原因在于他优化的函数式nop指令，也就是在系统空闲的时候调用的函数。&lt;/p&gt;&lt;p&gt;这让我想起了前一段时间我们系统所做的优化。由于系统发送邮件的数量越来越多，所有邮件堆积的数量和延时也越来越大。这个时候我们使用了基本的优化方法，多线程去发送邮件（多个线程同时连接邮件服务器）。在测试线上的得到的性能提升是非常的大的，但是到了生产线，去经常有连接超时，导致了一些奇怪的问题。最后我们经过和研究和咨询发现，原来邮件服务器在生产线上一个ip只允许同时5个连接，多了就拒绝。于是我们的努力也就白费了。&lt;/p&gt;&lt;p&gt;其实从上面的两个例子我们可以看到优化程序其实并没有我们想象的那么简单，为什么了？因为很多时候我们面对的并不是技术上的问题，而是业务上的一些变更，而这些变更又往往是我们所不熟悉的。那么我们应该怎么样优化程序了，我觉得以下几点可以参考。&lt;/p&gt;&lt;p&gt;一、优化之前先弄清楚性能的损耗情况，和可以优化的情况。一般情况下，我们遇到的都是比较乐观的情况，也就是性能损耗最大的地方就是可以优化的地方。但是，且慢，这个&amp;#8220;地方&amp;#8221;是一个可大可小的词。为什么了？因为如果宏观一点来看你会说我们在进行什么操作的时候会导致性能降低，但是如果微观一点来看你会说插入数据的时候会产生大量的block，数据库IO过大，导致操作时间过长。这个时候你该怎么样去优化了？&lt;/p&gt;&lt;p&gt;二、选择适度的优化粒度。接着上面的问题，我们可以看到，如果从微观来看，我们选择的优化方法可能是对数据库进行必要的改进，比如，多点commit。但是如果从宏观的角度来看，我们选择的就可能使批量提交。这两种方式各有各的适用地方。我再举一个例子。&lt;/p&gt;&lt;p&gt;我们的项目有一个地方需要向用户推送客户提供的html文件（包括图片，css，js等）但是由于业务原因，我们必须屏蔽掉所有文件的外链和处理所有文件的相对路径引用。这个功能很慢，慢的要死。当时有人提出的方法是改进正则表达式，以提高匹配速度。我提出的是缓存处理结果，所有html文件之处理一次，处理后的数据放到磁盘上，以后再读的时候就不需要再进行处理了。如果你是经理你会选择哪一个方案了？&lt;/p&gt;&lt;p&gt;三、选择适当的优化方法。其实优化的方法有很多种，但是不同的方法得到的效果往往是相差很大的。所以在确定适当的方法之前我建议大家还是先做一个简单的demo，来验证这个方法的有效性。比如图片大小的压缩，很多人是直接使用缩放的形式来实现的，但是缩放会导致一个很严重的问题，就是图片在放大的时候会变得很不清晰。其实有另外两种方法来实现大小的压缩，一个是直接改变图片的质量，另外一个是对图片进行hsl处理。后面两个其实连demo都不用自己写，网上有现成的。&lt;/p&gt;&lt;p&gt;四、跳出技术的角度来思考。其实这个是我们很多人的通病（包括我自己）。我们很多时候会钻牛角尖，会为一个问题的一个方向浪费很长很长的时间。比如我们在优化邮件投递的时候就有这样的一个情况，一个存储过程奇慢，30秒才查询出结果（1000条记录）。于是我们就去想各种各样的方法去优化，加索引，强制走索引（这个我其实是不赞成的，因为生产库由于环境和dba的维护问题，你不一定可以肯定你的索引名称一定有对应的索引），多处理器处理等等。但是效果都不好。这个时候你会怎么想？我后来提出的方案是，一次取10000条数据，就算是取数据时间增加为1分钟（这其实不大可能的，因为其实关系型数据库取数据的条数对速度影响不大），那么这个取数据的速度也比我们本身投递邮件的速度要快了。（是不是很简单？）&lt;/p&gt;&lt;p&gt;五、优化的前景。其实这个是很多人都会忽略的。最简单的就是系统统计的优化，因为系统统计一般是管理人员用的最多，他们跟我们的关系也是最近的，所以我们一般也会直接选择优化查询的性能。但是，不知道你们有没有想到这样子的一个问题。这些查询他们一个月可能才用一次，充其量，一个星期两次。但是比起优化前台页面，比起优化用户体验来说优化统计的性价比是极其低的。因为很多情况下它不会给你增加一分一毫的收益，但是前台则不同。所以我们现在的产品后台很烂，以致于运营经常说这不是给人用的，但是我们的经理也只是笑而不语。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hrmai/aggbug/1885970.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hrmai/archive/2010/11/23/1885970.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
