星期一 2007年01月01日
[原]GWT活学活用--起步
把玩GWT也有一阵子了,目前国内的相关资料并不多,算是与大家分享一下自己的经验吧。
本来也想取名为GWT从入门到精通,或者step by step,但一想自己以前最讨厌这种书了,加之自己也不能说是精通了吧。叫活学活用会更好些。这系列的文章会以GWT官方文档为主,补充一些自己的经验和思想。
[Read More]
Posted at 10:33下午 一月 01, 2007 by xMatrix in 软件工程 | 评论[0]
星期日 2006年12月31日
回首2006,我的
当然是我的2006了^_^
很久没有来了,曾经有一段时间是想重回这里的,可那时的速度实在无法忍受,也曾想换一个地方,但一直没有找到更好的,于是就放弃了。又要到新的一年了,回
来看看,这里已经换了模样,翻了翻在这里的处女作,竟然是2006年的元旦写的,回首当时的感言,是否自己在这一年里变的更加积极了呢,我也说不清
楚。。。
轻轻地甩一甩头,过去的就过去了,因为新的一年就快来了。
回首2006,所有开心的,伤心的,难忘的,遣忘的。。。都让他封存在即将逝去的2006中吧,只想说,2006,我不会忘记。
Posted at 10:44下午 十二月 31, 2006 by xMatrix in 软件工程 | 评论[0]
星期五 2006年09月08日
如何在代码中输出代码所有的类及其代码行(从log4j想起的)
在使用log4j时,对其在错误时候打印的错误信息很感兴趣,能够详细的给出具体的错误信息和具体的代码位置。通常我们在代码中会增加一些调试信息,便于定位问题,在项目比较小时还是比较方便,可当项目成长起来,类似的调试信息可能存在于多个地方,或者想不起来这个调试信息是哪个方法用的。这时,如果能具体地给出调试信息所有在的类及其代码行,就方便多了。
可如何来得到当前代码所在的类和代码行,一个方法就是写死了,可是以后修改代码后就需要时时更新,这个工作量可不小。另外就是动态地提供类及其代码行,Google了一下,好像是没有相关的API。我知道通过解析类文件,是可以得到相关的信息的,可是我在代码中可以这样做吗?理论上没有问题,不过实现起来可能就比较麻烦了.
那么就来看一下log4j的源程序吧,可是找了半天,也找不到相关的处理代码。难道说log4j根本没有做相关的工作。事实就是这样,我们绕了一圈才发现真理就在眼前,可我们就是看不见。
呵呵,其实就是这么简单,Throwable类已经提供了这样的方法,log4j只是调用了Throwable.toString()方法而已,这样一切就变得简单多了,我们通过Throwable来实现这个功能吧:
public abstract class LogUtil {
public static String wrapInfo(String info) {
StringBuffer buffer = new StringBuffer();
buffer.append(info).append("\r\n").append(new Exception().getStackTrace()[1]);
return buffer.toString();
}
}
很简单吧,我们不需要完整的异常椎栈,所以只取[1]的信息(即调用本方法的类的方法的信息)
Posted at 05:58下午 九月 08, 2006 by xMatrix in Java技术 | 评论[2]
星期二 2006年06月27日
XML中的文档格式验证规范
想想也已经用了很久的XML,大凡JAVA的应用中没有不用到XML的,但究竟XML是什么,一时之间也想不出个所以然,难道只是一种保存数据的方式吗,那么他与普通文本的区别又在哪里,难道只是因为流行所以才流行吗?
今天在看一个规范时,发现书中是用DTD来解释XML的格式的,可一时还真看不全懂,于是搜了一下,原来XML的文档格式验证规范已经有了三种,DTD/XML Schema/RELAX NG。其中DTD是最初的规范,但目前已不属于W3C的推荐规范了,XML Schema是目前W3C的推荐规范,而RELAX NG是一种新兴的规范(说新其实也已经有N年了),但不属于W3C的范围。
比较了一下三种规范,DTD是最简单的,但功能上就弱了一些,只能定义较粗的范围,XML Schema就比较复杂了,因而在功能上就非常强大,几乎可以做任何的限制,而RELAX NG提供了一种新方式,能以DTD的简单表达强大的功能,不过因为不是规范,用的也不广泛。
就个人而言,还是比较喜欢DTD,简单而又够用。
具体的比较就不说了,可以参考IBM的网站上的文章。
Posted at 09:45下午 六月 27, 2006 by xMatrix in Java技术 | 评论[0]
星期三 2006年06月14日
足球与软件
四年一度的世界杯,好像一切都与足球发生了关系。足球,足球,还是足球。。。
记得之前的《敏捷软件》笔记中有一段是说软件与运动的关系,作者认为软件开发与攀岩运动类似,这里我觉得软件开发与足球也很类似。同样的团队运动,同样的需要协作,需要经验,需要核心,需要质量保证。从足球来看,有11人制的正规比赛,有7人制的小场,有5人制足球赛,不同的规模需要使用不同的策略,就像软件开发中不同的规模需要不同的方法一样;同时有一些基本的要素是放之四海而皆准的,需要良好的技术,良好的体力,软件也一样。下面对比一下足球中的角色与软件中的角色:
教练 VS 项目经理
队长 VS 项目负责人
前锋 VS 开发人员
中场 VS 配置人员
后卫 VS 测试人员
门将 VS QA
上面的球队的基本要素,但取胜的关键并不是这些,而是:
战术 VS 开发方法
配合 VS 团队协作
球星 VS 技术高手
热身赛 VS DEMO
战术调整 VS 方法的调整
呵呵,作为世界杯中的一点感想。
Posted at 08:29下午 六月 14, 2006 by xMatrix in 软件工程 | 评论[0]
星期一 2006年06月12日
代码覆盖率工具之-cobertura
cobertura是clover的开源版本,基本的功能都已经有了,今天在使用的时候遇到了一些问题,贴出来分享一下,大家有需要用的时候可以少走一些弯路。 下面的cobertura示例中的build.xml,只对其中容易出错的地方注解一下:
<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura.jar" />
<include name="lib/**/*.jar" />
</fileset>
</path>
这部分是必须的,就是必须包含lib目录下的几个类库,否则在instrument任务时会报类找不到,开始还以后是自己的应用少了类库呢,结果是cobertura需要的
<taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
<target name="init">
<mkdir dir="${classes.dir}" />
<mkdir dir="${instrumented.dir}" />
<mkdir dir="${reports.xml.dir}" />
<mkdir dir="${reports.html.dir}" />
<mkdir dir="${coverage.xml.dir}" />
<mkdir dir="${coverage.html.dir}" />
</target>
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${classes.dir}" debug="yes">
<classpath refid="cobertura.classpath" />
</javac>
</target>
<target name="instrument" depends="init,compile">
<!--
Remove the coverage data file and any old instrumentation.
-->
<delete file="cobertura.ser"/>
<delete dir="${instrumented.dir}" />
<!--
Instrument the application classes, writing the
instrumented classes into ${build.instrumented.dir}.
-->
<cobertura-instrument todir="${instrumented.dir}">
<!--
The following line causes instrument to ignore any
source line containing a reference to log4j, for the
purposes of coverage reporting.
-->
<ignore regex="org.apache.log4j.*" />
<fileset dir="${classes.dir}">
<!--
Instrument all the application classes, but
don't instrument the test classes.
-->
<include name="**/*.class" />
<exclude name="**/*Test.class" />
</fileset>
</cobertura-instrument>
</target>
<target name="test" depends="init,compile">
<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
<!--
Note the classpath order: instrumented classes are before the
original (uninstrumented) classes. This is important.
-->
<classpath location="${instrumented.dir}" />
<classpath location="${classes.dir}" />
<!--
The instrumented classes reference classes used by the
Cobertura runtime, so Cobertura and its dependencies
must be on your classpath.
-->
<classpath refid="cobertura.classpath" />
<formatter type="xml" />
<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
<batchtest todir="${reports.xml.dir}" unless="testcase">
<fileset dir="${src.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
<junitreport todir="${reports.xml.dir}">
<fileset dir="${reports.xml.dir}">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${reports.html.dir}" />
</junitreport>
</target>
<target name="coverage-check">
<cobertura-check branchrate="34" totallinerate="100" />
</target>
<target name="coverage-report">
<!--
Generate an XML file containing the coverage data using
the "srcdir" attribute.
-->
<cobertura-report srcdir="${src.dir}" destdir="${coverage.xml.dir}" format="xml" />
</target>
这两部分不是必须的,生成HTML的报告用下面这一个就可以了
<target name="alternate-coverage-report">
<!--
Generate a series of HTML files containing the coverage
data in a user-readable form using nested source filesets.
-->
<cobertura-report destdir="${coverage.html.dir}">
<fileset dir="${src.dir}">
<include name="**/*.java"/>
</fileset>
</cobertura-report>
</target>
<target name="clean" description="Remove all files created by the build/test process.">
<delete dir="${classes.dir}" />
<delete dir="${instrumented.dir}" />
<delete dir="${reports.dir}" />
<delete file="cobertura.log" />
<delete file="cobertura.ser" />
</target>
<target name="coverage" depends="compile,instrument,test,coverage-report,alternate-coverage-report" description="Compile, instrument ourself, run the tests and generate JUnit and coverage reports."/>
Posted at 05:49下午 六月 12, 2006 by xMatrix in 软件工程 | 评论[0]
星期四 2006年04月06日
[译文]对话Eric Gammar--发布的文化
Bill Venners: 你在Eclipse项目中已经工作了多久,你认为什么是你和你的团队在开发过程学到的最重要的东西?
Erich Gamma: 从Eclispe项目开始我就参与了,很难给出具体的日期,因为有许多项目是跟Eclipse有关的。例如,我曾经在Visual Age IDE中工作,一些组件是在这个项目中开始的,然后被提取为Eclipse的一部分,也是在这个项目中SWT诞生了,我想大约有六年了吧。
在Eclipse项目开始的时候,OTI有一种专注于及时发布的文化,这帮助成员成为开发过程的核心。在那时我们都对这种方式有点意见,但通过在后来的六年我们逐渐适应了这种文化。我们不做无法完成的工作,我们只作可以完成的工作,我们也确实完成了所有的工作。
我们学到了持续发布的重要性。在开始的时候我们并不了解这一点,因此我们为了完成发布周期都有较大的压力。现在我们使用更短的发布间隔,通常六个星期为一个里程碑。这是我们改进的产物,现在我们都倾向于尽力做发布准备的模型--我们希望始终在Beta版本的状态。
因为我们是开源的,我们也学到社区反馈的重要性。与社区成员的沟通及让他们更容易地参与是非常重要的。我们已经取得了良好的沟通,但我们还在尽力改善和社区的沟通。显然更多的社区参与会有更好的结果。
Bill Venners: 看起来这好像是你欣赏的发布文化。
Erich Gamma: 是的,在软件开发中,酷的想法是好的,但能够发布他们才是最重要的。对我们来说只有发布了才是有意义的。这也是我们真正拥有的想法--注重发布,我们不想需要二三年才发布一次,需要的只是短时间的可发布性。在这种思维下你也需要计划、决定和实现。你需要关注风险,因为你知道什么才是你能够保质保量的按时发布所最重要的。
持续发布
Bill Venners: 在Eclipse项目中你是如何持续发布的?
Erich Gamma: 我们拆分发布周期为以六个星期为力度的里程碑,在每一个里程碑结束时有一个可用的构建。通常,这六个星期是一个小的开发周期,我们计划,开发并测试。在这种类型的计划中,我们能够有效地计划每一次发布的开发周期。我们会在每一个里程碑结束时,留一天的时间来测试。为每一个里程碑测试避免了积累大量的测试工作到发布的最后时间。然后我们记录下新的特性并提供给社区,因此他们可以了解我们的进度并提供前期的反馈。接着我们计划下一个里程碑,计算总的计划和个别的组件计划。
这也是我们说的保持Beta版本的概念。最重要的是人们不会几个月不知道我们在做什么。这么做的目标是让我们的社区跟踪我们的进度并提供持续地反馈。
Bill Venners: 为什么让社区跟踪进度是有意义的?是不是透明的开发更适合于开源项目,还是有一些东西你认为商业项目可以从中学习的?
Erich Gamma: 我认为这与是否开源无关。在软件开发中如果你想有一个增长的社区,那么创建社区并提供透明的开发方式是非常重要的。虽然开源比较特殊,但并不只是在某种许可下开放源程序,这还与创建社区有关。你创建了一个社区,并告诉他们正在做什么,那么意味着你的计划是公开的。所有的里程碑计划和项目计划在网页上都可见,所有的错误都是可见的,社区确实知道你正在做什么。当然,我们希望的是社区的参与,当然参与有很多种形式,如提供错误报告,捐献新闻组回答,提供补丁,实现额外的插件或写文章等等。重要的是一个快速的反馈循环,而这种反馈正是良好的可发布的产品的关键。事实证明Eclipse有一个活跃的社区是非常好而重要的财产,而这与是否开源无关。
Bill Venners: 你说有计划,执行和测试。那么在一个六星期的开发周期前你会计划多久呢?
Erich Gamma: 通常我们会花一个周的时候。在开发周期的最后一周是“黎明前的黑暗”,通常我们在周二进行项目编译,周三测试,周四修改问题,并在周五声明里程碑式的编译。为了声明一个里程碑,每一个组件团队需要保证自己的组件没有问题。如果某一个组件还有问题,那么通常还需要再编译一次。
这有点像开巴士,算出需要建立多少个车站。如果建立太多的站点,那么每次启动和停车会减慢速度,这也是为什么我选择六个星期的原因。我们需要一个周期来做计划,还需要大半个周来发布。
Bill Venners: 也就是说有四个星期的开发时间
Erich Gamma: 是,至少有四个星期,这段时间做些有用的事已经足够了。你需要在一个周期内解决大一点的问题。我们开始使用四星期人作为一个周期,但后来发现在这个周期中启动和停止的代价太高了。
Bill Venners: 你们是否在每次迭代周期间有一些放松的时间。
Erich Gamma: 我们每次完成一个主要版本后,我们有一个月左右的时间来休息。通常我们会在六月或七月来发布,这样人们可以享受他们的假期。当我们回顾反思的时候也会有一个休息时间。这通常也是寻找新成员的时间,然后我们就会为下一个版本做准备了。
Bill Venners: 那是否在每一次里程碑周期开始前存在一些更短的放松时间呢。
Erich Gamma: You need decompression time when you have really been compressed, but the idea of the milestone releases is to not be continuously compressed. Rather, we want a regular rhythm of sustained development. We start. We stop. At the end before we ship an actual—not milestone—release, then we have some compression. This is the end game, which is intense. We have to do testing and very careful fixing to address last-minute polish or performance items. We know we can only do this for a certain amount of time. The end game is tiring, and afterwards, you need decompression, because everyone has to do a lot of compressed development towards the end.
当你确实觉得需要放松一下就休息一下,但通常每次里程碑发布不会有太多的压力。此外,我们使用一种固定节奏的开发形式。我们开始,停止。在我们实际发布一个版本之前的结束时间,通常会有较大的压力,这就是所说的结束游戏。我们必须测试并且仔细地修复每一个问题。当然我们也知道我们不需要很长时间来一直做这种工作。结束游戏是非常累的,因此需要放松一下,因为每个人都是满负荷的工作。
Bill Venners: 什么结束游戏?
Erich Gamma: 结束游戏就是最后一个里程碑,我们有一个又一个的里程碑,发布前的最后一个里程碑就是结束游戏。通常这也是六个星期,在结束游戏中我们需要集中精力,我们会使版本更稳定地前进。每一个里程碑都被详细计划并且结束游戏是发布在网上的。结束游戏计划定义了测试、修复的节奏。整个团队在社区的支持下持续工作。所有的开发人员和社区先测试两三天,然后再用四五天的时间来修复,最后我们再用二三天的时候来验证,变更的规则会更严。换句话说,越到结束游戏的后期,变更越困难。例如,一个需要修复的问题需要发给开发人员邮件列表并且修改也需要同样验证。
在结束游戏中最大的压力是有时候我们的修改会影响到更上层。我们也想计划所有事,但在结束游戏期间这是很困难的。
Bill Venners: 什么样的影响?
Erich Gamma: 例如,我们发现一个底层中加入了一个新机制,但不能被所有的上层使用。这种影响是很难计划的,上层可能需要一个新功能而底层认为那个功能已经有了。
Bill Venners: 这听起来像是沟通的问题。做底层工作的人似乎需要与做高层工作的人更好的沟通。
Erich Gamma: 是的,但我的意思是即使像我们这种及时发布了多年的人也不能很好地做到。最好解决方案是底层通过补丁的方式来响应变化的需要并通知高层。我们想传递的思想是你不可能在一个功能影响到所有层次前完全地考虑到所有影响。
Eclipse开发中的敏捷实践
Bill Venners: Eclipse团队遵循的是什么样的敏捷实践?
Erich Gamma: 来支持自动构建,这一切在Eclipse中都很容易。
遵循这些敏捷实践,我们通常尽早,尽快地自动测试,对每一次构建我们都有超过20000的测试。我们有自动的夜晚构建,在早上得到构建报告。在最近的3.1版本中,我们增加了性能测试,这样我们不仅测试正确性,而且测试了性能。这对我们有不少帮助,实际上你也会注意到3.1中的性能改善。
我们使用增量设计,我们提前设计API,但我们也是增量地来改善。我们重构的时候会保证已发布API的稳定性,因为影响客户的使用是不允许的。我们会在白天修改问题,每一个组件输出其最新的插件并在其上运行。这是很重要的,因为你可以第一时间发现错误。当然在你构建IDE或工具时,你处于繁杂的位置,有时候我们需要一天部署多次。因为如果我们在最近的构建中引入了错误,我们会在日间构建之前发现他。
Bill Venners: 你们实际上是部署组件在开发人员的工作站上,那他们是使用当前发布的开发版本吗?
Erich Gamma: 是的。开发人员安装最新的构建版本然后运行。
客户的沟通也是一个敏捷实践。对应到开源项目中,就是社区的参与。而我们有一个非常活跃和大型的社区。他们提出有野心的需求,和这样的社区一起工作是一种享受。
另一个敏捷实践是持续集成。我们会每晚,每周,和每里程碑的构建。我们有一种构建提升的想法。每晚构建是集成最新的代码,我们用他来尽早地发现组件间的集成问题。更高级的是每周的集成构建,我们希望有一些功能足够好可以提供给其他成员使用。下一级是每六周的里程碑构建,这时我们需要的不只是提供给其他成员的版本,而是给整个社区的。这就是我们的持续集成。
我们也实践短周期开发,但我们的开发周期并不像XP那样短,就像我的公车站的比喻那样,我们认为最短周期也需要六个周。
我们也做增量地计划。假定我们以六个周为周期,这是我们的时限。我们的最初计划是一个动态的需要增量更新的计划。也就是我们不会有一个提前的最终计划。我们的初始计划列出了一些里程碑,主要工作项的主题,然后我们会逐步地完善。以前我们有过类似的教训,最初我们使用静态的计划,就是说计划在我们开始时就已经精确制定了。现在我们选择计划随着我们改变,最终的计划版本会在我们完成的时候完成。我们计划的所有部分都是透明的,对每一个计划项,我们表述他是否已处理或计划了,然后我们逐步地更新。这样社区会看到我们已经处理了什么,计划了什么。通常我们都希望完成目标,但如果目标完成不了,我们会考虑取消,不过我们一点也不喜欢删除已完成的项目。回顾3.1版本,我很高兴这种情况很少发生。
Posted at 10:12下午 四月 06, 2006 by xMatrix in 软件工程 | 评论[0]
星期日 2006年04月02日
[译文]对话Eric Gammar--设计模式的设计准则(下)
什么时候该考虑接口
Bill Venners: 关于接口,GoF书包含了一些UML类图,这些看起来好像混和了接口和实现。当你看的时候,看到的是代码的设计,而这很难分清楚什么是API什么是实现。相反地如果你看一下JavaDoc,你只会看到接口。另外我也觉得在XP看不到接口和实现的区别,好像XP只讨论代码。了解到你正在改变这种测试驱动开发的无组织状态,那么什么时候开发人员应该考虑接口而不是代码呢?
Erich Gamma: 在设计一个应用和你设计一个平台时你需要区别对待。在设计平台时,你必须关心什么是API,什么是内部的。现在的重构使得修改名字变得很容易因而你需要小心避免意外的修改已发布的API。这已经不只是定义哪种类型需要被发布,你还需要回答下面的问题:你是否允许客户继承你的类?在Eclipse的API中,我们尽力标明是否我们允许客户来继承某一个类。我们的团队中有一个API提倡者,他帮助我们不仅遵守规则而且使API保持一致。
而设计应用时,即使你提取出拥有多种变化的抽象。对设计来说,你需要的是给出关键抽象,然后让其他的代码与这些抽象交互,而不是特定的实现,这样你就拥有了灵活性。当一个抽象的新变化出现时,代码依然可以正常运行。对XP来说,就像我前面说的,流行的重构工具可以使你在代码中尽早地引入接口,因而XP也是一致的。
Bill Venners: 那就是说应用与平台是一样的思考方式,只不过少一些可伸缩性。另一个不同就是如果我控制了所有与这个接口相关的客户那么对我来说是不是就很容易根据需要改变接口了。
Erich Gamma: 是的,对应用来说思考方式是一样的。你也需要构建应用使其用得更久。响应需求的变更不应该影响整个应用。如果一旦你提供出去了代码而你不再可以访问所有的客户端,那么你就必须以API的角度来考虑了。
Bill Venners: 即使这些客户是由同一公司的不同部门开发的吗?
Erich Gamma: 是的,就是这样。
Bill Venners: 这听起来对接口的思考在项目需要扩展时变得更重要了。如果项目只有两三个人,那么接口就不那么重要了,因为你可以想修改就修改。重构工具可以...
Erich Gamma: 重构工具可以为你做这些。
Bill Venners: 但如果是100个人的团队,这意味着大家会被分为多个组,不同的组会有不同的责任区。
Erich Gamma: 我们遵循的一个实践是将组件分配给一个组,而这个组负责这个组件并且发布相关的API,然后通过API来定义依赖。我们来抵制那种定义如一些组件比其他的更适合内部使用这样的关系。在Eclispe中所有组件是平等的,例如,Java开发工具插件并不比其他插件有更多特权。
一旦你发布了API那么你就需要负责保持其稳定性,否则就会破坏其他组件使项目进程受到阻碍。在这种规模大小的项目中保持API的稳定性是一个项目继续的关键要素。
在一个封闭环境中,当变化发生时你需要更多的灵活性。例如,你可以使用Java的废弃功能来允许其他团队逐步适应你的修改。而当大家意见一致时就可以删除废弃的方法了,但这不太可能发生在一个开放的平台中,废弃的方法是不能被删除的因为会破坏客户的应用。
组合PK继承
Bill Venners: GoF书中描述的OO设计的另一个准则是“尽量使用组合而不继承”。这是什么意思,为什么需要这样做呢?
Erich Gamma: 即使10年后的今天我依然坚持这是需要的。继承是一种改变行为的很酷的方式,但我们知道这种方式是脆弱的,因为子类很容易假定他重写的方法的上下文。而这样就将基类与其子类紧耦合了,因为子类代码的上下文会被使用。而组合有一种更好的属性,通过一些小的方式来插入大的对象就减少了耦合,大的对象最后会返回给小的对象。从API的观点来年,可被重写的方法比可被调用的方法有更强的义务。
在子类中当重写的方法被调用时你可以假定父类的内部状态,当你只是嵌入一些行为,这会更简单些。但这也是为什么你应该尽量使用组合的原因。一种普遍的误解是组合不能使用继承,但实际上组合就是使用了继承,但通常你只是实现了一个小的接口而不是继承自一个大的类。Java的监听器方式就是一个好的例子,通过监听器你实现一个监听器接口或者继承称谓适配器的接口。然后你创建一个监听器对象并注册到一个按钮中,而这些并不需要继承按钮类来响应事件。
Bill Venners: 当我在我的设计课程中讨论设计模式时,我提及最主要的是使用接口继承式的组合来处理不同情况。我说的接口继承,指继承如C++中的纯虚基类或者说Java中的接口继承。你提及的监听器例子也是这种情况,我实现了MouseListener,当我通过AddMouseLIstener传递实例给Jpanel时,我就是在用组合,因为前端拥有MouseListener的JPanel会调用他的mouseClicked方法。
Erich Gamma: 是的,你已经减少了耦合。此外这时你已经有了分离的监听器对象,你甚至可以用另的对象也联结他。
Bill Venners: 组合优于继承的其他灵活性还有些是我很难解释的。下面是一些我希望你能自己理解的一些短语:为什么?真正有用的是什么?额外的灵活性到底来自什么地方。
Erich Gamma: 我们称这种为黑箱重用。有一个容器,然后你嵌入一些小的对象,这些小对象配置容器并且自定义容器的行为,因为容器代理了一些行为给小的接口,因此这种方式是可行的,最后你就可以通过配置来自定义行为了。这就为你提供了灵活性和小对象的重用机会,而这是最有用的。相对于给你冗长的解释,我更喜欢用策略模式来指点你。这也是我通常解释组合优于继承的原型例子。额外的灵活性来自于你可以嵌入不同的策略对象,甚至你可以在运行时动态地改变策略对象。
Bill Venners: 那么如果打算使用继承...
Erich Gamma: 那么你不能综合策略模式对象的优点,也不在运行时动态地实现了。
Posted at 10:13下午 四月 02, 2006 by xMatrix in 软件工程 | 评论[0]
星期五 2006年03月31日
[转载]如何进行一个完美的Project Launch
今天在查找如何进行Kick Off的准备时,gooogle到这篇来自于“大虫's Blog”的文章,对其中的一些观点还是非常赞同,好文共享。站点还有作者的一些创业经历,值得一读。 如何进行一个完美的Project Launch? 首先,我假定你为一个Project Manager。 何为Project Launch?Project Launch是SOW/Contract已经签订或者已经基本签定之后,Project Team在正式Kick Off前所作的工作。 Project Launch目的是充分利用这段时间,为正式启动做好相应的准备工作,避免出现项目开始时以下情况发生: 那么具体应该如何准备呢? 一、尽快同Presales/Sales进行交接 Presales或者Sales打单完,基本他/她的任务就完成了,而你被指定为Project Manager, 你应当正式或者非正式的向他们了解状况,获取信息,重要的包括以下内容: 二、确定Project Charter Project Charter是个项目管理专业术语,中文叫项目宪章,以下重要内容需要了解清楚了: 三、识别Project Stakeholders并管理他们的期望 所谓Project Stakeholders也是个项目管理专业术语,叫做 项目干系人,就是那些对项目有关系,会对项目的成败施加影响或者被结果所影响。 识 四、定义沟通模式(Communication Model) 沟通是最重要的事情之一! 五、定义项目生命周期(Lifecycle Selection) 七、Project Kick off meeting 结束语 一个完美的Project Launch是项目成功的第一步,加油吧!
1. 事情太多手忙脚乱
2. 没准备好导致进入project的人员没有事情好做
3. 一进入项目就发现进入了陷阱,走上了漫漫不归路
4. 没搞清状况就开始项目,犯错误或者丢失客户信任,需要很长时间来弥补
5. Kick off meeting因准备工作而失败或者效果不好,影响project后续进行
1. 方案/SOW/Contract, 一字一句千万看仔细了,这可是有法律意义的,特别时含混不清的定义或者不确定的条款,比如"完成任何相关需求", 问问他们不清楚的地方是怎么回事。如果你也参加了Presale的活动,那么可以略过。
2. Techinical solution
3. 当初报价时所做的估算,已经估算后面的Assumptions,这些东西可能不会写在Contract里面的,但是却非常非常重要!Presales们对此很清楚的。
4. 项目的Depenencies和Constraints
5. 在签合同时曾经预定的资源(当然,一般是指人),sales们为了合同答应在team里面加确定的强人,如果到时候来不了,你就等着客户拍砖吧。
6. Concerns from business side,Business和delivery的人思考问题的方向是不一样的,听听他们的Concern或者建议,对你以后会有帮助的。
1. Billing type, 就是合同类型或者付款方式,一般有3种:Fixed Price,固定总价; T&M (Time & Material, 工时与材料合同);还有一种就是两者的结合了。
2. 项目基本情况
3. 项目关键成员的指定
4. 项目范围(Scope)
5. 主要交付物(deliverables)
6. Assumptions
7. Goals
8. 项目成功的关键要素
别Stakeholders不难,难在要识别、分析和管理他们的期望。PM的工作是什么,达到Stakeholders的期望。而不同的
Stakeholders对project的期望是不同的和冲突的,而PM要做的就是做不同的balance,从而保证project的成功。
<注:这点太难描述了啊>
理解客户的team structure,很多客户的office里面水很深的,所以一定要预先了解清楚:谁说话能算数;谁不能得罪......
定义自己team的structure,定义好roles和responsibilities
定义沟通矩阵(Communication Matrix)
定义Issue处理机制
这个就是软件开发相关的了,不同的项目生命周期,那么它的阶段、交付物、里程碑都会不同,开发管理的方式也差别挺大,用的模板(template)也不同,比如下面几种典型的软件开发生命周期:
1. Waterfall(瀑布模型)
2. 关键的V模型
3. Staged Delivery(阶段交付模型)
4. Iterative & Incremental (迭代和增量模型)
5. COTS(我不说,嘿嘿)
6. ......
六、其它计划工作
如果项目正式开始后有一个Project Planning Phase,那么你有draft的计划就好了,但是以下内容需要注意:
1. Risk Management Plan
2. 在即将组成的team内部做skill survey并制定相关的training plan
3. 最最重要的是列好一个项目正式kickoff后2周内的项目schedule
4. Resource Plan
5. SCM Plan
6. SQA Plan
搞好上面的内容,需要准备Project Kick off meeting了。
Kick
off
meeting嘛,一般头头脑脑都会出现,每个说几句,轮到PM就没有太多时间了。Presentation的内容比较容易,从上面准备的内容简要的选择
内容就可以了,但是需要注意的是:kick off的presentation的每一页都必须提前跟客户达成共识,千万不要让客户在kick off
meeting上challenge你或者不爽,不让以后可真没有好日子过了。
具体准备project kick off meeting的步骤:
1.明确kick off meeting的purpose
2.确定Agenda和主持人, 千万别把头头们发言的次序搞错了
3.Date/Time
4.Location
5.Presentation Hardware
6.Invitations
7.Rehearsal,如果是很慎重的kickoff meeting,那么在此之前做一个预演是最保险的了。
Posted at 11:01下午 三月 31, 2006 by xMatrix in 软件工程 | 评论[0]
星期四 2006年03月30日
[译文]对话Eric Gammar--设计模式的设计准则(上)
摘要
在这次对话中,Erich Gamma讨论了两个设计准则:“面向接口编程,而不是实现”和“尽量使用组合而不是继承”。
面向接口编程,而不是实现
Bill Venners: 在书的简介中,你提到可重用OO设计的两个准则。第一个是“面向接口编程,而不是实现”。他的实际意义是什么,为什么要这么做呢?
Erich Gamma: 这个准则与大型应用中需要仔细考虑的依赖关系有很大关系。增加类的依赖很容易,并且是太容易了,通常只需要增加一个引入语句。但相反的想要删除一个不想要的依赖就不是那么容易了,可能需要细致的重构甚至更困难,使你难以重用相关代码。因此你必须在引入依赖的时候多留一个心眼。这个准则告诉我们依赖于接口是更好的选择。
Bill Venners: 为什么呢?
Erich Gamma:一旦你依赖于接口,你就从实现中解耦出来了。这意味着实现可以变化,而这正是良好的依赖关系。例如,因为测试的目的你可以用轻量级的伪实现来替代重量级的数据库实现。幸运地是,现在有了重构的支持,你不再需要预先使用接口了,你可以在确实理解了问题后从具体的类中抽象出接口。有用的接口只需要通过“抽象接口”这种重构方式就可以生成了。
这种方案提供了灵活性,而且将设计从实现中分离出来,这也使得客户端不再需要与实现耦合了。这里有一个问题是是否需要用Java的接口来实现这个目的,可能抽象类是更好的选择。实际上,抽象类在演变时提供了更多的灵活性,你完全可以在不影响客户端的情况下增加新的功能。
Bill Venners: 如何来实现呢?
Erich Gamma: Java中你在接口中增加一个新方法,就影响了所有的使用者。而你使用抽象类,你可以增加一个提供默认实现的方法,所有的使用者都不爱影响。当然这里你也需要权衡一下,接口给了你不需要考虑基类的自由,抽象类给了增加新方法的自由。通常用抽象类来定义接口并不是一定可以的,随着类的演变,你还是应该考虑一下抽象类是否足够。
因为改变接口会影响使用者,那么你在发布时就应该考虑是否将他们作为不可变的。通常需要为接口增加方法时你必须增加拆分接口。在Eclipse中我们认为API的稳定性非常重要,因此你会看类似I*2这样的接口,如IMarkerResolution2和IWorkbenchPart2等。这些接口为基接口增加了方法,这么就不会影响原来接口的使用者了。然而,这会增加调用者的负担因为他们需要在运行时确定一个对象是否实现了特定的扩展接口。
另一个经验是你应该不只是关注于第一个版本,你还需要关注后续的版本。这并不是说为将来的扩展性作设计,而是要注意你必须维护产生的API并在一段时间保证其稳定性。我需要将构建持久化,这也是我们启动开发Eclipse后的一个重要风格。我们将Eclipse作为一个平台来构建,在设计Eclispe时必须考虑他可能会被使用10-20年。
在我们开始项目时,我们为基平台增加了改进的支持。其中一个例子是IAdapable接口,实现这个接口的类可以被适应至另一个接口,这也是扩展对象模式的一个实例。
Bill Venners: 有意思的是现在我们已经非常先进了,但当我们说构建的持久性时是意味着十到二十年。那么当古埃及人考虑构建持久性时他们要...
Erich Gamma: 可能是几千年吧?但对Eclispe来说,十年到二十年就够了。老实说,我也不能预见某个软件考古学家会在十或二十年后找到安装在某个硬盘上的Eclispe.我只是说Eclisep还是应该在未来十到二十内可以保持一个活跃的社区。
接口的价值
Bill Venners: A前面你说接口是非常有用的。那么他的价值表现为什么?为什么比实现更有价值?
Erich Gamma: 接口提取了对象间协作的关系。接口对实现来说是自由的,他只定义了协作的要素。一旦理解了接口,那么就理解了系统的大部分。为什么呢?因为理解了所有的接口,就理解了问题的要素。
Bill Venners: 你说的“问题的要素”指的是什么?
Erich Gamma: 方法名字是什么?抽象是什么?抽象和方面名字就定义了要素。Java的Collections包就是一个好的例子。如何用集合来工作的要素就是提取如List或Set的接口。这些接口的实现可能很多,但只要你理解了接口就理解了所有。
Bill Venners: 那么我想“面向接口编程,而不是实现”的核心是:在Java中有一种特殊的类称为接口,编程时应该在接口的基础上进行。还有一个OO的接口概念,而且每一个类都有这种概念。
如果编写代码时需要使用对象,对象的类存在于某一类层次中。在最高层次中的类是最抽象的,而在最低层次的类就是最具体的。那么我认为面向接口编程就是不要编写远离层次的类,每一个层次的类型都有相应的契约。
Erich Gamma: 是的,按照层次中的类型编程就是面向接口编程。
Bill Venners:那么要如何编写实现呢?
Erich Gamma: 想像一个有五个方法的接口,定义一个实现类实现了接口的方法并增加了另外十个方法。那么如果仅有接口被作为API发布,你调用十个方法就只是内部调用。如果你违反约定调用了十个方法中的一个,那么这种行为可能在以后会被破坏。这就是公共和发布方法的不同地方。一些方法是公共的,但并不意味着你发布了他。
;这样简短的名字被用来作为API而长名字作为内部使用。当然使用私有的类和接口是另一种隐藏实现的方法。
Bill Venners: 现在我理解你的意思了。公共和发布是有区别的。
Erich Gamma: 在Eclipse中我们有对待这种区别的约定,还有工具上的支持。在Eclipse3.1中我们增加了定义发布API包定义规则的支持,这些访问规则在项目的类路径中定义。一旦你违反了定义的规则,IDE会以编译警告的方式来提示内部类的访问。例如在你增加了一个对没有发布的类的依赖时,你会得到警告。
Bill Venners: 这就是说如果我编写了调用未发布的类的接口,就是对实现编程了,而这可能会在以后被破坏。
Erich Gamma: 是的,从提供者的角度来说需要一些自由并且保留改变实现的权利。
Posted at 09:05下午 三月 30, 2006 by xMatrix in 软件工程 | 评论[0]
星期日 2006年03月26日
[读书笔记]敏捷软件开发-创新和沟通的合作游戏
“如果不用软件开发来表述的话,那么你认为什么最类似于软件开发呢?”。作者以提问的方式引出了本章的重点,究竟软件是一种什么样的东西。
游戏,这里并不是指狭义上的游戏,而是一种更广泛的语义,更确切的说可以是比赛。游戏有很多种类,零和游戏,非零和游戏,竟争性游戏,合作性游戏,有穷游戏,无穷游戏等等。作者认为软件开发与攀岩运行非常相似,是一种需要合作、有固定目标的游戏。最近一直在看TVB的《the apprentice》,我觉得这与软件开发更类似。影响成功的因素很多:压力平衡,团队协作,天才,相关技能,培训,工具,资源,计划,准备,乐趣及挑战。任何一项可能是成功的因素,也可能是失败的因素。
像软件开发这种有目标的合作游戏的最终目的是什么呢。在《飞黄腾达》中是项目成功,而且在多个团队中成绩最好。对软件项目来说项目完成并成功布署到实际中。当然还有些附加的产物,如:团队成员的技能提升,团队文化的形成,团队经验的积累。
想像目前国内的一些项目开发,要求在每一阶段都产生相应的工件,通过过程的控制来控制最后的结果。实际上是颠倒软了件开发的主次目标,期望人是一样的,只要在流程上进行控制,最后的结果是一样的。这真的可以吗,或许是他们没有认识到软件开发与一般工业生产的区别,人的能动性,在软件开发中人是最重要的,这也引出了下一回合的内容;人。
其实我们回顾一下,敏捷软件开发的四名真言:
1、人本身和相互间的沟通比过程和工具更重要
2、可运行的软件比复杂的文档更重要
3、客户的协作比合同约定更重要
4、拥抱变化比死守计划更重要
正是说明了人的重要性,试问如果有完美的人,还需要那么多的制度/过程/文档/约定/计划吗?AP与CMM之类的最大区别就在于前者想从人的角度也解决问题,充分发挥人的能动性;而后者由于控制不了人,只有制度/过程/文档/约定/计划来约束人。前者可以发挥人的最大的能量,而后者只能以平均人的能量来计算。
其实也说不上是AP更优秀,或者CMM更优秀。两者都有适用的地方,AP适合于成熟/稳定的团队,能干的成员,当然也就能够取得最高的效率;而CMM适合于不成熟/变化的团队,成员的能力不可预知,这时候平均的效率也许会更高些。
另注:昨天看完了《the apprentice IV》的结局,Randal成为了学徒,Rebecca输了。其实个人觉得Rebecca的能力似乎更强一些,尤其在最后的决赛中,我认为她在任务完成的过程中几乎是完美的(唯一的缺点是筹得的款项不足,但这很大程度上是Yahoo的关系)。而Randal的表现却不尽人意,而在最后在回答Trump的提问更显得有些欠缺;但我想Trump看中的可能最多的是Randal的学历,及其亲和力,还有就是涉世未深,保留了一些人性的率直。反观Rebecca,是那么的老练,可能跟她的职业有关吧。看得出来,Trump还是很想将Rebecca收入帐下,于是才会在雇用了Randal之后,问他从他的角度来看,是否会雇用Rebecca,而这时的Randal似乎有点晕了^_^
Posted at 09:52下午 三月 26, 2006 by xMatrix in 软件工程 | 评论[2]
星期六 2006年03月25日
[译文]对话Eric Gammar--模式与实践
摘要
在这次对话中,Erich Gamma讨论了设计模式是问题的解决方案,设计模式如何帮助理解其意图和权衡利弊及如何通过实践来成为更好的设计人员。
设计模式是问题的解决方案
Bill Venners: 我第一次深入理解OO编程是来自于阅读Scott Meyers的《Effective C++》。在那本书中有一准则说“要确信公共的继承模型是“是什么””,这句话使我真正理解了继承的含义。然而,另一条准则说“通过组合来为“拥有什么”或者“实现什么”建模”,但这一准则并没有使我更明白组合的用途。
然而在GoF书中我发现了更具体的使用组合的描述,如用组合来为如“适应什么”/“代理什么”/“装饰什么”建模。如果你看一下书中的UML图,会发现他们很类似。大部分都是通过接口继承来使用组合。模式的不同之处在于那些你尝试用组合和继承关系来解决问题。即使类图看起来类似,但其设计意图却不同。那么设计模式中代表意图的角色是什么呢?
Erich Gamma: 模式通常都对应于特定问题并且在一定的上下文中被使用。虽然不同的模式中的解决方案看起来可能类似,但他们解决的问题是不同的。实际上大量事实证明模式是通过增加中间层次来解决问题的。有趣的是这种中间层次是如何实现的及为什么需要。因此如果你只是看一下问题的解决方案,他可能并不是那么明显,所因为有的东西看起来都差不多。就像在我们写下设计模式时我们也常有这种感觉--他们好像都起源于策略模式。
开始的时候我们只描述解决方案,大概有20页的目录。有经验的开发人员理解起来也没什么问题而且反馈我们如“是的,我就是那样做的。”然而后来我们注意到很难找全所有的,因此我们给出不同的抽象,不同的代理,但最主要的还是寻找问题的解决方案。对模式的观点和前期读者的反馈使我们不再只关注于解决方案而且也注意起问题本身。模式包含一个问题和其解决方案,你需要两者都关注。例如,策略和状态模式有同样的解决方案:代理给分离的对象,然后使用对象类层次来适应行为变化的接口,但他们针对的问题是不同的。策略模式是用来插入算法,而状态是用来在类状态改变时改变相应的行为,就像一个状态机那样。
理解设计意图和权衡利弊
Bill Venners: 在GoF书,你说“理解这本书中的设计模式可以使你更容易理解现有的系统”。如何理解?
Erich Gamma: 你可以说包含模式的系统比较没有的更简洁。模式简化了设计的对话。我和Kent Beck在Eclipse书中的最后一节就是个好例子,我们描述了一些Eclispe的包含模式的设计,你可以看到是如何简洁的了。你可能会说“这是组合模式”,而不需要说更多,别人就知道是什么了。
有趣的是我们在Eclipse的早期版本中进行了这种模式分析,而分析结果对最新的版本依然有效。虽然结果已经过期但模式依然一致。
一旦你理解了系统是使用了一定集合的模式,而且你也了解这些模式的缺点,那么你就更容易理解使用这个解决方案的开发人员的意图了。模式不仅告诉了你其意图而且已经权衡了利弊。一旦你理解了设计的局限性,你就更容易成就一个可重用的设计如框架。而最坏的结果就是你与设计做对,这时你并没有实际理解设计,不只是其意图,而且可能你会说“我会用我的方式来做”。
Bill Venners: 你刚才说模式也告诉了我们利弊的权衡。这是什么意思?
Erich Gamma: 设计经常要权衡利弊,有很多可选方案而每一种方案都有自己的行为结果。在设计是通常需要做决定,每一个决定都有其优点及缺点。这也是我们从编写设计模式中学到的重要一课。开始时我们对模式都很兴奋,因为我们只看到正面的效果,直到有读者指出实际结果并不是这么美好。于是我们开始考虑另一面--模式的局限性。这时我们也认识到标识一个模式相对比实际使用一个模式更简单。举例来说:你增加了一个策略模式,然后有了更多的灵活性,但另一方面你使用了更多的对象和额外的中间层次。是吧?所有的事都是有代价的,这也是我说的利弊。模式的一个关键点在于他捕获这些利弊而你不再需要同样的分析了。在你遵循设计的流程时,模式会是一个路标。如果你继续下去,你也会理解其中的利弊。我认为这是非常有价值的。
应用设计模式
Bill Venners: 在书中你们说“知道这些设计模式可以使你成为更好的设计者”,如何理解?难道我不需要知道应用他们的时机吗?
Erich Gamma: 不,你还需要动用自己的思想。这并不是很明确什么时候来应用设计模式。此外,你也要知道模式在应用进的各种变化及如何也调整模式。你通常需要改变一个模式来适应特定的问题。
这里可能是对设计模式作一些坦白的时候,在书中我们只说了什么时候可以应用一个模式,但我们没有讨论什么时候删除一个模式。删除模式可以简化系统而且可能有一个简单的解决方案可以更好地解决问题。简单解决方案的出现可能是一个真正的挑战。
Bill Venners: 许多人想成为好的设计者,他们希望这本书帮助他达到目标,但只读这本书好像并不能。。。
Erich Gamma: 并不能成为好的设计者。这点我也同意。只通过阅读书籍来学习模式甚至设计并不能真正掌握他们。目前还有其他的好的模式的书籍,那么在看完GoF书后也可以参考了其他的。
Bill Venners: 那什么是成为好的设计者的因素呢?
Erich Gamma: 除了阅读书籍,还需要阅读和理解大量的代码,看一下现有的系统如何解决一个特定的问题及有经历的设计人员是如何做的。通常设计模式就是记录了有经验的人做过的东西。但只了解设计模式是不够的。你可以通过模仿优秀开发人员的工作来提高,如现在有许多开源的项目可以作为学习的范例,Eclipse也是其中一个。通常你对开源项目的捐献是被欣赏的。你不仅要学习成为设计人员,还要提出好的设计思想,还要沟通和讨论他们。你必须要实践,就像是一个刚上路的学徒,经过大量的实践你就会成为有经验的设计人员了。
实践,实践,还是实践
Bill Venners: 在书中你写到“很容易将模式看作一个解决方案,看作一个可以调整和重用的技术。但要看到何时何地将模式最好应用于特定的问题是很难的。”新手如何来理解呢?假设他们看完了书,也理解的模式,现在他们开始工作了,他们是该如何学习到何时使用一个模式是合适的,还是该成为一个“模式化”的设计人员尽力使用尽可能多的模式?
Erich Gamma: 不幸地是,许多事只有在实践后才能真正体会。如果我是一个新手,我最想有一个导师或者伙伴,我会和他们一起编程,然后导师会说“嘿,这个地方看起来有问题”或者“NND,你怎么又重复了一遍”。导师通常会提供即时的意见和帮助。这也是双人编程的优点,这是一种提高技术的有效方式。我经常从双人编程过程中学到东西而且我希望会学得更多。
当然底线是你需要通过编程来学习模式,而不只是过家家而已。你不可能从读书中学会模式,通过书你不可能完全掌握模式,只有你开始将模式应用到编程中的实际问题,你才会开始更好地理解模式并且为下一次提高作准备。
Posted at 11:04下午 三月 25, 2006 by xMatrix in 软件工程 | 评论[0]
星期六 2006年03月18日
[读书笔记]敏捷软件开发-无法完全理解和沟通(三)
听众的三个层次
人们从学习到精通一门新技术时通常都会经过三个阶段:按步就班,突破规范,自由发挥。在第一个阶段,通常都需要有明确的步骤来指导如何完成一次成功的体验;在第二阶段,人们开始寻找技术中的边界,并尝试在不同的环境下应用技术。在第三阶段,就不再需要遵循什么步骤了,可以以自己所喜欢的方式也完成。在软件开发中,一个领导过多个项目的项目经理通常不会在乎”过程“什么的,而是说”把任务交给我,我会在指定的时间内完成的“。这就是处于第三阶段的人的表现。
现来看一下这三个层次与方法学的关系,属于第一层次的书通常要求读者依样画葫芦就能够保证程序正常运行,如《编程学科》或《软件工程准则》,方法学中的代表则是RUP,他为读者详细描述了过程,技术和标准。属于第二层次的书如《计算机编程艺术》,为读者提供了一些技术,并示例在何时是最有效的。而第三层次的读者已经知道所有的软件技术是依赖于人的,因此通常他们会说“做可以做的事”,“在你真正使用的时候可能并不关心是否真的在使用”或者“用能解决问题的技术”。这些话对第三层次的人来说是正确的,而对第二层次的人来说有点迷惑,而对第一层次的人来说,就是对牛弹琴了。
那么如何来看待方法学呢,《XP编程释疑》的作者给出了不XP中的三个阶段:如果你处于第一阶段,那么按照所有的规则来做吧;如果你处于第二阶段,那么再看一下规则中的变化吧;如果你处于第三阶段,那么你都不用管是否你正在使用XP。
个人观点:因为软件业有太多的技术更新,你不可能精通所有的技术,那么如何来看待自己处于哪一个层次呢,是不是有一种新技术,就需要经历这三个阶段呢?我觉得最重要的应该是学习能力吧,或者说是变化(触类旁通)的能力。就像武侠小说中的高手,看到一门功夫,不会从入门级开始,而是直接能够触摸到其中的精髓。
Posted at 10:36下午 三月 18, 2006 by xMatrix in 软件工程 | 评论[0]
[译文]对话Eric Gammar--可重用性与灵活性(下)
预测的风险
Bill Venners: GoF书上说“最大化重用的关键在于参与新的需求和对现有需求的改变,在于设计你的系统能够逐步改善。为了设计这样的系统,他必须足够健壮,你必须考虑系统日后在其生命周期中可能需要的改变。就是一个在将来不需要冒风险来重做关键设计的设计。”这似乎与XP的观点相反。
Erich Gamma: 是这样的。这是说你应该提前考虑,应该做一些预测,关于灵活性的预测。我也知道XP提醒我们对灵活性的预测是代价高的,因此通常我不会严格地这样做。但为了增加灵活性,你确实需要考虑需求上的要求。如果没有这样的需求,那么也不需要在系统中预留相关的扩展点。
但我不认为XP与模式是对立的。这与你如何使用模式有关。XP开发人员也将模式作为他们的使用工具之一,他们会在一旦需要灵活性时利用模式进行重构。尽管这本书是在十年前说的这些话,但你现在还是可以用。你开始设计并提前考虑使用模式,但这不是XP开发人员的方式。
Bill Venners: 那么如果XP开发人员不使用模式会首先做什么呢?直接写代码吗?
Erich Gamma: 他们从测试用例开始。
Bill Venners: 是的,他们从测试开始。那么他们什么时候在实现功能,使测试通过之后进行检查看是否有需要重构是否需要模式呢?
Erich Gamma: 可能在有新需求时吧。我也喜欢这种需求驱动的灵活性方式,这也是Eclipse开发中使用的方式。在需要发布越来越多的API后,我们在有请求时就是这么做的。当客户说“我们必须使用或复制所有的内部类,而我们不想那样做”,于是我们就说“好的,我们会做一些修改来作为API发布。”就这样,我们会慢步地考虑这样情况,而不会在不适时的时候来提交。
Bill Venners: 是吗,如果有一些预测性的需求,那么你会说需要等到有需求驱动,而不是简单地解决问题吗?例如一些人说“是的我们确实需要这个功能”,那么他们说那是个需求,而另一些人说“我们确实需要这个功能吗?”。这时候如何来确定什么是预测的什么是实际的。谁来确认需求呢?作为程序员又该如何确认呢?
Erich Gamma: 你必须有一个客户或者产品的消费者。对Eclipse来说,我们的客户是编写插件的团体。我们与他们沟通,基于实际的使用我们能确切地了解他们需要的是什么。因此我建议程序员在必须做一些预测时,确保至少有一个客户参与,当然越多越好。对已经有一些想法时也非常有用。
Bill Venners: 这里你说的有一些想法是什么意思?
Erich Gamma: 有一个具体的例子。我想像如何使代码更抽象,而不是其他的用处。一旦我有了这种想法,我立刻听取来自我潜在客户的意见。
Bill Venners: 那么你首先需要构建一个具体的实例。
Erich Gamma: 两三个也可以,除非有问题。重复代码一次,又重复了一次,那么可能会再重复。这时候就需要抽象了,我会说如果这个类允许我们插入自定义的行为那么就不需要重复其余的了。
框架化的问题
Bill Venners: 框架、平台和工具集的区别及其不同的灵活性是什么?
Erich Gamma: 对平台来说主要是长期的稳定性,平台通常有兼容性的保证,因此在平台上构建是非常放心的。框架通常没有这种特性而且我们也可以看到许多框架在保证这种特性的失败案例。如果你看一下Eclipse,他包含框架、工具集,也提供平台API,所有这些是通过插件来完成的。框架抽象提供了更高级别的默认功能,为此框架需要受控。这种控制的缺失可能会导致称之为框架化的东西。
Bill Venners: 你的意思是想使框架超越所有的想法是有弊端的?
Erich Gamma: 框架化是一种框架承担了太多的东西或者他以一种你不需要但却不能改变的方式来运行的弊病。虽然得到这些功能都是免费的,但却损害了你自由获取功能的方式,你现在被绑定在这个架构上了。为了取得想要的行为你就不得不与框架进行斗争,而这通常就是你损失的开始,因为你很难要求框架以他不使用的方式来运行。工具集不会尝试为你提供控制因而也不会有框架化的问题。
Bill Venners: 那么工具集不控制是因为。。。
Erich Gamma: 使用工具集你创建和调用其对象并且注册监听器来响应相应事件,你是受控的。框架尝试可控的而且告诉你什么时候做什么。工具集给了你构建块但使你在受控范围内。
Bill Venners: 那么如果我继承类来创建EJB那么框架可能类似于EJB容器?
Erich Gamma: 是的。当然我们在开发框架时尝试开发尽量小型的框架,我们更倾向于小型框架而不在重量级的。
Bill Venners: 为什么?
Erich Gamma: 因为框架越大,他需要做的就越多,他的学习曲线就越大,从而维护起来就越麻烦。如果你愿意承担开发框架的风险,那么你也会开发小型而专注的框架,他可能只是一个可选项。这可以在你为必须使用框架而气馁时较好地避免框架化的问题。理想中我更倾向于拥有可挑选的小型框架的工具集,那样就可以承担合理的框架引入的代价。
Posted at 10:35下午 三月 18, 2006 by xMatrix in 软件工程 | 评论[0]
星期五 2006年03月17日
尘埃落定--16th "jolt" 大奖名单
书籍:大众类
Jolt Winner: Prefactoring by Ken Pugh (O'Reilly)《预构》
点评:重构流行后的另一更深入的想法
Productivity Winners:
Innovation Happens Elsewhere: Open Source as Business Strategy by Ron Goldman, Richard P. Gabriel (Morgan Kaufmann)
Producing Open Source Software: How to Run a Successful Free Software Project by Karl Fogel (O'Reilly)
The Art of Project Management by Scott Berkun (O'Reilly)
书籍:技术类
Jolt Winner: Agile Web Development with Rails by Dave Thomas, David Hansson, Leon Breedt and Mike Clark (Pragmatic Bookshelf)《Rails下的敏捷网页开发》
点评:Ruby on Rails流行的势头不弱啊
Productivity Winners:
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries by Krzysztof Cwalina and Brad Abrams (Addison-Wesley)
Practical Common Lisp by Peter Seibel (Apress)
Why Programs Fail: A Guide to Systematic Debugging by Andreas Zeller (Morgan Kaufmann)
企业级项目管理
Jolt Winner: WelcomRisk 2.6 (Welcom)
Productivity Winners:
Corticon Business Rules Management 4.0 (Corticon)
JBoss 2 Portal (JBoss)
Visual Studio Team System 2005 (Microsoft)
数据库引擎及工具
Jolt Winner: Microsoft SQL Server 2005 (Microsoft)
点评:MSSQL很久都没有出新版本了,也得给点面子
Productivity Winners:
Berkeley DB 4.4 (Sleepycat Software)
Google Maps API 2005 (Google)
MySQL 5.0 (MySQL)
缺陷跟踪及配置管理
Jolt Winner: Perforce SCM 2005 (Perforce)
Productivity Winners:
FogBugz 4.0 (Fog Creek)
Guiffy SureMerge 7.0 (Guiffy Software)
JIRA 3.4 (Atlassian Software)
设计及建模工具
Jolt Winner: Lattix LDM 2.0 (Lattix)
Productivity Winners:
Borland Together 2006 for Eclipse (Borland)
Enterprise Architect 6.0 (Sparx Systems)
MindManager Pro 6.0 (Mindjet)
开发平台
Jolt Winner: Visual Studio Team System 2005 (Microsoft)
点评:真的可以吗?Maybe...
Productivity Winners:
Eclipse SDK 3.1 (Eclipse.org)
IntelliJ IDEA 5.0 (JetBrains)
Komodo 3.5 (ActiveState)
类库/框架/组件
Jolt Winner: .NET Framework 2.0 (Microsoft)
点评:个人觉得Spring更有实力
Productivity Winners:
Dundas Chart for .NET 5.0 (Dundas Software)
Qt 4.0 (Trolltech)
Spring Framework 1.2.6 (SpringFramework.org)
移动开发平台
Jolt Winner: Crossfire 5.6 (AppForge)
Productivity Winners:
Carbide.c++ Express (Nokia)
Flash Lite 2.0 (Adobe)
NetBeans IDE 4.1 (Sun Microsystems)
项目质量管理
Jolt Winner: Rally 5.6 (Rally Software Development)
Productivity Winners:
CollabNet Enterprise Edition with Project Dashboard/Task Management 2005 (CollabNet)
QACenter Enterprise Edition 5.1 (Compuware)
TargetProcess Suite 1.4 (TargetProcess)
安全工具
Jolt Winner: Elemental Compliance System 1.4 (Elemental)
Productivity Winners:
CodeAssure 2.0 (Secure Software)
DevPartner SecurityChecker 1.0 (Compuware)
Fortify Security Tester 1.0 (Fortify)
测试工具
Jolt Winner: VMTN Subscription 2005 (VMware)
Productivity Winners:
Agitator 3.0 (Agitar Software)
AQtime 4.7 (AutomatedQA)
Clover 1.3 (Cenqua)
实用工具
Jolt Winner: Camtasia Studio 3.0 (TechSmith)
Productivity Winners:
DevPartner Studio 8 (Compuware)
Fog Creek Copilot 1.2 (Fog Creek Software)
ReSharper 1.5 (JetBrains)
网页开发工具
Jolt Winner: Rails 1.0 (rubyonrails.org)
点评:为什么是作为工具呢?
Productivity Winners:
JBoss Application Server 4x (JBoss)
Macromedia Studio 8 2005 (Adobe)
Zend Studio - Enterprise Edition 5.0 (Zend)
名人堂
Visual Studio Professional Edition (Microsoft)
点评:曾经的辉煌,值得留念
Posted at 01:14下午 三月 17, 2006 by xMatrix in 生活点滴 | 评论[0]