<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>D-tune</title>
    <description></description>
    <link>http://d-tune.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>组织架构图（水平方向的树视图）的实现</title>
        <author>D-tune</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://d-tune.javaeye.com">D-tune</a>&nbsp;
          链接：<a href="http://d-tune.javaeye.com/blog/119542" style="color:red;">http://d-tune.javaeye.com/blog/119542</a>&nbsp;
          发表时间: 2007年09月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现在的YUI-EXT也好，DOJO也好，等等，已经提供了功能极其强大的基于tree的widget。<br />但是类似于组织架构图或者说水平展开的树的UI还是比较少。正好前段时间因为工作的原因做了一个，现发布上来，给需要的朋友和有兴趣的朋友参考。<br /><br /><strong>原理说明：</strong>无序列表标签本身是含有结构信息的，所以我们要做的只是用css来改变的缺省的垂直布局而已。这个时候，css中float:left发挥了重要作用；另外：我们分别在div和a元素上使用2张不同的背景图片来达创建节点间连接线和掩盖连接线的多余部分。<br /><br /><strong>实际效果图：</strong><br /><img src="http://d-tune.javaeye.com/upload/picture/pic/5053/04355d34-aaca-4e7a-a6b7-2f075ff41891.png " /><br /><br /><strong>主要html代码：</strong><br /><pre name="code" class="java">
&lt;div id="contain">
	&lt;ul id="map" class="solo">
		&lt;li>&lt;div class="root section">&lt;a href="#">XXXCompany&lt;/a>&lt;/div>
			&lt;ul>
				&lt;li>&lt;div class="first">&lt;a href="#">HR&lt;/a>&lt;/div>&lt;/li>
				&lt;li>&lt;div class="section">&lt;a href="#">Development&lt;/a>&lt;/div>
						&lt;ul>
							&lt;li>&lt;div class="first">&lt;a href="#">Department1&lt;/a>&lt;/div>&lt;/li>
							&lt;li>&lt;div class="section">&lt;a href="#">Department2&lt;/a>&lt;/div>
								&lt;ul>
									&lt;li>&lt;div class="first">&lt;a href="#">Group1&lt;/a>&lt;/div>&lt;/li>
									&lt;li>&lt;div class="last">&lt;a href="#">Group2&lt;/a>&lt;/div>&lt;/li>
								&lt;/ul>	
							&lt;/li>
							&lt;li>&lt;div class="section">&lt;a href="#">Department3&lt;/a>&lt;/div>&lt;/li>
							&lt;li>&lt;div class="last">&lt;a href="#">Department4&lt;/a>&lt;/div>&lt;/li>
						&lt;/ul>
				&lt;/li>
				&lt;li>&lt;div class="last">&lt;a href="#">Administrator&lt;/a>&lt;/div>&lt;/li>
			&lt;/ul>
		&lt;/li>
	&lt;/ul>
&lt;/div>
</pre><br /><br /><strong>css代码：</strong><br /><pre name="code" class="java"> div#contain {
	width: 1000em;
	background: none;
}
 ul#map {
	float: none;
	margin: 0 auto;
}
 ul {
	clear: left;
	margin: 2em 0 0 0;
	padding: 0;
	background: #fff;
}
 ul ul {
	border-top: 1px solid #000;
	width: auto;
}
 ul.solo {
	border-top: 0;
}
 li {
	float: left;
	list-style: none;
	position: relative;
}
 li li {
	margin: -1px 0 0 0;
}
 div {
	background: url(../images/vLine.gif) 50% repeat-y;
	padding: 2em 5px 0 5px;
	margin: 0 .3em -2em .3em;
}
 div.section {
	padding: 2em 5px 2em 5px;
}
 div.first {
	background: url(../images/first.gif) 50% repeat-y;
	margin-left: 0;
}
 div.last {
	background: url(../images/last.gif) 50% repeat-y;
	margin-right: 0;
}
 div.root {
	padding-top: 0;
}
 a {
	display: block;
	background: #fff;
	border: 1px solid #000;
	padding: .25em .5em .5em .5em;
	color: #222;
	text-decoration: none;
	margin: 0 auto;
	width: 10em;
	line-height: 2em;
	text-align: center;
	font-size: 1.2em;
}
 a:hover {
	background: #eee;
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://d-tune.javaeye.com/blog/119542#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 02 Sep 2007 23:19:44 +0800</pubDate>
        <link>http://d-tune.javaeye.com/blog/119542</link>
        <guid>http://d-tune.javaeye.com/blog/119542</guid>
      </item>
      <item>
        <title>TreeTable的简单实现</title>
        <author>D-tune</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://d-tune.javaeye.com">D-tune</a>&nbsp;
          链接：<a href="http://d-tune.javaeye.com/blog/117668" style="color:red;">http://d-tune.javaeye.com/blog/117668</a>&nbsp;
          发表时间: 2007年08月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最终效果图：<br /><img src="http://d-tune.javaeye.com/upload/picture/pic/5018/979a2513-7651-4ed5-ac07-b5e37320eea5.png " /> <br /><br />UI说明：针对table本身进行增强的tree table组件。<br />tree的数据来源是单元格内a元素的自定义属性：level和type。具体代码如下：<br /><pre name="code" class="java">&lt;table id="treeGrid" border="0" cellpadding="0" cellspacing="0">
  &lt;THEAD>
  		&lt;tr>&lt;th>Department&lt;/th>&lt;th>EmployeeID&lt;/th>&lt;th>position&lt;/th>&lt;/tr>	
  &lt;/THEAD>
  &lt;TBODY>
		&lt;tr>&lt;td width="250px">&lt;a level="0" type="node" href="javascript:void(0);">Dept4&lt;/a>&lt;/td>&lt;td>-&lt;/td>&lt;td>-&lt;/td>&lt;/tr>
		&lt;tr>&lt;td>&lt;a level="1" type="leaf" href="javascript:void(0);">fanggw&lt;/a>&lt;/td>&lt;td>c3025&lt;/td>&lt;td>MASTER&lt;/td>&lt;/tr>
		&lt;tr>&lt;td>&lt;a level="1" type="node" href="javascript:void(0);">team1&lt;/a>&lt;/td>&lt;td>-&lt;/td>&lt;td>-&lt;/td>&lt;/tr>
		&lt;tr>&lt;td>&lt;a level="2" type="leaf" href="javascript:void(0);">zhanghy&lt;/a>&lt;/td>&lt;td>c3268&lt;/td>&lt;td>SE&lt;/td>&lt;/tr>
		&lt;tr>&lt;td>&lt;a level="2" type="leaf" href="javascript:void(0);">chenf&lt;/a>&lt;/td>&lt;td>c3401&lt;/td>&lt;td>SE&lt;/td>&lt;/tr>
   &lt;/TBODY>
&lt;/table></pre><br />根据上述数据源结构，先遍历该table，读取数据并建立整课树的数据模型，然后初始化整棵树的视图（node和leaf的显示由css样式定义，方便修改，如果需要可以进一步在初始化的时候由外部代码指定），并关联节点的click处理程序。<br /><br />下面是主要的实现代码：<br /><pre name="code" class="java">		
		var Class = {
		  create: function() {
		    return function() {
		      this.initialize.apply(this, arguments);
		    }
		  }
		}
    
    var Node = Class.create();
    Node.prototype = {
    	initialize: function(link, level, type) {
    		this.name = link.innerText;      
			  this.id;
			  this.link = link;
			  this.type = type;
			  this.level = level;	
			  this.isOpen = true;
			  this.isClicked = false;
			  this.root;
			  this.img;	//clicked img's path

				this.parent;
			  this.children = new Array();
			  this.getChildren();
			  
    	},
    	
    	getChildren: function() {
    		if (this.type == "node") {
    			//alert(this.link.innerText);
	    		var dataRows = document.getElementById("treeGrid").getElementsByTagName("TBODY")[0].getElementsByTagName("TR");
	    		var pushFlag = false;
	    		
	    		for(var j=0; j&lt;dataRows.length; j++) {
	    			var linkTag = dataRows[j].firstChild.firstChild;
	    			var level = linkTag.getAttribute("level");
	    			var type = linkTag.getAttribute("type");
	    			
	    			if (!pushFlag) {
	    				if (linkTag == this.link) {
	    					pushFlag = true;
	    				}
	    				continue;
	    			}
	    			//alert("cur lvl:"+level+"; type:"+type +" ;parentLvl:" +(parseInt(this.level)+1));
	    			
	    			if (level == (parseInt(this.level)+1)) {
	    				//alert("push node's lvl:"+level+"; type:"+type);
	    				var leaf = new Node(linkTag, level, type);
	    				leaf.parent = this;
	    				leaf.id = level+"_"+j;
	    				this.children.push(leaf);
	    			} else if (level == this.level) {
	    				break;
	    			} else {
	    				continue;
	    			}
	    			
	    		}
    		}
    		//for (var i=0; i&lt;this.children.length; i++) {
    			//this.children[i].parent = this;
    		//}
    		//alert("childs:"+this.children.length);
    	},
    	
    	getNext: function() {
    		var next = null;
    		//alert(this.name);
    		
    		if (this.parent) {
	    		for (var i=0; i&lt;this.parent.children.length; i++) {
	    			if (this.parent.children[i] == this && i &lt; (this.parent.children.length-1)) {
	    				next = this.parent.children[i+1];
	    				break;
	    			}
	    		}	
    		}
    		/*
    		if (next)
    			alert("next:"+next.name);
    		else 
    			alert("current is last");
    		*/
    		return next;
    	},
    	
    	
    	getCurrentRow: function() {
				return this.link.parentNode.parentNode.parentNode;   		
    	},
    	
    	changeClickImg: function() {
    		if (this.isOpen) {
    			this.img.src = this.img.src.replace("minus", "plus");
    		} else {
    			this.img.src = this.img.src.replace("plus","minus");
    		}
    		this.isOpen = this.isOpen?false:true;
    	},
    	
    	getInnerHTML: function() {
    		var oFragment = document.createDocumentFragment();
    		
    		//make the indent img by level
	    	for (var lvl = this.level-1; lvl>0; lvl--) {
	    		var indentImg = document.createElement("img");
	    		
	    		//get parent node by level
	    		var parentNode = this.parent;
	    		for (var i=1; i&lt;lvl; i++) {
	    			parentNode = parentNode.parent;
	    		}
	    		
	    		//alert(this.name+":"+parentNode.name);
	    		//alert(parentNode.getNext()?parentNode.getNext().name:"null");
	    		
	    		/* parent node has nextSibling insert vertical line img */
	    		if (parentNode.getNext()) {
	    			indentImg.src = "./images/I.gif";
	    		} else {
	    			/* parent node has nextSibling insert blank img */
	    			indentImg.src = "./images/blank.gif";
	    		}
    			indentImg.align = "absbottom";
					oFragment.appendChild(indentImg);
    		}

    		
    		//make the plus or minus img
    		var img = document.createElement('img');
    		var path;
    		if (this.type == "node") {
    			if (this.level == 0) {
    				path = "./images/minus.gif";
    			} else {
    				if (this.children.length > 0) {
    					if (this.getNext()) {
    						path = "./images/Tminus.gif";
    					} else {
    						path = "./images/Lminus.gif";
    					}
    				}
    				else {
    					if (this.getNext()) {
    						path = "./images/T.gif";
    					} else {
    						path = "./images/L.gif";
    					}
    				}
    			}    			
    		} else {
  				if (this.getNext()) {
  					path = "./images/T.gif";
  				}
  				else {
  					path = "./images/L.gif";
  				} 
    		}
    		img.src = path;
			  img.align = "absbottom";
			  //set cursor pointer style to the minus/plus img
			  img.style.cursor = "pointer"
			  this.img = img;
			  img.onclick = expand;
			  
			  oFragment.appendChild(img);
			  oFragment.appendChild(this.link);
			  
			  var div = document.createElement("div");
			  div.setAttribute("id", this.id);

			  /* div css class set by type */
			  div.className = (this.type=="node")?"node":"leaf"; 
			  
			  /* all node is margin to left by 10 pixel except root */
			  if (this.level > 0) {
				  div.style.marginLeft = "10px";
			  }
			  
				div.appendChild(oFragment);
				return div;
    		
    	}
    }
    
    /* global variable */
    //tree root
    var root;
    //all nodes of the tree
    var nodes = new Array();
    
    /* initialize the whole tree grid */
    function initTreeGrid() {
		  //dataRows is the datasource of the tree
			var dataRows = document.getElementById("treeGrid").getElementsByTagName("TBODY")[0].getElementsByTagName("TR");
    	
    	//find the root of the tree
    		for (var i=0; i&lt;dataRows.length; i++) {
    			var linkTag = dataRows[i].firstChild.firstChild;
    			var level = linkTag.getAttribute("level");
    			var type = linkTag.getAttribute("type");
    			
    			if (level == 0 && type == "node") {
	  				var root = new Node(linkTag, 0, "node");
	  				root.parent = null;
	  				root.id = "0_0";
						break;
    			}
    		}
    		
    		//put all node into 1-index array
    		nodes.push(root);
    		initNodes(root);
    		
    		//display the table tree
    		for (var j = 0; j&lt;nodes.length; j++) {
    			dataRows[j].firstChild.appendChild(nodes[j].getInnerHTML());
    		}
    }
    
    function initNodes(node) {
    	  for (var j=0; j&lt;node.children.length; j++) {
    			nodes.push(node.children[j]);
    			if (node.children[j].children.length > 0) {
    				initNodes(node.children[j]);
    			}
    		}
    }
    
    /* expand row elements by isOpen flag */
    function expand() {    	
    	var currentDivId = event.srcElement.parentNode.id;
    	var currentNode;
    	
    	//get the clicked node
    	for(var i=0; i&lt;nodes.length; i++) {
    		if (currentDivId == nodes[i].id) {
    			currentNode = nodes[i];
    			break;
    		}
    	}
    	
    	//expand the clicked node
    	expandChild(currentNode);
    	
    	//set the isClicked flag when the row minus img is clicked
    	currentNode.isClicked = currentNode.isClicked?false:true;
    }
    
    function expandChild(currentNode) {
    	//alert(currentNode.name);
    	for (var i=0; i&lt;currentNode.children.length; i++) {
    		var child = currentNode.children[i];
    		if (child.type == "node" && !child.isClicked) {
    			expandChild(child);
    		}
    		child.getCurrentRow().style.display = currentNode.isOpen?"none":"block";
    	}
    	currentNode.changeClickImg();
    }
		
		/* utility function */
		function addEvent(obj, evType, fn) {
		    /* adds an eventListener for browsers which support it
		       Written by Scott Andrew: nice one, Scott */
		    if (obj.addEventListener) {
		        obj.addEventListener(evType, fn, true);
		        return true;
		    }
		    else if (obj.attachEvent) {
			    var r = obj.attachEvent("on"+evType, fn);
		        return r;
		    }
		    else {
			    return false;
		    }
		}
		
		/* add load event to body element*/
		addEvent(window, "load", initTreeGrid);</pre><br />该组件已在IE6+，Firefox上测试通过。<br />有兴趣的朋友可以联系我，进行进一步的改进和扩展。
          <br/>
          <span style="color:red;">
            <a href="http://d-tune.javaeye.com/blog/117668#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 29 Aug 2007 01:23:27 +0800</pubDate>
        <link>http://d-tune.javaeye.com/blog/117668</link>
        <guid>http://d-tune.javaeye.com/blog/117668</guid>
      </item>
      <item>
        <title>关于软件工程实施的个人见解</title>
        <author>D-tune</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://d-tune.javaeye.com">D-tune</a>&nbsp;
          链接：<a href="http://d-tune.javaeye.com/blog/76404" style="color:red;">http://d-tune.javaeye.com/blog/76404</a>&nbsp;
          发表时间: 2007年05月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"><font color="#0000ff">写在前面：这篇文章是于2004年作者大三时修读《软件工程》这门课程时的读书笔记，最近在整理资料时翻阅到，虽文字和思想一样青涩，但是仍希望和大家共勉，若有不足和纰漏之处望大家见谅和指出。</font>&nbsp;</font></p>
<blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
<p dir="ltr" style="MARGIN-RIGHT: 0px"><font face="Arial">&nbsp;&nbsp;&nbsp; &ldquo;软件工程&ldquo;这个概念的提出，是希望能按照传统的工程模式来解决软件开发过程中遇到的诸如开发周期，经费，质量控制等问题。也就是向人们常说的那样&ldquo;让软件开发像实施工程一样&rdquo;，再说得明白一点也就是说&ldquo;是软件开发像运行工厂一样，处于质量控制之下，按照既定计划生产出合格的软件产品&rdquo;。但是人们却忽略了软件开发过程中起关键因素的资源是&ldquo;人&rdquo;，而人是不可能像机器一样按部就班，不出差错的生产出产品。每个开发小组都想比其他小组做得更出色，同时软件开发技术更新很快，又没有一个统一的开发模式依循。正是如此，才使得软件工程这门学科，从1968年诞生一直发展到现在，都没能研究出一套只要严格按照其执行就能开发出合格的软件产品的工程方法。所以我想针对&ldquo;人&rdquo;这个软件工程中主导因素来展开本文的探讨。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先，一个软件项目的参与者必然是人，包括项目投资人，项目经理，业务专家，软件设计，编码，测试人员以及文档撰写人员。他们在做一个软件工程时，必然先组成一个团队通过成员间的分工合作来达到最终目标。那么在软件开发的整个过程中，我们所见到的主要就是人的创造性思想以及这些思想在人和人之间的交流，人和计算机之间的交流，最后成为能正确工作，达到预定功能的软件产品。既然如此，我们可以看出一个成功的开发团队总是能做出满足需要的系统，这与使用的技术和软件开发过程没有什么必然的联系。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 林锐在他的《软件工程思想》这本书里主要谈到了程序员和项目经理这两类人在开发团队的一些特性，扮演其他角色的人员都没有提到。我不是想在这里否定林锐的著作，我想这可能是和程序员和项目经理在软件开发中所处位置的重要性有莫大的关系吧。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;但是我觉得除了这两者外，其他的人同样很重要，因为软件开发是一个团队活动，团队里任何成员都是同样重要，少了谁都不行。试想，要是没有了项目投资人，还有谁愿意白干活啊；同样要是没有了业务专家，软件的需求分析不准确，那么做出来的软件卖给谁？没有设计、编码人员，软件产品只能是纸上谈兵，无法变为实实在在的软件产品；没有测试人员和文档撰写人员的测试工作和文档，我相信软件的品质也难有保证。总之，&ldquo;人&ldquo;作为知识的载体和知识转化为产品的行为施行者，在软件开发过程中具有举足轻重的作用。</font></p>
<p dir="ltr" style="MARGIN-RIGHT: 0px"><font face="Arial"><br />
&nbsp;&nbsp;&nbsp;&nbsp; 其次，软件开发过程实际上是开发团队中各个参与人员活动的并集，起关键因素的是人本身，那么我们就必须了解人的特性。只有我们充分了解之后，我们才能在软件工程的过程中更好的实现开发者之间的交流互动。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第一：人是难以预料的，而且变化无常的，这将影响到软件开发过程中的各个方面。人是自发冲动的，有时做好事，有时又做坏事，有时候更是好心却做坏事。比如说一个程序员他本身工作情绪不好，可能导致他这一周工作效率地下，编写的代码错误百出，这不仅使得他要加长工作时间，拖延工期，还导致测试人员负担加重，甚至造成整个功能模块不能按预定计划进行组装。再举一个例子，一个人第一周工作3天，下周工作5天，他写出的源代码行数可能是上周的2倍，因为在额外的2天里他全身心投入工作，如果再下周他工作了7天，他写出的源代码可能还达不到第一周的数量，因为他已经筋疲力尽了。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 人往往又是自我矛盾的，在处理某类工作时糊里糊涂，但在处理另一类工作时却非常仔细；在某些场合非常健谈，而在某些场合却一言不发。<br />
&nbsp;&nbsp;&nbsp; &nbsp;每个人都富有自己的个性，并随着年龄，环境的改变而改变。一个人的个性在很大程度上决定了他（她）能不能很好的完成他的工作任务：一个项目经理希望项目组的所以成员都喜欢他，他不能做出会得罪一些人，但又必须做出的决定，那么项目进度将很难继续下去；项目组里的资深程序员被派去做新人的导师，由于缺乏辅导这些新人的耐心，他干脆直接帮新人的错误代码修改完事，虽然他的技术出色，但是他所在的团队并不能享受到工作的乐趣以及在工作中学习进步。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这些例子在现实的软件开发过程中是完全可能的，虽说并不是软件开发过程有什么问题，但是这些因素或多或少会影响到整个开发过程的正常进行，严重的还会造成项目的延期，或者开销过大等等。&nbsp;&nbsp;</font></p>
<font face="Arial">
<p dir="ltr" style="MARGIN-RIGHT: 0px"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二：人与人不同，呈现出多样性，这是不可避免的。正是由于人与人的不同，所以才有许许多多的开发方法，才有不同的分工。这些事实似乎很多人都了解，但是在具体的软件项目开发过程中却常常忘掉它们：不但制定了软件开发方法和工作方式，还要求所有人都使用同样的方法，做着同样的工作，这就忽略了每个人自身的个性。比如一个程序员他可能更擅长于用OO快速开发工具开发出人机界面，可项目经理却非要他去做底层的逻辑功能模块的开发工作；本来偏爱钻研系统内部结构的程序员，却让他来写需求分析文档。这样的工作安排不仅导致了其工作效率低下，还没做到知人善用，造成了人力资源的极大浪费。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;一个团队的人员的多样化是一件好事，它可以让项目经理在征求意见和建议的时候能听到不同的声音，使得项目在开发的过程中得到不断的修正，避免偏离其预先计划好的路线。总之，正是由于人的多样性，管理者才能充分发挥每个人的优势，做到知人善用，使团队以最大优势进行运作，这样才能做出好的软件产品。<br />
&nbsp;第三：人会犯错误，任何人在做事的过程中能真正做到不犯错误。这也正是软件开发过程中要采取迭代开发的原因吧，因为迭代的目的就是让人们难以避免的错误能相对更早的发现并得到纠正。在软件开发过程中，开发人员在评估，需求分析，设计，编码，测试，文档编写的各个环节中都可能出错，管理人员再项目的决策上也可能出现失误，我们必须接受这个事实，并且通过相应的过程或者方法来避免或解决这些错误。犯错并不是最严重的，最重要的是通过犯错后的学习并避免下一次再犯同样的错误，犯两次同样的错误是我们所不能容忍的了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后，我觉得在软件开发过程中，既然知道了人是工程成功与否的关键因素，并且了解了人的一些特性，那么就应该针对&ldquo;人是难以预料的，而且变化无常的，人是多样化的，每个人有自己的个性，同时人还会犯错误&rdquo;这些特性引入科学的激励机制和管理机制，从而才能避开人固有的不利因素，充分利用其有利因素，激发个人潜能，使得整个开发团队能够做到健康，有活力，执行效率高，最终实现软件工程的目的：使软件开发更加高效且保证软件质量。</p>
</font></blockquote>
<p dir="ltr" style="MARGIN-RIGHT: 0px"><font color="#0000ff" face="Arial">&nbsp;总结：本文看似洋洋洒洒3000字，实际上只针对人这个在软件工程中的主导者和执行者做了怎么来认识人的不确定性的问题，并没有涉及到软件工程中其他的问题。因为我觉得正是由于人的不确定性（变化无常，多样化，个性化，会犯错）才导致了软件工程的不确定性，使得软件产品不可能像传统产品在工厂里通过某种固定的工程模式就可以在确保质量的情况下生产出来。</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://d-tune.javaeye.com/blog/76404#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 May 2007 01:13:31 +0800</pubDate>
        <link>http://d-tune.javaeye.com/blog/76404</link>
        <guid>http://d-tune.javaeye.com/blog/76404</guid>
      </item>
  </channel>
</rss>