??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧洲精品在线,无码天堂亚洲国产AV,亚洲五月六月丁香激情http://www.tkk7.com/jinfeng_wang/category/699.htmlG-G-S,D-D-U!zh-cnThu, 18 Mar 2010 21:39:23 GMTThu, 18 Mar 2010 21:39:23 GMT60力_法分?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2010/03/19/315853.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 18 Mar 2010 16:27:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2010/03/19/315853.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/315853.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2010/03/19/315853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/315853.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/315853.html</trackback:ping><description><![CDATA[  <p>A)<span style="font-family: 'QS 明朝'">?/span><span style="font-family: SimSun">?/span><span style="font-family: 'QS 明朝'">人民共和?/span><span style="font-family: SimSun">力_</span><span style="font-family: 'QS 明朝'">合同?/span></p> <p><a >http://www.molss.gov.cn/gb/news/2007-06/30/content_184630.htm</a></p> <p>B)<span style="font-family: 'QS 明朝'">?/span><span style="font-family: SimSun">?/span><span style="font-family: 'QS 明朝'">人民共和?/span><span style="font-family: SimSun">力_</span><span style="font-family: 'QS 明朝'">合同?/span><span style="font-family: SimSun">?/span><span style="font-family: 'QS 明朝'">施条?/span><span style="font-family: 'QS 明朝'">(</span><span style="font-family: SimSun">解释力_法实?/span><span style="font-family: 'QS 明朝'">)</span></p> <p><a >http://www.gov.cn/flfg/2008-09/19/content_1099500.htm</a></p> <p>C)<span style="font-family: SimSun">关于立力_关系有关事项的通知</span></p> <p><a >http://www.law-lib.com/law/law_view.asp?id=92395</a></p> <p>D)<span style="font-family: SimSun">上v市女职工力_保护办法</span></p> <p><a >http://www.shanghai.gov.cn/shanghai/node2314/node3124/node3125/node3133/userobject6ai655.html</a></p> <p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">·<span style="font: 7pt 'Times New Roman'">                     </span><strong>C)</strong></span><strong><span style="font-family: SimSun">的相兛_容:(x)</strong></span></p> <p>     <span style="font-family: SimSun">用h单位未与力_者签订劳动合同,<strong><span style="color: red">认定双方存在力_关系</strong>时可参照下列凭证Q?/span></span></p> <p>(<span style="font-family: SimSun">一</span>)<span style="font-family: SimSun">工资支付凭证或记?/span>(<span style="font-family: SimSun">职工工资发放花名?/span>)<span style="font-family: SimSun">、缴U_社?x)保险费的记录?/span></p> <p>(<span style="font-family: SimSun">?/span>)<span style="font-family: SimSun">用h单位向劳动者发攄<strong><span style="color: red">“工作?#8221;?#8220;服务?#8221;{能够证明n份的证g</strong>Q?/span></span></p> <p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">·<span style="font: 7pt 'Times New Roman'">                     </span><strong>B) </strong></span><strong><span style="font-family: SimSun">的相兛_容:(x)</strong></span></p> <p style="margin-left: 69pt; text-indent: -48pt; tab-stops: list 69.0pt">W六?span style="font: 7pt 'Times New Roman'">        <span style="font-family: SimSun">用h单位自用工之日v<span style="color: blue">过一个月不满一q?/span>未与力_者订立书面劳动合同的Q应当依?span style="color: blue">力_合同法第八十二条的规定向力_者每月支付两倍的工资Qƈ与劳动者补订书面劳动合?/span>Q劳动者不与用人单位订立书面劳动合同的Q用人单位应当书面通知力_者终止劳动关p,<span style="color: blue">q依照劳动合同法W四十七条的规定支付l济补偿</span>?/span></span><strong><span style="color: red">(1</strong></span><strong><span style="color: red; font-family: SimSun">Q相当于l?/strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">倍工资,</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">Q补合同Q?/strong></span><strong><span style="color: red">3</strong></span><strong><span style="color: red; font-family: SimSun">Q如果辞退Q再按照有合同补偿)</strong></span></p> <p style="margin-left: 21pt"><span style="font-family: SimSun">W二十七条 力_合同法第四十七条规定?strong><span style="color: red">l济补偿的月工资按照力_者应得工资计,包括计时工资或者计件工资以?qing)奖?/strong><span style="color: red">?/span></span></span></p> <p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">·<span style="font: 7pt 'Times New Roman'">                     </span><strong>A)</strong></span><strong><span style="font-family: SimSun">的相兛_容:(x)</strong></span></p> <p>     <span style="font-family: SimSun">W四十二条 力_者有下列情Ş之一的,用h单位<strong><span style="color: red">不得依照</strong>本法W四十条、第四十一条的规定解除力_合同Q?/span></span></p> <p><strong><span style="color: red">        </strong></span><strong><span style="color: red; font-family: SimSun">Q四Q女职工在孕期、期、哺x?/strong></span></p> <p> <span style="font-family: SimSun"> W四十七条 l济补偿按劳动者在本单位工作的q限Q?strong><span style="color: red">每满一q支付一个月工资的标准向力_者支付。六个月以上不满一q的Q按一q计;</strong>不满六个月的Q向力_者支付半个月工资的经补ѝ?/span></span></p> <p>     <span style="font-family: SimSun">W八十二条 <strong><span style="color: red">用h单位自用工之日v过一个月不满一q未与劳动者订立书面劳动合同的Q应当向力_者每月支付二倍的工资?/strong></span></span></p> <p><strong><span style="color: red">    </strong></span><span style="font-family: SimSun">用h单位q反本法规定不与力_者订?strong><span style="color: red">无固定期限劳动合?/strong>的,自应当订立无固定期限力_合同之日起向力_者每?strong><span style="color: red">支付二倍的工资</span></strong>?/span></span></p> <p><strong><span style="color: red">     </strong></span><span style="font-family: SimSun">W八十七条 用h<strong><span style="color: red">单位q反本法</strong>规定解除或者终止劳动合同的Q应?strong><span style="color: red">依照本法W四十七?/span></strong>规定的经补?strong><span style="color: red">标准的二?/span></strong>向劳动者支付赔偉K?/span></span></p> <p> <span style="font-family: SimSun">W十四条 无固定期限劳动合同,是指用h单位与劳动者约定无定l止旉的劳动合同?/span></p> <p>    <span style="font-family: SimSun">用h单位与劳动者协商一_(d)可以订立无固定期限劳动合同。有下列情Ş之一Q劳动者提出或者同意箋订、订立劳动合同的Q除力_者提立固定期限劳动合同外Q应?strong><span style="color: red">订立无固定期限劳动合?/strong>Q?/span></span></p> <p>    <span style="font-family: SimSun">Q一Q劳动者在该用人单?span style="color: red">q箋<strong>工作满十q?/strong>的;</span></span></p> <p>    <span style="font-family: SimSun">Q二Q用人单位初ơ实行劳动合同制度或者国有企业改刉新订立劳动合同时Q劳动者在该用人单位连l工作满十年且距法定退休年龄不_q的Q?/span></p> <p>    <span style="font-family: SimSun">Q三Q?strong><span style="color: red">q箋订立二次固定期限力_合同</strong>Q且力_者没有本法第三十?ji)条和第四十条第一V第二项规定的情形,l订力_合同的?/span></span></p> <p>    <span style="font-family: SimSun">用h单位<strong><span style="color: red">自用工之日v满一q不与劳动者订立书面劳动合同的Q视为用人单位与力_者已订立无固定期限劳动合?/strong>?/span></span></p> <p><strong> </strong></p> <p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">·<span style="font: 7pt 'Times New Roman'">                     </span><strong>D) </strong></span><strong><span style="font-family: SimSun">的相兛_容:(x)</strong></span></p> <p><span style="font-family: SimSun">W十一?/span><span style="font-family: SimSun">对妊娠期的女职工Q?strong><span style="color: red">不应廉其劳动时?/strong>Q?/span></span></p> <p><span style="font-family: SimSun">W十四条</span><span style="font-family: SimSun">奌工假分别按下列情况执行Q?/span></p> <p>     <span style="font-family: SimSun">Q一Q单胎顺产者,l予<span style="color: red">产假?ji)十天,其中产前休息十五天,产后休息七十五天?/span></span></p> <p><span style="font-family: SimSun">W十五条</span><span style="font-family: SimSun">奌工生育后Q在其婴儿一周岁内应照顾其在每班力_旉?span style="color: red">授^两次Q包括h工喂养)?span style="color: red">每次</span>单胎U授x间ؓ(f)<span style="color: red">三十分钟</span>Q亦可将两次授^旉合ƈ使用。多?yu)胎生育者,每多生一胎,每次Z^旉增加三十分钟?/span></span></p> <p> <span style="font-family: SimSun">W十八条</span><span style="font-family: SimSun">奌工在<span style="color: red">产假期间的工资照发。按本规定n受的<span style="color: red">产前假和Z^假的工资</span>按本人原工资?span style="color: red">癑ֈ之八十发l?/span>。单位增加工资时Q女职工按规定n受的产前假、假、哺乛_Q应作出勤对待?/span></span></p> <p><strong><span style="color: red">    </strong></span></p> <p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 0cm"><span style="font-family: Symbol">·<span style="font: 7pt 'Times New Roman'">                     </span><strong><span style="font-family: SimSun">l论Q?/span></strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">1Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">认定力_关系Q工作证</span></strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">2Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">是否{֐?/span></strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">3Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">如果没签合同Q怎么补偿Q?/span></strong></span><span style="color: red">1</span><span style="color: red; font-family: SimSun">Q?strong>相当于给</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">倍工资,</strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">Q补合同Q?/strong></span><strong><span style="color: red">3</strong></span><strong><span style="color: red; font-family: SimSun">Q如果辞退Q再按照有合同补偿)</strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">4Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">如果是固定合同,怎么补偿Q?/span></strong></span><strong><span style="color: red">N+1</strong></span><strong><span style="color: red; font-family: SimSun">Q?/strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">5Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">如果是无期合同,</span></strong></span><strong><span style="color: red">2</strong></span><strong><span style="color: red; font-family: SimSun">?/strong></span></p> <p style="margin-left: 36pt; text-indent: -27pt; tab-stops: list 36.0pt"><strong><span style="color: red">6Q?span style="font: 7pt 'Times New Roman'">      </span></strong><strong><span style="color: red; font-family: SimSun">孕妇怎么处理Q?/span></strong></span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333">1</span><span style="background: silver; color: #333333; font-family: SimSun">、公司辞退孕妇的补偿情冉|准是怎样Q?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">{:(x)发放工资到哺x满;按工作年限计经补偉K?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333">2</span><span style="background: silver; color: #333333; font-family: SimSun">、公司是否可以以我的考核和我是孕产妇不能胜Q工作为由Ҏ(gu)q行降职降降薪处理Q?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">{:(x)不可以?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">我们的工资分为基本工资(U占</span><span style="background: silver; color: #333333">1/4)+</span><span style="background: silver; color: #333333; font-family: SimSun">岗位工资</span><span style="background: silver; color: #333333">+</span><span style="background: silver; color: #333333; font-family: SimSun">l效工资{。是否可能出现只要不降低我的基本工资是合法的行为?</span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">{:(x)不合理。工资是包括了岗位工资和l效工资?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333">3</span><span style="background: silver; color: #333333; font-family: SimSun">、如果公怾法破产,我是否有向集团主张赔偿的权利Q?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">{:(x)破也可以主张权利,在破产胦产中优先演戏ѝ?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333">4</span><span style="background: silver; color: #333333; font-family: SimSun">、如果可能需要诉诸法律,我应该准备哪些方面的举证Q?/span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">{:(x)存在力_关系的证据最重要Q此外,工资条、怀孕的证据、结婚证、准生证</span></p> <p style="margin-left: 9pt"><span style="background: silver; color: #333333; font-family: SimSun">也比较重要?/span><span style="background: silver; color: #333333; font-family: SimSun">Q?/span><strong><span style="background: silver; color: red; font-family: SimSun">按照力_?/span></strong><strong><span style="background: silver; color: red">42</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">条,不得解除三期【孕期、期、哺x】妇奟뀂那么如果一定要q反力_法解除劳动关p,只能按照q反力_法,按照W八十七条进行二倍赔偿,也就?/span></strong><strong><span style="background: silver; color: red">3</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">倍)</span></strong></p> <p style="margin-left: 9pt"><strong><span style="font-size: 13.5pt; color: #333333; font-family: 'QS 明朝'">案例</span></strong><strong><span style="font-size: 13.5pt; color: #333333">:</span></strong></p> <p style="margin-left: 9pt"><strong><span style="font-size: 13.5pt; color: #333333"><a >http://www.tianya.cn/publicforum/content/law/1/119373.shtml</a> </span></strong></p> <p style="margin-left: 9pt"><span style="background: silver; font-family: 'QS 明朝'">案情Q?/span><span style="background: silver">A</span><span style="background: silver; font-family: 'QS 明朝'">公司辞退</span><span style="background: silver">B</span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">Q不?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver">B</span><span style="background: silver; font-family: 'QS 明朝'">可能存在?/span><span style="background: silver; font-family: SimSun">q错</span><span style="background: silver; font-family: 'QS 明朝'">Q假</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver">A</span><span style="background: silver; font-family: 'QS 明朝'">毫无道理毫无依据的辞退</span><span style="background: silver">B</span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">Q?/span></p> <p style="margin-left: 9pt"><span style="background: silver; font-family: 'QS 明朝'">  </span><span style="background: silver; font-family: 'QS 明朝'">一</span><span style="background: silver; font-family: SimSun">审结</span><span style="background: silver; font-family: 'QS 明朝'">果:(x)<strong><span style="color: red">?/span></strong></span><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">?/span></strong><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">孕期?/span></strong><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">、全</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">额</span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">期(</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">?/span></strong><strong><span style="background: silver; color: red; font-family: SimSun">q?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">加了</span></strong><strong><span style="background: silver; color: red">15</span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">天)?/span></strong><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">?/span></strong><strong><span style="background: silver; color: red">75%</span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">的哺x?/span></strong><strong><span style="background: silver; color: red; font-family: SimSun">?/span></strong><span style="background: silver; font-family: 'QS 明朝'">Qƈ以入</span><span style="background: silver; font-family: SimSun">职时?/span><span style="background: silver; font-family: 'QS 明朝'">至三期届</span><span style="background: silver; font-family: SimSun">满ؓ(f)力_</span><span style="background: silver; font-family: 'QS 明朝'">合同</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">pd</span><span style="background: silver; font-family: SimSun">l?/span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">间计</span><span style="background: silver; font-family: 'QS 明朝'">在</span><span style="background: silver; font-family: SimSun">职时?/span><span style="background: silver; font-family: 'QS 明朝'">Q然后以</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">职时?/span><span style="background: silver; font-family: 'QS 明朝'">按照?/span><span style="background: silver; font-family: SimSun">力_</span><span style="background: silver; font-family: 'QS 明朝'">合同法》第八十七条?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">?/span><strong><span style="background: silver; color: red; font-family: SimSun">赔偿</span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">金(卛_法解除的</span></strong><strong><span style="background: silver; color: red; font-family: SimSun">补偿</span></strong><strong><span style="background: silver; color: red; font-family: 'QS 明朝'">金的双倍)</span></strong><span style="background: silver; font-family: 'QS 明朝'">。一</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">不是我代理的?/span></p> <p style="margin-left: 9pt"><span style="background: silver; font-family: 'QS 明朝'">  </span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver">A</span><span style="background: silver; font-family: 'QS 明朝'">公司扑ֈ我,我想当然的以</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">Q按照?/span><span style="background: silver; font-family: SimSun">力_</span><span style="background: silver; font-family: 'QS 明朝'">合同法》第八十七条?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">定,</span><span style="background: silver; font-family: SimSun">力_</span><span style="background: silver; font-family: 'QS 明朝'">者可?/span><span style="background: silver; font-family: SimSun">选择</span><span style="background: silver; font-family: 'QS 明朝'">要求</span><span style="background: silver; font-family: SimSun">l箋</span><span style="background: silver; font-family: 'QS 明朝'">履行Q不要求</span><span style="background: silver; font-family: SimSun">l箋</span><span style="background: silver; font-family: 'QS 明朝'">履行的,</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">?/span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">支付双?/span><span style="background: silver; font-family: SimSun">补偿</span><span style="background: silver; font-family: 'QS 明朝'">卛_Q一</span><span style="background: silver; font-family: SimSun">?/span><span style="background: silver; font-family: 'QS 明朝'">判决属适用法律</span><span style="background: silver; font-family: SimSun">错误</span><span style="background: silver; font-family: 'QS 明朝'">?/span></p> <img src ="http://www.tkk7.com/jinfeng_wang/aggbug/315853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2010-03-19 00:27 <a href="http://www.tkk7.com/jinfeng_wang/archive/2010/03/19/315853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创意是什么?创意在我n?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2007/02/15/100000.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 15 Feb 2007 13:25:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2007/02/15/100000.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/100000.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2007/02/15/100000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/100000.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/100000.html</trackback:ping><description><![CDATA[H然惛_q个问题Q?br /><br />创意在我们的n辏V?br /><br />偶然的进入sohu的blogQ?br /><br />看到了sohu  blog提供的音乐盒<br /><br />相当不错的一个结?br /><br />什么是门户Q什么是整合Q什么是资源复合Q?br /><br />也许我也可以试着利用搜烦引擎Q做一点其它的创意来?br /><br />很奇怪的是,sogou的mp3试听里面是用的其他网站的URLq接<br /><br />但是blog里面的mp3 q接好像直接来源?sohu<br /><br />嘿嘿Q?sohu不怕官怺Q?br /><br /><br />Q=Q=Q=Q=Q=Q=Q=Q=Q=<br />whois :  220.181.26.88<br /><br /><table cellspacing="0" cellpadding="2" border="1"><tbody><tr><td class="t_blue"><font size="2">地址D范? </font></td><td class="t_blue"><font size="2">220.181.0.0 - 220.181.255.255 </font></td></tr><tr><td class="t_blue"><font size="2">|络? </font></td><td class="t_blue"><font size="2">CHINANET-IDC-BJ </font></td></tr><tr><td class="t_blue"><font size="2">国家: </font></td><td class="t_blue"><font size="2">CN </font></td></tr><tr><td class="t_blue"><font size="2">单位描述: </font></td><td class="t_blue"><font size="2">CHINANET Beijing province network </font></td></tr><tr><td class="t_blue"><font size="2">单位描述: </font></td><td class="t_blue"><font size="2">China Telecom </font></td></tr><tr><td class="t_blue"><font size="2">单位描述: </font></td><td class="t_blue"><font size="2">No.31,jingrong street </font></td></tr><tr><td class="t_blue"><font size="2">单位描述: </font></td><td class="t_blue"><font size="2">Beijing 100032 </font></td></tr><tr><td class="t_blue"><font size="2">理联系? </font></td><td class="t_blue"><font size="2">CH93-AP </font></td></tr><tr><td class="t_blue"><font size="2">技术联pMh: </font></td><td class="t_blue"><font size="2">HC55-AP </font></td></tr><tr><td class="t_blue"><font size="2">附注: </font></td><td class="t_blue"><font size="2">hostmaster is not for spam complaint, </font></td></tr><tr><td class="t_blue"><font size="2">附注: </font></td><td class="t_blue"><font size="2">please send spam complaint to anti-spam@ns.chinanet.cn.net </font></td></tr><tr><td class="t_blue"><font size="2">l护方帐? </font></td><td class="t_blue"><font size="2">MAINT-CHINANET </font></td></tr><tr><td class="t_blue"><font size="2">ơl护? </font></td><td class="t_blue"><font size="2">MAINT-CHINATELECOM-BJ </font></td></tr><tr><td class="t_blue"><font size="2">地址D늊? </font></td><td class="t_blue"><font size="2">ALLOCATED NON-PORTABLE </font></td></tr><tr><td class="t_blue"><font size="2">更改记录: </font></td><td class="t_blue"><font size="2">hostmaster@ns.chinanet.cn.net 20030620 </font></td></tr><tr><td class="t_blue"><font size="2">更改记录: </font></td><td class="t_blue"><font size="2">hm-changed@apnic.net 20050715 </font></td></tr><tr><td class="t_blue"><font size="2">数据来源: </font></td><td class="t_blue"><font size="2">APNIC </font></td></tr><tr><td class="t_blue"><font size="2"><br /></font></td><td class="t_blue"><font size="2"><br /></font></td></tr><tr><td class="t_blue"><font size="2">联系? </font></td><td class="t_blue"><font size="2">Chinanet Hostmaster </font></td></tr><tr><td class="t_blue"><font size="2">联系人帐? </font></td><td class="t_blue"><font size="2">CH93-AP </font></td></tr><tr><td class="t_blue"><font size="2">?sh)子邮g: </font></td><td class="t_blue"><font size="2">anti-spam@ns.chinanet.cn.net </font></td></tr><tr><td class="t_blue"><font size="2">通信地址: </font></td><td class="t_blue"><font size="2">No.31 ,jingrong street,beijing </font></td></tr><tr><td class="t_blue"><font size="2">通信地址: </font></td><td class="t_blue"><font size="2">100032 </font></td></tr><tr><td class="t_blue"><font size="2">?sh)? </font></td><td class="t_blue"><font size="2">+86-10-58501724 </font></td></tr><tr><td class="t_blue"><font size="2">传真: </font></td><td class="t_blue"><font size="2">+86-10-58501724 </font></td></tr><tr><td class="t_blue"><font size="2">国家: </font></td><td class="t_blue"><font size="2">CN </font></td></tr><tr><td class="t_blue"><font size="2">更改记录: </font></td><td class="t_blue"><font size="2">lqing@chinatelecom.com.cn 20051212 </font></td></tr><tr><td class="t_blue"><font size="2">l护方帐? </font></td><td class="t_blue"><font size="2">MAINT-CHINANET </font></td></tr><tr><td class="t_blue"><font size="2">数据来源: </font></td><td class="t_blue"><font size="2">APNIC </font></td></tr><tr><td class="t_blue"><font size="2"><br /></font></td><td class="t_blue"><font size="2"><br /></font></td></tr><tr><td class="t_blue"><font size="2">联系? </font></td><td class="t_blue"><font size="2">Hostmaster of Beijing Telecom corporation CHINA TELECOM </font></td></tr><tr><td class="t_blue"><font size="2">联系人帐? </font></td><td class="t_blue"><font size="2">HC55-AP </font></td></tr><tr><td class="t_blue"><font size="2">?sh)子邮g: </font></td><td class="t_blue"><font size="2">bjnic@bjtelecom.net </font></td></tr><tr><td class="t_blue"><font size="2">通信地址: </font></td><td class="t_blue"><font size="2">Beijing Telecom </font></td></tr><tr><td class="t_blue"><font size="2">通信地址: </font></td><td class="t_blue"><font size="2">No. 107 XiDan Beidajie, Xicheng District Beijing </font></td></tr><tr><td class="t_blue"><font size="2">?sh)? </font></td><td class="t_blue"><font size="2">+86-010-58503461 </font></td></tr><tr><td class="t_blue"><font size="2">传真: </font></td><td class="t_blue"><font size="2">+86-010-58503054 </font></td></tr><tr><td class="t_blue"><font size="2">国家: </font></td><td class="t_blue"><font size="2">cn </font></td></tr><tr><td class="t_blue"><font size="2">更改记录: </font></td><td class="t_blue"><font size="2">bjnic@bjtelecom.net 20040115 </font></td></tr><tr><td class="t_blue"><font size="2">l护方帐? </font></td><td class="t_blue"><font size="2">MAINT-CHINATELECOM-BJ </font></td></tr><tr><td class="t_blue"><font size="2">数据来源: </font></td><td class="t_blue"><font size="2">APNIC </font></td></tr><tr><td class="t_blue"><font size="2"><br /></font></td><td class="t_blue"><font size="2"><br /></font></td></tr><tr><td class="t_blue"><font size="2"><br /></font></td></tr></tbody></table><br /><br /><br /><img src ="http://www.tkk7.com/jinfeng_wang/aggbug/100000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2007-02-15 21:25 <a href="http://www.tkk7.com/jinfeng_wang/archive/2007/02/15/100000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>人员、资源、操作及(qing)q三者构成的权限控制http://www.tkk7.com/jinfeng_wang/archive/2007/02/14/99819.htmljinfeng_wangjinfeng_wangWed, 14 Feb 2007 06:53:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/02/14/99819.htmlhttp://www.tkk7.com/jinfeng_wang/comments/99819.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/02/14/99819.html#Feedback5http://www.tkk7.com/jinfeng_wang/comments/commentRss/99819.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/99819.html
在谈到其安全性的时候,很多的都是从“网l安全”的角度ȝ待问题,D不知,堡垒
的内部是最最不安全的。对付“黑客攻几Z是pȝ理员所要面对的问题Q而如何更好的
加强堡垒内部自n的安全,是在WebE序的设计中需要考虑的问题?br />
pȝ理员所要面对的|络d、操作系l 安全不是我所考虑的问题,如何加强Webpȝ
自n的健h我所最最兛_的事情。?br />
从“构造URL”攻d“注入SQL文”攻击,都是属于q分信Q用户输入Q而造成的安全问题?br />q恰恰应该是由应用程序自w加以重视、解决的问题?br />
Z角色的安全控制已l逐渐的被大家逐渐的接受,每个用户被分配ؓ(f)不同的角Ԍ不同的角?br />h不同的操作权限?但是如何划分角色、用戗操作权限,则是需要认真对待的问题?br />
举例Q?br />一个MISpȝ中,员工有查询工资的权限Q但是某个员工是否具有查询其他员工的权限呢?

不能深入的追问问题,详细的分辨清楚系l中到底有多角艌Ӏ每个用h在的角色Q是不能完成安全控制的?br />


btw: 以上的问题,大家不妨在自qcMpȝ中自己去查一下,有此问题的占l大多数吧?br />看过此文的,愿意回答“是”“否”的Q可以留aQ 也当作一个调查吧?/font>


上面的这个例子,是一个很成熟的办公系l中存在的问题。用客L(fng)script脚本Q控制了用户的界面操作,D不知maxthon可以解除这个限制。此pȝ中,用户的请求都被整理ؓ(f)URLQget方式提交Q,虽然URL中的键值含义ƈ不是很明显,但是q是可以试着L击,获取U密?br />
认真的核查用L(fng)输入Q利用AOP部vQ细密的对用L(fng)输入q行核查Q是很有必要的事情?br />
某个人、某个资源、某个操作,q三个要素组l在一起则是:(x)某个人对某个资源q行某项操作
实际情况下,许多人、许多资源、对每个资源冰存在着多个操作?br />
h、资源、操作进行划分,可以得到Q?br />具体的某一cMhQ可以对某些资源Q进行某些的操作Q?q就是具体的某项权限限制?br />    某一cMhQ则可以归纳艌Ӏ?br />    Ҏ(gu)些资源的某些操作Q则可以归纳为工作Q务?br />也就是说Q整个系l是“某个角色去完成某些工作dQ而具体的一个帐户属于某个角Ԍ某项工作则具体的是指Ҏ(gu)个资源进行某个操作”?br />
相对来说Q系l中的h员是最Ҏ(gu)辨认的,pȝ中的资源也是可以在系l的功能调查时分清楚的,pȝ中的操作则是最复杂、最隑ֈ清晰Q甚臛_pȝ完成旉?x)变化的?br />
只有分L清楚了系l中的h、资源、操作,才能辨别清楚pȝ中的具体的权限限制?br />
“基于角色的安全控制”这L(fng)提法Q只提及(qing)了hQ未能强调将资源、操作进行规c,q是很不充分的一U提法?br />
在Webpȝ中,pȝ在设计的q程中,分清楚资源Q分清楚操作Q极大羃?yu)每个页面的功能、提高页面功能的原子性,q也是权限控制对pȝ设计提出的一要求?br />
前面提及(qing)使用AOPq行权限控制Q现在简qC下各部g的功能:(x)
   业务模块Q-完成具体的对某个资源的操作;
   前台面模块Q- 完成整体面的整合;
   安全控制模块Q-实现安全控制功能Q完成h员、角艌Ӏ工作的逻辑判断Q?br />   AOP配置整合模块Q-_合安全控制模块和业务模块;


在于如何去解冻I而是如何d现。隐藏v来的问题更是危险?br />
而如何发现问题,则完全是一个素质、能力的事情Q也许这是下一个话题?br />

jinfeng_wang 2007-02-14 14:53 发表评论
]]>
应用协议的设?(zz)http://www.tkk7.com/jinfeng_wang/archive/2007/02/13/99737.htmljinfeng_wangjinfeng_wangTue, 13 Feb 2007 09:32:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2007/02/13/99737.htmlhttp://www.tkk7.com/jinfeng_wang/comments/99737.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2007/02/13/99737.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/99737.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/99737.htmlhttp://www.ietf.org/rfc/rfc3117.txt

RFC 3117         On the Design of Application Protocols    November 2001


Table of Contents

   1.  A Problem 19 Years in the Making . . . . . . . . . . . . . . .  3
   2.  You can Solve Any Problem... . . . . . . . . . . . . . . . . .  6
   3.  Protocol Mechanisms  . . . . . . . . . . . . . . . . . . . . .  8
   3.1 Framing  . . . . . . . . . . . . . . . . . . . . . . . . . . .  8
   3.2 Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . .  9
   3.3 Reporting  . . . . . . . . . . . . . . . . . . . . . . . . . .  9
   3.4 Asynchrony . . . . . . . . . . . . . . . . . . . . . . . . . . 10
   3.5 Authentication . . . . . . . . . . . . . . . . . . . . . . . . 12
   3.6 Privacy  . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
   3.7 Let's Recap  . . . . . . . . . . . . . . . . . . . . . . . . . 13
   4.  Protocol Properties  . . . . . . . . . . . . . . . . . . . . . 14
   4.1 Scalability  . . . . . . . . . . . . . . . . . . . . . . . . . 14
   4.2 Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . . 15
   4.3 Simplicity . . . . . . . . . . . . . . . . . . . . . . . . . . 15
   4.4 Extensibility  . . . . . . . . . . . . . . . . . . . . . . . . 15
   4.5 Robustness . . . . . . . . . . . . . . . . . . . . . . . . . . 16
   5.  The BXXP Framework . . . . . . . . . . . . . . . . . . . . . . 17
   5.1 Framing and Encoding . . . . . . . . . . . . . . . . . . . . . 17
   5.2 Reporting  . . . . . . . . . . . . . . . . . . . . . . . . . . 19
   5.3 Asynchrony . . . . . . . . . . . . . . . . . . . . . . . . . . 19
   5.4 Authentication . . . . . . . . . . . . . . . . . . . . . . . . 21
   5.5 Privacy  . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
   5.6 Things We Left Out . . . . . . . . . . . . . . . . . . . . . . 21
   5.7 From Framework to Protocol . . . . . . . . . . . . . . . . . . 22
   6.  BXXP is now BEEP . . . . . . . . . . . . . . . . . . . . . . . 23
   7.  Security Considerations  . . . . . . . . . . . . . . . . . . . 23
   References . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
   Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 26
   Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 27


jinfeng_wang 2007-02-13 17:32 发表评论
]]>
ADO.NET Connection Status Maphttp://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50173.htmljinfeng_wangjinfeng_wangSat, 03 Jun 2006 13:35:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50173.htmlhttp://www.tkk7.com/jinfeng_wang/comments/50173.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50173.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/50173.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/50173.html

jinfeng_wang 2006-06-03 21:35 发表评论
]]>
Checked Exception VS UnChecked Excetion (l?)http://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50170.htmljinfeng_wangjinfeng_wangSat, 03 Jun 2006 13:22:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50170.htmlhttp://www.tkk7.com/jinfeng_wang/comments/50170.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/06/03/50170.html#Feedback5http://www.tkk7.com/jinfeng_wang/comments/commentRss/50170.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/50170.html    假设我的团队正在开发一个库E序Q由于某U原因,现在希望能够得到所有最外层 API 所抛出的所有异常的cd、各自的信息、ƈ且能够附上各U异常所出现的原因和解决办法。如果开发过E中内部使用的是 Unchecked Exception Q那么对于这个Q务简直就ȝ了。没办法Q开发h员一个个的自我进行检查然后统计吧Q但是往往q样的统计M(x)有漏|之鱹{现在的 MSDN 中的异常信息p糕的很Q最底层的公有库的异怿息内容可能完整一点,但是上层的库的异怿息糟p的不行Q根本不能完整的报全所有出错的可能性?/span>

你可以想象的出,一个库函数的异怿息不完整Q对于他的用h_(d)是多么不友好的事情。假?/span> MSDN ?/span> File.Open() ?x)抛?/span> IOException Q你的程序就很难惛_很规矩的?/span> IOException 做了 catch Q然后提C用h查相应位|的文g是否存在 / 被打开{。别指望 MSDN 的那些信息能够对l端用户有多大的帮助Q太多不懂计机的h在傻呆呆的握着鼠标了。再加上 MicroSoft 的提CZ息本w就存在着“答非所问”,“莫名其妙”的事情Q用L(fng)到这些情况就更不知道怎么解决问题了。再加上自己的应用程序中?x)弹Z个个“蹩脚”的q行旉误的错误框,真的不是一个很如意的创作?/span>

        但是Q如果用的?/span> Checked Exception Q这时候编译器?x)强q你的外部接口的异常相当的完_(d)最L(fng)可以做到?/span> MSDN 的异常类型齐整?/span>

 

 

 

 



jinfeng_wang 2006-06-03 21:22 发表评论
]]>
数据库驱动程序的试需要注意的问题http://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48597.htmljinfeng_wangjinfeng_wangSun, 28 May 2006 07:52:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48597.htmlhttp://www.tkk7.com/jinfeng_wang/comments/48597.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48597.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/48597.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/48597.html 1. 不要用TestCase的构造函数初始化FixtureQ而要?br />setUp()和tearDown()Ҏ(gu)?/font>

2. 不要依赖或假定测试运行的序Q因为JUnit利用
Vector保存?gu)试?gu)。所以不同的q_?x)按不同?br />序从Vector中取出测试方法?

3. 避免~写有副作用的TestCase。例如:(x)如果随后?br />试依赖于某些特定的交易数据Q就不要提交交易?br />据。简单的?x)滚可以了?/font>

  对于我们来说Q有时是必须要提交,以至于有副作用的?/font>
  例如Q在执行“插入“后Q数据库昄?x)多Z条数
据来。那么必d随后每个试自己消除自己的副
作用?/font>
  在这里,是自己“再删除刚插入的数据”。(q时?br />需要考虑到这个善后的工作不能自己׃能有副作用,
  删除多了其他的数据)?/font>
 
  q里的副作用q指“媄响到周围环境”,因ؓ(f)我们?br />在工作的人比较多Q所以最好大家的试服务器能?br />分开来,
 例如一个h一个Database实例Q可以徏得稍微小一
点)或者一个h一个数据库Q?/font>   注意这些个Z?br />有区别的内容用常量在每个q所有程序中?br />用。而不是分布在各个位置?/font>   否则以后要改换测?br />服务器,所有的E序都需要改动?/font>
 
  Z保证试E序能够很容易的到处执行Q请保证
大家的数据库服务器的试数据全部一致?/font>  否则Q?br />׃能做到很Ҏ(gu)得拿到FJ也可以很Ҏ(gu)的运行,
所以需要准备“测试数据集“?/font> 包括QSchema ,table Q?br />stored procedure{数据库对象的结构一_(d)  q包
括数据库的数据内容保持一致?/font>

4. 当承一个测试类Ӟ记得调用父类的setUp()?br />tearDown()Ҏ(gu)?

5. 测试代码和工作代码攑֜一P一边同步编?br />和更新。(使用Ant中有支持junit的task.Q?

6. 试cd试Ҏ(gu)应该有一致的命名Ҏ(gu)。如?br />工作cd前加上test从而Ş成测试类名?
可能q里我们需要改动,函数名和我们的试?br />例的~号一致v来?/font>

7. 保试与时间无养I不要依赖使用q期的数?br />q行试。导致在随后的维护过E中很难重现试?

8. 如果你编写的软g面向国际市场Q编写测试时?br />考虑国际化的因素。不要仅用母语的Localeq行试?

9. 可能地利用JUnit提供地assert/failҎ(gu)以及(qing)
异常处理的方法,可以使代码更为简z?
 
q个内容有其关键Qassert语句的好坏直接媄?br />到测试的正确性?/font> 因ؓ(f)assert是用于当前试
的正确性的?/font>

10.试要尽可能地小Q执行速度快?


==========
1Q将所有的数据库的试数据用ODBCE序自动
生成的?用户可以单的修改ConnectionStringQ?br />然后q行E序Q就可以创徏生成?/font>据库/数据?br />?存储l构Qƈ且自动插入数据?br />
 
   2Qؓ(f)了保证多个测试h员的不干扎ͼ分别
各自单独使用自己的数?/font>库。否则会(x)因ؓ(f)一个自
q错误Q媄响别人的工作?/font>
 
   3Q在自己的程序中Q所有涉?qing)环境的内容都?br />单独攑ֈ一个类中,用static帔R׃n使用Q这?br />׃于很Ҏ(gu)的更换环境再q行试Q做到很?br />易的UL试环境Q?/font>
 
   4Q关于数据库表结构,我徏议测试表中含有一
个主键,我们在插入数据的?/font>候,保证试用例Q?br />试用例E序Q测试用例程序中的数据,q三?br />的编号一致v来。便于出现问题时Q可以排除数据?/font>


jinfeng_wang 2006-05-28 15:52 发表评论
]]>
数据库驱动程序测试的http://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48596.htmljinfeng_wangjinfeng_wangSun, 28 May 2006 07:32:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48596.htmlhttp://www.tkk7.com/jinfeng_wang/comments/48596.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/05/28/48596.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/48596.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/48596.html 1. 不要用TestCase的构造函数初始化FixtureQ而要?br />setUp()和tearDown()Ҏ(gu)?/font>

2. 不要依赖或假定测试运行的序Q因为JUnit利用
Vector保存?gu)试?gu)。所以不同的q_?x)按不同?br />序从Vector中取出测试方法?

3. 避免~写有副作用的TestCase。例如:(x)如果随后?br />试依赖于某些特定的交易数据Q就不要提交交易
数据。简单的?x)滚可以了?br />

  对于我们来说Q有时是必须要提交,以至于有副作用的?/font>
  例如Q在执行“插入“后Q数据库昄?x)多Z条数据来?br />那么必须在随后每个测试自己消除自q副作用?/font>
  在这里,是自己“再删除刚插入的数据”。(q时候需?br />考虑到这个善后的工作不能自己׃能有副作用,   删除
多了其他的数据)?/font>
 
  q里的副作用q指“媄响到周围环境”,因ؓ(f)我们现在?br />作的人比较多Q所以最好大家的试服务器能够分开来,
 例如一个h一个Database实例Q可以徏得稍微小一点)?br />者一个h一个数据库Q?/font>   注意这些个Z间有区别的内
容用帔R在每个h自己的所有程序中公用。而不是分布在
各个位置?/font>   否则以后要改换测试服务器Q所有的E序都需
要改动?/font>
 
  Z保证试E序能够很容易的到处执行Q请保证大家
的数据库服务器的试数据全部一致?/font>  否则Q就不能做到
很容易得拿到FJ也可以很Ҏ(gu)的运行,所以需要准备“测
试数据集“?/font> 包括QSchema ,table Qstored procedure{数?br />库对象的l构一_(d)  q包括数据库的数据内容保持一致?/font>

4. 当承一个测试类Ӟ记得调用父类的setUp()和tearDown()Ҏ(gu)?

5. 测试代码和工作代码攑֜一P一边同步编译和更新?br />Q用Ant中有支持junit的task.Q?

6. 试cd试Ҏ(gu)应该有一致的命名Ҏ(gu)。如在工作类
名前加上test从而Ş成测试类名?
可能q里我们需要改动,函数名和我们的试用例的编号一致v来?/font>

7. 保试与时间无养I不要依赖使用q期的数据进行测试?br />D在随后的l护q程中很N现测试?

8. 如果你编写的软g面向国际市场Q编写测试时要考虑国际
化的因素。不要仅用母语的Localeq行试?

9. 可能地利用JUnit提供地assert/failҎ(gu)以及(qing)异常处理?br />Ҏ(gu)Q可以代码更ؓ(f)z?
 
q个内容有其关键Qassert语句的好坏直接媄响到试的正性?/font>
因ؓ(f)assert是用于当前试的正确性的?/font>

10.试要尽可能地小Q执行速度快?

=============
 1Q将所有的数据库的试数据E序自动生成的?
用户可以单的修改ConnectionStringQ然后运行程序,
可以创建生成数
据库/数据库表/存储l构Qƈ且自?br />插入数据?

   2Qؓ(f)了保证多个测试h员的不干扎ͼ分别各自
单独使用自己的数?/font>库。否则会(x)因ؓ(f)一个自q错误Q?br />影响别h的工作?/font>
 
   3Q在自己的程序中Q所有涉?qing)环境的内容都用单?br />攑ֈ一个类中,用static帔R׃n使用Q这样就便于?br />Ҏ(gu)的更换环境再q行试Q做到很Ҏ(gu)的移?/font>
环境Q?/font>
 
   4Q关于数据库表结构,我徏议测试表中含有一个主键,
我们在插入数据的?/font>候,保证试用例Q测试用例程序,
试用例E序中的数据Q这三者的~号一
致v来。便?br />出现问题Ӟ可以排除数据?/font>


jinfeng_wang 2006-05-28 15:32 发表评论
]]>
试、构建和重构(zz)http://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43358.htmljinfeng_wangjinfeng_wangWed, 26 Apr 2006 08:52:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43358.htmlhttp://www.tkk7.com/jinfeng_wang/comments/43358.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43358.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/43358.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/43358.html试、构建和重构
NUnit2.0详细使用Ҏ(gu)
重构啊重?/a>
.Net Code Cover
让代码更h可测试?/a>
NMock --- 从零开?/a>
Unit Test : rules,design and strategy
Concurrent connection limit
Log4Net Appender ?ADONetAppender
Bug理的流E和几个重点
把单元测试代码跟目代码攑֜一个工E中
Subversion配置安装教程Q三Q?
Subversion配置安装教程Q二Q?
Subversion配置安装教程Q一Q?/a>
敏捷QAMQ:(x)TDD(Test Driven DevelopmentQ实践与变化-->TADQTest Assist Development)
如何?.CS文g中加入版本跟t信息?
推荐一个关?架构"的演C文E?PPT)
什麼是 LoadRunnerQ?
推荐一个不错的VS.NET集成单元试工具TestDriven.NET
实战dailybuild-cc.net的配|?/a>
[译] NMock 两分钟教E?/a>
[译] NMock ?/a>
试驱动开的的实例
让代码更h可测试?/a>
重构QRefactoringQ技巧读书笔?之三
W一ơ用CVS后的程结Q其实VSS也一P
我也再补充一个NANT使用注意事项
重构QRefactoringQ技巧读书笔?之二
重构QRefactoringQ技巧读书笔?之一
Bugzilla明用手?/a>
Daily Build 的链?/a>
Test-Driven Development In .NET 部分译文
有关于Refactor(重构)与Source(?的比?/a>
l于完成了DailyBuild
用MSBuild.... DailyBuild和Y件开发流E的东东
DailyBuild全攻?/a>
关于Peer Review、代码评审和试驱动{?/a>
试开发驱动实?/a>


jinfeng_wang 2006-04-26 16:52 发表评论
]]>
q求代码质量: 不要被覆盖报告所qh(zz)http://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43340.htmljinfeng_wangjinfeng_wangWed, 26 Apr 2006 08:24:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43340.htmlhttp://www.tkk7.com/jinfeng_wang/comments/43340.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2006/04/26/43340.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/43340.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/43340.html试覆盖工具对单元测试具有重要的意义Q但是经常被误用。这个月QAndrew Glover ?x)在他的新系?—?q求代码质量 中向(zhn)介l值得参考的专家意见。第一部分深入Cl覆盖报告中数字的真实含义。然后他?x)提出(zhn)可以早q经常地利用覆盖来确保代码质量的三个Ҏ(gu)?/blockquote>

(zhn)还记得以前大多数开发h员是如何q求代码质量的吗。在那时Q有技巧地攄 main() Ҏ(gu)被视为灵zM适当的测试方法。经历了漫长的道路以后,现在自动试已经成ؓ(f)高质量代码开发的基本保证Q对此我很感谢。但是这q不是我所要感谢的全部。Java?开发h员现在拥有很多通过代码度量、静态分析等Ҏ(gu)来度量代码质量的工具。我们甚臛_l设法将重构分类成一pd便利的模式!

要获得有关代码质量问题的{案Q?zhn)可以讉K?Andrew Glover L?Code Quality 论坛?

所有的q些新的工具使得保代码质量比以前简单得多,不过(zhn)还需要知道如何用它们。在q个pd中,我将重点阐述有关保证代码质量的一些有时看上去有点秘的东ѝ除了带(zhn)一L(fng)(zhn)有关代码质量保证的众多工具和技术之外,我还ؓ(f)(zhn)说明:(x)

  • 定义q有效度量最影响质量的代码方面?
  • 讑֮质量保证目标q照此规划?zhn)的开发过E?
  • 定哪个代码质量工具和技术可以满x的需要?
  • 实现最?jng)_践(清除不好的)Qɼ保代码质量?qing)早q经常地 成ؓ(f)开发实践中L且有效的斚w?

在这个月Q我首先看?Java 开发h员中最行也是最Ҏ(gu)的质量保证工具包Q测试覆盖度量?/p>

谨防上当

q是一个晚上鏖战后的早晨,大家都站在饮水机边上。开发h员和理人员们了解到一些经q良好测试的cd以达到超q?90% 的覆盖率Q正在高兴地互换着 NFL 风格的点心。团队的集体信心I前高涨。从q处可以听到 “放d重构吧?的声韻Ig~陷已成为遥q的记忆Q响应性也已微不道。但是一个很的反对声在_(d)(x)

奛_们,先生们,不要被覆盖报告所愚弄?/p>

现在Q不要误解我的意思:(x)q不是说使用试覆盖工具是愚蠢的。对单元试范例Q它是很重要的。不q更重要的是(zhn)如何理解所得到的信息。许多开发团队会(x)在这儿犯W一个错?/p>

高覆盖率只是表示执行了很多的代码Qƈ不意味着q些代码?i>很好?/i> 执行。如果?zhn)x的是代码的质量,必ȝ地理解试覆盖工具能做什么,不能做什么。然后?zhn)才能知道如何使用q些工具去获取有用的信息。而不是像许多开发h员那P只是满于高覆盖率?/p>



回页?/font>


试覆盖度量

试覆盖工具通常可以很容易地d到确定的单元试q程中,而且l果可靠。下载一个可用的工具Q对(zhn)的 Ant ?Maven 构徏脚本作一些小的改动,(zhn)和(zhn)的同事有了在饮水上谈论的一U新报告Q?i>试覆盖报告。当 foo ?bar q样的程序包令h惊奇地显C?i>?/i> 覆盖率时Q?zhn)可以得到不小的安慰。如果?zhn)怿臛_(zhn)的部分代码可以保证?“没?BUG?的,(zhn)会(x)觉得很安心。但是这样做是一个错误?/p>

存在不同cd的覆盖度量,但是l大多数的工具会(x)x行覆?/i>Q也叫做语句覆盖。此外,有些工具?x)报?i>分支覆盖。通过用一个测试工h行代码库q捕h个测试过E中与被 “触?qing)?的代码对应的数据Q就可以获得试覆盖度量。然后这些数据被合成盖报告。在 Java 世界中,q个试工具通常?JUnit 以及(qing)名ؓ(f) Cobertura、Emma ?Clover {的覆盖工具?/p>

行覆?/i>只是指出代码的哪些行被执行。如果一个方法有 10 行代码,其中?8 行在试中被执行Q那么这个方法的行覆盖率?80%。这个过E在M层次上也工作得很好:(x)如果一个类?100 行代码,其中?45 行被触及(qing)Q那么这个类的行覆盖率就?45%。同P如果一个代码库包含 10000 个非注释性的代码行,在特定的试q行中有 3500 行被执行Q那么这D代码的行覆盖率是 35%?/p>

报告分支覆盖 的工兯囑ֺ量决{点Q比如包含逻辑 AND ?OR 的条件块Q的覆盖率。与行覆盖一P如果在特定方法中有两个分支,q且两个分支在测试中都被覆盖Q那么?zhn)可以说这个方法?100% 的分支覆盖率?/p>

问题是,q些度量有什么用Q很明显Q很Ҏ(gu)获得所有这些信息,不过(zhn)需要知道如何用它们。一些例子可以阐明我的观炏V?/p>



回页?/font>


代码覆盖在活?/font>

我在清单 1 中创Z一个简单的cM具体表述cdơ的概念。一个给定的cd以有一q串的父c,例如 VectorQ它的父cL AbstractListQ?code>AbstractList 的父cd?AbstractCollectionQ?code>AbstractCollection 的父cd?ObjectQ?/p>
清单 1. 表现cdơ的c?/b>
												
														package com.vanward.adana.hierarchy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Hierarchy {
  private Collection classes;
  private Class baseClass;

  public Hierarchy() {
    super();
    this.classes = new ArrayList();
  }

  public void addClass(final Class clzz){
    this.classes.add(clzz);
  }
  /**
   * @return an array of class names as Strings
   */
  public String[] getHierarchyClassNames(){
    final String[] names = new String[this.classes.size()];        
    int x = 0;
    for(Iterator iter = this.classes.iterator(); iter.hasNext();){
       Class clzz = (Class)iter.next();
       names[x++] = clzz.getName();
    }        
    return names;
  }

  public Class getBaseClass() {
    return baseClass;
  }

  public void setBaseClass(final Class baseClass) {
    this.baseClass = baseClass;
  }
}

												
										

正如(zhn)看到的Q清?1 中的 Hierarchy cd有一?baseClass 实例以及(qing)它的父类的集合。清?2 中的 HierarchyBuilder 通过两个复制 buildHierarchy 的重载的 static Ҏ(gu)创徏?Hierarchy cR?/p>
清单 2. cdơ生成器
												
														package com.vanward.adana.hierarchy;

public class HierarchyBuilder {  

  private HierarchyBuilder() {
    super();		
  }

  public static Hierarchy buildHierarchy(final String clzzName) 
    throws ClassNotFoundException{
      final Class clzz = Class.forName(clzzName, false, 
          HierarchyBuilder.class.getClassLoader());        
      return buildHierarchy(clzz);
  }

  public static Hierarchy buildHierarchy(Class clzz){
    if(clzz == null){
      throw new RuntimeException("Class parameter can not be null");
    }

    final Hierarchy hier = new Hierarchy();
    hier.setBaseClass(clzz);

    final Class superclass = clzz.getSuperclass();

    if(superclass != 
      null && superclass.getName().equals("java.lang.Object")){
       return hier; 
    }else{      
       while((clzz.getSuperclass() != null) && 
          (!clzz.getSuperclass().getName().equals("java.lang.Object"))){
             clzz = clzz.getSuperclass();
             hier.addClass(clzz);
       }	        
       return hier;
    }
  }      
}

												
										





回页?/font>


现在是测试时_(d)

有关试覆盖的文章怎么能缺测试案例呢Q在清单 3 中,我定义了一个简单的有三个测试案例的 JUnit 试c,它将试图执行 Hierarchy cd HierarchyBuilder c:(x)


清单 3. 试 HierarchyBuilderQ?/b>
												
														package test.com.vanward.adana.hierarchy;

import com.vanward.adana.hierarchy.Hierarchy;
import com.vanward.adana.hierarchy.HierarchyBuilder;
import junit.framework.TestCase;

public class HierarchyBuilderTest extends TestCase {
  
  public void testBuildHierarchyValueNotNull() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyName() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.Assert", 
       "junit.framework.Assert", 
         hier.getHierarchyClassNames()[1]);      
  }

  public void testBuildHierarchyNameAgain() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.TestCase", 
       "junit.framework.TestCase", 
         hier.getHierarchyClassNames()[0]);      
  }
 
}

												
										

因ؓ(f)我是一个狂热的试人员Q我自然希望q行一些覆盖测试。对?Java 开发h员可用的代码覆盖工具中,我比较喜Ƣ用 CoberturaQ因为它的报告很友好。而且QCorbertura 是开放源码项目,它派生出?JCoverage 目的前w?/p>



回页?/font>


Cobertura 的报?/font>

q行 Cobertura q样的工具和q行(zhn)的 JUnit 试一L(fng)单,只是有一个用专门逻辑在测试时查代码以报告覆盖率的中间步骤Q这都是通过工具?Ant d?Maven 的目标完成的Q?/p>

正如(zhn)在?1 中看到的Q?code>HierarchyBuilder 的覆盖报告说明部分代?i>没有 被执行。事实上QCobertura 认ؓ(f) HierarchyBuilder 的行覆盖率ؓ(f) 59%Q分支覆盖率?75%?/p>
?1. Cobertura 的报?/b>

q样看来Q我的第一ơ覆盖测试是p|的。首先,带有 String 参数?buildHierarchy() Ҏ(gu)Ҏ(gu)没有被测试。其ơ,另一?buildHierarchy() Ҏ(gu)中的两个条g都没有被执行。有的是,所要关注的正是W二个没有被执行?if 块?/p>

因ؓ(f)我所需要做的只是增加一些测试案例,所以我q不担心q一炏V一旦我到达了所x的区域,我就可以很好地完成工作。注意我q儿的逻辑Q我使用试报告来了解什?i>没有 被测试。现在我已经可以选择使用q些数据来增强测试或者l工作。在本例中,我准备增强我的测试,因ؓ(f)我还有一些重要的区域未覆盖?/p>

CoberturaQ第二轮

清单 4 是一个更新过?JUnit 试案例Q增加了一些附加测试案例,以试囑֮全执?HierarchyBuilderQ?


清单 4. 更新q的 JUnit 试案例
												
														package test.com.vanward.adana.hierarchy;

import com.vanward.adana.hierarchy.Hierarchy;
import com.vanward.adana.hierarchy.HierarchyBuilder;
import junit.framework.TestCase;

public class HierarchyBuilderTest extends TestCase {
  
  public void testBuildHierarchyValueNotNull() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyName() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.Assert", 
       "junit.framework.Assert", 
         hier.getHierarchyClassNames()[1]);      
  }

  public void testBuildHierarchyNameAgain() { zo       
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be junit.framework.TestCase", 
       "junit.framework.TestCase", 
         hier.getHierarchyClassNames()[0]);      
  }

  public void testBuildHierarchySize() {        
     Hierarchy hier = HierarchyBuilder.buildHierarchy(HierarchyBuilderTest.class);
     assertEquals("should be 2", 2, hier.getHierarchyClassNames().length);
  }

  public void testBuildHierarchyStrNotNull() throws Exception{
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertNotNull("object was null", hier);
  }

  public void testBuildHierarchyStrName() throws Exception{        
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertEquals("should be junit.framework.Assert", 
      "junit.framework.Assert",
        hier.getHierarchyClassNames()[1]);
  }

  public void testBuildHierarchyStrNameAgain() throws Exception{
    Hierarchy hier = 
       HierarchyBuilder.
       buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
    assertEquals("should be junit.framework.TestCase", 
      "junit.framework.TestCase",
        hier.getHierarchyClassNames()[0]);      
  }

  public void testBuildHierarchyStrSize() throws Exception{        
     Hierarchy hier = 
        HierarchyBuilder.
        buildHierarchy("test.com.vanward.adana.hierarchy.HierarchyBuilderTest");
     assertEquals("should be 2", 2, hier.getHierarchyClassNames().length);        
  }

  public void testBuildHierarchyWithNull() {
     try{
       Class clzz = null;
       HierarchyBuilder.buildHierarchy(clzz);
       fail("RuntimeException not thrown");
     }catch(RuntimeException e){}
  }
}

												
										

当我使用新的试案例再次执行试覆盖q程Ӟ我得C如图 2 所C的更加完整的报告。现在,我覆盖了未测试的 buildHierarchy() Ҏ(gu)Q也处理了另一?buildHierarchy() Ҏ(gu)中的两个 if 块。然而,因ؓ(f) HierarchyBuilder 的构造器?private cd的,所以我不能通过我的试cL试它Q我也不兛_Q。因此,我的行覆盖率仍然只有 88%?/p>
?2. 谁说没有W二ơ机?/b>

正如(zhn)看到的Q用一个代码覆盖工?i>可以 揭露重要的没有相应测试案例的代码。重要的事情是,在阅L告(特别 是覆盖率高的Q时需要小心,它们也许隐含危险的信息。让我们看看两个例子Q看看在高覆盖率后面隐藏着什么?/p>



回页?/font>


条g带来的麻?/font>

正如(zhn)已l知道的Q代码中的许多变量可能有多种状态;此外Q条件的存在使得执行有多条\径。在留意q些问题之后Q我在清单 5 中定义一个极其简单只有一个方法的c:(x)


清单 5.(zhn)能看出下面的缺陷吗Q?
												
														package com.vanward.coverage.example01;

public class PathCoverage {

  public String pathExample(boolean condition){
    String value = null;
    if(condition){
      value = " " + condition + " ";
    }
    return value.trim();
  }
}

												
										

(zhn)是否发C清单 5 中有一个隐藏的~陷呢?如果没有Q不要担心,我会(x)在清?6 中写一个测试案例来执行 pathExample() Ҏ(gu)q确保它正确地工作:(x)


清单 6. JUnit 来救_(d)
												
														package test.com.vanward.coverage.example01;

import junit.framework.TestCase;
import com.vanward.coverage.example01.PathCoverage;

public class PathCoverageTest extends TestCase {

  public final void testPathExample() {
    PathCoverage clzzUnderTst = new PathCoverage();
    String value = clzzUnderTst.pathExample(true);
    assertEquals("should be true", "true", value);
  }
}

												
										

我的试案例正确q行Q我的神奇的代码覆盖报告Q如下面?3 所C)使我看上d个超U明星,试覆盖率达C 100%Q?/p>
?3. 覆盖率明?

我想现在应该到饮水机边上去说了,但是{等Q我不是怀疑代码中有什么缺陷呢Q认真检查清?5 ?x)发玎ͼ如?condition ?falseQ那么第 13 行确实会(x)抛出 NullPointerException?i>YeeshQ这儿发生了什么?

q表明行覆盖的确不能很好地指C测试的有效性?/p>



回页?/font>


路径的恐?/font>

在清?7 中,我定义了另一个包?indirect 的简单例子,它仍然有不能容忍的缺陗请注意 branchIt() Ҏ(gu)?if 条g的后半部分。(HiddenObject cd在清?8 中定义。)


清单 7. q个代码_?/b>
												
														package com.vanward.coverage.example02;

import com.acme.someotherpackage.HiddenObject;

public class AnotherBranchCoverage {
   
  public void branchIt(int value){
    if((value > 100) || (HiddenObject.doWork() == 0)){
      this.dontDoIt();
    }else{
      this.doIt();
    }
  }                             

  private void dontDoIt(){
    //don't do something...
  }

  private void doIt(){
    //do something!
  }   
}

												
										

呀Q清?8 中的 HiddenObject ?i>有害?/i>。与清单 7 中一P调用 doWork() Ҏ(gu)?x)导?RuntimeExceptionQ?/p>
清单 8. 上半部分Q?
												
														package com.acme.someotherpackage.HiddenObject;

public class HiddenObject {

  public static int doWork(){
    //return 1;
    throw new RuntimeException("surprise!");
  }
}

												
										

但是我的可以通过一个良好的试捕获q个异常Q在清单 9 中,我编写了另一个好的测试,以图挽回我的明星光环Q?/p>
清单 9. 使用 JUnit 规避风险
												
														package test.com.vanward.coverage.example02;

import junit.framework.TestCase;
import com.vanward.coverage.example02.AnotherBranchCoverage;

public class AnotherBranchCoverageTest extends TestCase {
    
  public final void testBranchIt() {
    AnotherBranchCoverage clzzUnderTst = new AnotherBranchCoverage();
    clzzUnderTst.branchIt(101);
  }    
}

												
										

(zhn)对q个试案例有什么想法?(zhn)也怼(x)写出更多的测试案例,但是误想一下清?7 中不定的条件有不止一个的~短操作?x)如何。设惛_果前半部分中的逻辑比简单的 int 比较更复杂,那么(zhn)?/i> 需要写多少试案例才能满意Q?/p>

仅仅l我数字

现在Q对清单 7?? 的测试覆盖率的分析结果不再会(x)使?zhn)感到惊讶。在?4 的报告中昄我达C 75% 的行覆盖率和 100% 的分支覆盖率。最重要的是Q我执行了第 10 行!


?4.愚弄的报?/b>

从第一印象看,q让我骄傌Ӏ但是这个报告有什么误导吗Q只是粗略地看一看报告中的数字,?x)导致(zhn)怿代码是经q?i>良好试?/i>。基于这一点,(zhn)也怼(x)认ؓ(f)出现~陷的风险很低。这个报告ƈ不能帮助(zhn)确?or ~短操作的后半部分是一个定时炸弹!





回页?/font>


质量试

我不止一ơ地_(d)(x)(zhn)可以(而且应该Q用测试覆盖工具作为?zhn)的测试过E的一部分。但?i>不要被覆盖报告所愚弄。关于覆盖报告?zhn)需要了解的主要事情是,覆盖报告最好用来检查哪些代?i>没有l过 充分的测试。当(zhn)检查覆盖报告时Q找低的|q了解ؓ(f)什么特定的代码没有l过充分的测试。知道这些以后,开发h员、管理h员以?QA 专业人员可以在真正需要的地方使用试覆盖工具。通常有下列三U情况:(x)

  • 估计修改已有代码所需的时?
  • 评估代码质量
  • 评定功能试

现在我可以断定对试覆盖报告的一些用方法会(x)?zhn)引入歧途,下面q些最?jng)_践可以得测试覆盖报告可以真正ؓ(f)(zhn)所用?/p>

1. 估计修改已有代码所需的时?/font>

对一个开发团队而言Q针对代码编写测试案例自然可以增加集体的信心。与没有相应试案例的代码相比,l过试的代码更Ҏ(gu)重构、维护和增强。测试案例因为暗CZ代码在测试工作中?i>如何 工作的,所以还可以充当内行的文。此外,如果被测试的代码发生改变Q测试案例通常也会(x)作相应的改变Q这与诸如注释和 Javadoc q样的静态代码文档不同?/p>

在另一斚wQ没有经q相应测试的代码更难于理解和安全?/i> 修改。因此,知道代码有没有被试Qƈ看看实际的测试覆盖数|可以让开发h员和理人员更准地预知修改已有代码所需的时间?/p>

再次回到饮水上,可以更好地阐明我的观炏V?/p>

市场部的 LindaQ“我们想让系l在用户完成一W交易时?x 工作。这需要多长时间。我们的用户需要尽快实现这一功能。?

理人员 JeffQ“让我看看,q个代码?Joe 在几个月前编写的Q需要对业务层和 UI 做一些变动。Mary 也许可以在两天内完成q项工作。?

LindaQ“JoeQ他是谁Q?

JeffQ“哦QJoeQ因Z不知道自己在q什么,所以被我解雇了。?

情况g有点不妙Q不是吗Q尽如此,Jeff q是Q务分配给?MaryQMary 也认够在两天内完成工?—?切地说Q在看到代码之前Ҏ(gu)q么认ؓ(f)的?/p>

MaryQ“Joe 写这些代码时是不?i>睡着?/i>Q这是我所见过的最差的代码。我甚至不能认q是 Java 代码。除非推倒重来,要不我根本没法修攏V?

情况?“饮水机?团队不妙Q不是吗Q但是我们假设,如果在这个不q的事g的当初,Jeff ?Mary 拥有一份测试报告,那么情况?x)如何呢Q当 Linda 要求实现新功能时QJeff 做的W一件事是查以前生成的覆盖报告。注意到需要改动的软g包几乎没有被覆盖Q然后他׃(x)?Mary 商量?/p>

JeffQ“Joe ~写的这个代码很差,l大多数没经q测试。?zhn)认?f)要支?Linda 所说的功能需要多长时_(d)?

MaryQ“这个代码很混ؕ。我甚至都不想看到它。ؓ(f)什么不?Mark 来做呢??

JeffQ“因?Mark 不编写测试,刚被我解雇了。我需要?zhn)试q个代码q作一些改动。告诉我(zhn)需要多长时间。?

MaryQ“我臛_需要两天编写测试,然后我会(x)重构q个代码Q增加新的功能。我xd需要四天吧。?

正如他们所说的Q知识的力量是强大的。开发h员可以在试图修改代码之前 使用覆盖报告来检查代码质量。同P理人员可以使用覆盖数据更好C计开发h员实际所需的时间?/p>

2. 评估代码质量

开发h员的试可以降低代码中存在缺L(fng)风险Q因此现在很多开发团队在新开发和更改代码的同旉要编写单元测试。然而正如前面所提到?Mark 一Pq不L在编码的同时q行单元试Q因而会(x)D低质量代码的出现?/p>

监控覆盖报告可以帮助开发团队迅速找Z断增长的没有 相应试的代码。例如,在一周开始时q行覆盖报告Q显C项目中一个关键的软g包的覆盖率是 70%。如果几天后Q覆盖率下降C 60%Q那么?zhn)可以推断Q?/p>

  • 软g包的代码行增加了Q但是没有ؓ(f)C码编写相应的试Q或者是新增加的试不能有效地覆盖新代码Q?br />
  • 删除了测试案例?br />
  • 上述两种情况都发生了?

能够监控事情的发展,无疑是g好事。定期地查阅报告使得讑֮目标Q例如获得覆盖率、维护代码行的测试案例的比例{)q监控事情的发展变得更ؓ(f)Ҏ(gu)。如果?zhn)发现试没有如期~写Q?zhn)可以提前采取一些行动,例如对开发h员进行培训、指导或帮助。与其让用户 “在使用中?发现E序~陷Q这些缺h应该在几个月前通过单的试暴露出来Q,或者等到管理h员发现没有编写单元测试时再感到惊Ӟ和愤怒)Q还不如采取一些预防性的措施?/p>

使用覆盖报告来确保正的试是一伟大的实践。关键是要训l有素地完成q项工作。例如,使每晚生成ƈ查阅覆盖报告成ؓ(f)q箋累计 q程的一部分?/p>

3. 评定功能试

假设覆盖报告在指?i>没有l过 _试的代码部分方面非常有效,那么质量保证人员可以使用q些数据来评定与功能试有关的关注区域。让我们回到 “饮水机?团队来看?QA 的负责h Drew 是如何评?Joe 的代码的Q?/p>

Drew ?Jeff _(d)(x)“我们ؓ(f)下一个版本编写了试案例Q我们注意到很多代码没有被覆盖。那好像是与股票交易有关的代码。?

JeffQ“哦Q我们在q个领域有好些问题。如果我是一个赌徒的话,我会(x)对这个功能区域给予特别的x。Mary 正在对这个应用程序做一些其他的修改 —?她在~写单元试斚w做得很好Q但是这个代码也太差了点。?

DrewQ“是的,我正在确定工作的资源和别,看上L没必要那么担心了Q我估计我们的团队会(x)对股交易模块引赯够的x。?

知识再次昄了其强大的力量。与其他软g生命周期中的风险承担者(例如 QAQ配合,(zhn)可以利用覆盖报告所提供的信息来降低风险。在上面的场景中Q也?Jeff 可以?Drew 的团队提供一个早期的不包?Mary 的所有修改的版本。不q无论如何,Drew 的团队都应该x应用E序的股交易方面,与其他具有相应单元测试的代码相比Q这个地方似乎存在更大的~陷风险?/p>



回页?/font>


试有什么好?/font>

对单元测试范例而言Q测试覆盖度量工h一个有点奇怪的l成部分。对于一个已存在的有益的q程Q覆盖度量可以增加其深度和精度。然而,(zhn)应该仔l地阅读代码覆盖报告。单独的高覆盖率q不能确保代码的质量。对于减缺P代码的高覆盖q不是必要条Ӟ管高覆盖的代码的确更少 有缺陗?/p>

试覆盖度量的窍门是使用覆盖报告扑և未经 试的代码,分别在微观和宏观两个U别。通过从顶层开始分析?zhn)的代码库Q以?qing)分析单个类的覆盖,可以促进深入的覆盖测试。一旦?zhn)能够l合q些原则Q?zhn)和(zhn)的组l就可以在真正需要的地方使用覆盖度量工具Q例如估计一个项目所需的时_(d)持箋监控代码质量以及(qing)促进?QA 的协作?/p>


jinfeng_wang 2006-04-26 16:24 发表评论
]]>
工作之大局?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2005/06/07/5655.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Tue, 07 Jun 2005 04:51:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2005/06/07/5655.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/5655.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2005/06/07/5655.html#Feedback</comments><slash:comments>23</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/5655.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/5655.html</trackback:ping><description><![CDATA[转自Q?<A target=_blank><FONT color=#333399>http://blog.csdn.net/hongbo781202/archive/2004/09/26/117271.aspx</FONT></A> <BR><BR><B>1. 从奴隶社?x)到徏后?/B><BR><BR>工作?WorkFlow)的概忉|在现代信息系l的中逐步形成的,它有一个从局部到整体、从初到高U、从单到复杂、从奴隶C会(x)到封建盛世的发展q程Q按其发展历E,我们一般把它分Z个阶D?<BR><BR><B>H?EDF(?sh)子数据?阶段</B><BR><BR>EDF(?sh)子数据?阶段是工作流的奴隶社?x)阶Dc(din)此时的工作在信息技术中的应?仅着g利用信息技术减Mh们在程中的计算强度,如设计一个流E用来协调多个会(x)计统计帐目。所?EDF最主要的特Ҏ(gu)仅对企业单项业务q行处理,基本不涉?qing)管理的内容?BR><BR><B>H?TPF(事务处理?阶段</B><BR><BR>TPF(事务处理?阶段是工作流的封建初期。TPFq没有Ş成对企业的全局业务的管?而着g对企业局部业务的理,比如,设计一套工作流E?来管理物资的采购和供应?BR><BR><B>H?IMF(信息理?阶段</B><BR><BR>当今的工作流已经发展到封建后?------IMF(信息理?阶段, IMF对企业业务的全局的整体性的理。在q个阶段,工作就是ؓ(f)了完成同一目标而相互衔接、自动进行的一pd业务zd或Q务。目?工作技术与信息技术以?qing)企业管理紧密结?已经(zhn)?zhn)渗入MISpȝ、ERPpȝ和CRMpȝ{企业关键pȝ?q迅速成些系l的核心。在q个阶段,保皇zַ作流l历了大发展,革新zַ作流也风涌而现?BR><BR><B>2. 保皇z与革新z?/B><BR><BR>与其它信息技术相?工作技术属于较新的一? 它现在仍处于标准的制定阶D?目前已有的标准按采用的技术分Z大派?W一z是保皇z?ZUXML技?W二z是革新z?ZWeb服务技术。保皇派与革新派打得隑ֈ难解,所?现在仍有一些工作流引擎没有采用M标准而独立实?也就是说,它们不依靠保皇派,也不依靠革新z?BR><BR><B>2.1 保皇zֈ?/B><BR><BR><B>H?XPDLQXml Process Definition LanguageQ?/B><BR><BR>XPDL是保皇派最得h心的一z?因ؓ(f)它是太子。在工作领域第一个致力于标准化工作的是Workflow Management Coalition (WfMC)Q它成立?993q?994q?1月,wfmc发布了工作流理pȝ的参考模型。参考模型提Z五类接口Q有兌E模型的定义则构成了接口一的核心内宏V接口一早期的标准ؓ(f)WPDLQWorkflow Process Definition LanguageQ,后来,q一接口的规范变更ؓ(f)XPDL。XPDL是至今工作流领域最为重要的一个标?目前大多数工作流引擎是依据该标准设计开发的?BR><BR><B>H?BPML(Business Process Model Language)</B><BR><BR>因ؓ(f)对太子派的工作方式不满意QBPMI发布BPML规范,成立新的八爷党。由于八爷党发展的非怹快,W(xu)fMC和BPMI?002q??6日宣布将合作制定业务程和工作流标准Q即采用BPML来描q工作流q程Q同旉用XPDL所定义的工作流模型?BR><BR><B>H?OMG的Workflow Management Facility</B><BR><BR>四爷OMG是支持太子的,不过四爷q个人很有报?在其他领域也做的有声有色。四爷OMG的Workflow Management Facility联合太子的WfMC规范Q定义如何将工作向CORBA转换---要知? CORBA可是四爷的强V现在很多老百姓支持四爷OMG的Workflow Management Facility。四爯?发展了自q势力,又不惹太子生?真是妙啊!<BR><BR>保皇zօ它分支势力很?q里׃多说了?BR><BR><B>2.2 革新zֈ?/B><BR><BR><B>H?WSCI</B><BR><BR>2002q??6日,BEA,Intalio,SAP,Sun四家公司提出了基于xml的WSCI规范Q推动Web服务q入了一个全新的阶段。这个规范主要描qC一个参与和其它服务q行协作交互的Web服务所交换的消息流。WSCI是第一个革新派,后来又发展了几个新的革新z?<BR><BR>如WSFL(属IBM),Xlang(属MS),因有天生~陷,均没有很大v艌Ӏ?BR><BR><B>H?ebXML</B><BR><BR>ebXML是一l支持模块化?sh)子商务框架的规范。ebXML支持一个全球化的电(sh)子市场,它得Q意规模的企业通过交换ZXML的信息,不受地域限制地接z和处理生意。ebXML是联合国QUN/CEFACTQN易促q和?sh)子商务中心Q和OASISQ结构化信息标准发展l织Q共同倡导、全球参与开发和使用的规范。由于现在老百姓都不喜Ƣ抬着去换米,而喜Ƣ在|上来个B2C,所以革新派ebXML最q发展很快?BR><BR><B>H?BPEL</B><BR><BR>2002q??日,Microsoft, BEA, IBM, SAP & Siebel联合提交发布了BPEL规范?BPEL联合了一pd革新z?保皇z֊量( XLANG, WSFL, BPMLQ。此规范描述如何处理输入的消息,它不是一个关于业务流E规格化定义的规范。简单的_(d)可以它看作XML形式的编E语aQ提供将WSDL-Servicesl合成控制流的能力。顾名思义Q此规范重点在(也不只限于)Web Service?BR><BR>q有其它的革新派如RosettaNet{,因ؓ(f)势力很小,q里也不多说了?BR><BR><B>3. 大户人家</B><BR><BR>q里所谈的大户人家指工作流领域的商业Y件供应商Q他们都背靠靠山,或穷或富。我们这里按地区来划分他们?BR><BR><B>3.1中国之外的大?/B><BR><BR>H?BEA 的WLI</B><BR><BR>H?Fujitsu?i-Flow<BR><BR>H?IBM?Holosofx<BR><BR>H?SAP 的NetWeaver<BR><BR>H?Sonic 的Orchestration Server<BR><BR>H?Ultimus<BR><BR>H?Versata<BR><BR>q些人家大都非常富有;如果需?误己搜索他们的信息?BR><BR><B>3.2国内的大户h?/B><BR><BR>H?信雅辄SunFlow q个公司留给我的印象很好,包括他们的ȝ理石怅R?BR><BR>H?西安协同的协同工作流<BR><BR>H?上v东兰的DLFlo<BR><BR>q里对公司就不多介绍?否则有做q告的嫌疑J。本人有国内工作品的比较报告,大家需要可以给我发邮g索取?BR><BR><B>4. 寒门傲骨</B><BR><BR>q里的寒门傲骨指的是开源工作流引擎的实玎ͼ寒门子弟也是有政d向的,我们q是按保皇派和革新派来区分他们,而自由派指没有按固定的标准来实现的工作流门派?BR><BR><B>4.1保皇z֯?/B><BR><BR>H?OFBiz<BR><BR>OFBiz最主要的特Ҏ(gu)OFBiz提供了一整套的开发基于Java的web应用E序的组件和工具。其中包括实体引? 服务引擎, 消息引擎, 工作引? 规则引擎{。OFBiz先前的工作流引擎ZWfMC和OMG的规范,使用XPDL作ؓ(f)程定义语言,也就是说,它是支持太子XPDL?而且和十三爷OMG的关p非怹好。OFBiz新版的工作流引擎采用Shark工作引?我们不徏议再d?fn)OFBiz自n的工作流引擎?BR><BR>H?OBE<BR><BR>OBE 是由Adrian PriceL开发的一个开放源码的Java工作引擎,支持WfMC规范Q包括接?QXPDLQ、接?/3QWAPIQ和接口5。OBE主要ZJ2EE实现。OBE的接?实现得非常好,可惜,OBE的蝲体公司Zaplet已经于前不久被合qӞ合ƈ后的公司没有l箋发展OBE的打。Adrian Priced了原来的公司,投奔我们前面说过的大户Versata。Versata也不打算l箋OBE。OBE至今没有release版,很是可惜?BR><BR>H?Shark<BR><BR>Shark是完全根据WFMC规范实施的,可扩展功能的工作引擎,它利用xpdl来定义流E,同时q包括服务器端的用于zd节点执行的WFMC工具代理API。Shark中的每个lg例如持久层,事物理器,脚本引擎Q流E库Q都是可以按照标准实施运用的Q而且q可以被具体目的模块扩展和替换。Shark和XPDL定义工具的事实标准JAWE同出名门,市场前景被很多h看好。OFBiz新版的工作流引擎采用Shark工作引擎,OBE的蝲体公司Zaplet被合qӞ对Shark的发展将很有利?004q??日,shark发布1.0版本,对它的发展无疑是一剂强心针。笔者从Shark发展的早期就在国内力推它,有幸成ؓ(f)Shark工作引擎在国内的主要推q者之一(http://blog.csdn.net/hongbo781202/),感到十分荣幸。Shark的讨看http://211.95.124.238:22/cgi-bin/forums.cgi?forum=24?BR><BR><B>4.2 革新z֯?/B><BR><BR>H?OpenebXML<BR><BR>OpenebXML目致力于提供一个ebXML框架Q主要支?UN/CEFACT和OASIS发布的ebXML规范2.0版?BR><BR>H?Bonita<BR><BR>Bonita是一个符合WfMC规范、灵zȝ协同工作系l。BonitaZ览器、用SOAP和XML数据l定技术的Web Services装了已有的工作业务方法ƈ它们以ZJ2EE的Web Service形式发布?BR><BR>H?Twister<BR><BR>Twister的目标是提供C代、易集成、应用Java领域中最新成果、面向B(ti)2B的工作流解决Ҏ(gu)。流E引擎基于BPEL业务程规范和W(xu)eb Service标准?BR><BR>H?ActiveBpel<BR><BR>ActiveBPEL引擎是一个于今年7月发布的健壮的运行时环境,它能执行用户按BPWL4WS规范~写的业务流E。ActiveBPEL引擎由Active Endpoints公司开发和l护,该公司同时在它的多个商业产品中用了该技术。本人将密切观注ActiveBPEL引擎的技术发展和产品状态?BR><BR><B>4.3 自由z֯?/B><BR><BR>H?OSWorkflow<BR><BR>OSWorkflow的最大特Ҏ(gu)灉|<BR><BR>H?OpenWFE<BR><BR>OpenWFE是一个开放源码的Java工作引擎?它的思想来源?SchemeQ包括可升的三个组Ӟ(x)引擎、工作列表和W(xu)eb界面?BR><BR>HjBpm<BR><BR>jBpm是tom baeyens~写的一个灵zd扩展的工作流理pȝ。jBmp工作流应用开发的便利性和杰出的企业应用集成(EAIQ能力结合了h。jBmp包括一个Web应用E序和一个日E安排程序。jBmp是一lJ2SElgQ可以作为J2EE应用集群部v。国内目前有部分人研IjBpm?BR><BR><B>5 大局?/B><BR><BR>目前是封建社?x)后期,以太子党XPDL为首的保皇派q将辉煌一D|间。我个h认ؓ(f)Q在Ofbiz投靠SharkQ强势派OBE倒台Q自由派不得人心的情况下QShark工作引擎依靠与XPDL定义工具JAWE的兄弟关p,坐上保皇派头把交椅?BR><BR>目前Q革新派和保皇派的争夺ƈ不激烈。因为在现在的情况下, 革新z根基Web服务q不劳靠Q在老百姓中的媄响不太大Q所以革新派只求从保皇派嘴边分口食就行了。但随着C会(x)的发? Web服务越来越行Q现在,MS/IBM/BEA{跨国巨头越来越LBPEL4WS标准Qƈ且已l发布基于BPEL4WS标准的系列品,而且Q他们还LIntegration/Portal的概念,q些概念把工作带入资本主义阶Dc(din)?<img src ="http://www.tkk7.com/jinfeng_wang/aggbug/5655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-06-07 12:51 <a href="http://www.tkk7.com/jinfeng_wang/archive/2005/06/07/5655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>driving develop from agile use caseshttp://www.tkk7.com/jinfeng_wang/archive/2005/04/14/3274.htmljinfeng_wangjinfeng_wangThu, 14 Apr 2005 04:36:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2005/04/14/3274.htmlhttp://www.tkk7.com/jinfeng_wang/comments/3274.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2005/04/14/3274.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/3274.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/3274.htmlhttp://www.netobjectives.com/streamzines/CurrentStreamzine/player.html


swf download url:  http://www.netobjectives.com/streamzines/CurrentStreamzine/data/swf/slide1.swf
                             ......
                            http://www.netobjectives.com/streamzines/CurrentStreamzine/data/swf/slide36.swf

jinfeng_wang 2005-04-14 12:36 发表评论
]]>
Dynamic Delegation and Its ApplicationsbyQzzQ?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2005/03/20/2264.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Sun, 20 Mar 2005 10:23:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2005/03/20/2264.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/2264.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2005/03/20/2264.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/2264.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/2264.html</trackback:ping><description><![CDATA[Dynamic Delegation and Its Applicationsby <A lid="Lu Jian">Lu Jian</A><BR>11/17/2004<BR clear=all><!-- sidebar begins --><!-- don't move sidebars --><!-- sidebar ends --><!-- co: jamie - the "so" is gratuitous, but the previous sentence ended with a <code>...</code> term, and two of them together look like a java object reference: Something.somethingElse. ca --> <P>The Proxy pattern is an important and widely used design pattern in object-oriented programming. Do you ever use <CODE><FONT color=#003366>Proxy</FONT></CODE> in Java since its introduction in JDK 1.3? A dynamic proxy class is a class that implements a list of interfaces specified at runtime. An implementation for the proxy's behavior can be provided at runtime through an <CODE><FONT color=#003366>InvocationHandler</FONT></CODE>. So <CODE><FONT color=#003366>Proxy</FONT></CODE> is an important class in Java's reflection package, and is widely used in many Java applications.</P> <P>One limitation of <CODE><FONT color=#003366>Proxy</FONT></CODE> is that it can only accept interfaces. In some circumstances, you need to apply the Proxy pattern not only to interfaces, but also to abstract classes, and even concrete classes.</P> <P>This article introduces <I>Dynamic Delegation</I>, which can create delegation for both interfaces and classes at runtime.</P> <H3>Proxy Overview</H3> <P>In JDK 1.3, the <CODE><FONT color=#003366>Proxy</FONT></CODE> class was added to <CODE><FONT color=#003366>java.lang.reflect</FONT></CODE>. It can create a concrete class that implements all of the specified interfaces at runtime. The dynamically generated class redirects all of the method calls defined in the interfaces to an <CODE><FONT color=#003366>InvocationHandler</FONT></CODE>.</P> <P>Given two interfaces, <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>, <CODE><FONT color=#003366>Proxy</FONT></CODE> will create a <CODE><FONT color=#003366>IdelProxy</FONT></CODE> class as the proxy of these two interfaces (I use <CODE><FONT color=#003366>IdelProxy</FONT></CODE> as the generated proxy class name for convenience). Figure 1 shows this arrangement.</P> <P><IMG height=259 alt="Class Diagram of IdelProxy" src="http://www.onjava.com/onjava/2004/11/17/graphics/proxy.gif" width=500><BR><I>Figure 1. Class diagram of <CODE><FONT color=#003366>IdelProxy</FONT></CODE></I></P> <P>Below is the related code snippet.</P><PRE><CODE> <FONT color=#003366> Class clazz = Proxy.getProxyClass( Idel1.class.getClassLoader(), new Class[] { Idel1.class, Idel2.class }); </FONT></CODE></PRE> <H3>Delegation Versus Proxy</H3> <P><CODE><FONT color=#003366>Proxy</FONT></CODE> only works for interfaces. What if we need it to work for both classes and interfaces? The <A el="http://dunamis.dev.java.net" lid="Dunamis project">Dunamis project</A> on <A lid="java.net">java.net</A> introduces <CODE><FONT color=#003366>Delegation</FONT></CODE> as an alternative to <CODE><FONT color=#003366>Proxy</FONT></CODE>. <CODE><FONT color=#003366>Delegation</FONT></CODE> uses a different approach than <CODE><FONT color=#003366>Proxy</FONT></CODE>.</P> <P>Given a class named <CODE><FONT color=#003366>TestBean</FONT></CODE>, the delegation class <CODE><FONT color=#003366>TestBeanDelegation</FONT></CODE>'s class diagram is shown in Figure 2.</P> <P><A lid="/onjava/2004/11/17/graphics/delegation_t.gif" fn="delegation.gif"><IMG height=197 alt="Class Diagram of TestBeanDelegation" src="http://www.onjava.com/onjava/2004/11/17/graphics/delegation_t.gif" width=400 border=0></A><BR><I>Figure 2. Class diagram of <CODE><FONT color=#003366>TestBeanDelegation</FONT></CODE> (click for full-size image)</I></P> <P><CODE><FONT color=#003366>TestBeanDelegation</FONT></CODE> implements the <CODE><FONT color=#003366>Delegation</FONT></CODE> interface and extends the <CODE><FONT color=#003366>TestBean</FONT></CODE> class. It also contains references to <CODE><FONT color=#003366>TestBean</FONT></CODE> and <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE>. All of the method calls on <CODE><FONT color=#003366>TestBeanDelegation</FONT></CODE> will be delegated to them.</P> <P>Take <CODE><FONT color=#003366>getName()</FONT></CODE> as an example. The chart in Figure 3 illustrates the sequence of the method call.</P> <P><A lid="/onjava/2004/11/17/graphics/sequence_t.gif" fn="sequence.gif"><IMG height=332 alt="Sequence Chart of TestBeanDelegation.getName()" src="http://www.onjava.com/onjava/2004/11/17/graphics/sequence_t.gif" width=350 border=0></A><BR><I>Figure 3. Sequence chart of <CODE><FONT color=#003366>TestBeanDelegation.getName()</FONT></CODE> (click for full-size image)</I></P> <P>The related pseudocode is: </P><PRE><CODE> <FONT color=#003366>//The delegation class is a sub-class of the class to be delegated public class TestBeanDelegation extends TestBean implements Delegation { //The object to be delegated TestBean bean; //The invocation handler DelegationInvocationHandler handler; ... static Method m0 = null; ... static { ... try { m0 = TestBean.class.getMethod("getName", new Class[] {}); } catch (Exception exception) { } ... } public TestBeanDelegation(Object bean) { this.bean = (TestBean)bean; } public String getName() { boolean goon = true; String ret = null; Throwable t = null; try { goon = handler.invokeBefore(bean, m0, new Object[] {}); if (goon) try { ret = bean.getName(); } catch (Throwable throwable) { t = throwable; } if (t != null) ret = handler.invokeAfterException(bean, m0, new Object[] {}, t); else ret = handler.invokeAfter(bean, m0, new Object[] { name }, null); return ret; } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } } </FONT></CODE></PRE> <H3>An Introduction to Dynamic Delegation</H3> <P>Dynamic Delegation is based on the Jakarta <A el="http://jakarta.apache.org/bcel/index.html" lid="Byte-Code Engineering Library (BCEL)">Byte-Code Engineering Library (BCEL)</A>. It can analyze the existing class and generate a delegation class in byte code for an interface, abstract class, or even a concrete class at runtime.</P><!-- sidebar begins --><!-- sidebar ends --> <P>The interface/class to be delegated should meet the following conditions:</P> <UL> <LI>Dynamic Delegation can accept one class at most, but can accept multiple interfaces. <P>This limitation is based on Java's single inheritance model. One Java class can have at most one superclass. Since the generated delegation class takes the given class as its superclass, it is illegal to specify more than one class. If no class specified, the default superclass is <CODE><FONT color=#003366>Object</FONT></CODE>.</P> <LI>The input class should have a default constructor with a public or protected modifier. <P>The delegation class will call the superclass' default constructor in its own constructor.</P> <LI>The input class cannot be final, and should be visible to the caller. <P>The proxy class generated by <CODE><FONT color=#003366>Proxy</FONT></CODE> is final. It will not be accepted by Dynamic Delegation.</P> <LI>Dynamic Delegation cannot accept any class that implements the <CODE><FONT color=#003366>Delegation</FONT></CODE> interface. <P>Since it is already a delegation class, why would you need to delegate it again?</P></LI></UL> <P>The generated delegation class has the following characteristics:</P> <UL> <LI>It is generated on the fly and has no class file. <LI>It implements all of the given interfaces and extends the given class. <LI>It also implements the <CODE><FONT color=#003366>Delegation</FONT></CODE> interface. <LI>It has a constructor that accepts an <CODE><FONT color=#003366>Object</FONT></CODE> instance as a parameter. </LI></UL> <P><CODE><FONT color=#003366>DelegationGenerator</FONT></CODE> is the main class of Dynamic Delegation. A client can use it to generate a delegation class/object for a specific class/interface/object. <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> is an interface defining all of the delegation behaviors and is expected to be implemented by the client's developer. The delegation object can use the <CODE><FONT color=#003366>_getInvocationHandler()</FONT></CODE> and <CODE><FONT color=#003366>_setInvocationHandler()</FONT></CODE> methods defined in <CODE><FONT color=#003366>Delegation</FONT></CODE> to access the <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance in the delegation object.<BR><BR></P> <H4>Exercise 1. Create a Delegation Class for a Concrete Class</H4> <P>Suppose there is a concrete class named <CODE><FONT color=#003366>ConcreteClass</FONT></CODE>:</P><PRE><CODE> <FONT color=#003366>//ConcreteClass.java package org.jingle.util.dydelegation.sample; public class ConcreteClass { public void hello() { System.out.println("Hello from ConcreteClass"); } protected void hello2() { System.out.println("Hello again from ConcreteClass"); } } </FONT></CODE></PRE> <P>The following code generates a delegation class for <CODE><FONT color=#003366>ConcreteClass</FONT></CODE>.</P><PRE><CODE> <FONT color=#003366>//ConcreteClassTest.java package org.jingle.util.dydelegation.sample; import org.jingle.util.dydelegation.DelegationGenerator; public class ConcreteClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator .getDelegationClass(new Class[] { ConcreteClass.class }); System.out.println("Delegation class name = " + clazz.getName()); System.out.println( ConcreteClass.class.isAssignableFrom(clazz)); } } </FONT></CODE></PRE> <P>The output shows:</P><PRE><CODE> <FONT color=#003366>Delegation class name = org.jingle.util.dydelegation.sample.ConcreteClass_Delegation_0 true </FONT></CODE></PRE> <P><CODE><FONT color=#003366>DelegationGenerator.getDelegationClass()</FONT></CODE> accepts a class array as parameter and return a Java <CODE><FONT color=#003366>Class</FONT></CODE> that extends/implements the given class/interfaces. By default, the generated delegation class is in the same package as the class to be delegated.</P> <P>The delegation class can be instantiated as below:</P><PRE><CODE> <FONT color=#003366>//object to be delegated Object obj = ...; //some concrete invocation handler instance DelegationInvocationHandler h = ...; Constructor c = clazz.getConstructor(new Class[] { Object.class }); Object inst = c.newInstance(new Object[] {obj}); ((Delegation) inst)._setInvocationHandler(h); </FONT></CODE></PRE> <H4>Exercise 2. Create a Delegation Class for an Abstract Class</H4> <P><CODE><FONT color=#003366>DelegationGenerator</FONT></CODE> can also generate a concrete delegation class for an abstract class.</P><PRE><CODE> <FONT color=#003366>//AbstractClass.java package org.jingle.util.dydelegation.sample; public abstract class AbstractClass { public abstract void wave(); } //AbstractClassTest.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Modifier; import org.jingle.util.dydelegation.DelegationGenerator; public class AbstractClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator .getDelegationClass(new Class[] { AbstractClass.class }); System.out.println("Delegation class name = " + clazz.getName()); System.out.println( Modifier.isAbstract(clazz.getModifiers())); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Delegation class name = org.jingle.util.dydelegation.sample.AbstractClass_Delegation_0 false </FONT></CODE></PRE> <P>The generated delegation class is a concrete class instead of an abstract class.</P> <H4>Exercise 3. Create a Delegation Class for Both a Class and Multiple Interfaces</H4> <P><CODE><FONT color=#003366>DelegationGenerator.getDelegationClass()</FONT></CODE> can accept a class and multiple interfaces simultaneously to generate a delegation class to delegate the given class and interfaces. Duplicate interfaces will be eliminated.</P><PRE><CODE> <FONT color=#003366>//Idel1.java package org.jingle.util.dydelegation.sample.bean; public interface Idel1 { public void idel1(); } //Idel2.java package org.jingle.util.dydelegation.sample.bean; public interface Idel2 { public void idel2(); } //ComplexClassTest.java package org.jingle.util.dydelegation.sample; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.sample.bean.Idel1; import org.jingle.util.dydelegation.sample.bean.Idel2; public class ComplexClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator.getDelegationClass(new Class[] { ConcreteClass.class, Idel1.class, Idel2.class }); System.out.println( Idel1.class.isAssignableFrom(clazz)); System.out.println( Idel2.class.isAssignableFrom(clazz)); System.out.println( ConcreteClass.class.isAssignableFrom(clazz)); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>true true true </FONT></CODE></PRE> <P>The generated delegation class extends the given class <CODE><FONT color=#003366>ConcreteClass</FONT></CODE> and implements all of the given interfaces: <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>.</P> <H4>Exercise 4. Create a Delegation Object for a Specific Object</H4> <P><CODE><FONT color=#003366>DelegationGenerator</FONT></CODE> can generate a delegation object directly, according to a specific object to be delegated.</P><PRE><CODE> <FONT color=#003366>// ConcreteClassTest2.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Method; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.DelegationInvocationHandler; import org.jingle.util.dydelegation.DummyInvocationHandler; public class ConcreteClassTest2 { public static void main(String[] args) { ConcreteClass inst = new ConcreteClass(); DelegationInvocationHandler handler = new SimpleHandler(); ConcreteClass delegation = (ConcreteClass) DelegationGenerator.newDelegationInstance(inst, handler); delegation.hello(); delegation.hello2(); System.out.println(delegation.toString()); } } class SimpleHandler extends DummyInvocationHandler { public boolean invokeBefore(Object bean, Method method, Object[] args) throws Throwable { System.out.println("Interrupted by SimpleHandler"); return super.invokeBefore(bean, method, args); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Interrupted by SimpleHandler Hello from ConcreteClass Hello again from ConcreteClass Interrupted by SimpleHandler org.jingle.util.dydelegation.sample.ConcreteClass@ef5502 </FONT></CODE></PRE> <P><CODE><FONT color=#003366>DummyInvocationHandler</FONT></CODE> is a dummy implementation of <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE>. It always returns <CODE><FONT color=#003366>true</FONT></CODE> in <CODE><FONT color=#003366>invokeBefore()</FONT></CODE>, returns the input result directly in <CODE><FONT color=#003366>invokeAfter()</FONT></CODE>, and throws the input throwable directly in <CODE><FONT color=#003366>invokeAfterException()</FONT></CODE>. The delegation object with <CODE><FONT color=#003366>DummyInvocationHandler</FONT></CODE> has same behavior as the object to be delegated.</P> <P><CODE><FONT color=#003366>DelegationGenerator.newDelegationInstance()</FONT></CODE> accepts an object and an <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance as parameters. It returns a delegation object to delegate the given object.</P> <P>All of the methods called on the delegation object will be delegated to the <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance, except:</P> <UL> <LI>Methods without a public modifier. <LI>Methods with a final modifier. <LI>Methods with a static modifier. <LI>Methods declared in the <CODE><FONT color=#003366>Object</FONT></CODE> class, other than <CODE><FONT color=#003366>hashCode()</FONT></CODE>, <CODE><FONT color=#003366>equals()</FONT></CODE>, and <CODE><FONT color=#003366>toString()</FONT></CODE>. </LI></UL> <P><BR></P> <H4>Exercise 5. Create Delegation Object for the Object of a Java Core Class</H4> <P>Did you ever want to delegate an object of an existing Java core class? Delegate it as usual.</P><PRE><CODE> <FONT color=#003366>//DateTest.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Method; import java.util.Date; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.DelegationInvocationHandler; import org.jingle.util.dydelegation.DummyInvocationHandler; public class DateTest { public static void main(String[] args) { Date date = new Date(); DelegationInvocationHandler handler = new DateClassHandler(); Date delegation = (Date) DelegationGenerator .newDelegationInstance(date, handler); System.out.println("Delegation class = " + delegation.getClass().getName()); System.out.println("True date = " + date.getTime()); System.out.println("Delegation date = " + delegation.getTime()); } } class DateClassHandler extends DummyInvocationHandler { public Object invokeAfter(Object bean, Method method, Object[] args, Object result) throws Throwable { if (method.getName().equals("getTime")) { return new Long(((Long)result).longValue() - 1000); } return super.invokeAfter(bean, method, args, result); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Delegation class = org.jingle.util.dydelegation.Date_Delegation_0 True date = 1099380377665 Delegation date = 1099380376665 </FONT></CODE></PRE> <P>When creating a delegation class for a Java core class, the delegation class will not be in the same package as the Java core class, because the Java security model does not allow a user-defined <CODE><FONT color=#003366>ClassLoader</FONT></CODE> to define a class in a package starting with <CODE><FONT color=#003366>java</FONT></CODE>.</P> <P><CODE><FONT color=#003366>DateClassHandler</FONT></CODE> catches the <CODE><FONT color=#003366>getTime()</FONT></CODE> method call in <CODE><FONT color=#003366>invokeAfter()</FONT></CODE>, and makes the return value 1000 less than the normal return value.</P> <H3>Advanced Usage</H3> <H4>Exercise 6. Simulate Proxy Behavior</H4> <P>Can Dynamic Delegation do what <CODE><FONT color=#003366>Proxy</FONT></CODE> does? Absolutely! Dynamic Delegation covers the functions of <CODE><FONT color=#003366>Proxy</FONT></CODE>. Given a proper delegation handler, it can simulate the behavior of a Java <CODE><FONT color=#003366>Proxy</FONT></CODE>.</P><PRE><CODE> <FONT color=#003366>// ProxyTest.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Method; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.DelegationInvocationHandler; import org.jingle.util.dydelegation.DummyInvocationHandler; import org.jingle.util.dydelegation.sample.bean.Idel1; import org.jingle.util.dydelegation.sample.bean.Idel2; public class ProxyTest { public static void main(String[] args) { DelegationInvocationHandler handler = new ProxyHandler(); Object delegation = DelegationGenerator.newDelegationInstance(null, new Class[] { Idel1.class, Idel2.class }, null, handler); ((Idel1) delegation).idel1(); ((Idel2) delegation).idel2(); } } class ProxyHandler extends DummyInvocationHandler { public boolean invokeBefore(Object bean, Method method, Object[] args) throws Throwable { return false; } public Object invokeAfter(Object bean, Method method, Object[] args, Object result) throws Throwable { String name = method.getName(); if (name.equals("idel1")) System.out.println("Hello from idel1"); else if (name.equals("idel2")) System.out.println("Hello from idel2"); return super.invokeAfter(bean, method, args, result); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Hello from idel1 Hello from idel2 </FONT></CODE></PRE> <P><CODE><FONT color=#003366>ProxyHandler</FONT></CODE> returns <CODE><FONT color=#003366>false</FONT></CODE> in <CODE><FONT color=#003366>invokeBefore()</FONT></CODE>, which means all of the method calls on the delegation object will not be delegated to the original object. It uses <CODE><FONT color=#003366>invokeAfter()</FONT></CODE> to define the delegation behavior as being what <CODE><FONT color=#003366>Proxy</FONT></CODE> does.</P> <P><CODE><FONT color=#003366>DelegationGenerator.newDelegationInstance()</FONT></CODE> has another version. It contains four arguments: </P> <UL> <LI><B>The <CODE><FONT color=#003366>Object</FONT></CODE> to be delegated</B>. <P>This can be <CODE><FONT color=#003366>null</FONT></CODE>. If it is not <CODE><FONT color=#003366>null</FONT></CODE>, it must be an instance of all of the given classes and interfaces.</P> <LI><B>An array of <CODE><FONT color=#003366>Class</FONT></CODE> to be delegated</B>. <P>This can contain multiple interfaces and, at most, one class.</P> <LI><B>Delegation class name</B>. <P>If <CODE><FONT color=#003366>null</FONT></CODE>, a system-generated name will be provided.</P> <LI><B>A <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance, which is used to define the delegation's behavior</B>. </LI></UL> <P>From the output, we can see that the delegation object is an instance of both <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>. Its behavior is just what is defined in the handler.</P> <H4>Exercise 7. Partial Delegation</H4> <P>Until now, we've delegated all of the functions of the specific object. How about just delegating part of the object's functions?</P><PRE><CODE> <FONT color=#003366>//MyDate.java package org.jingle.util.dydelegation.sample.bean; import java.util.Date; public class MyDate extends Date implements Idel1, Idel2 { public void idel1() { } public void idel2() { } } // MyDateTest.java package org.jingle.util.dydelegation.sample; import java.util.Date; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.DelegationInvocationHandler; import org.jingle.util.dydelegation.DummyInvocationHandler; import org.jingle.util.dydelegation.sample.bean.Idel1; import org.jingle.util.dydelegation.sample.bean.Idel2; import org.jingle.util.dydelegation.sample.bean.MyDate; public class MyDateTest { public static void main(String[] args) { MyDate inst = new MyDate(); DelegationInvocationHandler handler = new DummyInvocationHandler(); Object delegation = DelegationGenerator.newDelegationInstance(inst, new Class[] { Idel1.class, Idel2.class }, null, handler); System.out.println(delegation instanceof Idel1); System.out.println(delegation instanceof Idel2); System.out.println(delegation instanceof Date); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>true true false </FONT></CODE></PRE> <P><CODE><FONT color=#003366>MyDate</FONT></CODE> extends <CODE><FONT color=#003366>Date</FONT></CODE> and implements the <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE> interfaces. <CODE><FONT color=#003366>DelegationGenerator.newDelegationInstance()</FONT></CODE> uses a <CODE><FONT color=#003366>MyDate</FONT></CODE> instance as the object instance to be delegated, and limits the delegation scope in <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>. In other words, the generated delegation object is an instance of <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>, but not an instance of <CODE><FONT color=#003366>Date</FONT></CODE>.</P> <H3>Conclusion</H3> <P>The Dunamis project introduces Dynamic Delegation to extend the function of the Java <CODE><FONT color=#003366>Proxy</FONT></CODE> reflection utility. It can generate delegation for both classes and interfaces at runtime. This article introduces Dynamic Delegation in brief with simple examples. In the real world, Dynamic Delegation can be used in many areas, such as mock objects in unit testing, Java GUI MVC framework, and more.</P> <H3>Reference</H3> <UL> <LI>Dunamis project: <A el="http://dunamis.dev.java.net" lid="dunamis.dev.java.net">dunamis.dev.java.net</A> <LI>Download sample code for this article: <A el="http://dunamis.dev.java.net/servlets/ProjectDocumentList" lid="sample code">sample code</A> <LI>BCEL: <A el="http://jakarta.apache.org/bcel/index.html" lid="jakarta.apache.org/bcel/index.html">jakarta.apache.org/bcel/index.html</A> </LI></UL> <P><I><A lid="Lu Jian">Lu Jian</A> is a senior Java architect/developer with four years of Java development experience. </I><BR><BR></P> <H4>Exercise 1. Create a Delegation Class for a Concrete Class</H4> <P>Suppose there is a concrete class named <CODE><FONT color=#003366>ConcreteClass</FONT></CODE>:</P><PRE><CODE> <FONT color=#003366>//ConcreteClass.java package org.jingle.util.dydelegation.sample; public class ConcreteClass { public void hello() { System.out.println("Hello from ConcreteClass"); } protected void hello2() { System.out.println("Hello again from ConcreteClass"); } } </FONT></CODE></PRE> <P>The following code generates a delegation class for <CODE><FONT color=#003366>ConcreteClass</FONT></CODE>.</P><PRE><CODE> <FONT color=#003366>//ConcreteClassTest.java package org.jingle.util.dydelegation.sample; import org.jingle.util.dydelegation.DelegationGenerator; public class ConcreteClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator .getDelegationClass(new Class[] { ConcreteClass.class }); System.out.println("Delegation class name = " + clazz.getName()); System.out.println( ConcreteClass.class.isAssignableFrom(clazz)); } } </FONT></CODE></PRE> <P>The output shows:</P><PRE><CODE> <FONT color=#003366>Delegation class name = org.jingle.util.dydelegation.sample.ConcreteClass_Delegation_0 true </FONT></CODE></PRE> <P><CODE><FONT color=#003366>DelegationGenerator.getDelegationClass()</FONT></CODE> accepts a class array as parameter and return a Java <CODE><FONT color=#003366>Class</FONT></CODE> that extends/implements the given class/interfaces. By default, the generated delegation class is in the same package as the class to be delegated.</P> <P>The delegation class can be instantiated as below:</P><PRE><CODE> <FONT color=#003366>//object to be delegated Object obj = ...; //some concrete invocation handler instance DelegationInvocationHandler h = ...; Constructor c = clazz.getConstructor(new Class[] { Object.class }); Object inst = c.newInstance(new Object[] {obj}); ((Delegation) inst)._setInvocationHandler(h); </FONT></CODE></PRE> <H4>Exercise 2. Create a Delegation Class for an Abstract Class</H4> <P><CODE><FONT color=#003366>DelegationGenerator</FONT></CODE> can also generate a concrete delegation class for an abstract class.</P><PRE><CODE> <FONT color=#003366>//AbstractClass.java package org.jingle.util.dydelegation.sample; public abstract class AbstractClass { public abstract void wave(); } //AbstractClassTest.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Modifier; import org.jingle.util.dydelegation.DelegationGenerator; public class AbstractClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator .getDelegationClass(new Class[] { AbstractClass.class }); System.out.println("Delegation class name = " + clazz.getName()); System.out.println( Modifier.isAbstract(clazz.getModifiers())); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Delegation class name = org.jingle.util.dydelegation.sample.AbstractClass_Delegation_0 false </FONT></CODE></PRE> <P>The generated delegation class is a concrete class instead of an abstract class.</P> <H4>Exercise 3. Create a Delegation Class for Both a Class and Multiple Interfaces</H4> <P><CODE><FONT color=#003366>DelegationGenerator.getDelegationClass()</FONT></CODE> can accept a class and multiple interfaces simultaneously to generate a delegation class to delegate the given class and interfaces. Duplicate interfaces will be eliminated.</P><PRE><CODE> <FONT color=#003366>//Idel1.java package org.jingle.util.dydelegation.sample.bean; public interface Idel1 { public void idel1(); } //Idel2.java package org.jingle.util.dydelegation.sample.bean; public interface Idel2 { public void idel2(); } //ComplexClassTest.java package org.jingle.util.dydelegation.sample; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.sample.bean.Idel1; import org.jingle.util.dydelegation.sample.bean.Idel2; public class ComplexClassTest { public static void main(String[] args) { Class clazz = DelegationGenerator.getDelegationClass(new Class[] { ConcreteClass.class, Idel1.class, Idel2.class }); System.out.println( Idel1.class.isAssignableFrom(clazz)); System.out.println( Idel2.class.isAssignableFrom(clazz)); System.out.println( ConcreteClass.class.isAssignableFrom(clazz)); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>true true true </FONT></CODE></PRE> <P>The generated delegation class extends the given class <CODE><FONT color=#003366>ConcreteClass</FONT></CODE> and implements all of the given interfaces: <CODE><FONT color=#003366>Idel1</FONT></CODE> and <CODE><FONT color=#003366>Idel2</FONT></CODE>.</P> <H4>Exercise 4. Create a Delegation Object for a Specific Object</H4> <P><CODE><FONT color=#003366>DelegationGenerator</FONT></CODE> can generate a delegation object directly, according to a specific object to be delegated.</P><PRE><CODE> <FONT color=#003366>// ConcreteClassTest2.java package org.jingle.util.dydelegation.sample; import java.lang.reflect.Method; import org.jingle.util.dydelegation.DelegationGenerator; import org.jingle.util.dydelegation.DelegationInvocationHandler; import org.jingle.util.dydelegation.DummyInvocationHandler; public class ConcreteClassTest2 { public static void main(String[] args) { ConcreteClass inst = new ConcreteClass(); DelegationInvocationHandler handler = new SimpleHandler(); ConcreteClass delegation = (ConcreteClass) DelegationGenerator.newDelegationInstance(inst, handler); delegation.hello(); delegation.hello2(); System.out.println(delegation.toString()); } } class SimpleHandler extends DummyInvocationHandler { public boolean invokeBefore(Object bean, Method method, Object[] args) throws Throwable { System.out.println("Interrupted by SimpleHandler"); return super.invokeBefore(bean, method, args); } } </FONT></CODE></PRE> <P>Output:</P><PRE><CODE> <FONT color=#003366>Interrupted by SimpleHandler Hello from ConcreteClass Hello again from ConcreteClass Interrupted by SimpleHandler org.jingle.util.dydelegation.sample.ConcreteClass@ef5502 </FONT></CODE></PRE> <P><CODE><FONT color=#003366>DummyInvocationHandler</FONT></CODE> is a dummy implementation of <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE>. It always returns <CODE><FONT color=#003366>true</FONT></CODE> in <CODE><FONT color=#003366>invokeBefore()</FONT></CODE>, returns the input result directly in <CODE><FONT color=#003366>invokeAfter()</FONT></CODE>, and throws the input throwable directly in <CODE><FONT color=#003366>invokeAfterException()</FONT></CODE>. The delegation object with <CODE><FONT color=#003366>DummyInvocationHandler</FONT></CODE> has same behavior as the object to be delegated.</P> <P><CODE><FONT color=#003366>DelegationGenerator.newDelegationInstance()</FONT></CODE> accepts an object and an <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance as parameters. It returns a delegation object to delegate the given object.</P> <P>All of the methods called on the delegation object will be delegated to the <CODE><FONT color=#003366>DelegationInvocationHandler</FONT></CODE> instance, except:</P> <UL> <LI>Methods without a public modifier. <LI>Methods with a final modifier. <LI>Methods with a static modifier. <LI>Methods declared in the <CODE><FONT color=#003366>Object</FONT></CODE> class, other than <CODE><FONT color=#003366>hashCode()</FONT></CODE>, <CODE><FONT color=#003366>equals()</FONT></CODE>, and <CODE><FONT color=#003366>toString()</FONT></CODE>. </LI></UL><img src ="http://www.tkk7.com/jinfeng_wang/aggbug/2264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-03-20 18:23 <a href="http://www.tkk7.com/jinfeng_wang/archive/2005/03/20/2264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐一文章:(x)架构更新http://www.tkk7.com/jinfeng_wang/archive/2005/03/18/2191.htmljinfeng_wangjinfeng_wangFri, 18 Mar 2005 05:58:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2005/03/18/2191.htmlhttp://www.tkk7.com/jinfeng_wang/comments/2191.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2005/03/18/2191.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/2191.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/2191.htmlhttp://forum.javaeye.com/viewtopic.php?t=11474&highlight=

《企业架构模式》中Q对其中各局部的具体选择Q有了非常棒的讨论?BR>


jinfeng_wang 2005-03-18 13:58 发表评论
]]>
Maven存在的问?疑惑Q?/title><link>http://www.tkk7.com/jinfeng_wang/archive/2005/03/10/1898.html</link><dc:creator>jinfeng_wang</dc:creator><author>jinfeng_wang</author><pubDate>Thu, 10 Mar 2005 04:52:00 GMT</pubDate><guid>http://www.tkk7.com/jinfeng_wang/archive/2005/03/10/1898.html</guid><wfw:comment>http://www.tkk7.com/jinfeng_wang/comments/1898.html</wfw:comment><comments>http://www.tkk7.com/jinfeng_wang/archive/2005/03/10/1898.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jinfeng_wang/comments/commentRss/1898.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jinfeng_wang/services/trackbacks/1898.html</trackback:ping><description><![CDATA[1、如果整个项目用maven理Q那么每个开发客L(fng)都需要配|maven才行?BR>      如果要在Eclipse里面集成mavenQ例如用maven ideQ那么还要对maven ideq行配置?BR>      q里提醒一下哦QEclipse里面使用maven ide的时候会(x)下蝲mavenQ在eclipse\plugins\org.apache.maven_1.0.0\lib目录中,如果你想Q还需要象maven那样自己配置?BR><BR>2、如果你惛_客户端debug怎么办?那还是需要将lib库拷贝到本地。现在只能统一映射|络盘。那是在开发的时候是一U方式,在发布的时候又是一U模式。maven对开发的帮助q不是很大,有意义的内容在于maven?x)“强q”要求你量分开projcet之间的各层?BR><BR>3、maven的各artifact 之间的依赖问题。maven artifact 的version军_与POM中的currentversionQ而没用能够和CVS的versionq接h。如果在开发过E中Q会(x)生成A、B两个artifactQA依赖于BQ但是Bl过改动后,~译A、BQ此时Mavenq不能自动发觉B已经改动q。只要maven在repository发现了B.currentversion.jarQ那么它?yu)׃会(x)将B重新打包Qmavenq是必须通过U种人工手段才能够完成先~译B(ti)再编译A。在试的时候也是如此。MQ必还是需要h为的参与才能保证序的正,才能保证你所使用的库Q是最新的库?BR><BR>4、如果maven只能提供一个repository的功能和利用POM减少script的功能,那用mavenq吗呢?何况每个developerq需要自己机器上拥有repository。如果说maven提供了许多的pluginQ那么现在的ant也可以支持,只是未能正式成Ş?BR><BR>我的意思是_(d)(x)maven带来的内容ƈ不是ant的完全替代品Q有时候甚至需要h工参与才能让maven完成d。当Ӟmaven提供jellyQ自己写scriptQ但那不是又ȝ了么Q?BR><BR><BR><FONT color=#008000>//maven 可以先排队哦Q问?解决?/FONT><img src ="http://www.tkk7.com/jinfeng_wang/aggbug/1898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jinfeng_wang/" target="_blank">jinfeng_wang</a> 2005-03-10 12:52 <a href="http://www.tkk7.com/jinfeng_wang/archive/2005/03/10/1898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Why do I like TDD?(zz)http://www.tkk7.com/jinfeng_wang/archive/2005/03/09/1873.htmljinfeng_wangjinfeng_wangWed, 09 Mar 2005 06:11:00 GMThttp://www.tkk7.com/jinfeng_wang/archive/2005/03/09/1873.htmlhttp://www.tkk7.com/jinfeng_wang/comments/1873.htmlhttp://www.tkk7.com/jinfeng_wang/archive/2005/03/09/1873.html#Feedback0http://www.tkk7.com/jinfeng_wang/comments/commentRss/1873.htmlhttp://www.tkk7.com/jinfeng_wang/services/trackbacks/1873.htmlhttp://www.theserverside.com/news/thread.tss?thread_id=32394#160253

Why do I like TDD?

1) by the nature of software engineering any code needs refactoring. Having code covered with unit-tests, gives me confidence during the refactoring. I do not know any other reliable way of having the same kind of confidence. Without the confidence, I would be afraid to do refactorings often, which would make the software product of lesser quality.

1)本质上,软g开发中一切代码都需要重构。经q单元测试覆盖的代码可以让我拥有信心去重构。我也不知道q有什么其他办法能够让我获得如此的信心。如果没有信心,那么我就不太敢经常的重构Q这也必然媄响代码的品质?/SPAN>

2) Due to the nature of unit-tests (emphasize: unit), it is impossible to test a "badly-smelling" code. In order to be able to unit-test your code, it has to be cleaner, and better designed: short, focused methods, writing to Interfaces, lously coupled etc.
2
Q由于单元测试的自然Ҏ(gu)(注意是单元测试)Q无法对h“坏味道”的代码q行单元试。而ؓ(f)了能够顺利的对你的代码进行单元测试,那么你的代码׃(x)逐渐的变得更加清晰、设计更加完善:(x)代码短小、专注方法、针Ҏ(gu)口编E、降低耦合{?/SPAN>

 

I think, this might not have been something that was foreseen initially but discovered later. My guess is, initially, people just wanted to make computer do what it is best for - repetitive work (in this case - testing) and have code test the application, not humans. But as a "byproduct" they noticed that testing requires design improvement, too. When they discovered it, somebody smart-enough had an idea - if it is so, why not write tests first? Design is supposed to come before the implementation and if tests affect design, it makes sense to write them before the implementation, too.

我想Q也许单元测试的提倡者事前也未曾?x)预料到它能够带来这已经证实了的益处。我惻I刚开始h们也只是希望发挥计机的特点,让它完成重复性的工作Q这里是指测试)Q而不再需要h去进行测试。但是他们发C“副产品”―测试需要更好的设计。接着Q他们中的杰提Z一个全新的xQ既然如此,那何不事先写好测试呢Q设计是应该在代码实C前的Q而如果测试可以媄响设计,那么何不也将试在代码实C前进行编写呢Q?/SPAN>

 

And the TDD started...

于是TDD开始了…??BR>

====================================

http://www.theserverside.com/news/thread.tss?thread_id=32394#160294

I think I agree with some of the objections raised with TDD, but the problem seems more with how people use it than a basic flaw in the concept. The 2 primary objections raised are:
1. There is a lot of test-centric coding with less focus on ensuring overall business requirement is fulfilled.
2. Developers seem to think that having run the product through the Unit tests ensures that the product is well-tested and production ready.

我对TDD所引v的问题非常的同意Q但是问题更在于Z如何解决它,而不是仅停留在基本的观念上。TDD主要引v的问题是Q?
1?存在着太多的“以试Z心”的代码Q而更的x于整体的业务需求?
2、开发者好像开始认遍单元测试就可以保证产品的可试和品的质量?



All that TDD should be expected to do is run a sanity check at the end of a new build to ensure that the contracts that each unit of code is supposed to fulfill have not been broken. You still need to go through your entire QA cycle to ensure you have a functional product. So, the automated unit tests are just additional checks and do not replace QA. But, unfortunately I have seen situations where people believe that once they have a proper build and unit tested they can reduce the time they spend in QA. Not really true!!! It just ensures that if the unit tests were written properly, the quality of the code reaching QA will be a little better.

所有的TDD能做的是在整个项目构建结束之后完成一个检查工作,保证原有的单元之间的契约没用被打破。在目构徏完成后,q需要一个质量保?quality assurance)的过E,以保证整个项目的功能。也是说自动化试只是一个附加的查,而不是对质量保证的全盘替代。但不幸的是Q我看到的h们却非如此。他们认Z旦单元测试成功,那么可以减QA上面的时间。但事实真的不是q样的。单元测试所能做倒的也仅在于单元试已经很好的编写完成,代码的质量更Ҏ(gu)辑ֈQA的标准?



jinfeng_wang 2005-03-09 14:11 发表评论
]]>
վ֩ģ壺 ޸Ů侫| 뾫Ʒ| ˿Ƶ| ҹƵ߹ۿ| aëƬվ| һ߲ͨ| þƷ| ޳ɫWWWþվ| Ʒ޳| ޳AƬ߹ۿWWW| պӰ߹ۿƵ| Ů18ëƬˮѿ| ƵԿ120| ôӲˬѲ| Ƶһ| ҹƵ߹ۿ| Ʒ߹ۿѲ| ҹɫ˽ӰԺվӰ| һëƬȫ| Ļþþһ| ޾ǧ˾ղ| þþþavרˮ| ޵һҳƵ| ۺɫ| ޹ۺһҳ| þպƬ| 2022| AVһ| žѾþоƷ23| AVۺɫһ| ҹػaëƬѲ| 99þѹƷ| 99þ޾Ʒһ| 2019Ļѿ| 99ƵѾƷǿ6| ɫƷvrһ| þþ뾫Ʒպ| רһvav| һһƬһëƬ| һƬaѲſ֮ | ƷҳѸ߹ۿ|