﻿<?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-JAVA进行式-文章分类-传递经典</title><link>http://www.blogjava.net/aw815/category/4719.html</link><description>让我们把JAVA进行到底!</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 07:46:22 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 07:46:22 GMT</pubDate><ttl>60</ttl><item><title>怎样成为优秀的软件模型设计者</title><link>http://www.blogjava.net/aw815/articles/24102.html</link><dc:creator>水秀清灵</dc:creator><author>水秀清灵</author><pubDate>Thu, 15 Dec 2005 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/aw815/articles/24102.html</guid><wfw:comment>http://www.blogjava.net/aw815/comments/24102.html</wfw:comment><comments>http://www.blogjava.net/aw815/articles/24102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aw815/comments/commentRss/24102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aw815/services/trackbacks/24102.html</trackback:ping><description><![CDATA[<P class=MsoNormal><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们期待自己成为一个优秀的软件模型设计者，但是，要怎样做，又从哪里开始呢？</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">将下列原则应用到你的软件工程中，你会获得立杆见影的成果。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">人远比技术重要</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你开发软件是为了供别人使用，没有人使用的软件只是没有意义的数据的集合而已。许多在软件方面很有成就的行家在他们事业的初期却表现平平，因为他们那时侯将主要精力都集中在技术上。显然，构件（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">components</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">），</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">EJB</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Enterprise Java Beans</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）和代理（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">agent</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）是很有趣的东西。但是对于用户来说，如果你设计的软件很难使用或者不能满足他们的需求，后台用再好的技术也于事无补。多花点时间到软件需求和设计一个使用户能很容易理解的界面上。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">理解你要实现的东西</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">好的软件设计人员把大多数时间花费在建立系统模型上，偶尔写一些源代码，但那只不过是为了验证设计过程中所遇到的问题。这将使他们的设计方案更加可行。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">谦虚是必须的品格</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你不可能知道一切，你甚至要很努力才能获得足够用的知识。软件开发是一项复杂而艰巨的工作，因为软件开发所用到的工具和技术是在不断更新的。而且，一个人也不可能了解软件开发的所有过程。在日常生活中你每天接触到的新鲜事物可能不会太多。但是对于从事软件开发的人来说，每天可以学习很多新东西（如果愿意的话）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">需求就是需求</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果你没有任何需求，你就不要动手开发任何软件。成功的软件取决于时间（在用户要求的时间内完成）、预算和是否满足用户的需求。如果你不能确切知道用户需要的是什么，或者软件的需求定义，那么你的工程注定会失败。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">需求其实很少改变，改变的是你对需求的理解</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object ToolSmiths</SPAN></SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">公司（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">www.objecttoolsmiths.com</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Doug Smith</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">常喜欢说：</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">分析是一门科学，设计是一门艺术</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">。他的意思是说在众多的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">正确</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">分析模型中只存在一个最</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">正确</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">分析模型可以完全满足解决某个具体问题的需要（我理解的意思是需求分析需要一丝不苟、精确的完成</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">,</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">而设计的时候反而可以发挥创造力和想象力</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana"> - </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">译者注）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果需求经常改动，很可能是你没有作好需求分析，并不是需求真的改变了。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你可以抱怨用户不能告诉你他们想得到什么，但是不要忘记，收集需求信息是你工作。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你可以说是新来的开发人员把事情搞得一团糟，但是，你应该确定在工程的第一天就告诉他们应该做什么和怎样去做。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果你觉得公司不让你与用户充分接触，那只能说明公司的管理层并不是真正支持你的项目。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你可以抱怨公司有关软件工程的管理制度不合理，但你必须了解大多同行公司是怎么做的。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你可以借口说你们的竞争对手的成功是因为他们有了一个新的理念，但是为什么你没先想到呢？</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">需求真正改变的情况很少，但是没有做好需求分析工作的理由却很多。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">经常阅读</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在这个每日都在发生变化的产业中，你不可能在已取得的成就上陶醉太久。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">每个月至少读</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">2</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">3</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">本专业杂志或者</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">1</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">本专业书籍。保持不落伍需要付出很多的时间和金钱，但会使你成为一个很有实力的竞争者。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">降低软件模块间的耦合度</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">高耦合度的系统是很难维护的。一处的修改引起另一处甚至更多处的变动。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你可以通过以下方法降低程序的耦合度：隐藏实现细节，强制构件接口定义，不使用公用数据结构，不让应用程序直接操作数据库（我的经验法则是：当应用程序员在写</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">SQL</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">代码的时候，你的程序的耦合度就已经很高了）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">耦合度低的软件可以很容易被重用、维护和扩充。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">提高软件的内聚性</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果一个软件的模块只实现一个功能，那么该模块具有高内聚性。高内聚性的软件更容易维护和改进。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">判断一个模块是否有高的内聚性，看一看你是否能够用一个简单的句子描述它的功能就行了。如果你用了一段话或者你需要使用类似</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">或</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">等连词，则说明你需要将该模块细化。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">只有高内聚性的模块才可能被重用。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">考虑软件的移植性</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">移植是软件开发中一项具体而又实际的工作，不要相信某些软件工具的广告宣传（比如</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">java </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">的宣传口号</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">write once run many ? </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">译者注）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">即使仅仅对软件进行常规升级，也要把这看得和向另一个操作系统或数据库移植一样重要。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">记得从</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">16</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">位</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Windows</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">移植到</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">32</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">位</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">windows</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">乐趣</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">吗</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana"> </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">？当你使用了某个操作系统的特性，如它的进程间通信</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">(IPC)</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">策略，或用某数据库专有语言写了存储过程。你的软件和那个特定的产品结合度就已经很高了。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">好的软件设计者把那些特有的实现细节打包隐藏起来，所以，当那些特性该变的时候，你的仅仅需要更新那个包就可以了。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">接受变化</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">这是一句老话了：唯一不变的只有变化。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你应该将所有系统将可能发生的变化以及潜在需求记录下来</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">,</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">以便将来能够实现（参见</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“Architecting for Change”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Thinking Objectively, May 1999</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">通过在建模期间考虑这些假设的情况，你就有可能开发出足够强壮且容易维护的软件。设计强壮的软件是你最基本的目标。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">不要低估对软件规模的需求</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Internet </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">带给我们的最大的教训是你必须在软件开发的最初阶段就考虑软件规模的可扩充性。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">今天只有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">100</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">人的部门使用的应用程序，明天可能会被有好几万人的组织使用，下月，通过因特网可能会有几百万人使用它。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在软件设计的初期，根据在用例模型中定义的必须支持的基本事务处理，确定软件的基本功能。然后，在建造系统的时候再逐步加入比较常用的功能。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在设计的开始考虑软件的规模需求，避免在用户群突然增大的情况下，重写软件。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">性能仅仅是很多设计因素之一</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">关注软件设计中的一个重要因素</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">--</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">性能，这好象也是用户最关心的事情。一个性能不佳的软件将不可避免被重写。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;但是你的设计还必须具有可靠性，可用性，便携性和可扩展性。你应该在工程开始就应该定义并区分好这些因素，以便在工作中恰当使用。性能可以是，也可以不是优先级最高的因素，我的观点是，给每个设计因素应有的考虑。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">管理接口</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;“UML User Guide”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Grady Booch</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Ivar Jacobson</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">Jim Rumbaugh ,Addison Wesley, 1999</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）中指出，你应该在开发阶段的早期就定义软件模块之间的接口。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">这有助于你的开发人员全面理解软件的设计结构并取得一致意见，让各模块开发小组相对独立的工作。一旦模块的接口确定之后，模块怎样实现就不是很重要了。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">从根本上说，如果你不能够定义你的模块</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">从外部看上去会是什么样子</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">，你肯定也不清楚模块内要实现什么。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">走近路需要更长的时间</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在软件开发中没有捷径可以走。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">缩短你的在需求分析上花的时间，结果只能是开发出来的软件不能满足用户的需求，必须被重写。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在软件建模上每节省一周，在将来的编码阶段可能会多花几周时间，因为你在全面思考之前就动手写程序。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你为了节省一天的测试时间而漏掉了一个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">bug</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">，在将来的维护阶段，可能需要花几周甚至几个月的时间去修复。与其如此，还不如重新安排一下项目计划。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">避免走捷径，只做一次但要做对（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">do it once by doing it right</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">别信赖任何人</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">产品和服务销售公司不是你的朋友，你的大部分员工和高层管理人员也不是。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">大部分产品供应商希望把你牢牢绑在他们的产品上，可能是操作系统，数据库或者某个开发工具。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">大部分的顾问和承包商只关心你的钱并不是你的工程（停止向他们付款，看一看他们会在周围呆多长时间）。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">大部分程序员认为他们自己比其他人更优秀，他们可能抛弃你设计的模型而用自己认为更好的。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">只有良好的沟通才能解决这些问题。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">要明确的是，不要只依靠一家产品或服务提供商，即使你的公司（或组织）已经在建模、文档和过程等方面向那个公司投入了很多钱。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">证明你的设计在实践中可行</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在设计的时候应当先建立一个技术原型，</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana"> </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">或者称为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">端到端</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">原型。以证明你的设计是能够工作的。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你应该在开发工作的早期做这些事情，因为，如果软件的设计方案是不可行的，在编码实现阶段无论采取什么措施都于事无补。技术原型将证明你的设计的可行性，从而，你的设计将更容易获得支持。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">应用已知的模式</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">目前，我们有大量现成的分析和设计模式以及问题的解决方案可以使用。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">一般来说，好的模型设计和开发人员，都会避免重新设计已经成熟的并被广泛应用的东西。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.ambysoft.com/processPatternsPage.html </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">收藏了许多开发模式的信息。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;18. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">研究每个模型的长处和弱点</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">目前有很多种类的模型可以使用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">,</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如下图所示。用例捕获的是系统行为需求，数据模型则描述支持一个系统运行所需要的数据构成。你可能会试图在用例中加入实际数据描述，但是，这对开发者不是非常有用。同样，数据模型对描述软件需求来说是无用的。每个模型在你建模过程中有其相应的位置，但是，你需要明白在什么地方，什么时候使用它们。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;19. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在现有任务中应用多个模型</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">当你收集需求的时候，考虑使用用例模型，用户界面模型和领域级的类模型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">当你设计软件的时候，应该考虑制作类模型，顺序图、状态图、协作图和最终的软件实际物理模型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">程序设计人员应该慢慢意识到，仅仅使用一个模型而实现的软件要么不能够很好地满足用户的需求，要么很难扩展。</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;20. </SPAN></SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">教育你的听众</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你花了很大力气建立一个很成熟的系统模型，而你的听众却不能理解它们，甚至更糟－连为什么要先建立模型都不知道。那么你的工作是毫无意义的。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">教给你开发人员基本的建模知识；否则，他们会只看看你画的漂亮图表，然后继续编写不规范的程序。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">另外，</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana"> </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你还需要告诉你的用户一些需求建模的基础知识。给他们解释你的用例</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">(uses case)</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">和用户界面模型，以使他们能够明白你要表达地东西。当每个人都能使用一个通用的设计语言的时候（比如</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">UML-</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">译者注），你的团队才能实现真正的合作。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;21. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">带工具的傻瓜还是傻瓜</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">你给我</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">CAD/CAM</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">工具，请我设计一座桥。但是，如果那座桥建成的话，我肯定不想当第一个从桥上过的人，因为我对建筑一窍不通。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">使用一个很优秀的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">CASE</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">工具并不能使你成为一个建模专家，只能使你成为一个优秀</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">CASE</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">工具的使用者。成为一个优秀的建模专家需要多年的积累，不会是一周针对某个价值几千美元工具的培训。一个优秀的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">CASE</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">工具是很重要，但你必须学习使用它，并能够使用它设计它支持的模型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;22. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">理解完整的过程</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">好的设计人员应该理解整个软件过程，尽管他们可能不是精通全部实现细节。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">软件开发是一个很复杂的过程，还记得《</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">object-oriented software process</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">》第</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">36</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">页的内容吗？除了编程、建模、测试等你擅长工作外，还有很多工作要做。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">好的设计者需要考虑全局。必须从长远考虑如何使软件满足用户需要，如何提供维护和技术支持等。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;23. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">常做测试，早做测试</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果测试对你的软件来说是无所谓的，那么你的软件多半也没什么必要被开发出来。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">建立一个技术原型供技术评审使用，以检验你的软件模型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">在软件生命周期中，越晚发现的错误越难修改，修改成本越昂贵。尽可能早的做测试是很值得的。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;24. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">把你的工作归档</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">不值得归档的工作往往也不值得做。归档你的设想，以及根据设想做出的决定；归档软件模型中很重要但不很明显的部分。</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana"> </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">给每个模型一些概要描述以使别人很快明白模型所表达的内容。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;25. </SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">技术会变，基本原理不会</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">如果有人说</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">“</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">使用某种开发语言、某个工具或某某技术，我们就不需要再做需求分析，建模，编码或测试</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">”</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">。不要相信，这只说明他还缺乏经验。抛开技术和人的因素，实际上软件开发的基本原理自</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">20</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">世纪</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">70</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">年代以来就没有改变过。你必须还定义需求，建模，编码，测试，配置，面对风险，发布产品，管理工作人员等等。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">软件建模技术是需要多年的实际工作才能完全掌握的。好在你可以从我的建议开始，完善你们自己的软件开发经验。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Verdana">&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体">以鸡汤开始，加入自己的蔬菜。然后，开始享受你自己的丰盛晚餐吧。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(转载自<A href="http://www.vchome.net/swengineer/umlrosecmm/uml26.htm">http://www.vchome.net/swengineer/umlrosecmm/uml26.htm</A>)</SPAN></P><img src ="http://www.blogjava.net/aw815/aggbug/24102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aw815/" target="_blank">水秀清灵</a> 2005-12-15 22:49 <a href="http://www.blogjava.net/aw815/articles/24102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse插件及电子书列表（转载）</title><link>http://www.blogjava.net/aw815/articles/22361.html</link><dc:creator>水秀清灵</dc:creator><author>水秀清灵</author><pubDate>Sat, 03 Dec 2005 11:27:00 GMT</pubDate><guid>http://www.blogjava.net/aw815/articles/22361.html</guid><wfw:comment>http://www.blogjava.net/aw815/comments/22361.html</wfw:comment><comments>http://www.blogjava.net/aw815/articles/22361.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aw815/comments/commentRss/22361.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aw815/services/trackbacks/22361.html</trackback:ping><description><![CDATA[<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下是从“恋花和尚”的——六欲红尘（博客）处看到的一个关于Eclipse的东东，因为近日在学习使用Eclipse，觉得他整理的这个列表很好，一时看不完，特意抓到自己的本本里，嘿嘿，可以留着慢慢看：<BR><BR>1、Apress.The.Definitive.Guide.to.SWT.and.JFace<BR>Apress出版的《The.Definitive.Guide.to.SWT.and.JFace》chm格式电子书，Eclipse平台的两个用户界面工具箱－SWT和JFace的java编程指南。<BR><A href="http://www.amazon.com/exec/obidos/tg/detai...6889430-0550522">http://www.amazon.com/exec/obidos/tg/detai...6889430-0550522</A><BR><A href="http://images.amazon.com/images/P/15905932...SCMZZZZZZZ_.jpg">http://images.amazon.com/images/P/15905932...SCMZZZZZZZ_.jpg</A></P>
<P>2、JasperAssistant.v1.4.2<BR>JasperAssistant是一款可视化的JasperReports报表设计工具，JasperReports是一个非常流行的开放源码报告引擎。JasperAssistant基于Eclipse的插件程序结构，通过逼真的图形界面方便的创建JasperReports报表定义文件。<BR><A href="http://www.jasperassistant.com/">http://www.jasperassistant.com/</A><BR><A href="http://www.jasperassistant.com/shots/full.png">http://www.jasperassistant.com/shots/full.png</A></P>
<P>3、JVider.for.Eclipse.v1.7e1.Java<BR>一款为JavaSwing应用程序设计的GUIBuilder工具。在他的帮助下，你可以很简单的为你的Java校应用程序和程序设计图形用户界面。<BR><A href="http://www.jvider.com/">http://www.jvider.com/</A><BR><A href="http://www.jvider.com/jviderscreen.png">http://www.jvider.com/jviderscreen.png</A></P>
<P>4、RMI.Plugin.for.Eclipse.v1.6.1<BR>Eclipse开发平台的RMI（基于Java的分布计算框架）插件，是在JavaSDK平台通过调用RMI编译器自动生成远程对象stub（桩）和skeleton（框架）的简便方法。<BR><A href="http://www.genady.net/rmi/">http://www.genady.net/rmi/</A><BR><A href="http://www.genady.net/rmi/v16/screenshots/...rmi-eclipse.png">http://www.genady.net/rmi/v16/screenshots/...rmi-eclipse.png</A></P>
<P>5、ddison.Wesley.Professional.SWT.The.Standard.Widget.Toolkit.Volume.1.Jun.2004<BR>电子书，Eclipse系列之SWT精解，SWT就是StandardWidgetToolkit，是在java中创建图形界面的类库<BR><A href="http://www.amazon.com/exec/obidos/ASIN/032...8151071-6877408">http://www.amazon.com/exec/obidos/ASIN/032...8151071-6877408</A><BR><A href="http://images.amazon.com/images/P/0321256638.01.LZZZZZZZ.jpg">http://images.amazon.com/images/P/0321256638.01.LZZZZZZZ.jpg</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/22338_AddisonWesley.html">http://0daycheck.eastgame.net/0day/archives/22338_AddisonWesley.html</A></P>
<P>6、Omondo.Eclipse.UML.Studio.Edition.v1.1.0<BR>OmondoEclipseUML是一款可视化的模块设计工具，可以完全集成于Eclipse和CVS。<BR><A href="http://www.omondo.com/">http://www.omondo.com</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/21757_OmondoEclipse.html">http://0daycheck.eastgame.net/0day/archives/21757_OmondoEclipse.html</A></P>
<P>Omondo.Eclipse.UML.Studio.Edition.v1.1.0<BR>OmondoEclipseUML是一款可视化建模工具，可以与Eclipse和CVS无缝集成。</P>
<P>7、Oxygen.XML.Editor.v5.0.Eclipse.plugin<BR>OxygenXMLeditor是一款基于Java的XML编辑器，支持XML,XSL,TXT,XSD,DTD文档，能自行校验XML,XSL,XSD代码，提示脚本错误。Oxygen能自动完成结束标签，代码高亮现实，支持Unicode。<BR><A href="http://www.oxygenxml.com/features/">http://www.oxygenxml.com/features/</A><BR><A href="http://www.oxygenxml.com/img/oxygen-mac.gif">http://www.oxygenxml.com/img/oxygen-mac.gif</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/19151_OxygenXMLEdit.html">http://0daycheck.eastgame.net/0day/archives/19151_OxygenXMLEdit.html</A></P>
<P>8、Jigloo.GUI.Builder.v3.0.1<BR>为EclipseJavaIDE和WebSphereStudio设计的插件，可以用来创建和管理Swing和SWTGUI类。<BR><A href="http://cloudgarden.com/jigloo/">http://cloudgarden.com/jigloo/</A><BR><A href="http://cloudgarden.com/jigloo/images/screenshot4_sm.jpg">http://cloudgarden.com/jigloo/images/screenshot4_sm.jpg</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/19038_JiglooGUIBuil.html">http://0daycheck.eastgame.net/0day/archives/19038_JiglooGUIBuil.html</A></P>
<P>9、Code.Pro.Studio.3.0.0<BR>一款为那些使用IBMwebspherestuodio和eclipse开发环境的开发者设计的软件。能够让java的开发者有效开速的开发高质量的软件。这款软件可以通过许多重复任务来完成软件的开发，同时能够极大的提高用户界面和使开发活动流水线化。此款软件集成了CodeProAdisor，CodeProAgilityandCodeProBuild。<BR><A href="http://www.instantiations.com/codepro/default.htm">http://www.instantiations.com/codepro/default.htm</A><BR><A href="http://www.instantiations.com/codepro/imag...pstudio3-sm.gif">http://www.instantiations.com/codepro/imag...pstudio3-sm.gif</A></P>
<P>10、Window.Builder.Pro.2.1.1<BR>一款基于EclipseSWT技术上的双向javaGui设计软件。具备SWT设计以及Swing设计两个主要功能。该软件会被作为一个插件镶嵌入Eclipse以及其他一些兼容的IDEs中（WSSD,WSAD,WSED等等）。新的2.0版本支持Eclipse3.0。<BR><A href="http://www.windowbuilderpro.com/">http://www.windowbuilderpro.com/</A><BR><A href="http://www.instantiations.com/swt-designer...ts/designer.gif">http://www.instantiations.com/swt-designer...ts/designer.gif</A></P>
<P>11、Jigloo.GUI.Builder.v3.0.0<BR>Jigloo.GUI.Builder是一个为Eclipsejave和WebSphereStudio开发的插件，能够创建出滚动控制和SWTGUI的效果界面。</P>
<P>Vi.plugin.for.Eclipse3.v1.86<BR>ViPlugin可以在vi编辑器上添加一个功能条，这个是用于Eclipse3+的。</P>
<P>12、Parasoft.JTest.v5.1.71.DC.20040912.WinNT2kXP<BR>自动进行JAVA单元测试和代码标准检查来帮助开发人员编写克号的代码的工具。可分析类，然后生成单元测试案例来包括最大的覆盖测试，发现未处理的异常并校验需求。<BR>-自动的基本错误预防，包括单元测试和自动代码标准检查<BR>-生成并执行单元测试案例<BR>-提供了进行黑盒测试、模型测试和系统测试的快速简单的途径<BR>-识别并预防未处理的运行时异常，函数错误，内存泄露，性能问题和安全弱点<BR>-对群或方案优先作测试和报告<BR>-监控测试的覆盖范围<BR>-自动回归测试<BR>-支持按比例压缩设计<BR>-检查超过400个来自JAVA专家的编码规范<BR>-改正违反超过200个编码规范的错误<BR>-允许用户创建自己的编码规范<BR>-可在小组范围内管理共享测试文件<BR>-和IBMWebSphere和Eclipse集成<BR>-支持Borland？JBuilder？,Together？ControlCenter？,和Ant</P>
<P>13、Borland.Together.for.Eclipse.v6.3<BR>最佳的程序分析设计工具，提供实时的协同工作能力。<BR>·支持所有主要的UML图形<BR>充分利用UnifiedModelingLanguage(统一建模语言—UML)搭建正确的架构，以便满足你的业务目标。每一个软件项目都需要一个蓝图，以保持整个小组向相同的方向前进并构建正确的软件。通过集成UML能力的方式，Together扩展了开发框架，简化了构建软件的复杂过程。<BR>·TogetherLiveSource自动进行模型与代码的同步<BR>使用同步的模型与代码，允许进行更加有效的开发小组沟通与协作。同时的同步化让手工更新成为过去，使用相同的信息保持开发小组的信息更新。模型处于灵活的状态，不会过时，这是因为开发小组做出的任何变化总是同时反映在代码与模型之中，让开发小组更加高效、更加有效。<BR>·自动文档生成<BR>保持开发小组专注于设计与实现，而不是拟制文档。Together提供了强大的、可以定制的文档生成能力，其中包括多种文档格式与定制模板的能力。通过自动生成文档的方式，开发者可以集中精力搞软件开发，而小组领导随时都有所需要的信息。<BR>·支持业界标准的模式<BR>使用业界领先的模式着手开发工作，改善了架构的质量。Together支持标准的模式，比如GoF与J2EE，并且同时也提供了更改现有模式、创建新模式的能力。广泛的模式支持使得开发小组在将来的项目中复用模式，改善所有项目的架构质量。<BR>·使用审计测定软件质量<BR>审计为开发小组提供了在软件开发的初期测定质量，强化企业标准的能力—在软件开发的初期，开发小组还在编制软件的代码呢。在分发之前测定质量，开发者可以改善代码的质量，在代码转交QA小组之前，发现并修复自己的错误。审计变量可以被定制并保存，这样开发小组就能制订代码标准，监视代码超出认可规范的问题。审计也被用来改变开发者的个人代码编制风格，以便符合企业的编码标准。<BR>·使用度量进行软件开发的量化<BR>量度为开发小组提供了测量软件项目复杂程度、质量与规模的能力。通过测量并对信息进行标准检查，管理人员能够知晓开发小组与开发过程的质量与效率，更好地进行当前与未来项目的量化。<BR>·重构<BR>在Together技术之中的大量重构特性验证所有的系统变化都被正确地传送到整个应用。所得到的结果便是代码不易出错，应用的质量得到改善。<BR>·Together与Eclipse的集成<BR>Eclipse是一种开放源代码的业界平台，Together技术与Eclipse的集成为Eclipse用户提供了一种熟悉的环境，用来进行软件开发。在Eclipse环境中，开发者可以利用TogetherEditionforEclipse之中的、领先的建模、设计与质量保证功能，快速构建高质量的企业应用。通过在Eclipse本地开发用于TogetherEditionforEclipse的用户接口，用户可受益于紧密的集成，并利用在同一个工具之中两种技术的优势。<BR><A href="http://www.borland.com/together/index.html">http://www.borland.com/together/index.html</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/16494_BorlandTogethe.html">http://0daycheck.eastgame.net/0day/archives/16494_BorlandTogethe.html</A></P>
<P>14、Clay.Database.Modeling.Pro.for.Eclipse.v1.0.5<BR>作为插件运行于Eclipse开发环境的数据库设计工具。通过直观的界面图形化地设计数据库模型。它可以通过逆向设计来根据现存数据库来设计新的数据库模型。更多地，它还能生成适合你的数据库的SQL(DDL)代码。<BR><A href="http://www.azzurri.jp/en/software/clay/index.jsp">http://www.azzurri.jp/en/software/clay/index.jsp</A><BR><A href="http://www.azzurri.jp/en/software/clay/ima...y_eclipse_1.png">http://www.azzurri.jp/en/software/clay/ima...y_eclipse_1.png</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/11208_ClayDatabaseM.html">http://0daycheck.eastgame.net/0day/archives/11208_ClayDatabaseM.html</A></P>
<P>15、Oxygen.XML.Editor.v4.2.Eclipse.plugin<BR>OxygenXMLeditor是一款基于Java的XML编辑器，支持XML,XSL,TXT,XSD,DTD文档，能自行校验XML,XSL,XSD代码，提示脚本错误。Oxygen能自动完成结束标签，代码高亮现实，支持Unicode。<BR><A href="http://www.oxygenxml.com/features/">http://www.oxygenxml.com/features/</A><BR><A href="http://www.oxygenxml.com/img/oxygen-mac.gif">http://www.oxygenxml.com/img/oxygen-mac.gif</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/10689_OxygenXMLEdit.html">http://0daycheck.eastgame.net/0day/archives/10689_OxygenXMLEdit.html</A></P>
<P>16、MC.Press.Eclipse.Step.by.Step<BR>MCPress出版的《Eclipse循序渐近》(Eclipse:StepbyStep)电子版，Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言，它只是一个框架和一组服务，用于通过插件组件构建开发环境。幸运的是，Eclipse附带了一个标准的插件集，包括Java开发工具（JavaDevelopmentTools，JDT）。该书包括了Eclipse平台开发的方方面面，可以手把手帮助你编写完整的可用的程序，并更好的立即各种基本概念<BR><A href="http://www.amazon.com/exec/obidos/tg/detail/-/1583470441/">http://www.amazon.com/exec/obidos/tg/detail/-/1583470441/</A><BR><A href="http://images.amazon.com/images/P/15834704...SCMZZZZZZZ_.jpg">http://images.amazon.com/images/P/15834704...SCMZZZZZZZ_.jpg</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/10486_MCPressEclips.html">http://0daycheck.eastgame.net/0day/archives/10486_MCPressEclips.html</A></P>
<P>17、Window.Builder.Pro.v2.0.1<BR>一款基于EclipseSWT技术上的双向JavaGui设计软件。具备SWT设计以及Swing设计两个主要功能。该软件会被作为一个插件镶嵌入Eclipse以及其他一些兼容的IDEs中（WSSD,WSAD,WSED等等）。新的2.0版本支持Eclipse3.0。<BR><A href="http://www.windowbuilderpro.com/">http://www.windowbuilderpro.com/</A><BR><A href="http://www.instantiations.com/swt-designer...ts/designer.gif">http://www.instantiations.com/swt-designer...ts/designer.gif</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/10310_WindowBuilder.html">http://0daycheck.eastgame.net/0day/archives/10310_WindowBuilder.html</A></P>
<P>18、XMLBuddy.PRO.v2.0.11<BR>Eclipse插件，提供XML编辑功能，支持XML,DTD,XMLSchema,RELAXNG,RELAXNGcompactsyntax,XSLT<BR><A href="http://xmlbuddy.com/">http://xmlbuddy.com/</A><BR><A href="http://xmlbuddy.com/2.0/screen.jpg">http://xmlbuddy.com/2.0/screen.jpg</A><BR><A href="http://0daycheck.eastgame.net/0day/archives/9848_XMLBuddyPROv2.html">http://0daycheck.eastgame.net/0day/archives/9848_XMLBuddyPROv2.html</A></P>
<P>19、Compuware.DevPartner.Java.Edition.v3.0.3<BR>快速高质量的开发java程序的开发工具箱，增强组件和软件的可靠性。可以针对个人定制不同的浏览数据窗口和调试工具。<BR>新的3.03版本具有如下更新：<BR>-具有Eclipse插件<BR>-可以在系统，开发环境和应用程序之间交互切换<BR>-还有其他更新等。</P>
<P>20、Manning.Publications.Company.Eclipse.in.Action.A.Guide.for.the.Java.Developer<BR>电子书-Eclipse实践：java开发人员指南。<BR><A href="http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/">http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/</A><BR><A href="http://images.amazon.com/images/P/1930110960.01.<u>PE32_PIdp-schmoo2,TopRight,7,-26_SCMZZZZZZZ</u>.jpg">http://images.amazon.com/images/P/1930110960.01.&lt;u&gt;PE32_PIdp-schmoo2,TopRight,7,-26_SCMZZZZZZZ&lt;/u&gt;.jpg</A></P>
<P>21、Manning.Publications.Company.Eclipse.in.Action.A.Guide.for.the.Java.Developer<BR>电子书《jave开发指南》<BR><A href="http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/">http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/</A><BR><A href="http://images.amazon.com/images/P/19301109...SCMZZZZZZZ_.jpg">http://images.amazon.com/images/P/19301109...SCMZZZZZZZ_.jpg</A></P>
<P>22、SignSoft_intelliBO_v3.6.2<BR>一个中间件的应用，不仅仅执行JavaDataObjects标准(JDO)（现在支持JDO标准1.0.1），而且实现智能的数据访问，所以称作：“intelligentBusinessObjects”。可集成于Eclipse及IBMWebsphereApllicationDeveloperIDE。</P>
<P>23、OReilly.Eclipse.A.Java.Developers.Guide.eBook<BR>《Java开发者指南》</P>
<P>24、IBM.Redbooks.Eclipse.Development.Using.the.Graphical.Editing.Framework.and.the.Eclipse.Modeling.Framework.eBook<BR>电子书，提供给那些具备良好知识基础以及丰富经验的使用EclipseSDK来开发插件代码的程序员,用以校验插件的工作性能。<BR><A href="http://publib-b.boulder.ibm.com/Redbooks.n...s/sg246302.html">http://publib-b.boulder.ibm.com/Redbooks.n...s/sg246302.html</A></P>
<P>25、IBM.Redbooks.Eclipse.Development.Using.the.Graphical.Editing.Framework.and.the.Eclipse.Modeling.Framework.eBook<BR>书名：《使用Graphical.Editing.Framework和Eclipse.Modeling.Framework进行Eclipse开发》<BR>作者：BillMooreetal.<BR>出版社：IBMRedbooks<BR>格式：CHM<BR>分类：计算机/软件开发<BR>ISBN：0738453161<BR>内容简介：<BR>一本介绍使用GraphicalEditingFramework(GEF)和EclipseModelingFramework(EMF).进行Eclipseplugin开发的书。</P>
<P>26、Rational.XDE.v2003.Developer.Plus.NET.Edition.Retail<BR>RationalXDEDeveloper是一个十分完善的可视化设计和开发的环境，它可以结合Rational支持的集成开发环境（IDE）来使用，比如Eclipseplatform,IBMWebSphereStudioApplicationDeveloper,MicrosoftVisualStudio.NET等。RationalXDEDeveloper可以在构建企业应用和Web为中心的解决方案上开发人员提供支持。通过结合使用RationalXDEDeveloper的多种特性（比如，代码的双向工程，自动和按需的对代码和模型进行同步，模式引擎支持，多模型的支持，将数据库资产逆向工程为数据模型，团队协作，可选择的过程指南）可以减轻一些被需要的代码开发和设计的工作。这个是VisualStudio.NET版本的License。<BR><A href="http://www.rational.com/products/xde/index.jsp">http://www.rational.com/products/xde/index.jsp</A></P>
<P>27、Addison.Wesley.Contributing.To.Eclipse.Principles.Patterns.And.Plug-Ins.eBook---1<BR>讲述在Eclipse(一种正在兴起的软件开发环境)下进行插件开发的电子图书</P>
<P>28、Addison.Wesley.Contributing.To.Eclipse.Principles.Patterns.And.Plug-Ins.eBook---2<BR>出版：Addison-WesleyPubCo；作者：ErichGamma,KentBeck；ISBN：0321205758。<BR>一本关于Eclipse的书。这本书不仅仅教你怎么做而且使你完全理解Eclipse。<BR><A href="http://www.amazon.com/exec/obidos/tg/detai...l/-/0321205758/">http://www.amazon.com/exec/obidos/tg/detai...l/-/0321205758/</A></P>
<P>29、Addison.Wesley.Eclipse.Modeling.Framework.A.Developers.Guide.eBook<BR>电子书，EclipseModelingFramework模型构架可以使Java,XML,和UML语言开发者统一起来使用令人惊讶的模板快速构建健康的应用程序,是一本软件开发人员指导书<BR><A href="http://www.amazon.com/exec/obidos/ASIN/013...1308053-5737658">http://www.amazon.com/exec/obidos/ASIN/013...1308053-5737658</A></P><img src ="http://www.blogjava.net/aw815/aggbug/22361.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aw815/" target="_blank">水秀清灵</a> 2005-12-03 19:27 <a href="http://www.blogjava.net/aw815/articles/22361.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>操作JTextPane对象的代码实例</title><link>http://www.blogjava.net/aw815/articles/21869.html</link><dc:creator>水秀清灵</dc:creator><author>水秀清灵</author><pubDate>Tue, 29 Nov 2005 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/aw815/articles/21869.html</guid><wfw:comment>http://www.blogjava.net/aw815/comments/21869.html</wfw:comment><comments>http://www.blogjava.net/aw815/articles/21869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aw815/comments/commentRss/21869.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aw815/services/trackbacks/21869.html</trackback:ping><description><![CDATA[<P>/* HTMLDocumentEditor.java <BR>* @author: Charles Bell <BR>* @version: May 27, 2002 <BR>*/ </P>
<P>import java.awt.*; <BR>import java.awt.event.*; <BR>import java.io.*; </P>
<P>import javax.swing.*; <BR>import javax.swing.event.*; <BR>import javax.swing.filechooser.*; <BR>import javax.swing.text.*; <BR>import javax.swing.text.html.*; <BR>import javax.swing.undo.*; </P>
<P>/**HTML文件文档编辑器*/<BR>public class HTMLDocumentEditor extends JFrame implements ActionListener<BR>{ <BR>&nbsp;/** 声明一个网页文档对象变量*/<BR>&nbsp;private HTMLDocument document; <BR>&nbsp;/** 创建一个文本编辑板*/<BR>&nbsp;private JTextPane textPane = new JTextPane(); <BR>&nbsp;private boolean debug = false; <BR>&nbsp;/** 声明一个文件对象变量*/<BR>&nbsp;private File currentFile; <BR>&nbsp;<BR>&nbsp;/** 侦听在当前文档上的编辑器 */ <BR>&nbsp;protected UndoableEditListener undoHandler = new UndoHandler(); <BR>&nbsp;<BR>&nbsp;/** 添加撤消管理器 */ <BR>&nbsp;protected UndoManager undo = new UndoManager(); <BR>&nbsp;<BR>&nbsp;/** 添加撤消侦听器*/<BR>&nbsp;private UndoAction undoAction = new UndoAction(); <BR>&nbsp;/** 添加恢复侦听器*/<BR>&nbsp;private RedoAction redoAction = new RedoAction(); <BR>&nbsp;<BR>&nbsp;/** 添加剪切侦听器*/<BR>&nbsp;private Action cutAction = new DefaultEditorKit.CutAction(); <BR>&nbsp;/** 添加复制侦听器*/<BR>&nbsp;private Action copyAction = new DefaultEditorKit.CopyAction(); <BR>&nbsp;/** 添加粘贴侦听器*/<BR>&nbsp;private Action pasteAction = new DefaultEditorKit.PasteAction(); <BR>&nbsp;<BR>&nbsp;/** 添加加粗侦听器*/<BR>&nbsp;private Action boldAction = new StyledEditorKit.BoldAction(); <BR>&nbsp;/** 添加加下划线侦听器*/<BR>&nbsp;private Action underlineAction = new StyledEditorKit.UnderlineAction(); <BR>&nbsp;/** 添加倾斜侦听器*/<BR>&nbsp;private Action italicAction = new StyledEditorKit.ItalicAction(); <BR>&nbsp;<BR>&nbsp;private Action insertBreakAction = new DefaultEditorKit.InsertBreakAction(); <BR>&nbsp;private HTMLEditorKit.InsertHTMLTextAction unorderedListAction = new HTMLEditorKit.InsertHTMLTextAction("Bullets", "&lt;ul&gt;&lt;li&gt; &lt;/li&gt;&lt;/ul&gt;",HTML.Tag.P,HTML.Tag.UL); <BR>&nbsp;private HTMLEditorKit.InsertHTMLTextAction bulletAction = new HTMLEditorKit.InsertHTMLTextAction("Bullets", "&lt;li&gt; &lt;/li&gt;",HTML.Tag.UL,HTML.Tag.LI); <BR>&nbsp;<BR>&nbsp;/** 构造方法*/<BR>&nbsp;public HTMLDocumentEditor()<BR>&nbsp;{ <BR>&nbsp;&nbsp;/** 设置主窗体标题*/<BR>&nbsp;&nbsp;super("HTMLDocumentEditor"); <BR>&nbsp;&nbsp;HTMLEditorKit editorKit = new HTMLEditorKit(); <BR>&nbsp;&nbsp;/** 创建默认文档指向网页引用document*/<BR>&nbsp;&nbsp;document = (HTMLDocument)editorKit.createDefaultDocument(); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;// 强制SWINGSET实现跨平台，不改变风格 <BR>&nbsp;&nbsp;try <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); <BR>&nbsp;&nbsp;&nbsp;// 如果你想用系统的界面风格替代，请注释掉上一行代码，而取消下一行代码的注释： <BR>&nbsp;&nbsp;&nbsp;//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;catch (Exception exc) <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;//产生异常，则显示错误消息：加载L&amp;F错误<BR>&nbsp;&nbsp;&nbsp;System.err.println("Error loading L&amp;F: " + exc); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//调用初始化方法<BR>&nbsp;&nbsp;init(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**主方法，起动程序*/<BR>&nbsp;public static void main(String[] args)<BR>&nbsp;{ <BR>&nbsp;&nbsp;//创建一个类的实例，即创建一个网页编辑器<BR>&nbsp;&nbsp;HTMLDocumentEditor editor = new HTMLDocumentEditor(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**初始化各组件的方法*/<BR>&nbsp;public void init()<BR>&nbsp;{ <BR>&nbsp;&nbsp;//调用自定义继承WindowListener的侦听器FrameListener，给主窗体添加WindowListener<BR>&nbsp;&nbsp;addWindowListener(new FrameListener()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuBar menuBar = new JMenuBar(); <BR>&nbsp;&nbsp;getContentPane().add(menuBar, BorderLayout.NORTH); <BR>&nbsp;&nbsp;JMenu fileMenu = new JMenu("File"); &nbsp;//文件<BR>&nbsp;&nbsp;JMenu editMenu = new JMenu("Edit"); &nbsp;//编辑<BR>&nbsp;&nbsp;JMenu colorMenu = new JMenu("Color"); &nbsp;//颜色<BR>&nbsp;&nbsp;JMenu fontMenu = new JMenu("Font"); &nbsp;//字体<BR>&nbsp;&nbsp;JMenu styleMenu = new JMenu("Style"); &nbsp;//样式<BR>&nbsp;&nbsp;JMenu alignMenu = new JMenu("Align"); &nbsp;//对齐<BR>&nbsp;&nbsp;JMenu helpMenu = new JMenu("Help"); &nbsp;//帮助<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;menuBar.add(fileMenu); <BR>&nbsp;&nbsp;menuBar.add(editMenu); <BR>&nbsp;&nbsp;menuBar.add(colorMenu); <BR>&nbsp;&nbsp;menuBar.add(fontMenu); <BR>&nbsp;&nbsp;menuBar.add(styleMenu); <BR>&nbsp;&nbsp;menuBar.add(alignMenu); <BR>&nbsp;&nbsp;menuBar.add(helpMenu); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem newItem = new JMenuItem("New", new ImageIcon("whatsnew-bang.gif")); &nbsp;//新建<BR>&nbsp;&nbsp;JMenuItem openItem = new JMenuItem("Open",new ImageIcon("open.gif")); &nbsp;&nbsp;&nbsp;//打开<BR>&nbsp;&nbsp;JMenuItem saveItem = new JMenuItem("Save",new ImageIcon("save.gif")); &nbsp;&nbsp;&nbsp;//保存<BR>&nbsp;&nbsp;JMenuItem saveAsItem = new JMenuItem("Save As"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//另存<BR>&nbsp;&nbsp;JMenuItem exitItem = new JMenuItem("Exit",new ImageIcon("exit.gif")); &nbsp;&nbsp;&nbsp;//退出<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;newItem.addActionListener(this); <BR>&nbsp;&nbsp;openItem.addActionListener(this); <BR>&nbsp;&nbsp;saveItem.addActionListener(this); <BR>&nbsp;&nbsp;saveAsItem.addActionListener(this); <BR>&nbsp;&nbsp;exitItem.addActionListener(this); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;fileMenu.add(newItem); <BR>&nbsp;&nbsp;fileMenu.add(openItem); <BR>&nbsp;&nbsp;fileMenu.add(saveItem); <BR>&nbsp;&nbsp;fileMenu.add(saveAsItem); <BR>&nbsp;&nbsp;fileMenu.add(exitItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//给菜单项添加侦听器<BR>&nbsp;&nbsp;JMenuItem undoItem = new JMenuItem(undoAction); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//撤消<BR>&nbsp;&nbsp;JMenuItem redoItem = new JMenuItem(redoAction); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//恢复<BR>&nbsp;&nbsp;JMenuItem cutItem = new JMenuItem(cutAction); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//剪切<BR>&nbsp;&nbsp;JMenuItem copyItem = new JMenuItem(copyAction); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//复制<BR>&nbsp;&nbsp;JMenuItem pasteItem = new JMenuItem(pasteAction); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//粘贴<BR>&nbsp;&nbsp;JMenuItem clearItem = new JMenuItem("Clear"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清除<BR>&nbsp;&nbsp;JMenuItem selectAllItem = new JMenuItem("Select All"); &nbsp;&nbsp;&nbsp;&nbsp;//全选<BR>&nbsp;&nbsp;JMenuItem insertBreaKItem = new JMenuItem(insertBreakAction); &nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem unorderedListItem = new JMenuItem(unorderedListAction); <BR>&nbsp;&nbsp;JMenuItem bulletItem = new JMenuItem(bulletAction); &nbsp;&nbsp;&nbsp;&nbsp;//项目符号<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;cutItem.setText("Cut"); <BR>&nbsp;&nbsp;copyItem.setText("Copy"); <BR>&nbsp;&nbsp;pasteItem.setText("Paste"); <BR>&nbsp;&nbsp;insertBreaKItem.setText("Break"); <BR>&nbsp;&nbsp;cutItem.setIcon(new ImageIcon("cut.gif")); <BR>&nbsp;&nbsp;copyItem.setIcon(new ImageIcon("copy.gif")); <BR>&nbsp;&nbsp;pasteItem.setIcon(new ImageIcon("paste.gif")); <BR>&nbsp;&nbsp;insertBreaKItem.setIcon(new ImageIcon("break.gif")); <BR>&nbsp;&nbsp;unorderedListItem.setIcon(new ImageIcon("bullets.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;clearItem.addActionListener(this); <BR>&nbsp;&nbsp;selectAllItem.addActionListener(this); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;editMenu.add(undoItem); <BR>&nbsp;&nbsp;editMenu.add(redoItem); <BR>&nbsp;&nbsp;editMenu.add(cutItem); <BR>&nbsp;&nbsp;editMenu.add(copyItem); <BR>&nbsp;&nbsp;editMenu.add(pasteItem); <BR>&nbsp;&nbsp;editMenu.add(clearItem); <BR>&nbsp;&nbsp;editMenu.add(selectAllItem); <BR>&nbsp;&nbsp;editMenu.add(insertBreaKItem); <BR>&nbsp;&nbsp;editMenu.add(unorderedListItem); <BR>&nbsp;&nbsp;editMenu.add(bulletItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem redTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Red",Color.red)); <BR>&nbsp;&nbsp;JMenuItem orangeTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Orange",Color.orange)); <BR>&nbsp;&nbsp;JMenuItem yellowTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Yellow",Color.yellow)); <BR>&nbsp;&nbsp;JMenuItem greenTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Green",Color.green)); <BR>&nbsp;&nbsp;JMenuItem blueTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Blue",Color.blue)); <BR>&nbsp;&nbsp;JMenuItem cyanTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Cyan",Color.cyan)); <BR>&nbsp;&nbsp;JMenuItem magentaTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Magenta",Color.magenta)); <BR>&nbsp;&nbsp;JMenuItem blackTextItem = new JMenuItem(new StyledEditorKit.ForegroundAction("Black",Color.black)); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;redTextItem.setIcon(new ImageIcon("red.gif")); <BR>&nbsp;&nbsp;orangeTextItem.setIcon(new ImageIcon("orange.gif")); <BR>&nbsp;&nbsp;yellowTextItem.setIcon(new ImageIcon("yellow.gif")); <BR>&nbsp;&nbsp;greenTextItem.setIcon(new ImageIcon("green.gif")); <BR>&nbsp;&nbsp;blueTextItem.setIcon(new ImageIcon("blue.gif")); <BR>&nbsp;&nbsp;cyanTextItem.setIcon(new ImageIcon("cyan.gif")); <BR>&nbsp;&nbsp;magentaTextItem.setIcon(new ImageIcon("magenta.gif")); <BR>&nbsp;&nbsp;blackTextItem.setIcon(new ImageIcon("black.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;colorMenu.add(redTextItem); <BR>&nbsp;&nbsp;colorMenu.add(orangeTextItem); <BR>&nbsp;&nbsp;colorMenu.add(yellowTextItem); <BR>&nbsp;&nbsp;colorMenu.add(greenTextItem); <BR>&nbsp;&nbsp;colorMenu.add(blueTextItem); <BR>&nbsp;&nbsp;colorMenu.add(cyanTextItem); <BR>&nbsp;&nbsp;colorMenu.add(magentaTextItem); <BR>&nbsp;&nbsp;colorMenu.add(blackTextItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenu fontTypeMenu = new JMenu("Font Type"); <BR>&nbsp;&nbsp;fontMenu.add(fontTypeMenu); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;String[] fontTypes = {"SansSerif", "Serif", "Monospaced", "Dialog", "DialogInput"}; <BR>&nbsp;&nbsp;for (int i = 0; i &lt; fontTypes.length;i++)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;if (debug) System.out.println(fontTypes[i]); <BR>&nbsp;&nbsp;&nbsp;JMenuItem nextTypeItem = new JMenuItem(fontTypes[i]); <BR>&nbsp;&nbsp;&nbsp;nextTypeItem.setAction(new StyledEditorKit.FontFamilyAction(fontTypes[i], fontTypes[i])); <BR>&nbsp;&nbsp;&nbsp;fontTypeMenu.add(nextTypeItem); <BR>&nbsp;&nbsp;} <BR>&nbsp;<BR>&nbsp;&nbsp;JMenu fontSizeMenu = new JMenu("Font Size"); <BR>&nbsp;&nbsp;fontMenu.add(fontSizeMenu); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;int[] fontSizes = {6, 8,10,12,14, 16, 20,24, 32,36,48,72}; <BR>&nbsp;&nbsp;for (int i = 0; i &lt; fontSizes.length;i++)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;if (debug) System.out.println(fontSizes[i]); <BR>&nbsp;&nbsp;&nbsp;JMenuItem nextSizeItem = new JMenuItem(String.valueOf(fontSizes[i])); <BR>&nbsp;&nbsp;&nbsp;nextSizeItem.setAction(new StyledEditorKit.FontSizeAction(String.valueOf(fontSizes[i]), fontSizes[i])); <BR>&nbsp;&nbsp;&nbsp;fontSizeMenu.add(nextSizeItem); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem boldMenuItem = new JMenuItem(boldAction); <BR>&nbsp;&nbsp;JMenuItem underlineMenuItem = new JMenuItem(underlineAction); <BR>&nbsp;&nbsp;JMenuItem italicMenuItem = new JMenuItem(italicAction); <BR>&nbsp;<BR>&nbsp;&nbsp;boldMenuItem.setText("Bold"); <BR>&nbsp;&nbsp;underlineMenuItem.setText("Underline"); <BR>&nbsp;&nbsp;italicMenuItem.setText("Italic"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;boldMenuItem.setIcon(new ImageIcon("bold.gif")); <BR>&nbsp;&nbsp;underlineMenuItem.setIcon(new ImageIcon("underline.gif")); <BR>&nbsp;&nbsp;italicMenuItem.setIcon(new ImageIcon("italic.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;styleMenu.add(boldMenuItem); <BR>&nbsp;&nbsp;styleMenu.add(underlineMenuItem); <BR>&nbsp;&nbsp;styleMenu.add(italicMenuItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem subscriptMenuItem = new JMenuItem(new SubscriptAction()); <BR>&nbsp;&nbsp;JMenuItem superscriptMenuItem = new JMenuItem(new SuperscriptAction()); <BR>&nbsp;&nbsp;JMenuItem strikeThroughMenuItem = new JMenuItem(new StrikeThroughAction()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;subscriptMenuItem.setText("Subscript"); <BR>&nbsp;&nbsp;superscriptMenuItem.setText("Superscript"); <BR>&nbsp;&nbsp;strikeThroughMenuItem.setText("StrikeThrough"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;subscriptMenuItem.setIcon(new ImageIcon("subscript.gif")); <BR>&nbsp;&nbsp;superscriptMenuItem.setIcon(new ImageIcon("superscript.gif")); <BR>&nbsp;&nbsp;strikeThroughMenuItem.setIcon(new ImageIcon("strikethough.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;styleMenu.add(subscriptMenuItem); <BR>&nbsp;&nbsp;styleMenu.add(superscriptMenuItem); <BR>&nbsp;&nbsp;styleMenu.add(strikeThroughMenuItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem leftAlignMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction("Left Align",StyleConstants.ALIGN_LEFT)); <BR>&nbsp;&nbsp;JMenuItem centerMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction("Center",StyleConstants.ALIGN_CENTER)); <BR>&nbsp;&nbsp;JMenuItem rightAlignMenuItem = new JMenuItem(new StyledEditorKit.AlignmentAction ("Right Align",StyleConstants.ALIGN_RIGHT)); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;leftAlignMenuItem.setText("Left Align"); <BR>&nbsp;&nbsp;centerMenuItem.setText("Center"); <BR>&nbsp;&nbsp;rightAlignMenuItem.setText("Right Align"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;leftAlignMenuItem.setIcon(new ImageIcon("left.gif")); <BR>&nbsp;&nbsp;centerMenuItem.setIcon(new ImageIcon("center.gif")); <BR>&nbsp;&nbsp;rightAlignMenuItem.setIcon(new ImageIcon("right.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;alignMenu.add(leftAlignMenuItem); <BR>&nbsp;&nbsp;alignMenu.add(centerMenuItem); <BR>&nbsp;&nbsp;alignMenu.add(rightAlignMenuItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem helpItem = new JMenuItem("帮助"); <BR>&nbsp;&nbsp;helpItem.addActionListener(this); <BR>&nbsp;&nbsp;helpMenu.add(helpItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem shortcutsItem = new JMenuItem("Keyboard Shortcuts"); <BR>&nbsp;&nbsp;shortcutsItem.addActionListener(this); <BR>&nbsp;&nbsp;helpMenu.add(shortcutsItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JMenuItem aboutItem = new JMenuItem("About QuantumHyperSpace"); <BR>&nbsp;&nbsp;aboutItem.addActionListener(this); <BR>&nbsp;&nbsp;helpMenu.add(aboutItem); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JPanel editorControlPanel = new JPanel(); <BR>&nbsp;&nbsp;//editorControlPanel.setLayout(new GridLayout(3,3)); <BR>&nbsp;&nbsp;editorControlPanel.setLayout(new FlowLayout()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;/* 按钮 */ <BR>&nbsp;&nbsp;JButton cutButton = new JButton(cutAction); &nbsp;&nbsp;&nbsp;//创建“剪切”按钮，添加剪切侦听<BR>&nbsp;&nbsp;JButton copyButton = new JButton(copyAction); &nbsp;&nbsp;&nbsp;//创建“复制”按钮，添加复制侦<BR>&nbsp;&nbsp;JButton pasteButton = new JButton(pasteAction); &nbsp;&nbsp;//创建“粘贴”按钮，添加粘贴侦<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JButton boldButton = new JButton(boldAction); &nbsp;&nbsp;&nbsp;//创建“加粗”按钮，添加加粗侦听<BR>&nbsp;&nbsp;JButton underlineButton = new JButton(underlineAction); //创建“下划线”按钮，添加下划线侦听<BR>&nbsp;&nbsp;JButton italicButton = new JButton(italicAction); &nbsp;&nbsp;//创建“斜体”按钮，添加斜体侦听<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//JButton insertButton = new JButton(insertAction); <BR>&nbsp;&nbsp;//JButton insertBreakButton = new JButton(insertBreakAction); <BR>&nbsp;&nbsp;//JButton tabButton = new JButton(tabAction); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;cutButton.setText("Cut"); <BR>&nbsp;&nbsp;copyButton.setText("Copy"); <BR>&nbsp;&nbsp;pasteButton.setText("Paste"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;boldButton.setText("Bold"); <BR>&nbsp;&nbsp;underlineButton.setText("Underline"); <BR>&nbsp;&nbsp;italicButton.setText("Italic"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//insertButton.setText("Insert"); <BR>&nbsp;&nbsp;//insertBreakButton.setText("Insert Break"); <BR>&nbsp;&nbsp;//tabButton.setText("Tab"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;cutButton.setIcon(new ImageIcon("cut.gif")); <BR>&nbsp;&nbsp;copyButton.setIcon(new ImageIcon("copy.gif")); <BR>&nbsp;&nbsp;pasteButton.setIcon(new ImageIcon("paste.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;boldButton.setIcon(new ImageIcon("bold.gif")); <BR>&nbsp;&nbsp;underlineButton.setIcon(new ImageIcon("underline.gif")); <BR>&nbsp;&nbsp;italicButton.setIcon(new ImageIcon("italic.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;editorControlPanel.add(cutButton); <BR>&nbsp;&nbsp;editorControlPanel.add(copyButton); <BR>&nbsp;&nbsp;editorControlPanel.add(pasteButton); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;editorControlPanel.add(boldButton); <BR>&nbsp;&nbsp;editorControlPanel.add(underlineButton); <BR>&nbsp;&nbsp;editorControlPanel.add(italicButton); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//editorControlPanel.add(insertButton); <BR>&nbsp;&nbsp;//editorControlPanel.add(insertBreakButton); <BR>&nbsp;&nbsp;//editorControlPanel.add(tabButton); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JButton subscriptButton = new JButton(new SubscriptAction()); <BR>&nbsp;&nbsp;JButton superscriptButton = new JButton(new SuperscriptAction()); <BR>&nbsp;&nbsp;JButton strikeThroughButton = new JButton(new StrikeThroughAction()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;subscriptButton.setIcon(new ImageIcon("subscript.gif")); <BR>&nbsp;&nbsp;superscriptButton.setIcon(new ImageIcon("superscript.gif")); <BR>&nbsp;&nbsp;strikeThroughButton.setIcon(new ImageIcon("strikethough.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JPanel specialPanel = new JPanel(); <BR>&nbsp;&nbsp;specialPanel.setLayout(new FlowLayout()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;specialPanel.add(subscriptButton); <BR>&nbsp;&nbsp;specialPanel.add(superscriptButton); <BR>&nbsp;&nbsp;specialPanel.add(strikeThroughButton); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//JButton leftAlignButton = new JButton(new AlignLeftAction()); <BR>&nbsp;&nbsp;//JButton centerButton = new JButton(new CenterAction()); <BR>&nbsp;&nbsp;//JButton rightAlignButton = new JButton(new AlignRightAction()); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JButton leftAlignButton = new JButton(new StyledEditorKit.AlignmentAction("Left Align",StyleConstants.ALIGN_LEFT)); <BR>&nbsp;&nbsp;JButton centerButton = new JButton(new StyledEditorKit.AlignmentAction("Center",StyleConstants.ALIGN_CENTER)); <BR>&nbsp;&nbsp;JButton rightAlignButton = new JButton(new StyledEditorKit.AlignmentAction ("Right Align",StyleConstants.ALIGN_RIGHT)); <BR>&nbsp;&nbsp;JButton colorButton = new JButton(new StyledEditorKit.AlignmentAction ("Right Align",StyleConstants.ALIGN_RIGHT)); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;leftAlignButton.setIcon(new ImageIcon("left.gif")); <BR>&nbsp;&nbsp;centerButton.setIcon(new ImageIcon("center.gif")); <BR>&nbsp;&nbsp;rightAlignButton.setIcon(new ImageIcon("right.gif")); <BR>&nbsp;&nbsp;colorButton.setIcon(new ImageIcon("color.gif")); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;leftAlignButton.setText("Left Align"); <BR>&nbsp;&nbsp;centerButton.setText("Center"); <BR>&nbsp;&nbsp;rightAlignButton.setText("Right Align"); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;JPanel alignPanel = new JPanel(); <BR>&nbsp;&nbsp;alignPanel.setLayout(new FlowLayout()); <BR>&nbsp;&nbsp;alignPanel.add(leftAlignButton); <BR>&nbsp;&nbsp;alignPanel.add(centerButton); <BR>&nbsp;&nbsp;alignPanel.add(rightAlignButton); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;document.addUndoableEditListener(undoHandler); <BR>&nbsp;&nbsp;resetUndoManager(); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;textPane = new JTextPane(document); <BR>&nbsp;&nbsp;textPane.setContentType("text/html"); <BR>&nbsp;&nbsp;JScrollPane scrollPane = new JScrollPane(textPane); <BR>&nbsp;&nbsp;Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); <BR>&nbsp;&nbsp;Dimension scrollPaneSize = new Dimension(5*screenSize.width/8,5*screenSize.height/8); <BR>&nbsp;&nbsp;scrollPane.setPreferredSize(scrollPaneSize); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//创建工具栏面板，并设置面板布局管理器，添加子面板<BR>&nbsp;&nbsp;JPanel toolPanel = new JPanel(); <BR>&nbsp;&nbsp;toolPanel.setLayout(new BorderLayout()); <BR>&nbsp;&nbsp;toolPanel.add(editorControlPanel, BorderLayout.NORTH); <BR>&nbsp;&nbsp;toolPanel.add(specialPanel, BorderLayout.CENTER); <BR>&nbsp;&nbsp;toolPanel.add(alignPanel, BorderLayout.SOUTH); <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;//向主窗体添加菜单栏<BR>&nbsp;&nbsp;getContentPane().add(menuBar, BorderLayout.NORTH); <BR>&nbsp;&nbsp;//向主窗体添加工具栏<BR>&nbsp;&nbsp;getContentPane().add(toolPanel, BorderLayout.CENTER); <BR>&nbsp;&nbsp;//向主窗体添加滚动面板<BR>&nbsp;&nbsp;getContentPane().add(scrollPane, BorderLayout.SOUTH); <BR>&nbsp;&nbsp;pack(); <BR>&nbsp;&nbsp;setLocationRelativeTo(null); <BR>&nbsp;&nbsp;startNewDocument(); <BR>&nbsp;&nbsp;show(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void actionPerformed(ActionEvent ae)<BR>&nbsp;{ <BR>&nbsp;&nbsp;String actionCommand = ae.getActionCommand(); <BR>&nbsp;&nbsp;if (debug)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;int modifier = ae.getModifiers(); <BR>&nbsp;&nbsp;&nbsp;long when = ae.getWhen(); <BR>&nbsp;&nbsp;&nbsp;String parameter = ae.paramString(); <BR>&nbsp;&nbsp;&nbsp;System.out.println("actionCommand: " + actionCommand); <BR>&nbsp;&nbsp;&nbsp;System.out.println("modifier: " + modifier); <BR>&nbsp;&nbsp;&nbsp;System.out.println("when: " + when); <BR>&nbsp;&nbsp;&nbsp;System.out.println("parameter: " + parameter); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;if (actionCommand.compareTo("New") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;startNewDocument(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Open") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;openDocument(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Save") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;saveDocument(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Save As") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;saveDocumentAs(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Exit") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;exit(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Clear") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;clear(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Select All") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;selectAll(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("帮助") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;help(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("Keyboard Shortcuts") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;showShortcuts(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;else if (actionCommand.compareTo("About QuantumHyperSpace") == 0)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;aboutQuantumHyperSpace(); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void startNewDocument()<BR>&nbsp;{ <BR>&nbsp;&nbsp;Document oldDoc = textPane.getDocument(); <BR>&nbsp;&nbsp;if(oldDoc != null) <BR>&nbsp;&nbsp;oldDoc.removeUndoableEditListener(undoHandler); <BR>&nbsp;&nbsp;HTMLEditorKit editorKit = new HTMLEditorKit(); <BR>&nbsp;&nbsp;document = (HTMLDocument)editorKit.createDefaultDocument(); <BR>&nbsp;&nbsp;textPane.setDocument(document); <BR>&nbsp;&nbsp;currentFile = null; <BR>&nbsp;&nbsp;setTitle("HTMLDocumentEditor"); <BR>&nbsp;&nbsp;textPane.getDocument().addUndoableEditListener(undoHandler); <BR>&nbsp;&nbsp;resetUndoManager(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void openDocument()<BR>&nbsp;{ <BR>&nbsp;&nbsp;try<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;File current = new File("."); <BR>&nbsp;&nbsp;&nbsp;JFileChooser chooser = new JFileChooser(current); <BR>&nbsp;&nbsp;&nbsp;chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); <BR>&nbsp;&nbsp;&nbsp;chooser.setFileFilter(new HTMLFileFilter()); <BR>&nbsp;&nbsp;&nbsp;int approval = chooser.showSaveDialog(this); <BR>&nbsp;&nbsp;&nbsp;if (approval == JFileChooser.APPROVE_OPTION)<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;currentFile = chooser.getSelectedFile(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;setTitle(currentFile.getName()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;FileReader fr = new FileReader(currentFile); <BR>&nbsp;&nbsp;&nbsp;&nbsp;Document oldDoc = textPane.getDocument(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;if(oldDoc != null) <BR>&nbsp;&nbsp;&nbsp;&nbsp;oldDoc.removeUndoableEditListener(undoHandler); <BR>&nbsp;&nbsp;&nbsp;&nbsp;HTMLEditorKit editorKit = new HTMLEditorKit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;document = (HTMLDocument)editorKit.createDefaultDocument(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;editorKit.read(fr,document,0); <BR>&nbsp;&nbsp;&nbsp;&nbsp;document.addUndoableEditListener(undoHandler); <BR>&nbsp;&nbsp;&nbsp;&nbsp;textPane.setDocument(document); <BR>&nbsp;&nbsp;&nbsp;&nbsp;resetUndoManager(); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;catch(BadLocationException ble)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.err.println("BadLocationException: " + ble.getMessage()); <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;catch(FileNotFoundException fnfe)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.err.println("FileNotFoundException: " + fnfe.getMessage()); <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;catch(IOException ioe)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.err.println("IOException: " + ioe.getMessage()); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void saveDocument()<BR>&nbsp;{ <BR>&nbsp;&nbsp;if (currentFile != null)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;try<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;FileWriter fw = new FileWriter(currentFile); <BR>&nbsp;&nbsp;&nbsp;&nbsp;fw.write(textPane.getText()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;fw.close(); <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;catch(FileNotFoundException fnfe)<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;System.err.println("FileNotFoundException: " + fnfe.getMessage()); <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;catch(IOException ioe)<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;System.err.println("IOException: " + ioe.getMessage()); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;else<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;saveDocumentAs(); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void saveDocumentAs()<BR>&nbsp;{ <BR>&nbsp;&nbsp;try<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;File current = new File("."); <BR>&nbsp;&nbsp;&nbsp;JFileChooser chooser = new JFileChooser(current); <BR>&nbsp;&nbsp;&nbsp;chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); <BR>&nbsp;&nbsp;&nbsp;chooser.setFileFilter(new HTMLFileFilter()); <BR>&nbsp;&nbsp;&nbsp;int approval = chooser.showSaveDialog(this); <BR>&nbsp;&nbsp;&nbsp;if (approval == JFileChooser.APPROVE_OPTION)<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;File newFile = chooser.getSelectedFile(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;if (newFile.exists())<BR>&nbsp;&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String message = newFile.getAbsolutePath() + " already exists. \n" + "Do you want to replace it?"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (JOptionPane.showConfirmDialog(this, message) == JOptionPane.YES_OPTION)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentFile = newFile; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTitle(currentFile.getName()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileWriter fw = new FileWriter(currentFile); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fw.write(textPane.getText()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fw.close(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (debug) System.out.println("Saved " + currentFile.getAbsolutePath()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentFile = new File(newFile.getAbsolutePath()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTitle(currentFile.getName()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileWriter fw = new FileWriter(currentFile); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fw.write(textPane.getText()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fw.close(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (debug) System.out.println("Saved " + currentFile.getAbsolutePath()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;catch(FileNotFoundException fnfe)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.err.println("FileNotFoundException: " + fnfe.getMessage()); <BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;catch(IOException ioe)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.err.println("IOException: " + ioe.getMessage()); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void exit()<BR>&nbsp;{ <BR>&nbsp;&nbsp;String exitMessage = "Are you sure you want to exit?"; <BR>&nbsp;&nbsp;if (JOptionPane.showConfirmDialog(this, exitMessage) == JOptionPane.YES_OPTION)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;System.exit(0); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**调用startNewDocument()方法，清除当前文本，开始一个新文档*/<BR>&nbsp;public void clear()<BR>&nbsp;{ <BR>&nbsp;&nbsp;startNewDocument(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**调用JTextPane的全选方法*/<BR>&nbsp;public void selectAll()<BR>&nbsp;{ <BR>&nbsp;&nbsp;textPane.selectAll(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**利用消息框显示帮助信息*/<BR>&nbsp;public void help()<BR>&nbsp;{ <BR>&nbsp;&nbsp;JOptionPane.showMessageDialog(this,"DocumentEditor.java\n" + "Author: Charles Bell\n" + "Version: May 25, 2002\n" + <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<A href="http://www.quantumhyperspace.com\n">http://www.quantumhyperspace.com\n</A>" + "QuantumHyperSpace Programming Services"); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**利用消息框显示快捷键*/<BR>&nbsp;public void showShortcuts()<BR>&nbsp;{ <BR>&nbsp;&nbsp;String shortcuts = "Navigate in | Tab\n" + "Navigate out | Ctrl+Tab\n" + "Navigate out backwards | Shift+Ctrl+Tab\n" + <BR>&nbsp;&nbsp;"Move up/down a line | Up/Down Arrown\n" + "Move left/right a component or char | Left/Right Arrow\n" + <BR>&nbsp;&nbsp;"Move up/down one vertical block | PgUp/PgDn\n" + "Move to start/end of line | Home/End\n" + <BR>&nbsp;&nbsp;"Move to previous/next word | Ctrl+Left/Right Arrow\n" + "Move to start/end of data | Ctrl+Home/End\n" + <BR>&nbsp;&nbsp;"Move left/right one block | Ctrl+PgUp/PgDn\n" + "Select All | Ctrl+A\n" + <BR>&nbsp;&nbsp;"Extend selection up one line | Shift+Up Arrow\n" + "Extend selection down one line | Shift+Down Arrow\n" + <BR>&nbsp;&nbsp;"Extend selection to beginning of line | Shift+Home\n" + "Extend selection to end of line | Shift+End\n" + <BR>&nbsp;&nbsp;"Extend selection to beginning of data | Ctrl+Shift+Home\n" + "Extend selection to end of data | Ctrl+Shift+End\n" + <BR>&nbsp;&nbsp;"Extend selection left | Shift+Right Arrow\n" + "Extend selection right | Shift+Right Arrow\n" + <BR>&nbsp;&nbsp;"Extend selection up one vertical block | Shift+PgUp\n" + "Extend selection down one vertical block | Shift+PgDn\n" + <BR>&nbsp;&nbsp;"Extend selection left one block | Ctrl+Shift+PgUp\n" + "Extend selection right one block | Ctrl+Shift+PgDn\n" + <BR>&nbsp;&nbsp;"Extend selection left one word | Ctrl+Shift+Left Arrow\n" + "Extend selection right one word | Ctrl+Shift+Right Arrow\n"; <BR>&nbsp;&nbsp;JOptionPane.showMessageDialog(this,shortcuts); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void aboutQuantumHyperSpace()<BR>&nbsp;{ <BR>&nbsp;&nbsp;JOptionPane.showMessageDialog(this,"QuantumHyperSpace Programming Services\n" + "<A href="http://www.quantumhyperspace.com\n">http://www.quantumhyperspace.com\n</A>" + <BR>&nbsp;&nbsp;"email: <A href="mailto:support@quantumhyperspace.com\n">support@quantumhyperspace.com\n</A>" + &nbsp;" or \n" + "email: <A href="mailto:charles@quantumhyperspace.com\n">charles@quantumhyperspace.com\n</A>", <BR>&nbsp;&nbsp;"QuantumHyperSpace",JOptionPane.INFORMATION_MESSAGE, new ImageIcon("quantumhyperspace.gif")); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;/**内部类：自定义继承WindowListener的侦听器FrameListener*/<BR>&nbsp;class FrameListener extends WindowAdapter<BR>&nbsp;{ <BR>&nbsp;&nbsp;/**处理点击窗体关闭按钮事件，实现程序的关闭停止*/<BR>&nbsp;&nbsp;public void windowClosing(WindowEvent we)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;exit(); <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;class SubscriptAction extends StyledEditorKit.StyledTextAction<BR>&nbsp;{ <BR>&nbsp;<BR>&nbsp;&nbsp;public SubscriptAction()<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;super(StyleConstants.Subscript.toString()); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;public void actionPerformed(ActionEvent ae)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;JEditorPane editor = getEditor(ae); <BR>&nbsp;&nbsp;&nbsp;if (editor != null) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyledEditorKit kit = getStyledEditorKit(editor); <BR>&nbsp;&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;boolean subscript = (StyleConstants.isSubscript(attr)) ? false : true; <BR>&nbsp;&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setSubscript(sas, subscript); <BR>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;} </P>
<P>&nbsp;class SuperscriptAction extends StyledEditorKit.StyledTextAction<BR>&nbsp;{ <BR>&nbsp;<BR>&nbsp;&nbsp;public SuperscriptAction()<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;super(StyleConstants.Superscript.toString()); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;public void actionPerformed(ActionEvent ae)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;JEditorPane editor = getEditor(ae); <BR>&nbsp;&nbsp;&nbsp;if (editor != null) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyledEditorKit kit = getStyledEditorKit(editor); <BR>&nbsp;&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;boolean superscript = (StyleConstants.isSuperscript(attr)) ? false : true; <BR>&nbsp;&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setSuperscript(sas, superscript); <BR>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;} </P>
<P>&nbsp;class StrikeThroughAction extends StyledEditorKit.StyledTextAction<BR>&nbsp;{ <BR>&nbsp;&nbsp;public StrikeThroughAction()<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;super(StyleConstants.StrikeThrough.toString()); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;public void actionPerformed(ActionEvent ae)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;JEditorPane editor = getEditor(ae); <BR>&nbsp;&nbsp;&nbsp;if (editor != null) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyledEditorKit kit = getStyledEditorKit(editor); <BR>&nbsp;&nbsp;&nbsp;&nbsp;MutableAttributeSet attr = kit.getInputAttributes(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;boolean strikeThrough = (StyleConstants.isStrikeThrough(attr)) ? false : true; <BR>&nbsp;&nbsp;&nbsp;&nbsp;SimpleAttributeSet sas = new SimpleAttributeSet(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;StyleConstants.setStrikeThrough(sas, strikeThrough); <BR>&nbsp;&nbsp;&nbsp;&nbsp;setCharacterAttributes(editor, sas, false); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;} </P>
<P>&nbsp;class HTMLFileFilter extends javax.swing.filechooser.FileFilter<BR>&nbsp;{ <BR>&nbsp;&nbsp;public boolean accept(File f)<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;return ((f.isDirectory()) ||(f.getName().toLowerCase().indexOf(".htm") &gt; 0)); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;public String getDescription()<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;return "html"; <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;protected void resetUndoManager() <BR>&nbsp;{ <BR>&nbsp;&nbsp;undo.discardAllEdits(); <BR>&nbsp;&nbsp;undoAction.update(); <BR>&nbsp;&nbsp;redoAction.update(); <BR>&nbsp;} </P>
<P>&nbsp;class UndoHandler implements UndoableEditListener <BR>&nbsp;{ <BR>&nbsp;&nbsp;/** <BR>&nbsp;&nbsp;* Messaged when the Document has created an edit, the edit is <BR>&nbsp;&nbsp;* added to &lt;code&gt;undo&lt;/code&gt;, an instance of UndoManager. <BR>&nbsp;&nbsp;*/ <BR>&nbsp;&nbsp;public void undoableEditHappened(UndoableEditEvent e) <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;undo.addEdit(e.getEdit()); <BR>&nbsp;&nbsp;&nbsp;undoAction.update(); <BR>&nbsp;&nbsp;&nbsp;redoAction.update(); <BR>&nbsp;&nbsp;} <BR>&nbsp;} </P>
<P>&nbsp;class UndoAction extends AbstractAction <BR>&nbsp;{ <BR>&nbsp;&nbsp;public UndoAction() <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;super("Undo"); <BR>&nbsp;&nbsp;&nbsp;setEnabled(false); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;public void actionPerformed(ActionEvent e) <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;try <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;undo.undo(); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;catch (CannotUndoException ex) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Unable to undo: " + ex); <BR>&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace(); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;update(); <BR>&nbsp;&nbsp;&nbsp;redoAction.update(); <BR>&nbsp;&nbsp;} <BR>&nbsp;<BR>&nbsp;&nbsp;protected void update() <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;if(undo.canUndo()) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;setEnabled(true); <BR>&nbsp;&nbsp;&nbsp;&nbsp;putValue(Action.NAME, undo.getUndoPresentationName()); <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;else <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;setEnabled(false); <BR>&nbsp;&nbsp;&nbsp;&nbsp;putValue(Action.NAME, "Undo"); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;} </P>
<P>&nbsp;class RedoAction extends AbstractAction <BR>&nbsp;{ <BR>&nbsp;<BR>&nbsp;&nbsp;public RedoAction() <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;super("Redo"); <BR>&nbsp;&nbsp;&nbsp;setEnabled(false); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;public void actionPerformed(ActionEvent e) <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;try <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;undo.redo(); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;catch (CannotRedoException ex) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;System.err.println("Unable to redo: " + ex); <BR>&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace(); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;update(); <BR>&nbsp;&nbsp;&nbsp;undoAction.update(); <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;protected void update() <BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;if(undo.canRedo()) <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;setEnabled(true); <BR>&nbsp;&nbsp;&nbsp;&nbsp;putValue(Action.NAME, undo.getRedoPresentationName()); <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;else <BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;setEnabled(false); <BR>&nbsp;&nbsp;&nbsp;&nbsp;putValue(Action.NAME, "Redo"); <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;} <BR>} <BR></P><img src ="http://www.blogjava.net/aw815/aggbug/21869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aw815/" target="_blank">水秀清灵</a> 2005-11-29 22:10 <a href="http://www.blogjava.net/aw815/articles/21869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的垃圾回收机制详解和调优大全(转载)</title><link>http://www.blogjava.net/aw815/articles/20566.html</link><dc:creator>水秀清灵</dc:creator><author>水秀清灵</author><pubDate>Sat, 19 Nov 2005 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/aw815/articles/20566.html</guid><wfw:comment>http://www.blogjava.net/aw815/comments/20566.html</wfw:comment><comments>http://www.blogjava.net/aw815/articles/20566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aw815/comments/commentRss/20566.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aw815/services/trackbacks/20566.html</trackback:ping><description><![CDATA[1.JVM的gc概述 <BR><BR>gc即垃圾收集机制是指JVM用于释放那些不再使用的对象所占用的内存。Java语言并不要求JVM有gc，也没有规定gc如何工作。不过常用的JVM都有gc，而且大多数gc都使用类似的算法管理内存和执行收集操作。 <BR><BR>在充分理解了垃圾收集算法和执行过程后，才能有效的优化它的性能。有些垃圾收集专用于特殊的应用程序。比如，实时应用程序主要是为了避免垃圾收集中断，而大多数OLTP应用程序则注重整体效率。理解了应用程序的工作负荷和JVM支持的垃圾收集算法，便可以进行优化配置垃圾收集器。 <BR><BR>垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。 <BR><BR>1.1.引用计数 <BR><BR>引用计数存储对特定对象的所有引用数，也就是说，当应用程序创建引用以及引用超出范围时，JVM必须适当增减引用数。当某对象的引用数为0时，便可以进行垃圾收集。 <BR><BR>1.2.对象引用遍历 <BR><BR>早期的JVM使用引用计数，现在大多数JVM采用对象引用遍历。对象引用遍历从一组对象开始，沿着整个对象图上的每条链接，递归确定可到达（reachable）的对象。如果某对象不能从这些根对象的一个（至少一个）到达，则将它作为垃圾收集。在对象遍历阶段，gc必须记住哪些对象可以到达，以便删除不可到达的对象，这称为标记（marking）对象。 <BR><BR>下一步，gc要删除不可到达的对象。删除时，有些gc只是简单的扫描堆栈，删除未标记的未标记的对象，并释放它们的内存以生成新的对象，这叫做清除（sweeping）。这种方法的问题在于内存会分成好多小段，而它们不足以用于新的对象，但是组合起来却很大。因此，许多gc可以重新组织内存中的对象，并进行压缩（compact），形成可利用的空间。 <BR><BR>为此，gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止，只有gc运行。结果，在响应期间增减了许多混杂请求。另外，更复杂的gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作，有的则采用多线程以增加效率。 <BR><BR>2.几种垃圾回收机制 <BR><BR>2.1.标记－清除收集器 <BR><BR>这种收集器首先遍历对象图并标记可到达的对象，然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。 <BR><BR>2.2.标记－压缩收集器 <BR><BR>有时也叫标记－清除－压缩收集器，与标记－清除收集器有相同的标记阶段。在第二阶段，则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。 <BR><BR>2.3.复制收集器 <BR><BR>这种收集器将堆栈分为两个域，常称为半空间。每次仅使用一半的空间，JVM生成的新对象则放在另一半空间中。gc运行时，它把可到达对象复制到另一半空间，从而压缩了堆栈。这种方法适用于短生存期的对象，持续复制长生存期的对象则导致效率降低。 <BR><BR>2.4.增量收集器 <BR><BR>增量收集器把堆栈分为多个域，每次仅从一个域收集垃圾。这会造成较小的应用程序中断。 <BR><BR>2.5.分代收集器 <BR><BR>这种收集器把堆栈分为两个或多个域，用以存放不同寿命的对象。JVM生成的新对象一般放在其中的某个域中。过一段时间，继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。 <BR><BR>2.6.并发收集器 <BR><BR>并发收集器与应用程序同时运行。这些收集器在某点上（比如压缩时）一般都不得不停止其他操作以完成特定的任务，但是因为其他应用程序可进行其他的后台操作，所以中断其他处理的实际时间大大降低。 <BR><BR>2.7.并行收集器 <BR><BR>并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高Java应用程序的可扩展性。 <BR><BR>3.Sun HotSpot <BR><BR>1.4.1 JVM堆大小的调整 <BR><BR>Sun HotSpot 1.4.1使用分代收集器，它把堆分为三个主要的域：新域、旧域以及永久域。JVM生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后，便获得使用期并进入旧域。 <BR><BR>在永久域中JVM则存储class和method对象。就配置而言，永久域是一个独立域并且不认为是堆的一部分。下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。 <BR><BR>下面的命令是把初始大小设置为128M： <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java –Xms128m</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>–Xmx256m为控制新域的大小，可使用-XX:NewRatio设置新域在堆中所占的比例。下面的命令把整个堆设置成128m，新域比率设置成3，即新域与旧域比例为1：3，新域为堆的1/4或32M： <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java –Xms128m –Xmx128m</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。 <BR><BR>下面的命令把新域的初始值和最大值设置成64m: <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java –Xms256m –Xmx256m –Xmn64m</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>永久域默认大小为4m。运行程序时，JVM会调整永久域的大小以满足需要。每次调整时，JVM会对堆进行一次完全的垃圾收集。 <BR><BR>使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时，经常需要增加永久域的最大值。当JVM加载类时，永久域中的对象急剧增加，从而使JVM不断调整永久域大小。为了避免调整，可使用-XX:PerSize标志设置初始值。下面把永久域初始值设置成32m，最大值设置成64m。 <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java -Xms512m -Xmx512m -Xmn128m 
-XX:PermSize=32m
-XX:MaxPermSize=64m</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>默认状态下，HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden，用于生成新的对象。另两部分称为救助空间，当Eden充满时，收集器停止应用程序，把所有可到达对象复制到当前的from救助空间，一旦当前的from救助空间充满，收集器则把可到达对象复制到当前的to救助空间。 <BR><BR>From和to救助空间互换角色。维持活动的对象将在救助空间不断复制，直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可控制新域子空间的大小。 <BR><BR>同NewRation一样，SurvivorRation规定某救助域与Eden空间的比值。比如，以下命令把新域设置成64m，Eden占32m，每个救助域各占16m： <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java -Xms256m -Xmx256m -Xmn64m 
-XX:SurvivorRation =2</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER><BR><BR>如前所述，默认状态下HotSpot对新域使用复制收集器，对旧域使用标记－清除－压缩收集器。在新域中使用复制收集器有很多意义，因为应用程序生成的大部分对象是短寿命的。理想状态下，所有过渡对象在移出Eden空间时将被收集。 <BR><BR>如果能够这样的话，并且移出Eden空间的对象是长寿命的，那么理论上可以立即把它们移进旧域，避免在救助空间反复复制。但是，应用程序不能适合这种理想状态，因为它们有一小部分中长寿命的对象。 <BR><BR>最好是保持这些中长寿命的对象并放在新域中，因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制，可用-XX:TargetSurvivorRatio控制救助空间的比例（该值是设置救助空间的使用比例。 <BR><BR>如救助空间位1M，该值50表示可用500K）。该值是一个百分比，默认值是50。当较大的堆栈使用较低的sruvivorratio时，应增加该值到80至90，以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。 <BR><BR>为放置所有的复制全部发生以及希望对象从eden扩展到旧域，可以把MaxTenuring Threshold设置成0。设置完成后，实际上就不再使用救助空间了，因此应把SurvivorRatio设成最大值以最大化Eden空间，设置如下： <BR><BR>
<CENTER><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>Java … -XX:MaxTenuringThreshold=0
–XX:SurvivorRatio＝50000 …</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR></CENTER>
<P align=justify><BR>4.BEA JRockit JVM的使用 <BR><BR>Bea WebLogic 8.1使用的新的JVM用于Intel平台。在Bea安装完毕的目录下可以看到有一个类似于jrockit81sp1_141_03的文件夹。这就是Bea新JVM所在目录。不同于HotSpot把Java字节码编译成本地码，它预先编译成类。 <BR><BR>JRockit还提供了更细致的功能用以观察JVM的运行状态，主要是独立的GUI控制台（只能适用于使用Jrockit才能使用jrockit81sp1_141_03自带的console监控一些cpu及memory参数）或者WebLogic Server控制台。 <BR><BR>Bea JRockit JVM支持4种垃圾收集器： <BR><BR>4.1.1.分代复制收集器 <BR><BR>它与默认的分代收集器工作策略类似。对象在新域中分配，即JRockit文档中的nursery。这种收集器最适合单cpu机上小型堆操作。 <BR><BR>4.1.2.单空间并发收集器 <BR><BR>该收集器使用完整堆，并与背景线程共同工作。尽管这种收集器可以消除中断，但是收集器需花费较长的时间寻找死对象，而且处理应用程序时收集器经常运行。如果处理器不能应付应用程序产生的垃圾，它会中断应用程序并关闭收集。 <BR><BR>分代并发收集器 这种收集器在护理域使用排它复制收集器，在旧域中则使用并发收集器。由于它比单空间共同发生收集器中断频繁，因此它需要较少的内存，应用程序的运行效率也较高，注意，过小的护理域可以导致大量的临时对象被扩展到旧域中。这会造成收集器超负荷运作，甚至采用排它性工作方式完成收集。 <BR><BR>4.1.3.并行收集器 <BR><BR>该收集器也停止其他进程的工作，但使用多线程以加速收集进程。尽管它比其他的收集器易于引起长时间的中断，但一般能更好的利用内存，程序效率也较高。 <BR><BR>默认状态下，JRockit使用分代并发收集器。要改变收集器，可使用： <BR><BR></P><CCID_NOBR>
<CENTER>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>-Xgc:&lt;gc_name&gt;</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CENTER></CCID_NOBR>
<P align=justify><BR><BR>对应四个收集器分别为gencopy，singlecon，gencon以及parallel。可使用-Xms和-Xmx设置堆的初始大小和最大值。要设置护理域，则使用： <BR><BR></P><CCID_NOBR>
<CENTER>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>-Xns:Java –jrockit –Xms512m 
–Xmx512m –Xgc:gencon –Xns128m…</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CENTER></CCID_NOBR>
<P align=justify><BR><BR>尽管JRockit支持-verbose:gc开关，但它输出的信息会因收集器的不同而异。JRockit还支持memory、load和codegen的输出。 <BR><BR>注意 ：如果 使用JRockit JVM的话还可以使用WLS自带的console（C:\bea\jrockit81sp1_141_03\bin下）来监控一些数据，如cpu，memery等。要想能构监控必须在启动服务时startWeblogic.cmd中加入－Xmanagement参数。 <BR><BR>5.如何从JVM中获取信息来进行调整 <BR><BR>-verbose.gc开关可显示gc的操作内容。打开它，可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。打开-xx:+ printgcdetails开关，可以详细了解gc中的变化。 <BR><BR>打开-XX: + PrintGCTimeStamps开关，可以了解这些垃圾收集发生的时间，自JVM启动以后以秒计量。最后，通过-xx: + PrintHeapAtGC开关了解堆的更详细的信息。 <BR><BR>为了了解新域的情况，可以通过-XX:=PrintTenuringDistribution开关了解获得使用期的对象权。 </P>
<P align=justify><BR>6.Pdm系统JVM调整 <BR><BR>6.1.服务器：前提内存1G 单CPU <BR><BR>可通过如下参数进行调整：－server 启用服务器模式（如果CPU多，服务器机建议使用此项） <BR><BR>－Xms,－Xmx一般设为同样大小。 800m <BR><BR>－Xmn 是将NewSize与MaxNewSize设为一致。320m <BR><BR>－XX:PerSize 64m <BR><BR>－XX:NewSize 320m <BR><BR>此值设大可调大新对象区，减少Full GC次数 <BR><BR>－XX:MaxNewSize 320m <BR><BR>－XX:NewRato NewSize <BR><BR>设了可不设。 <BR><BR>－XX: SurvivorRatio <BR><BR>－XX:userParNewGC <BR><BR>可用来设置并行收集 <BR><BR>－XX:ParallelGCThreads <BR><BR>可用来增加并行度 <BR><BR>－XXUseParallelGC <BR><BR>设置后可以使用并行清除收集器 <BR><BR>－XX：UseAdaptiveSizePolicy <BR><BR>与上面一个联合使用效果更好，利用它可以自动优化新域大小以及救助空间比值 <BR><BR>6.2.客户机：通过在JNLP文件中设置参数来调整客户端JVM <BR><BR>JNLP中参数：initial-heap-size和max-heap-size <BR><BR>这可以在framework的RequestManager中生成JNLP文件时加入上述参数，但是这些值是要求根据客户机的硬件状态变化的（如客户机的内存大小等）。建议这两个参数值设为客户机可用内存的60％（有待测试）。 <BR><BR>为了在动态生成JNLP时以上两个参数值能够随客户机不同而不同，可靠虑获得客户机系统信息并将这些嵌到首页index.jsp中作为连接请求的参数。 <BR><BR>在设置了上述参数后可以通过Visualgc 来观察垃圾回收的一些参数状态，再做相应的调整来改善性能。一般的标准是减少fullgc的次数，最好硬件支持使用并行垃圾回收（要求多CPU）。 <BR><BR>(转载自赛迪网开发者论坛) </P><img src ="http://www.blogjava.net/aw815/aggbug/20566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aw815/" target="_blank">水秀清灵</a> 2005-11-19 12:54 <a href="http://www.blogjava.net/aw815/articles/20566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>提问的智慧 (转载)</title><link>http://www.blogjava.net/aw815/articles/20307.html</link><dc:creator>水秀清灵</dc:creator><author>水秀清灵</author><pubDate>Thu, 17 Nov 2005 12:19:00 GMT</pubDate><guid>http://www.blogjava.net/aw815/articles/20307.html</guid><wfw:comment>http://www.blogjava.net/aw815/comments/20307.html</wfw:comment><comments>http://www.blogjava.net/aw815/articles/20307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aw815/comments/commentRss/20307.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aw815/services/trackbacks/20307.html</trackback:ping><description><![CDATA[<H1><A name=How_To_Ask_Questions_The_Smart_W></A>How To Ask Questions The Smart Way&nbsp; </H1>
<P>Copyright (C) 2001 by Eric S. Raymond 
<P>中文版Copyleft 2001 by D.H.Grand(nOBODY/Ginux) 
<P>英文版： <A href="http://www.tuxedo.org/~esr/faqs/smart-questions.html" target=_top>http://www.tuxedo.org/~esr/faqs/smart-questions.html</A> 
<P>中文版原版位置： <A href="http://www.linuxforum.net/doc/smartq-grand.html" target=_top>http://www.linuxforum.net/doc/smartq-grand.html</A> 
<P>
<P>&nbsp;</P><CODE>==</CODE> 
<H2><A name=1></A><A name=1_></A>1.简介 </H2><CODE>==</CODE> 
<P>在黑客世界里，当提出一个技术问题时，你能得到怎样的回答？这取决于挖出答案的难度，同样取决于你提问的方法。本指南旨在帮助你提高发问技巧，以获取你最想要的答案。 
<P>首先你必须明白，黑客们只偏爱艰巨的任务，或者能激发他们思维的好问题。如若不然，我们还来干吗？如果你有值得我们反复咀嚼玩味的好问题，我们自会对你感激不尽。好问题是激励，是厚礼，可以提高我们的理解力，而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言，“问得好！”是发自内心的大力称赞。 
<P>尽管黑客们有蔑视简单问题和不友善的坏名声，有时看起来似乎我们对新手，对知识贫乏者怀有敌意，但其实不是那样的。 
<P>我们不想掩饰对这样一些人的蔑视--他们不愿思考，或者在发问前不去完成他们应该做的事。这种人只会谋杀时间--他们只愿索取，从不付出，无端消耗我们的时间，而我们本可以把时间用在更有趣的问题或者更值得回答的人身上。我们称这样的人为“失败者”（由于历史原因，我们有时把它拼作“lusers”）。 
<P>我们也知道，很多人只想使用我们编写的软件，对技术细节没什么兴趣。对多数人们而言，计算机不过是一个工具，一种达到目的的手段；他们有更重要的事情要做，有更重要的生活要过。我们明白这点，也并不奢望每个人都对另我们痴狂的技术问题有兴致。然而，我们回答问题的风格是针对这样一群人--他们有兴趣，并且愿意积极参与问题的解决。这点不会改变，也不应该改变；如果变了，我们将失去我们引以为傲的效率。 
<P>我们在很大程度上属于志愿者，从繁忙的生活中抽出时间来解惑答疑，而且时常被提问淹没。所以我们无情的滤掉一些话题，特别是抛弃那些看起来象失败者的家伙，以便更高效的利用时间来回答胜利者的问题。 
<P>如果你觉得我们过于傲慢的态度让你不爽，让你委屈，不妨设身处地想想。我们并没有要求你向我们屈服--事实上，我们中的大多数人最喜欢公平交易不过了，只要你付出小小努力来满足最起码的要求，我们就会欢迎你加入到我们的文化中来。但让我们帮助那些不愿意帮助自己的人是没有意义的。如果你不能接受这种“歧视”，我们建议你花点钱找家商业公司签个技术支持协议得了，别向黑客乞求帮助。 
<P>如果你决定向我们求助，当然不希望被视为失败者，更不愿成为失败者中的一员。立刻得到有效答案的最好方法，就是象胜利者那样提问--聪明、自信、有解决问题的思路，只是偶尔在特定的问题上需要获得一点帮助。 
<P>（欢迎对本指南提出改进意见。任何建议请E-mail至esr@thyrsus.com，然而请注意，本文并非网络礼节的通用指南，我通常会拒绝无助于在技术论坛得到有用答案的建议。） 
<P>（当然，如果你写中文，最好还是寄到DHGrand@hotmail.com;-） 
<P><CODE><B>====</B></CODE> 
<H2><A name=2></A><A name=2_></A>2.提问之前 </H2><CODE><B>====</B></CODE> 
<P>在通过电邮、新闻组或者聊天室提出技术问题前，检查你有没有做到： 
<P>
<OL>
<LI>通读手册，试着自己找答案。 
<LI>在FAQ里找答案（一份维护得好的FAQ可以包罗万象:）。 
<LI>在网上搜索（个人推荐google~）。 
<LI>向你身边精于此道的朋友打听。 </LI></OL>
<P>
<P>当你提出问题的时候，首先要说明在此之前你干了些什么；这将有助于树立你的形象：你不是一个妄图不劳而获的乞讨者，不愿浪费别人的时间。能说明你从这些操作中学到了什么就更好了。如果提问者能从答案中学到东西，我们更乐于回答他的问题。 
<P>周全的思考，准备好你的问题，草率的发问只能得到草率的回答，或者根本得不到任何答案。越表现出在寻求帮助前为解决问题付出的努力，你越能得到实质性的帮助。 
<P>小心别问错了问题。如果你的问题基于错误的假设，普通黑客（J. Random Hacker）通常会用无意义的字面解释来答复你，心里想着“蠢问题...”，希望着你会从问题的回答（而非你想得到的答案）中汲取教训。 
<P>决不要自以为够资格得到答案，你没这种资格。毕竟你没有为这种服务支付任何报酬。你要自己去“挣”回一个答案，靠提出一个有内涵的，有趣的，有思维激励作用的问题--一个对社区的经验有潜在贡献的问题，而不仅仅是被动的从他人处索要知识--去挣到这个答案。 
<P>另一方面，表明你愿意在找答案的过程中做点什么，是一个非常好的开端。“谁能给点提示？”、“我这个例子里缺了什么？”以及“我应该检查什么地方？”比“请把确切的过程贴出来”更容易得到答复。因为你显得只要有人指点正确的方向，你就有完成它的能力和决心。 
<P><CODE><B>====</B></CODE> 
<H2><A name=3></A><A name=3_></A>3.怎样提问 </H2><CODE><B>====</B></CODE> 
<P>
<HR>

<H3><A name=3_1></A><A name=3_1_></A>3.1谨慎选择论坛 </H3>
<HR>

<P>
<P>小心选择提问的场合。如果象下面描述的那样，你很可能被忽略掉或者被看作失败者： 
<P>
<OL>
<LI>在风马牛不相及的论坛贴出你的问题 
<LI>在探讨高级技巧的论坛张贴非常初级的问题；反之亦然 
<LI>在太多的不同新闻组交叉张贴 </LI></OL>
<P>黑客们通常砍掉问错地方的问题，以保护自己的社区不被大量无关帖子淹没。你不会希望自己的帖子被这样砍掉吧。 
<P>总的说来，问题发到精心挑选的公众论坛，比发到封闭的小圈子更容易得到有用的答案。这一现象有多种原因，其中之一是公众论坛有更多潜在的问题回答者；另一个原因是公众论坛有更多的听众。黑客们更愿意让尽量多的人--而非有限的一两个--从回答中受益。 
<P>
<HR>

<H3><A name=3_2></A><A name=3_2_></A>3.2尽量使用邮件列表 </H3>
<HR>

<P>如果某项目有自己的开发邮件列表，要把问题发到这个邮件列表而不是某个开发者，即使你很清楚谁最能回答你的问题。仔细查看项目文档和项目主页，找到这个项目的邮件列表地址，这样做的理由有四： 
<P>
<OL>
<LI>任何值得问某位开发者的好问题，都值得向整个开发团体提出。反之，若你认为这个问题不值得在邮件列表中提起，就没有理由用它来骚扰任何一位开发者。 
<LI>在邮件列表提问可以分担开发者的工作量。某位开发者（尤其当他是项目负责人的情况下），可能忙得没时间回答你的问题。 
<LI>大多数邮件列表都有历史存档，而且都能在搜索引擎中检索到。人们可以从中找到你的问题和答案，不用一遍又一遍在列表中发问。 
<LI>如果某个问题经常被提出，开发者可以据此改进文档或改进软件，以减少用户的困惑。而如果问题总在私下提出，就不会有人对此有整体上的把握了。 </LI></OL>
<P>如果你找不到项目的邮件列表地址，只能看到项目维护者的，那就写给维护者吧。在这种情况下，也别以为邮件列表并不存在。在你的信中写明你已尽力寻找，仍无法找到邮件列表。另外表明你不介意将此消息转给他人。（大多数人认为私信就应该是私下的，即使并没有什么可保密的内容。允许你的消息被转寄给他人，给了收信者一种处理你邮件的选择。） 
<P>
<P>
<HR>

<H3><A name=3_3></A><A name=3_3_></A>3.3用辞贴切，语法正确，拼写无误 </H3>
<HR>

<P>我们从经验中发现，粗心的写作者通常也是马虎的思考者（我敢打包票）。回答粗心大意者的问题很不值得，我们宁愿把时间耗在别处。 
<P>因此，明确充分表述你的问题非常重要。如果你嫌这样做麻烦，我们也会懒得搭理你。注意推敲你的用辞，不一定要用呆板正式的语言--事实上，黑客文化的价值观是不拘小节。准确的运用俚语和富有幽默感的语言，但别乱用；一定要能表明你在思考，在关注。 
<P>
<P>正确的拼写，标点符号和大小写很重要。别把“its”和“it's”或者“loose”和“lose”搞混淆了。别用全部大写的形式，这被视为粗鲁的大声叫嚷（全都用小写也好不到哪儿去，因为这会给阅读带来困难。Alan Cox可以用全部小写，但你不行）。 
<P>
<P>更一般的说，如果你的提问写得象个半文盲，你很有可能被忽视。如果写得象一个窥客（破解爱好者）或者灰客（只会用现成工具的捣乱者）绝对是自己找死，保证你除了无情的抵制什么也得不到（或者，最好的结局是得到一大堆挖苦嘲笑的“帮助”）。 
<P>如果你在使用非母语的论坛提问，你可以犯点拼写和语法上的小错--但决不能在思考上马虎（没错，我们能弄清两者的分别）。另外，除非你确切知道你的回答者会使用什么语言，否则请用英文。匆匆忙忙的黑客往往简单的跳过他们看不懂的问题，而英文是网络上的工作语言。用英文可以降低你的问题未被阅读即遭抛弃的风险。 
<P>
<HR>

<H3><A name=3_4></A><A name=3_4_></A>3.4用易读格式发送问题 </H3>
<HR>

<P>如果人为造成你的提问难以阅读和理解，将会更容易被人忽略。因此你要： 
<P>
<OL>
<LI>使用纯文本邮件，不要使用HTML（关掉HTML并不难）。 
<LI>通常可以附加MIME附件，但一定要有真正的内容（例如附加的源文件或者补丁），而不仅仅是你的邮件客户端产生的文件模板（例如你邮件的一份拷贝）。 
<LI>不要把所有问题放在不停换行的一整段中。（这将让答复的人难于回答其中一部分问题，即使能回答所有问题，我也更希望条理清楚的一个一个来:）。很可能收件人只能在80个字符宽度的文本显示器上读信，因此要相应的把行环绕模式设在80字符以内。 
<LI>不要在英文论坛使用MIME Quoted-Printable编码发送；这种编码格式对ASCII码不能表达的语言来说是非常必要的，但很多邮件代理不支持它，这时，满篇的“=20”符号把文字分割开，既难看，又分散注意力。 
<LI>永远不要指望黑客会乐于阅读封闭所有权的文件格式，例如萎软的Word格式。多数黑客对此的反应就象你在门口的阶梯上堆满热烘烘的猪粪（意即谁也不会踏进你的门--译者注）。 
<LI>如果你通过一台安装Windows的电脑发送邮件，关闭萎软愚蠢的“智能引用”功能。这能使你免于在邮件中夹带垃圾字符。 </LI></OL>
<P>
<HR>

<H3><A name=3_5></A><A name=3_5_></A>3.5使用含义丰富，描述准确的标题 </H3>
<HR>

<P>在邮件列表或者新闻组中，大约50字以内的主题标题是抓住资深专家注意力的黄金时机。别用喋喋不休的“帮帮忙”（更别说“救命啊！！！！！”这样让人反感的话）来浪费这个机会。不要妄想用你的痛苦程度来打动我们，别用空格代替问题的描述，哪怕是极其简短的描述。 
<P>蠢问题： 
<P>救命啊！我的膝上机不能正常显示了！ 
<P>聪明问题： 
<P>XFree86 4.1下鼠标光标变形，Fooware MV1005的显示芯片。 
<P>如果你在回复中提出问题，记得要修改内容标题，表明里面有一个问题。一个看起来象“Re：测试”或者“Re：新bug”的问题很难引起足够重视。另外，引用并删减前文的内容，给新来的读者留下线索。 
<P>
<HR>

<H3><A name=3_6></A><A name=3_6_></A>3.6精确描述，信息量大 </H3>
<HR>

<P>
<OL>
<LI>谨慎明确的描述症状。 
<LI>提供问题发生的环境（机器配置、操作系统、应用程序以及别的什么）。 
<LI>说明你在提问前是怎样去研究和理解这个问题的。 
<LI>说明你在提问前采取了什么步骤去解决它。 
<LI>罗列最近做过什么可能有影响的硬件、软件变更。 </LI></OL>
<P>尽量想象一个黑客会怎样反问你，在提问的时候预先给他答案。 
<P>Simon Tatham写过一篇名为《如何有效的报告Bug》的出色短文。强力推荐你也读一读。 
<P>
<P>
<HR>

<H3><A name=3_7></A><A name=3_7_></A>3.7话不在多 </H3>
<HR>

<P>你需要提供精确有效的信息。这并不是要求你简单的把成吨的出错代码或者数据完全转储摘录到你的提问中。如果你有庞大而复杂的测试条件，尽量把它剪裁得越小越好。 
<P>这样做的用处至少有三点。 
<P>
<UL>
<LI>第一，表现出你为简化问题付出了努力，这可以使你得到回答的机会增加； 
<LI>第二，简化问题使你得到有用答案的机会增加； 
<LI>第三，在提炼你的bug报告的过程中，也许你自己就能找出问题所在或作出更正。 </LI></UL>
<P>
<HR>

<H3><A name=3_8></A><A name=3_8_></A>3.8只说症状，不说猜想 </H3>
<HR>

<P>告诉黑客们你认为问题是怎样引起的没什么帮助。（如果你的推断如此有效，还用向别人求助吗？），因此要确信你原原本本告诉了他们问题的症状，不要加进你自己的理解和推论。让黑客们来诊断吧。 
<P>蠢问题： 
<P>我在内核编译中一次又一次遇到SIG11错误，我怀疑某条飞线搭在主板的走线上了，这种情况应该怎样检查最好？ 
<P>聪明问题： 
<P>我自制的一套K6/233系统，主板是FIC-PA2007 （VIA Apollo VP2芯片组），256MBCorsair PC133 SDRAM，在内核编译中频频产生SIG11错误，从开机20分钟以后就有这种情况，开机前20分钟内从没发生过。重启也没有用，但是关机一晚上就又能工作20分钟。所有内存都换过了，没有效果。相关部分的典型编译记录如下...。 
<P>
<HR>

<H3><A name=3_9></A><A name=3_9_></A>3.9按时间顺序列出症状 </H3>
<HR>

<P>对找出问题最有帮助的线索，往往就是问题发生前的一系列操作，因此，你的说明应该包含操作步骤，以及电脑的反应，直到问题产生。在命令行操作的情况下，保存一个操作记录（例如使用脚本工具），并且引用相关的大约20条命令会大有帮助。 
<P>如果崩溃的程序有诊断选项（例如用 -v 转到详尽模式），试着仔细考虑选择选项以在操作记录中增加有用的调试信息。 
<P>如果你的说明很长（超过四个段落），在开头简述问题会有所帮助，接下来按时间顺序详述。这样黑客们就知道该在你的说明中找什么。 
<P>
<HR>

<H3><A name=3_10></A><A name=3_10_></A>3.10别要求私下答复 </H3>
<HR>

<P>黑客们认为解决问题应该有公开、透明的流程。只要任何更有见地的人注意到答案的不完善或者不正确，这个最初的答案就可以和应该得到纠正。同时，通过能力和知识被大家注意，被大家接受，回答问题者得到了应有的奖励。 
<P>如果你要求对方私下回答你，这既破坏了整个流程，也破坏了奖励制度。别提这要求，这是回答者的权利，由他来选择是否私下答复--如果他选择这样做，通常是因为他认为这个答案过于显而易见或者有不良的公开影响，别人不会感兴趣。 
<P>只有一种有限的例外：如果你预计将收到大量雷同的答复，你可以说：“把答案寄给我，由我来汇总吧。”将邮件列表或者新闻组从大量重复的帖子中打救出来是很有君子之风的--但请记住，履行自己关于汇总的承诺。 
<P>
<HR>

<H3><A name=3_11></A><A name=3_11_></A>3.11明白你想问什么 </H3>
<P>
<HR>

<P>漫无边际的提问近乎无休无止的时间黑洞。最能给你有用答案的人也正是最忙的人（他们忙是因为要亲自完成大部分工作）。这样的人对无节制的时间黑洞不太感冒，因此也可以说他们对漫无边际的提问不大感冒。 
<P>如果你明确表述需要回答者做什么（提供建议，发送一段代码，检查你的补丁或是别的），就最有可能得到有用的答案。这会定出一个时间和精力的上限，便于回答者集中精力来帮你，这很凑效。 
<P>要理解专家们生活的世界，要把专业技能想象为充裕的资源，而回复的时间则是贫乏的资源。解决你的问题需要的时间越少，越能从忙碌的专家口中掏出答案。 
<P>因此，优化问题的结构，尽量减少专家们解决它所需要的时间，会有很大的帮助--这通常和简化问题有所区别。因此，问“我想更好的理解X，能给点提示吗？”通常比问“你能解释一下X吗？”更好。如果你的代码不能工作，问问它有什么地方不对，比要求别人替你修改要明智得多。 
<P>
<P>
<HR>

<H3><A name=3_12></A><A name=3_12_></A>3.12别问应该自己解决的问题 </H3>
<HR>

<P>黑客们总是善于分辨哪些问题应该由你自己解决；因为我们中的大多数都曾自己解决这类问题。同样，这些问题得由你来搞定，你会从中学到东西。你可以要求给点提示，但别要求得到完整的解决方案。 
<P>
<HR>

<H3><A name=3_13></A><A name=3_13_></A>3.13去除无意义的疑问 </H3>
<HR>

<P>别用无意义的话结束提问，例如“有人能帮我吗？”或者“有答案吗？”。 
<UL>
<LI>首先：如果你对问题的描述不很合适，这样问更是画蛇添足。 
<LI>其次：由于这样问是画蛇添足，黑客们会很厌烦你--而且通常会用逻辑上正确的回答来表示他们的蔑视，例如：“没错，有人能帮 </LI></UL>你”或者“不，没答案”。 
<P>
<HR>

<H3><A name=3_14></A><A name=3_14_></A>3.14谦逊绝没有害处，而且常帮大忙 </H3>
<HR>

<P>彬彬有礼，多用“请”和“先道个谢了”。让大家都知道你对他们花费时间义务提供帮助心存感激。 
<P>实话实说，虽然这不象合乎语法、清楚准确的描述，避免私有格式等等那么重要（也不能用来替代它们）；黑客一般更喜欢直接了当然而技术上敏锐的bug报告，而不是彬彬有礼的废话（如果这让你迷惑不解，请记住，我们衡量一个问题价值的标准是：它能让我们学会多少）。 
<P>然而，如果你有很多问题无法解决，礼貌将会增加你得到有用答案的机会。 
<P>（我们注意到，自从本指南发布后，从资深黑客处得到的唯一严重缺陷反馈，就是对预先道谢这一条。一些黑客觉得“先谢了”的言外之意是过后就不会再感谢任何人了。我们的建议是：都道谢。） 
<P>
<HR>

<P>
<H3><A name=3_15></A><A name=3_15_></A>3.15问题解决后，加个简短说明 </H3>
<HR>

<P>问题解决后，向所有帮助过你的人发个说明，让他们知道问题是怎样解决的，并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注，应该在那里贴一个补充说明。 
<P>补充说明不必很长或是很深入；简单的一句“你好，原来是网线出了问题！谢谢大家--Bill”比什么也不说要强。事实上，除非结论真的很有技术含量，否则简短可爱的小结比长篇学术论文更好。说明问题是怎样解决的，但大可不必将解决问题的过程复述一遍。 
<P>
<P>除了表示礼貌和反馈信息以外，这种补充有助于他人在邮件列表/新闻组/论坛中搜索对你有过帮助的完整解决方案，这可能对他们也很有用。 
<P>最后（至少？），这种补充有助于所有提供过帮助的人从中得到满足感。如果你自己不是老手或者黑客，那就相信我们，这种感觉对于那些你向他们求助的导师或者专家而言，是非常重要的。问题久拖未决会让人灰心；黑客们渴望看到问题被解决。好人有好报，满足他们的渴望，你会在下次贴出新问题时尝到甜头。 
<P><CODE><B>========</B></CODE> 
<H2><A name=4></A><A name=4_></A>4.如何理解答案 </H2><CODE><B>========</B></CODE> 
<P>
<HR>

<H3><A name=4_1RTFM_STFW></A><A name=4_1RTFM_STFW_></A>4.1RTFM和STFW：别烦我啦 </H3>
<HR>

<P>有一个古老而神圣的传统：如果你收到“RTFM （Read The Fucking Manual）”的回复，回答者认为你应该去读TMD手册。当然，基本上他是对的，你应该读一读。 
<P>RTFM有一个年轻的亲戚。如果答案是“STFW （Search The Fucking Web）”，回答者认为你应该到TMD的网上去搜索。基本上，他也是对的，你就去找吧。 
<P>通常，用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址，而且他们打这些字的时候正在阅读着。这些答复意味着回答者认为 
<P>
<UL>
<LI>(1). 你需要的信息非常容易获得； 
<LI>(2). 你自己去搜索这些信息比灌给你能让你学到更多。 </LI></UL>
<P>别为这个而不爽；依照黑客的标准，他没有对你的要求视而不见，已经能大致能表示对你的关注。你应该对他祖母般的慈祥表示感谢。 
<P>
<HR>

<H3><A name=4_2></A><A name=4_2_></A>4.2还是不懂:( </H3>
<HR>

<P>如果你不是很理解答案，别立刻要求对方解释。象你以前试着自己解决问题时那样（利用手册，FAQ，网络，身边的高手），去理解它。如果你真的需要对方解释，记得表现出你已经学到了点什么。 
<P>比方说，如果我回答你：“看来似乎是zEntry被阻塞了；你应该先清除它。”，然后： 
<P>一个很糟的后续问题：“zEntry是什么？” 
<P>聪明的问法应该是这样：“哦~我看过帮助了:)但是只有-z和-p两个参数中提到了zEntry:(而且还都没有清楚的解释:&lt;你是指这两个中的哪一个吗？还是我看漏了什么？” 
<P>
<P>
<HR>

<H3><A name=4_3></A><A name=4_3_></A>4.3面对无礼 </H3>
<HR>

<P>黑客圈子里很多貌似粗鲁的言行并非有意冒犯。更恰当的说，这是直率、不说废话的沟通方式的产物，这种沟通方式源于人们关注问题的解决--多过让人感受温暖亲情然而却依旧糊里糊涂--的天性。 
<P>如果你觉得受到粗鲁的对待，请保持冷静。如果真有人表现粗野，通常会有列表/新闻组/论坛的长辈找他谈心，如果没有这样，而你又大发脾气，则很可能对方的言行是黑客社区行为规范许可内，而你被认为是有过错的。这会不利于你得到信息或者帮助。 
<P>另一方面，你偶尔也会无缘无故有粗野的言行和心态。上述现象的另一面是，人们允许狠狠打击真正的冒犯者，用尖刻的言语剖析他们的不当言行。如果你真决定这样做，先仔细又仔细的掂量一下你自己的分量。合理的粗鲁与发动一场无意义的论战之间只隔了一条细细的线，冒冒失失撞上去的黑客不在少数；如果你是新手或者门外汉，不犯这种错的机会是很渺茫的。如果你想得到信息而不是来胡闹，别冒险回复，最好把手从键盘上拿开。 
<P>（有些人声称多数黑客有孤僻症或者社交障碍综合征的轻度症状，而且确实缺少部分有助“常人”进行社交行为的脑组织结构。这也许是真的，也许不是。如果你自己不是黑客，那么，把我们想象成脑部有缺陷的人有助你面对我们的古怪。有话直说，我们无所谓；我们乐于按自己的想法生活，而且总是对医学概念持相当怀疑的态度。） 
<P>在下一节里，我们将谈论另一个话题；当你行差踏错时可能遇到的“无礼”。 
<P><CODE><B>============</B></CODE> 
<H2><A name=5></A><A name=5_></A>5.决不要象个失败者 </H2><CODE><B>============</B></CODE> 
<P>很有可能，你在黑客社区的论坛会受到很多公开的攻击--用本文提到的各种方式或类似的方法，而且很可能会有各式各样的旁敲侧击来告诉你你有多讨厌。 
<P>如果噩梦成真，你能做的最糟的事就是为此发牢骚，抱怨受到人身攻击，要求对方道歉，尖叫，屏住呼吸，威胁要控诉对方，向他老板告状，不掀起马桶座圈，等等等等。然而，你应该这样： 
<P>由它去吧，这没什么大不了的。实际上这么做是恰当的和有益的（主要是有利身心健康:）。 
<P>社区的规范不靠社区，而是靠积极推行它们的人们来维护，这种维护是公开的，显而易见的。别抱怨说一切批评都应该通过私信传送，它本来就不该那样。当别人指出你的话有错误，或者他有不同观点的时候，坚持认为他在羞辱你是没有用的。这些都是失败者的态度。 
<P>有那么一些黑客论坛，出于对高度自谦的误解，禁止参与者张贴专给人找茬的帖子，而且被告知“如果不愿帮助用户，那就闭嘴。”，他们认为，引开参与者的话题，只会使得他们陶醉在毫无意义的喋喋不休中，从而失去了技术论坛的意义。 
<P>夸张的“友善”（以那种方式）还是有用的帮助：你自己选择吧。 
<P>记住：当黑客说你很烦人，（无论用多么粗暴的语言）警告你别再那样做了，他的本意并非是针对(1)你，以及(2)他的社区。他本来可以轻易的忽略你，把你从他的视线中抹去。如果你无法接受要向他表示感激，至少应该表现出你的气度，别抱怨，别期望只因为你是新人，你有戏剧般的敏感脆弱的神经和自封的权利，而受到易碎玩偶般的特别对待。 
<P><CODE><B>======</B></CODE> 
<H2><A name=6></A><A name=6_></A>6.三思而后问 </H2><CODE><B>======</B></CODE> 
<P>以下是几个经典蠢问题，以及黑客在拒绝回答时的心中所想： 
<P>问题：我能在哪找到X程序？ 
<P>问题：我的程序/配置/SQL申明没有用 
<P>问题：我的Windows有问题，你能帮我吗？ 
<P>问题：我在安装Linux（或者X）时有问题，你能帮我吗？ 
<P>问题：我怎么才能破解root帐号/窃取OP特权/读别人的邮件呢？ 
<P>提问：我能在哪找到X程序？ 
<P>回答：就在我找到它的地方啊蠢货--搜索引擎的那一头。天呐！还有人不会用Google吗？ 
<P>
<P>提问：我的程序（配置、SQL申明）没有用 
<P>回答：这不算是问题吧，我对找出你的真正问题没兴趣--如果要我问你二十个问题才找得出来的话--我有更有意思的事要做呢。在看到这类问题的时候，我的反应通常不外如下三种： 
<P>
<OL>
<LI>你还有什么要补充的吗？ 
<LI>真糟糕，希望你能搞定。 
<LI>这跟我有什么鸟相关？ </LI></OL>
<P>提问：我的Windows有问题，你能帮我吗？ 
<P>回答：能啊，扔掉萎软的垃圾，换Linux吧。 
<P>提问：我在安装Linux（或者X）时有问题，你能帮我吗？ 
<P>回答：不能，我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的Linux用户组寻求手把手的指导吧（你能在这儿找到用户组的清单）。 
<P>提问：我怎么才能破解root帐号/窃取OP特权/读别人的邮件呢？ 
<P>回答：想要这样做，说明你是个卑鄙小人；想找个黑客帮你，说明你是个白痴！ 
<P><CODE><B>==========</B></CODE> 
<H2><A name=7></A><A name=7_></A>7.好问题，坏问题 </H2><CODE><B>==========</B></CODE> 
<P>最后，我举一些例子来说明，怎样聪明的提问；同一个问题的两种问法被放在一起，一种是愚蠢的，另一种才是明智的。 
<P>蠢问题：我可以在哪儿找到关于Foonly Flurbamatic的资料？ 
<P>这种问法无非想得到“STFW”这样的回答。 
<P>聪明问题：我用Google搜索过“Foonly Flurbamatic 2600”，但是没找到有用的结果。谁知道上哪儿去找对这种设备编程的资料？ 
<P>这个问题已经STFW过了，看起来他真的遇到了麻烦。 
<P>蠢问题：我从FOO项目找来的源码没法编译。它怎么这么烂？ 
<P>他觉得都是别人的错，这个傲慢自大的家伙:( 
<P>聪明问题：FOO项目代码在Nulix 6.2版下无法编译通过。我读过了FAQ，但里面没有提到跟Nulix有关的问题。这是我编译过程的记录，我有什么做得不对的地方吗？ 
<P>他讲明了环境，也读过了FAQ，还指明了错误，并且他没有把问题的责任推到别人头上，这个家伙值得留意。 
<P>蠢问题：我的主板有问题了，谁来帮我？ 
<P>普通黑客对这类问题的回答通常是：“好的，还要帮你拍拍背和换尿布吗？” ，然后按下删除键。 
<P>聪明问题：我在S2464主板上试过了X、Y和Z，但没什么作用，我又试了A、B和C。请注意当我尝试C时的奇怪现象。显然边带传输中出现了收缩，但结果出人意料。在多处理器主板上引起边带泄漏的通常原因是什么？谁有好主意接下来我该做些什么测试才能找出问题？ 
<P>这个家伙，从另一个角度来看，值得去回答他。他表现出了解决问题的能力，而不是坐等天上掉答案。 
<P>在最后一个问题中，注意“告诉我答案”和“给我启示，指出我还应该做什么诊断工作”之间微妙而又重要的区别。 
<P>事实上，后一个问题源自于2001年8月在Linux内核邮件列表上的一个真实的提问。我（Eric）就是那个提出问题的人。我在Tyan S2464主板上观察到了这种无法解释的锁定现象，列表成员们提供了解决那一问题的重要信息。 
<P>通过我的提问方法，我给了大家值得玩味的东西；我让人们很容易参与并且被吸引进来。我显示了自己具备和他们同等的能力，邀请他们与我共同探讨。我告诉他们我所走过的弯路，以避免他们再浪费时间，这是一种对他人时间价值的尊重。 
<P>后来，当我向每个人表示感谢，并且赞赏这套程序（指邮件列表中的讨论--译者注）运作得非常出色的时候，一个Linux内核邮件列表（lkml）成员表示，问题得到解决并非由于我是这个列表中的“名人”，而是因为我用了正确的方式来提问。 
<P>我们黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙；我相信他是对的，如果我象个乞讨者那样提问，不论我是谁，一定会惹恼某些人或者被他们忽视。他建议我记下这件事，给编写这个指南的人一些指导。 
<P><CODE><B>============</B></CODE> 
<H2><A name=8></A><A name=8_></A>8.找不到答案怎么办 </H2><CODE><B>============</B></CODE> 
<P>如果仍得不到答案，请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。没有回应不代表你被忽视，虽然不可否认这种差别很难区分。 
<P>
<P>总的说来，简单的重复张贴问题是个很糟的想法。这将被视为无意义的喧闹。你可以通过其它渠道获得帮助，这些渠道通常更适合初学者的需要。 
<P>有许多网上的以及本地的用户组，由狂热的软件爱好者（即使他们可能从没亲自写过任何软件）组成。通常人们组建这样的团体来互相帮助并帮助新手。 
<P>另外，你可以向很多商业公司寻求帮助，不论公司大还是小（Red Hat和LinuxCare就是两个最常见的例子）。别为要付费才能获得帮助而感到沮丧！毕竟，假使你的汽车发动机汽缸密封圈爆掉了--完全可能如此--你还得把它送到修车铺，并且为维修付费。就算软件没花费你一分钱，你也不能强求技术支持总是免费的。 
<P>对大众化的软件，就象Linux之类而言，每个开发者至少会有上万名用户。根本不可能由一个人来处理来自上万名用户的求助电话。要知道，即使你要为帮助付费，同你必须购买同类软件相比，你所付出的也是微不足道的（通常封闭源代码软件的技术支持费用比开放源代码软件要高得多，而且内容也不那么丰富）。 
<P>
<P>-- <A class=twikiLink href="http://www.pgsqldb.org/twiki/bin/view/Main/LaserHe">LaserHe</A> - 13 Jul 2005 
<UL>
<LI>提问的智慧: <BR><IMG height=649 alt=提问的智慧 src="http://www.pgsqldb.org/twiki/pub/PgSQL/HowToAskQuestiongInASmartWay/question.jpeg" width=458> </LI></UL>
<P>
<P>
<HR>

<P>（转载自<A href="http://www.pgsqldb.org">http://www.pgsqldb.org</A>）</P><img src ="http://www.blogjava.net/aw815/aggbug/20307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aw815/" target="_blank">水秀清灵</a> 2005-11-17 20:19 <a href="http://www.blogjava.net/aw815/articles/20307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>