﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava--文章分类-程序员之路</title><link>http://www.blogjava.net/dodoma/category/9060.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 17:55:44 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 17:55:44 GMT</pubDate><ttl>60</ttl><item><title>面向对象的思维方法 </title><link>http://www.blogjava.net/dodoma/articles/37776.html</link><dc:creator>dodoma</dc:creator><author>dodoma</author><pubDate>Tue, 28 Mar 2006 05:16:00 GMT</pubDate><guid>http://www.blogjava.net/dodoma/articles/37776.html</guid><wfw:comment>http://www.blogjava.net/dodoma/comments/37776.html</wfw:comment><comments>http://www.blogjava.net/dodoma/articles/37776.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dodoma/comments/commentRss/37776.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dodoma/services/trackbacks/37776.html</trackback:ping><description><![CDATA[
		<span class="javascript" id="text76284">作者：范凯<br />E-mail: robbin_fan@yahoo.com.cn<br /><br />我是从学习Java编程开始接触OOP(面向对象编程)，刚开始使用Java编写程序的时候感觉很别扭，因为我早以习惯用C来编写程序，很欣赏C的简洁性和高效性，喜欢C简练而表达能力丰富的风格，特别忍受不了Java运行起来慢吞吞的速度，相对冗长的代码，而且一个很简单的事情，要写好多类，一个类调用一个类，心里的抵触情绪很强。<br /><br />我对Java的面向对象的特性琢磨良久，自认为有所领悟，也开始有意识的运用OOP风格来写程序，然而还是经常会觉得不知道应该怎样提炼类，面对一个具体的问题的时候，会觉得脑子里千头万绪的，不知道怎么下手，一不小心，又会回到原来的思路上去。<br /><br />举个例子，要发广告邮件，广告邮件列表存在数据库里面。倘若用C来写的话，一般会这样思考，先把邮件内容读入，然后连接数据库，循环取邮件地址，调用本机的qmail的sendmail命令发送。<br /><br />然后考虑用Java来实现，既然是OOP，就不能什么代码都塞到main过程里面，于是就设计了三个类：<br /><br />一个类是负责读取数据库，取邮件地址，调用qmail的sendmail命令发送；<br />一个类是读邮件内容，MIME编码成HTML格式的，再加上邮件头；<br />一个主类负责从命令读参数，处理命令行参数，调用发email的类。<br /><br />把一件工作按照功能划分为3个模块分别处理，每个类完成一件模块任务。<br /><br />仔细的分析一下，就会发现这样的设计完全是从程序员实现程序功能的角度来设计的，或者说，设计类的时候，是自低向上的，从机器的角度到现实世界的角度来分析问题的。因此在设计的时候，就已经把程序编程实现的细节都考虑进去了，企图从底层实现程序这样的出发点来达到满足现实世界的软件需求的目标。<br /><br />这样的分析方法其实是不适用于Java这样面向对象的编程语言，因为，如果改用C语言，封装两个C函数，都会比Java实现起来轻松的多，逻辑上也清楚的多。<br /><br />我觉得面向对象的精髓在于考虑问题的思路是从现实世界的人类思维习惯出发的，只要领会了这一点，就领会了面向对象的思维方法。<br /><br />举一个非常简单的例子：假使现在需要写一个网页计数器，客户访问一次页面，网页计数器加1，计数器是这样来访问的<br /><br /><a class="ilink" href="http://hostname/count.cgi?id=xxx" target="_blank">http://hostname/count.cgi?id=xxx</a><br /><br />后台有一个数据库表，保存每个id（一个id对应一个被统计访问次数的页面）的计数器当前值，请求页面一次，对应id的计数器的字段加1(这里我们忽略并发更新数据库表，出现的表锁定的问题)。<br /><br />如果按照一般从程序实现的角度来分析，我们会这样考虑：首先是从HTTP GET请求取到id，然后按照id查数据库表，获得某id对应的访问计数值，然后加1，更新数据库，最后向页面显示访问计数。<br /><br />现在假设一个没有程序设计经验的人，他会怎样来思考这个问题的呢？他会提出什么样的需求呢？他很可能会这样想：<br /><br />我需要有一个计数器，这个计数器应该有这样的功能，刷新一次页面，访问量就会加1，另外最好还有一个计数器清0的功能，当然计数器如果有一个可以设为任意值的功能的话，我就可以作弊了。<br /><br />做为一个没有程序设计经验的人来说，他完全不会想到对数据库应该如何操作，对于HTTP变量该如何传递，他考虑问题的角度就是我有什么需求，我的业务逻辑是什么，软件应该有什么功能。<br /><br />按照这样的思路(请注意，他的思路其实就是我们平时在生活中习惯的思维方式)，我们知道需要有一个计数器类 Counter，有一个必须的和两个可选的方法：<br /><br />getCount() // 取计数器值方法<br />resetCounter() // 计数器清0方法<br />setCount() // 设计数器为相应的值方法<br /><br />把Counter类完整的定义如下：<br /><br />public class Counter {<br />public int getCount(int id) {}<br />public void resetCounter(int id) {}<br />public void setCount(int id, int currentCount) {}<br />}<br /><br />解决问题的框架已经有了，来看一下如何使用Counter。 在count.cgi里面调用Counter来计数，程序片断如下：<br /><br />// 这里从HTTP环境里面取id值<br />...<br />Counter myCounter = new Counter(); // 获得计数器<br />int currentCount = myCounter.getCount(id); // 从计数器中取计数<br />// 这里向客户浏览器输出<br />...<br /><br />程序的框架全都写好了，剩下的就是实现Counter类方法里面具体的代码了，此时才去考虑具体的程序语言实现的细节，比如，在getCount()方法里面访问数据库，更新计数值。<br /><br />从上面的例子中看到，面向对象的思维方法其实就是我们在现实生活中习惯的思维方式，是从人类考虑问题的角度出发，把人类解决问题的思维方式逐步翻译成程序能够理解的思维方式的过程，在这个翻译的过程中，软件也就逐步被设计好了。<br /><br />在运用面向对象的思维方法进行软件设计的过程中，最容易犯的错误就是开始分析的时候，就想到了程序代码实现的细节，因此封装的类完全是基于程序实现逻辑，而不是基于解决问题的业务逻辑。<br /><br />学习JDBC编程的经典错误问法是：“我怎样封装对数据库的select操作？”<br /><br />面向对象的设计是基于解决业务问题的设计，而不是基于具体编程技术的设计。我不会去封装select语句的，我只封装解决问题的业务逻辑，对数据库的读取是在业务逻辑的编码实现阶段才去考虑的问题。<br /><br />回过头看上面那个发广告邮件的例子，应该如何应用面向对象的思维方法呢？<br /><br />对于一个邮件来说，有邮件头，邮件体，和邮件地址这三个属性，发送邮件，需要一个发送的方法，另外还需要一个能把所有邮件地址列出来的方法。所以应该如下设计：<br /><br />类JunkMail<br /><br />属性：<br />head<br />body<br />address<br />方法：<br />sendMail() // 发送邮件<br />listAllMail() // 列邮件地址<br /><br />用Java来表示：<br /><br />public class JunkMail {<br />private String head;<br />private String body;<br />private String address;<br />public JunkMain() { // 默认的类构造器<br />// 从外部配置文件读邮件头和邮件体<br />this.head=...;<br />this.body=...;<br />}<br /><br />public static boolean sendMail(String address) {<br />// 调用qmail，发送email<br />}<br /><br />public static Collection listAllMail() {<br />// 访问数据库，返回一个邮件地址集合<br />}<br />}<br /><br />当把JunkMail设计好了以后，再调用JunkMail类完成邮件的发送，将是非常轻松的事情。<br /><br />如果说传统的面向过程的编程是符合机器运行指令的流程的话，那么面向对象的思维方法就是符合现实生活中人类解决问题的思维过程。<br /><br />在面向对象的软件分析和设计的时候，要提醒自己，不要一上来就去想程序代码的实现，应该抛开具体编程语言的束缚，集中精力分析我们要实现的软件的业务逻辑，分析软件的业务流程，思考应该如何去描述和实现软件的业务。毕竟软件只是一个载体，业务才是我们真正要实现的目标。<br /><br />但是在设计过程中，心里却往往在担心，如果我完全不去考虑程序代码的实现的话，那么我怎么知道我的设计一定合理呢？我怎么知道我设计的类、接口一定可以实现呢？所以经常可以看到的现象就是：<br /><br />在设计过程中，虽然知道不能过早考虑代码实现，但是每设计一个类，一个接口，心里都要不知不觉的用自己熟悉的编程语言大概的评估一下，看看能否编出来，因此，一不小心，就会又回到按照程序功能实现的思路进行设计的老路上去了。<br /><br />举个例子来说明，在做Web程序设计的时候，经常要遇到分页显示数据的情况。比如说需要把系统中所有的用户都列出来这样的功能。假设使用User类来表示用户，增加用户addUser()，删除用户deleteUser()，查询所有用户listUsers()方法。而数据库中有一个user表，一条记录是一个用户的信息。下面考虑一下User类的方法的实现：<br /><br />addUser()和deleteUser()方法都好实现，就是对数据库增加记录和删除记录。对于listUsers()方法，其实就是对user表的select，取出一个记录集。但是该怎么从listUsers()方法中得到所有用户的列表呢？<br /><br />一个方法调用的返回值只有一个，没有多个，所以很多情况下采用的办法就是返回值定义为集合类型，比如Vector。这样就可以在listUsers()方法的具体代码实现的时候，从数据库依次取出一个个记录，插入到Vector里面来。在主程序里面，调用listUsers()方法可以返回一个Vector，然后再对Vector遍历操作，就可以得到用户列表了。<br /><br />public class User {<br /><br />public static void addUser(...) {<br />// 数据库insert一条记录<br />}<br /><br />public static void deleteUser(...) {<br />// 数据库delete一条记录<br />}<br /><br />public Vector listUsers(...) {<br />// 数据库select结果放到一个集合里面<br />}<br />}<br /><br />这样的设计基本合理，但是仍然有点小问题。因为在设计的时候，就考虑到了用Java的集合类Vector来实现对不定长数据集的存放，因而违反了面向对象设计的一个原则：在设计的时候不应过早的考虑具体程序语言的实现。所以必须用抽象的方法，和具体实现无关的方法来表达业务逻辑。<br /><br />我们知道，通常对具有集合特征的数据结构进行遍历通常可以使用next和hasNext方法，next实现取下一个用户，hasNext判断是否还有元素。 因此我们定义一个接口Iterator，这个接口中定义两个方法next和hasNext：<br /><br />public interface Iterator {<br />public boolean hasNext() {}<br />public Object next() {}<br />}<br /><br />而User类的listUses方法返回值改为Iterator接口的实现类:<br /><br />public class User {<br />...<br />public Iterator listUsers() {<br />}<br />...<br />}<br /><br />这样就把User类的设计和具体的实现方法分离开了，因为此时任何实现了next()和hasNext()方法的类都可以做为listUsers的返回值，都可以被用来表达“用户列表”，而不仅仅可以使用Vector而已。比如，我可以用ArrayList来表达用户列表，因为ArrayList也实现了Iterator，当然我也可以自己专门写一个类来存放用户列表，只要实现next()和hasNext()方法就行了。<br /><br />这样在具体的编写代码的时候，程序员具有了最大的灵活性，可以根据具体的情况，采用不同的编程方法来存放用户列表。特别是降低了程序的耦合度，提高了程序的可移植性。对于上面那个JunkMail的listAllMail()方法也同样应该改为接口类型。<br /><br />然后，在主程序里面就这样来使用User类的listUsers方法：<br /><br />User myUser = new User();<br />Iterator iterator = myUser.listUsers();<br />while (iterator.hasNext()) {<br />iterator.next();<br />}<br /><br />这样就可以完全不用考虑程序代码实现了，从高层次上把功能抽象出来，定义成为接口，同时又可以把系统设计的很合理，完全根据业务的需求来进行设计。<br /><br />结语<br /><br />通过上面的几个例子的设计说明，使用面向对象的思维方法，其实是一个把业务逻辑从具体的编程技术当中抽象出来的过程，而这个抽象的过程是自上而下的，非常符合人类的思维习惯，也就是先不考虑问题解决的细节，把问题的最主要的方面抽象成为一个简单的框架，集中精力思考如何解决主要矛盾，然后在解决问题的过程中，再把问题的细节分割成一个一个小问题，再专门去解决细节问题。<br /><br />因而一旦牢牢的抓住了这一点，你就会发现在软件设计和开发过程中，你自己总是会不知不觉的运用面向对象的思维方法来设计和编写程序，并且程序的设计和开发也变得不再那么枯燥，而一个合理运用面向对象技术进行设计和架构的软件，更是具备了思维的艺术美感。<br /><br />最后，愿面向对象的思维方法也能给您的程序设计之路带来创作的乐趣。</span>
<img src ="http://www.blogjava.net/dodoma/aggbug/37776.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dodoma/" target="_blank">dodoma</a> 2006-03-28 13:16 <a href="http://www.blogjava.net/dodoma/articles/37776.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从coding fan到真正技术专家 </title><link>http://www.blogjava.net/dodoma/articles/37774.html</link><dc:creator>dodoma</dc:creator><author>dodoma</author><pubDate>Tue, 28 Mar 2006 05:11:00 GMT</pubDate><guid>http://www.blogjava.net/dodoma/articles/37774.html</guid><wfw:comment>http://www.blogjava.net/dodoma/comments/37774.html</wfw:comment><comments>http://www.blogjava.net/dodoma/articles/37774.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dodoma/comments/commentRss/37774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dodoma/services/trackbacks/37774.html</trackback:ping><description><![CDATA[
		<p>
				<span class="javascript">摘选自：中国java开发网 ---http://www.cjsdn.net</span>
		</p>
		<p>
				<span class="javascript">以下文章都是经典，看不看随你的便，我只希望知识掌握在更多中国人的手里！<br /><br />中国有很多小朋友，他们18,9岁或21,2岁，通过自学也写了不少代码，他们有的代码写的很漂亮，一些技术细节相当出众，也很有钻研精神，但是他们被一些错误的认识和观点左右，缺乏对系统，对程序的整体理解能力，这些人，一个网上的朋友说得很好，他们实际上只是一些Coding fans，压根没有资格称为程序员，但是据我所知，不少小网络公司的CTO就是这样的coding fans,拿着吓人的工资，做着吓人的项目，项目的结局通常也很吓人。 <br />程序员基本素质： <br /><br />作一个真正合格的程序员，或者说就是可以真正合格完成一些代码工作的程序员，应该具有的素质。 <br /><br />1：团队精神和协作能力 <br />把它作为基本素质，并不是不重要，恰恰相反，这是程序员应该具备的最基本的，也是最重要的安身立命之本。把高水平程序员说成独行侠的都是在呓语，任何个人的力量都是有限的，即便如linus这样的天才，也需要通过组成强大的团队来创造奇迹，那些遍布全球的为linux写核心的高手们，没有协作精神是不可想象的。独行侠可以作一些赚钱的小软件发点小财，但是一旦进入一些大系统的研发团队，进入商业化和产品化的开发任务，缺乏这种素质的人就完全不合格了。 <br /><br />2：文档习惯 <br />说高水平程序员从来不写文档的肯定是乳臭未干的毛孩子，良好的文档是正规研发流程中非常重要的环节，作为代码程序员，30％的工作时间写技术文档是很正常的，而作为高级程序员和系统分析员，这个比例还要高很多。缺乏文档，一个软件系统就缺乏生命力，在未来的查错，升级以及模块的复用时就都会遇到极大的麻烦。 <br /><br />3：规范化，标准化的代码编写习惯 <br />作为一些外国知名软件公司的规矩，代码的变量命名，代码内注释格式，甚至嵌套中行缩进的长度和函数间的空行数字都有明确规定，良好的编写习惯，不但有助于代码的移植和纠错，也有助于不同技术人员之间的协作。 <br />有些coding fans叫嚣高水平程序员写的代码旁人从来看不懂，这种叫嚣只能证明他们自己压根不配自称程序员。代码具有良好的可读性，是程序员基本的素质需求。 <br />再看看整个linux的搭建，没有规范化和标准化的代码习惯，全球的研发协作是绝对不可想象的。 <br />4：需求理解能力 <br />程序员需要理解一个模块的需求，很多小朋友写程序往往只关注一个功能需求，他们把性能指标全部归结到硬件，操作系统和开发环境上，而忽视了本身代码的性能考虑，有人曾经放言说写一个广告交换程序很简单，这种人从来不知道在百万甚至千万数量级的访问情况下的性能指标是如何实现的，对于这样的程序员，你给他深蓝那套系统，他也做不出太极链的并访能力。性能需求指标中，稳定性，并访支撑能力以及安全性都很重要，作为程序员需要评估该模块在系统运营中所处的环境，将要受到的负荷压力以及各种潜在的危险和恶意攻击的可能性。就这一点，一个成熟的程序员至少需要2到3年的项目研发和跟踪经验才有可能有心得。 <br /><br />5：复用性，模块化思维能力 <br />经常可以听到一些程序员有这样的抱怨，写了几年程序，变成了熟练工，每天都是重复写一些没有任何新意的代码，这其实是中国软件人才最大浪费的地方，一些重复性工作变成了熟练程序员的主要工作，而这些，其实是完全可以避免的。 <br />复用性设计，模块化思维就是要程序员在完成任何一个功能模块或函数的时候，要多想一些，不要局限在完成当前任务的简单思路上，想想看该模块是否可以脱离这个系统存在，是否可以通过简单的修改参数的方式在其他系统和应用环境下直接引用，这样就能极大避免重复性的开发工作，如果一个软件研发单位和工作组能够在每一次研发过程中都考虑到这些问题，那么程序员就不会在重复性的工作中耽误太多时间，就会有更多时间和精力投入到创新的代码工作中去。 <br />一些好的程序模块代码，即便是70年代写成的，拿到现在放到一些系统里面作为功能模块都能适合的很好，而现在我看到的是，很多小公司软件一升级或改进就动辄全部代码重写，大部分重复性工作无谓的浪费了时间和精力。 <br /><br />6：测试习惯 <br />作为一些商业化正规化的开发而言，专职的测试工程师是不可少的，但是并不是说有了专职的测试工程师程序员就可以不进行自测；软件研发作为一项工程而言，一个很重要的特点就是问题发现的越早，解决的代价就越低，程序员在每段代码，每个子模块完成后进行认真的测试，就可以尽量将一些潜在的问题最早的发现和解决，这样对整体系统建设的效率和可靠性就有了最大的保证。 <br />测试工作实际上需要考虑两方面，一方面是正常调用的测试，也就是看程序是否能在正常调用下完成基本功能，这是最基本的测试职责，可惜在很多公司这成了唯一的测试任务，实际上还差的远那；第二方面就是异常调用的测试，比如高压力负荷下的稳定性测试，用户潜在的异常输入情况下的测试，整体系统局部故障情况下该模块受影响状况的测试，频发的异常请求阻塞资源时的模块稳定测试等等。当然并不是程序员要对自己的每段代码都需要进行这种完整测试，但是程序员必须清醒认识自己的代码任务在整体项目中的地位和各种性能需求，有针对性的进行相关测试并尽早发现和解决问题，当然这需要上面提到的需求理解能力。 <br /><br />7：学习和总结的能力 <br />程序员是人才很容易被淘汰，很容易落伍的职业，因为一种技术可能仅仅在三两年内具有领先性，程序员如果想安身立命，就必须不断跟进新的技术，学习新的技能。 <br />善于学习，对于任何职业而言，都是前进所必需的动力，对于程序员，这种要求就更加高了。但是学习也要找对目标，一些小coding fans们，他们也津津乐道于他们的学习能力，一会学会了asp，一会儿学会了php，一会儿学会了jsp，他们把这个作为炫耀的资本，盲目的追逐一些肤浅的，表面的东西和名词，做网络程序不懂通讯传输协议，做应用程序不懂中断向量处理，这样的技术人员，不管掌握了多少所谓的新语言，永远不会有质的提高。 <br />善于总结，也是学习能力的一种体现，每次完成一个研发任务，完成一段代码，都应当有目的的跟踪该程序的应用状况和用户反馈，随时总结，找到自己的不足，这样逐步提高，一个程序员才可能成长起来。 <br />一个不具备成长性的程序员，即便眼前看是个高手，建议也不要选用，因为他落伍的时候马上就到了。 <br />具备以上全部素质的人，应当说是够格的程序员了，请注意以上的各种素质都不是由IQ决定的，也不是大学某些课本里可以学习到的，需要的仅仅是程序员对自己工作的认识，是一种意识上的问题。 <br /><br />那么作为高级程序员，以至于系统分析员，也就是对于一个程序项目的设计者而言，除了应该具备上述全部素质之外，还需要具备以下素质： <br /><br />第一，需求分析能力 <br />对于程序员而言，理解需求就可以完成合格的代码，但是对于研发项目的组织和管理者，他们不但要理解客户需求，更多时候还要自行制定一些需求，为什么这么说呢？ <br />一般而言，进行研发任务，也许是客户提出需求，也许是市场和营销部门提出的需求，这时候对于研发部门，他们看到的不是一个完整的需求，通常而言，该需求仅仅是一些功能上的要求，或者更正规些，可能获得一个完整的用户视图；但是这都不够，因为客户由于非技术因素多一些，他们可能很难提出完整和清晰，或者说专业性的性能需求，但是对于项目组织者和规划者，他必须能够清醒认识到这些需求的存在并在完成需求分析报告的时候适当的提出，同时要完整和清晰的体现在设计说明书里面，以便于程序员编码时不会失去这些准则。 <br />程序设计者必须正确理解用户需求所处的环境，并针对性做出需求的分析，举例而言，同样一个软件通过ASP租用方式发布和通过License方式发布，性能需求可能就是有区别的，前者强调的是更好的支撑能力和稳定性，而后者则可能更强调在各种平台下的普适性和安装使用的简捷性。 <br /><br />第二，项目设计方法和流程处理能力 <br />程序设计者必须能够掌握不少于两到三种的项目设计方法（比如自顶至下的设计方法，比如快速原型法等等），并能够根据项目需求和资源搭配来选择合适的设计方法进行项目的整体设计。设计方法上选择不当，就会耽误研发周期，浪费研发资源，甚至影响研发效果。 <br />一个程序设计者还需要把很多功夫用在流程图的设计和处理上，他需要做数据流图以确立数据词典；他需要加工逻辑流图以形成整体的系统处理流程。一个流程有问题的系统，就算代码多漂亮，每个模块多精致，也不会成为一个好的系统。当然，做好流程分析并选择好项目设计方法，都需要在需求分析能力上具有足够的把握。 <br /><br />第三，复用设计和模块化分解能力 <br />这个似乎又是老调重谈，前面基本素质上不是已经说明了这个问题吗？ <br />作为一个从事模块任务的程序员，他需要对他所面对的特定功能模块的复用性进行考虑，而作为一个系统分析人员，他要面对的问题复杂的多，需要对整体系统按照一种模块化的分析能力分解为很多可复用的功能模块和函数，并针对每一模块形成一个独立的设计需求。举个例子，好比是汽车生产，最早每辆汽车都是独立安装的，每个部件都是量身定做的，但是后来不一样了，机器化大生产了，一个汽车厂开始通过流水线来生产汽车，独立部件开始具有一定的复用性，在后来标准化成为大趋势，不同型号，品牌甚至不同厂商的汽车部件也可以进行方便的换装和升级，这时候，汽车生产的效率达到最大化。软件工程也是同样的道理，一个成熟的软件行业，在一些相关项目和系统中，不同的部件是可以随意换装的，比如微软的许多桌面软件，在很多操作模块（如打开文件，保存文件等等）都是复用的同一套功能模块，而这些接口又通过一些类库提供给了桌面应用程序开发者方便挂接，这就是复用化的模块设计明显的一个佐证。 <br />将一个大型的，错综复杂的应用系统分解成一些相对独立的，具有高度复用性的，并能仅仅依靠几个参数完成数据联系的模块组合，是作为高级程序员和系统分析员一项最重要的工作，合适的项目设计方法，清晰的流程图，是实现这一目标的重要保证。 <br /><br />第四，整体项目评估能力 <br />作为系统设计人员，必须能够从全局出发，对项目又整体的清醒认识，比如公司的资源配置是否合理和到位，比如工程进度安排是否能最大化体现效率又不至于无法按期完成。评估项目整体和各个模块的工作量，评估项目所需的资源，评估项目可能遇到的困难，都需要大量的经验积累，换言之，这是一种不断总结的累计才能达到的境界。在西方一些软件系统设计的带头人都是很年长的，比如4，50岁，甚至更老，他们在编码方面已经远远不如年轻人那样活络，但是就项目评估而言，他们几十年的经验积累就是最重要和宝贵的财富。中国缺这么一代程序员，主要还不是缺那种年纪的程序员，而是那种年纪的程序员基本上都是研究单位作出来的，都不是从专业的产品化软件研发作出来的，他们没有能积累那种产品化研发的经验，这也是没有办法的事情。 <br />第五，团队组织管理能力 <br />完成一个项目工程，需要团队的齐心协力，作为项目设计者或研发的主管人，就应当有能力最大化发挥团队的整体力量，技术管理由于其专业性质，不大同于一般的人事管理，因为这里面设计了一些技术性的指标和因素。 <br />首先是工作的量化，没有量化就很难做到合适的绩效考核，而程序量化又不是简单的代码行数可以计算的，因此要求技术管理人员需要能真正评估一个模块的复杂性和工作量。 <br />其次是对团队协作模式的调整，一般而言，程序开发的协作通常分为小组进行，小组有主程序员方式的，也有民主方式的，根据程序员之间的能力水平差距，以及根据项目研发的需求，选择合适的组队方式，并能将责权和成员的工作任务紧密结合，这样才能最大发挥组队的效率。 <br />一个代码水平高的人，未必能成为一个合格的项目研发主管，这方面的能力欠缺往往是容易被忽视的。 <br /><br />综上可以看到，作为一个主管研发的负责人，一个项目设计者，所需要具备的素质和能力并不是程序代码编写的能力，当然一般情况下，一个程序员通过不断的总结提高达到了这种素质的时候，他所具有的代码编写能力也已经相当不简单了，但是请注意这里面的因果关系，一个高水平的项目设计者通常已经是代码编写相当优秀的人了，但是并不是一个代码相当优秀的程序员就可以胜任项目设计的工作，这里面存在的也不是智商和课本的问题，还是在于一个程序员在积累经验，逐步提升的时候没有意识到应当思考哪方面的东西，没有有意识的就项目的组织和复用设计进行揣摩，没有经常性的文档习惯和总结习惯，不改变这些，我们的合格的项目设计者还是非常欠缺。 <br /><br />另外，为防止有无聊的人和我较真，补充一点，本文针对目标是作商业化的软件项目和工程，那些科研机构的编程高手，比如算法高手，比如图象处理高手，他们的工作是研究课题而非直接完成商业软件（当然最终间接成为商业产品，比如微软研究院在作的研究课题），因此他们强调的素质可能是另外的东西，这些人（专家），并不能说是程序员，不能用程序员的标准去衡量。 <br /><br />最后补充一点东西，一个软件项目研发的设计流程是怎样的呢？以通常标准的设计方法为例，（不过笔者喜欢快速原型法）。 <br /><br />第一个步骤是市场调研，技术和市场要结合才能体现最大价值。 <br /><br />第二个步骤是需求分析，这个阶段需要出三样东西，用户视图，数据词典和用户操作手册。用户视图是该软件用户（包括终端用户和管理用户）所能看到的页面样式，这里面包含了很多操作方面的流程和条件。数据词典是指明数据逻辑关系并加以整理的东东，完成了数据词典，数据库的设计就完成了一半多。用户操作手册是指明了操作流程的说明书。请注意，用户操作流程和用户视图是由需求决定的，因此应该在软件设计之前完成，完成这些，就为程序研发提供了约束和准绳，很遗憾太多公司都不是这样做的，因果颠倒，顺序不分，开发工作和实际需求往往因此产生隔阂脱节的现象。 <br />需求分析，除了以上工作，笔者以为作为项目设计者应当完整的做出项目的性能需求说明书，因为往往性能需求只有懂技术的人才可能理解，这就需要技术专家和需求方（客户或公司市场部门）能够有真正的沟通和了解。 <br /><br />第三个步骤是概要设计，将系统功能模块初步划分，并给出合理的研发流程和资源要求。作为快速原型设计方法，完成概要设计就可以进入编码阶段了，通常采用这种方法是因为涉及的研发任务属于新领域，技术主管人员一上来无法给出明确的详细设计说明书，但是并不是说详细设计说明书不重要，事实上快速原型法在完成原型代码后，根据评测结果和经验教训的总结，还要重新进行详细设计的步骤。 <br />第四个步骤是详细设计，这是考验技术专家设计思维的重要关卡，详细设计说明书应当把具体的模块以最‘干净’的方式(黑箱结构）提供给编码者，使得系统整体模块化达到最大；一份好的详细设计说明书，可以使编码的复杂性减低到最低，实际上，严格的讲详细设计说明书应当把每个函数的每个参数的定义都精精细细的提供出来，从需求分析到概要设计到完成详细设计说明书，一个软件项目就应当说完成了一半了。换言之，一个大型软件系统在完成了一半的时候，其实还没有开始一行代码工作。那些把作软件的程序员简单理解为写代码的，就从根子上犯了错误了。 <br /><br />第五个步骤是编码，在规范化的研发流程中，编码工作在整个项目流程里最多不会超过1/2，通常在1/3的时间，所谓磨刀不误砍柴功，设计过程完成的好，编码效率就会极大提高，编码时不同模块之间的进度协调和协作是最需要小心的，也许一个小模块的问题就可能影响了整体进度，让很多程序员因此被迫停下工作等待，这种问题在很多研发过程中都出现过。编码时的相互沟通和应急的解决手段都是相当重要的，对于程序员而言，bug永远存在，你必须永远面对这个问题，大名鼎鼎的微软，可曾有连续三个月不发补丁的时候吗？从来没有！ <br /><br />第六个步骤是测试 <br />测试有很多种：按照测试执行方，可以分为内部测试和外部测试；按照测试范围，可以分为模块测试和整体联调；按照测试条件，可以分为正常操作情况测试和异常情况测试；按照测试的输入范围，可以分为全覆盖测试和抽样测试。以上都很好理解，不再解释。 <br />总之，测试同样是项目研发中一个相当重要的步骤，对于一个大型软件，3个月到1年的外部测试都是正常的，因为永远都会又不可预料的问题存在。 <br />完成测试后，完成验收并完成最后的一些帮助文档，整体项目才算告一段落，当然日后少不了升级，修补等等工作，只要不是想通过一锤子买卖骗钱，就要不停的跟踪软件的运营状况并持续修补升级，知道这个软件被彻底淘汰为止。 <br /><br />写这些步骤算不上卖弄什么，因为实话讲我手边是一本《软件工程》，在大学里这是计算机专业的必修课程，但是我知道很多程序员似乎从来都只是热衷于什么《30天精通VC》之类的，他们有些和我一样游击队出身，没有正规学过这个专业，还有一些则早就在混够学分后就把这些真正有用的东西还给了老师。 <br /><br />网上现在也很浮躁，一些coding fans乱嚷嚷，混淆视听，实际上真正的技术专家很少在网上乱发帖子的，如笔者这样不知天高地厚的，其实实在是算不上什么高手，只不过看不惯这种对技术，对程序员的误解和胡说，只好挺身而出，做拨乱反正之言，也希望那些还沉迷于一些错误人士的coding fans们能认真想想，走到正途上，毕竟那些聪明的头脑还远远没有发挥应有的价值。 </span>
				<br />
				<br />
		</p>
		<br />
		<br />
<img src ="http://www.blogjava.net/dodoma/aggbug/37774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dodoma/" target="_blank">dodoma</a> 2006-03-28 13:11 <a href="http://www.blogjava.net/dodoma/articles/37774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>