项目启动

Posted by & filed under Uncategorized.

项目启动会议,标志一个项目的正式开始。那在这之前,我们通常做哪些准备工作? 其实可以用一句话概括:项目经理必须知道项目的关键驱动因素是什么、项目怎样才算“完成”,而且要把这些结论写到项目章程中,让项目团队都能了如指掌。 明白上面这句话,其实不难。首先,我们来看看什么是项目。PMBOK里的定义是为创造独特的产品、服务或成果而进行的临时性工作。这个定义强调了项目的独特性和有明确的完成时间。来看一个更详细的定义,一个独特的任务或是系统化的流程,其目的是创建新的产品或服务,产品或服务交付完成标志着项目的结束。项目都有风险,并且受制于有限的资源。这个定义除了项目独特性和明确的完成时间,还突出了项目完成的标志及项目的风险。 通过项目的定义,我们知道项目有风险。资源冲突,质量漏洞百出,技术目标难以达成等等一些列风险,这些都需要项目经理来管理。项目经理要搞清楚每个项目独特性的真正含义,明确项目的风险,搞清楚项目实现的目标。那项目经理该如何定义呢?负责向团队清晰说明完成的含义,并带领团队完成项目的人。很显然,项目完成就是项目经理的责任。那如何定义完成呢?那我们就要说到项目的关键驱动因素。只有明确了项目的关键驱动因素,我们才能准确定义项目的完成。 “铁三角”想必大家都听说过。就是成本、时间、质量或范围。我们不能让客户简单的选择其看重的两个边,来交付他想要的东西。这种方式过于理想化。那如何确定关键驱动因素呢? 首先,需要通过与客户交流,得到客户的期望。从客户的角度来了解项目的驱动因素。比如说客户想要什么(功能集合),他们期望何时收到交付物(发布时间),可交付物的质量如何(缺陷等级)。接下来,写下项目的约束。环境是什么样子?能否灵活安排团队位置?必须遵循什么流程?预算多少? 这些约束是可以改变的(一般只有出问题时才改变)。我们拿到期望列表和项目的约束列表后,可以对这些指标进行优先级排序。如下矩阵所示。 找出最重要的一个作为项目的关键驱动因素。然后,我们再选择几个项目的约束条件。一般两到三个。话虽这么说,我们获得了项目的驱动因素,我如何给每个驱动因素打分?如何确定哪个分值最高,重要度最高呢? Read more […]

[转]编写自文档化的代码

Posted by & filed under Uncategorized.

文所以载道也。  —— 宋·周敦颐《通书·文辞》 对于我们程序员来说,我们的工作也是写作——几乎每天都要写代码;而且还要载“道”,不仅仅要满足客户的需求,还要让代码具有高度的可读性,这样其他的程序员可以更容易地对代码进行修改和扩展。 按这样的要求,我们需要为代码编写足够的文档,也就是将代码“文档化”。常见的做法有两种,外部文档和注释。 外部文档 外部文档指的是在代码文件之外编写的附加文档,比如在Word文档中采用大量的篇幅(如UML图、表格)来设计或记录相关的包、类型、类型成员、成员参数之类的信息。这看起来很规范,但如果你用过这种方式,一定会讨厌它。这种方式的主要问题在于: 1)增加很多额外的工作:编写代码本身的压力已经很大,在压力之下,我们往往选择做那些最必需的事情,就是实现功能,如果时间紧急,编写文档就可能是草草了事了。 2)文档需要与代码保持同步:即使你在开始认真编写了文档,后来代码有了修改和扩展(这是不可避免的,即使采用所谓的冻结需求),那么文档就需要更新,否则就会提供误导信息。 3)大量的文档难以管理:如果代码量较大,那么本身就需要大量的文档;同时文档也需要进行版本管理,那么就产生了不同版本的文档;另外这些文档基本上是一些简单的文本。如此一来,要在这些文档中找到所需的信息,难上加难。 文档具有这些问题,一个重要的原因是,它们离代码太“远”了。我们可以将它们搬到代码文件里面,这就是第二种做法:注释。 注释 程序员对文档往往比较抵触,对注释的态度就温和多了,甚至相当一部分人支持编写大量的注释。的确,如果在IDE中看到分布合理的绿色代码块(注释文本的常见颜色),人们会感觉比较舒服,如果满屏幕全是代码,心里不免会犯怵。 从语法的角度来看,注释就是编译器将忽略不计的源代码块。所以,在这里你想写什么就写什么。 从语义的角度来看,注释是昏暗泥泞的小路和明亮通畅的大道之间的区别。注释是对其所处位置的代码的解释,它可以强调某些特定问题、描述某个复杂算法、对代码进行合理分隔、协助进行维护的程序员(这个人有可能是你自己)。由此可把注释看作是代码的一种“内部文档”。 那是不是就需要大量的注释呢?至少我们曾经被这样教导过,但事实并非如此。不知道你的习惯怎样,我在阅读代码的时候,看到注释一般会先看注释,我在假定这些注释对代码提供了附加的价值。但我发现,注释往往很随意,甚至有可能误导别人。你可以说,这是注释编写者的问题,注释是无辜的,但必须承认的是,注释比代码更容易说谎。究其原因,注释虽然离代码很近,但仍然是一种文档,它具有与外部文档类似的问题: 1)增加很多额外的工作 2)需要与代码保持同步 3)大量的注释可能会妨碍代码的阅读:注释在那里,人们不能置之不理,如果注释太多就成阻碍了。《重构》一书认为注释过多是一种“坏味道”。 看来,注释也有不少问题,它们离代码仍有距离。能否将“文档”与代码的距离再拉近一点?那该怎么做? 先来考虑我们为什么要添加注释。这往往是因为代码本身不容易让人看懂,也就是说代码的意图和表现有距离,所以才需要使用注释。如果能够做到让代码本身就体现出意图,是不是就不需要注释了?这种方式就是本文的主题:代码的自文档化。(需要注意的是,自文档化能够取代大多数的注释,但并不能100%取代) 什么是代码的自文档化(Self Read more […]

[转]如何提升工作中的影响力

Posted by & filed under Uncategorized.

    今天,我们的主题是如何提高自身在工作中的影响力,我想用三句话来概括我对这个话题的一些思考。   知己知彼 Self Awareness & Interpersonal Awareness        进入到第一个话题“知己知彼”之前,我先分享一段担任Visual InterDev开发主管期间的经历。当时我们团队来了一位刚被提拔的开发经理,我和另几位开发主管直接向他汇报,自然我们都会与他有定期的1对1会议,沟通各自的工作进度。几乎每次当我陈述完一个问题,他都会迫不及待地提出他的解决方案。我当时的反应就是“我到这儿来不是因为我没有自己的解决方案,而是来告诉你我正在做些什么事情。”在我看来,这两者是完全不一样的。        在这之后很长的一段时间,他还是一直习惯性地建议我如何如何处理问题。通过平日的观察,我也发现他更喜欢花时间对技术和产品进行深度探讨,而非团队管理。于是几个月后,我找了一个机会跟他说,“我觉得你做软件架构师说不定会更有意思。”而他自己也觉得这个建议不错。几个星期后,他真的转去做架构师的工作,我们团队也迎来了一个新的开发经理。        我觉得这就是一个有关影响力的典型例子。毫无疑问,我不能决定我的老板到底是做开发经理还是架构师。我只是觉得他比较适合,并让他对自己的优势也有了一个全新的认识。与此同时,我也让其他的主管意识到他对架构师的工作更有热情。整个过程中在一定程度上体现了下属的一种影响力。        任何一位微软的高管,在做每一个重要决定前都会去听取相关人员的反馈和建议,以确保自己考虑了问题的方方面面。如果我们希望将自己的信息传达给这些决策者,当然需要找到那些他/她会听取意见的关键人物,通过他们来延伸我们的影响力。因此,当我们要向另一个人或另一个团队提出一个方案以完成某项工作,就要仔细考虑以下几个问题: 1) Read more […]

Javascript加载执行问题

Posted by & filed under Uncategorized.

首先大家看看如下的代码: 一: 原始情况

  估计90%的程序员都会把js文件放在head中,但是大家有没有深究过呢?很多浏览器都会使用单一的线程来做“界面UI的更新”和“JS脚本的处理“, 也就是当执行引擎遇到”<script>“的时候,此时页面的下载和渲染都必须等待<script>执行完毕。那么对用户而言就悲哀了,看着锁住的页面, 此时用户很可能就会给你关掉。   从上面的瀑布图中我们可以看出二点: 第一: 三个js文件并行下载,但是按我上面的理论中js应该是一个接一个的执行。然而在IE8,Firefox3.5和Chrome2都实现了js的并行下载, 这是相当不错的,但是他还是会阻碍一些其他资源的下载,比如说图片。 第二: 图片1.jpg的下载是在js执行完成后触发的,这也验证了上面所说的情况,阻止了image的加载。   二:第一步优化 既然js阻止了UI渲染,那么我们可以考虑将js放在</body>前,这样就可以让<script>前的html完美的呈现,不会让用户看到页面空白等待 而苦恼的情况,自然就提高了友好性。

  下面的图也展示了1.jpg和三个js几乎并行下载和执行。时间由上面的“469ms+”缩小到“326ms”。   三:第二步优化 看上面的“瀑布图”,估计大家也看出来了,三个js文件进行了三次“Get”请求,大家都知道Get请求是需要带http头的, 所以说需要耗费时间,那么我们采取的方案自然就是减少Get请求。通常有两种方案。 第一:合并js文件,比如将上面的“hello.js”和“world.js“合并掉。 第二:利用第三方工具,比如php中的Minify。 关于第二种做法,taobao用的还是比较多的,看一下其中的一个script,应用了三个js文件。由3个Get请求变为了1个。   四:第三步优化 不管是把js文件放在脚尾,还是三个合并一个,其本质都是”阻塞模式“,就是说锁死浏览器,当web页面越来越复杂,js文件越来越多,还是 让我们头疼的,此时我们就提倡一种“无阻塞模式“加载js脚本,也就是页面全部呈现完再追加js,也就对应着window.onload事件触发后,我们才 追加js,这就是所谓的“无阻塞“,但是其中有一个非常要注意的地方就是我们对js的要求是否有严格的顺序。 第一:无顺序要求,比如我对”hello.js“和”world.js”没有顺序要求,那么我们完全可以用jquery来动态追加实现。

    从图中可以看出,”hello.js”和“world.js”出现在蓝色线以后,也就说明这两个js是在DomContentLoad结束后再进行触发加载的,这样就不会造成页面的锁定 等待。   第二:有顺序要求 为什么一定要有顺序要求这个概念呢?对于上面的那个动态追加的“两个js”文件,在IE系列中,你不能保证hello.js一定会在world.js前执行, 他只会按照服务器端返回的顺序执行代码。

      大家也能看到,页面完全Load的时间其实也就310ms左右,大大提高了网页的下载呈现和友好型。   同样也可以看看腾讯网,他也是这么干的。     Read more […]

[转]减少.NET应用程序内存占用的一则实践

Posted by & filed under Uncategorized.

最近一周比较忙,主要的工作内容是在做一个叫“键盘精灵”的东西,简单来讲就是将很多数据放到内存中,对这些数据进行快速检索,然后找出根据输入条件最匹配的10条记录并予以展示。具体和下面两款炒股软件的相关功能类似: 数据以文本形式存在文件中,且数据量较大,有近20万条,每一条记录有几个字段,以分隔符分割。当时使用的是6万条记录的测试数据,文本文件将近10M,这个模块加载到内存并建立缓存之后,大概会占用将近70-80M的内存。自我接手以后,主要的任务就是降低内存消耗和提高匹配效率。 一、避免创建不必要的对象   拿到代码后,第一步就是看设计文档,然后断点一步一步的看代码,大概明白了逻辑之后,发现思路有一些问题。之前的代码处理流程思路大概是下面这样的: 将文件读取到内存,实例化 根据条件对文件进行检索,并存储到结果集1中 对结果集1中的结果进行匹配度计算,并存储到结果集中2 按对结果集2进行匹配度排序,取最匹配的10条记录,然后返回 这个过程中规中矩。但是其中有很多问题,最大的问题是,临时变量存储了太多的中间处理结果,而这些对象在一次查询完成后又马上丢弃,大量的临时对象带来了很大的GC压力。举例来说,当用户在输入框中输入1的时候,假设使用Contains来匹配,那么从6万条记录中找出包含1的记录可能有4万多条,然后需要把这4万多条记录存储在临时变量中进行处理,进一步计算这4万条记录的匹配度,然后存储到一个类似KeyValuePair的集合中,key为匹配度,然后对这个集合按Key进行排序,然后取前10条最优记录。可以看到,中间创建了大量的临时变量,使得内存剧增,大量临时对象创建之后马上会被回收,GC压力山大。 而在设计文档中,只要求返回最最匹配的10条记录,之前的解决方案中似乎并没有注意到这一点。所以接手后,第一步就是对上面的处理过程进行精简。精简后如下: 将文件读取到内存,实例化 根据条件对文件进行检索,如果存在,则: 计算匹配度。 以匹配度为Key,存储到只有11个容量的SortList中。 如果SortList集合添加记录后大于10个,则移除最后面一个元素,始终保持着前10个最小(匹配度最优)的记录。 遍历完成之后,返回这个集合对象 经过这一修改,减少了大量临时数据对内存的占用,整个过程中,我只是使用一个容量为11的SortList结构存储中间的过程,每一次插入一个元素,SortList帮我们排好序,然后移除最不匹配的那一个,也就是最后一个元素(从小到大排序,越匹配,值越小)。这里面的消耗主要是SortList的插入,内部排序和移除记录。 Read more […]

[转]任务分配及管理

Posted by & filed under Uncategorized.

前面说到过,刚开始带小组,接到一个任务,我就估算了我大概要多少时间,然后小组多少个人就算是多少个我,估算时间=我要的总时间”小组人数(好笨的想法呀,不用时间跟组员交待任务的吗?个个组员都是我吗,比我强的还好,顶多做完了休息,差一点的就麻烦了),结果实际时间多了很多,而且小组里有的人做完了无事可做,有的人则忙得焦头烂额,容易打击组员的积极性,造成组员之间的不满。 随着经验的积累,要想把任务分配得比较合适,首先要对自己的组员有一定的了解,最好能量化,其次要把握好任务(这就看需求分析及系统设计的功力了),以下是我的一点经验,我把我的组员分类(简称ABC分类),主要划分的指标有技术能力,做事速度,业务理解能力。 主要看前两个指标,因为我在做需求分析的时候已经把业务弄熟了,分配任务的时候我会尽量从程序员的角度跟他们描述业务逻辑,以下是我跟组员讨论业务的一点心得: 1,业务上的一些概念名词要注意讲清楚,不要一带而过;特别是跟程序名词相近的。 2,讲流程,尽量多画图,对着流程图讲解方便易懂,把来龙去脉讲清楚。 3,多讲讲为什么这样做(思想),反过来可以验证自己是否真的理解了业务了。 4,对于组员提出来的疑问,要能明确回答(验证业务、设计是经得起别人考验) 组员划分等级(每项满分10分),如图:   能力等级 技术能力 做事速度 A+ 非常好(8-9) 慢(5) A 好(7) 快(6) B 一般(6) 快(6) C 一般(6) 一般(6) 工作任务,主要从两个指标进行划分难度(技术,业务上),工作量,如图:   任务类型 技术难度 工作量 X 大 小 Y 大 大 Z 小 大 Z- 小 小 分配任务,任务类型对号入座到相应能力等级的组员中去(红色能力等级优先分配,依次往右递减):   任务类型 能力等级 X A+   Read more […]

web开发-flush让页面分块,逐步呈现

Posted by & filed under Uncategorized.

在处理比较耗时的请求的时候,我们总希望先让用户先看到部分内容,让用户知道系统正在进行处理,而不是无响应。一般大家在处理这种情况,都使用ajax,先把html输出到客户端,然后再用ajax取加载比较耗时的资源。用ajax麻烦的地方是增加了请求数,而且需要写额外的js代码、和js调用的请求接口。 正对这种情况,还有一种处理方法,就是让response分块编码进行传输。response分块编码,可以先传输一部分不需要处理的html代码到客户端,等其他耗时代码执行完毕后再传输另外的html代码。   分块编码(chunked encoding) chunked encoding 是http1.1 才支持编码格式(当然目前没有哪个浏览器不支持1.1了),chunked Read more […]

[转]程序员究竟该如何提高效率

Posted by & filed under Uncategorized.

“拖延症”这个名词近些年很火,似乎每个人都觉得自己的效率不高,很难集中注意力做好手头的事,那我们究竟该如何提高自己的工作效率呢,大牛来告诉你. Aaron Swartz写过一篇很有名的文章,叫做”HOWTO: Be more productive”,这篇文章写的实在是太好了,我看了好多遍,很赞同作者的观点。我借鉴了作者提到的一些方法并运用到自己的生活中,发现确实有效果,所以我愿意让更多的人看到这篇文章。Aaron Swartz这个人绝对是大牛人,他14时就参与了RSS1.0的制定,他在Stanford读了一年就主动退学了,成为了YC的一员,他的公司后来与reddit合并了,他还是web.py框架的创始人。 废话少说,下面就是译文: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 肯定有人跟你说过这样的话“你有看电视的那么长时间,都可以用来写一本书了”,不可否认写书肯定比看电视更好的利用了时间,但是这个结论的成立需要一个假设:”时间是可互换的”,也就是说看电视的时间可以轻松的用来写书。但是很遗憾,事实并非如此。 不同的时间有不同的质量等级。如果我在走向地铁站的路上发现自己的笔记本忘带了,我就很难集中注意力写文章。同样,当你不停的被打断的时候,你也很难集中注意力。这里还有一些心理和情感上的因素,有的时候我心情很好,愿意主动去做一些事,但还有一些时候我感到很抑郁和疲惫,就只能看看电视了。 如果你想变的更加有效率,你必须意识到这个事实,并且很好的处理它。首先,你必须很好的利用不同种类的时间。其次,你必须让你的时间更有效率。 更有效的利用你的时间 选择合适的问题 生命是如此的短暂,为什么浪费时间做一些没意义的事呢?做一些让你感到舒适的事很容易,但是你应该问问自己为什么要做这些事呢?有没有一些更重要的事等着你去做?为什么你不去做那些事呢?这些问题很难回答,但是每解决一个都会让你更有效率。 这不是说你所有的时间都应该用来做那些最重要的事。我的时间就肯定不是这样(否则,我现在就不会在写这篇文章了)。但是,这是我衡量自己的生活是否充实的重要标准。 收集很多问题 另一个很多人都知道的秘密是:如果你认准一个问题,投入全部精力去解决它,这样你的效率是最高的。我发现这却是很难实现的。以现在为例,我正在锻炼身体,喝橙汁,整理桌面,和我弟弟聊天,同时在写现在这篇文章。今天一整天,我写了现在这篇文章,读了一本书,吃了点东西,回复了几封邮件,和一些朋友聊了聊天,买了点东西,改了改其他几篇文章,备份了硬盘,还整理了一下图书列表。 有很多不同的项目让我能够在不同质量的时间下做不同的工作。更重要的是,在你卡壳或是厌烦的时候有其他的一些事可以做。 这同时会让你变得更加有创造力。创造力就是你把自己从其他地方学到的东西能够用到你的工作中。如果你同时做许多不同方向的工作,那你就会得到更多的想法和创意。 列一个清单 找一些不同的事同时做并不困难,大部分人都有很多很多的待办事项。但是如果你想把它们全记在脑袋里的话,它们就会慢慢消失。要记住所有这些事所给你带来的心智上的压力会把你压垮。解决办法仍然是很简单:把它们写下来。 一旦你把要做的事列成了一个清单,你就可以更好的分类组织它们了。比如说,我的清单包括:编程,思考,差事,读书,娱乐休息。 大部分项目都包括很多不同的任务。以写这篇文章为例,除了真正的写作过程,还包括了阅读其他关于拖沓的文章,考虑文章的各个部分,整理语句,向别人请教问题等等。每一项任务都属于清单的不同部分,所以你可以在合适的时间才去做某一部分。 把任务清单和你的生活结合起来 一旦你有了这样一个任务清单,你需要做的事就是时常记得它,而记住它的最好方法是把它放在你能看到的地方。比如说,我总在我桌子上放一摞书,最上面的那一本就是我最近在读的。当我想要读书的时候,我就直接从上面拿一本书来读。 对于看电视/电影我也这么做。当我对某一个电影感兴趣的时候,我会把它放在电脑中一个特殊的文件夹内。每当我想休息一下,看看电影的时候,我就会打开那个文件夹。 我也想过一些更深入的方式,比如说我把一些想看的文章标记为”待读”(to Read more […]

浅谈JavaScript核心(2)

Posted by & filed under Uncategorized.

变量对象(Variable Object) 变量对象(Variable Object)是一个抽象的概念,不同的上下文中,它表示使用不同的object。例如,在global全局上下文中,变量对象也是全局对象自身[global object]。(这就是我们可以通过全局对象的属性来指向全局变量)。 让我们看看下面例子中的全局执行上下文情况:

全局上下文中的变量对象(VO)会有如下属性: 图 7. 全局变量对象 如上所示,函数“baz”如果作为函数表达式则不被不被包含于变量对象。这就是在函数外部尝试访问产生引用错误(ReferenceError) 的原因。请注意,ECMAScript和其他语言相比(比如C/C++),仅有函数能够创建新的作用域。在函数内部定义的变量与内部函数,在外部非直接可见并且不污染全局对象。使用 Read more […]

浅谈JavaScript核心(1)

Posted by & filed under Uncategorized.

对象(Object) ECMAScript是一门高度抽象的面向对象(object-oriented)语言,用以处理Objects对象. 当然,也有基本类型,但是必要时,也需要转换成object对象来用。 让我们来举一个基本Object的例子,首先我们要清楚,一个Object的prototype是一个内部的[[prototype]]属性的引用。 不过一般来说,我们会使用__<内部属性名>__ 下划线来代替双括号,例如__proto__(这是某些脚本引擎比如SpiderMonkey的对于原型概念的具体实现,尽管并非标准)。

  上述代码foo对象有两个显式的属性[explicit own properties]和一个自带隐式的 __proto__ 属性[implicit __proto__ property],指向foo的原型。 图 1. 一个含有原型的基本对象 为什么需要原型呢,让我们考虑 Read more […]