RSS 2.0 Feed
Agile/XP
摘要:前面用透明代理机制实现简单AOP的文章一发,很快收到很多朋友的反馈,其中就有一些朋友提出关于文中所述的透明代理等技术还能够用于什么应用场合的疑问。说实在的,本来我就是想写一些关于这些技术在实际项目中应用的随笔的,可是想到可能会有很多朋友对这些技术的基本原理还不熟悉,这才萌生了先写一系列文章作铺垫的念头(可惜由于工作比较忙的缘故,至今还欠一篇没有写完,还请大家见谅啦,我抓紧时间补上——这篇内容更精彩噢!呵呵)。   今天我们又一次把我前面这两篇文字中提到的技术应用在项目开发中,初步反馈还是非常positive的,这里我不妨把问题先说出来,请看过文章的朋友们好好想想,看看如何利用已经学到的知识来解决这个实际问题吧——稍后我会回来说说我的想法(当然如果大家看过偶的文章以后都能够想出这种解决方案的话那当然就最好了:),当然如果你有其他更好的办法,更是欢迎你通过发表评论和大家分享!   这个问题和单元测试(Unit Testing)有密切关系(虽然我们的项目还不能算是完全的TDD,但是充分、必要的单元测试还是不可或缺),这里我们还是以简单的例子来说明,比如这里有一个银行服务的接口:   interface IBankService{  void Withdraw(Account account, int amount);  void Deposit(Account account, int amount);  int QueryBalance(Account account);}   这个接口的三个方法的作用很简单:取款、存款、查询余额。我们肯定要开发一个实现这个接口的具体业务操作类;与此同时,由于该服务接口对安全性的严格要求,项目组中专门负责安全规则的部门将以DECORATOR的方式针对该接口的每一个方法编写负责安全保障的修饰类(最终在运行时由组件工厂动态组合)。以这种设计方式,只要确定了服务接口,则两个类的开发就可以充分的并行进行了——真的是这样吗?我们写写看:   class BankServiceSecurityGuard: ComponentDecorator, IBankService{  void IBankService.Withdraw(Account account, int amount)  {    if ( … )      throw new DailyAmountExceedsException( … );    if ( … )      throw new AccountBlockedException( … );    if ( … )      throw new PermissionNotGrantedException( … );    …    ((IBankService)Decoratee).Withdraw(account, amount);      }  …}   这个方法的实现就是一个把门儿的逻辑:结合方法调用参数使尽各种必要手段确保只有在符合所有安全规则的前提下才能够把调用转发到被修饰的(即decoratee)对象(也就是IBankService的核心实现类上)。也就是说,开发并测试这个安全保障修饰类的时候最终还是要依赖于一个能够工作的核心实现类,否则就算可以编译通过(还好这种依赖已经被接口隔离开了),你也无法让单元测试通过。我们能不能用什么办法来独立的测试这个修饰对象使之不依赖于一个正确工作的核心实现类呢?换句话说,有没有办法在没有可工作的核心实现类的情况下(这种情况常见于核心类开发周期较长的时候),让下面针对安全保障修饰类的单元测试代码正常起到单元测试的作用(一是驱动开发过程、二是形成软件规格说明、三是跟踪软件缺陷……)呢(我们先假设Account类是已经存在且经过充分测试的——其实对该类的隔离测试也是类似的道理)?   [TestFixture]public class BankServiceSecurityTest{  private IBankService bankService;  [SetUp]  public void Initialization()  {    bankService = new BankServiceSecurityGuard(???);  }  [ExpectedException(typeof(DailyAmountExceedsException))]  public void TestForExceedingDailyAmount()  {    AccountState state = AccountState.DailyAmountReached;    Account account = new MockAccount(state);    bankService.Withdraw(10);  }  public void TestForNormalWithdraw()  {    AccountState state = AccountState.Normal;    int initialBalance =......[阅读全文]

posted @ | Feedback (11) | Filed Under [ .NET Stuffs Agile/XP ]

摘要:  昨天,我第一次在实际开发工作中体验到了结对开发的魔力(以前也就是两个人一起研究问题而已),那确实是一种令人神怡且有效的工作方式——至少it works extremely well for me!   在下午三四个小时的开发工作中,我和我的搭档一起解决了已经困扰了我很久的几个问题,并令人激动不已的在NUnit中点绿了单元测试中所有的测试项(就这几个问题我已经拖了半个月了还没能解决)——这意味着我可以放心的开始对代码进行重构(而不是重写)了(本来一直没有信心这样做,因为到处都有红灯,而每一个红灯都牵扯到很多的问题)……体会一:结对编程消除了最影响开发人员情绪的孤独感,进而重新迸发工作激情,大大提升工作效率和质量。   其他同事都下班以后,我们简直是进入了一种turbo的开发状态——我们先是一起总结了前面开发中最不爽的几个环节,并一致认为一定有好办法能够让开发变得更简单一些——于是我的灵感突然涌出,我告诉他“我将把让我们的开发变得繁琐的这些类都删掉,用一个custom proxy搞定所有的类”!“听上去不错,可是……有这么好的事吗?”“看我的——你就帮我瞧着那些绿灯吧!”当然,我在下手之前还是像唐僧一样把改造的思路说了几遍,当我确信搭档已经明白我的意图后,我开始动手了:三下五除二,我先把一个private成员提为internal(本来它只是被自己的一系列public gateway methods访问的,现在我要让它能被custom proxy使用),并马上写出了这个custom proxy,用它替代了以前那些繁琐的method gateway和那个接口实现类,最后,我到组件工厂中把实现接口的类换为由custom proxy构造的transparent proxy——NUnit.Run! Bingo! We got it! 体会二:两个人的智慧确实大于一个人,尤其当两个人从两个方向共同考虑同一个问题的时候——当然,彼此持续、默契的交流是必不可少的。   现在回头想想,这一下午的进展真的是匪夷所思,我又一次亲身体会到了结对编程的魔力和乐趣——当然,坐在我对面的项目经理估计也体验了他工作以来强度最大、持续时间最长的人造噪音。不过我想说的不是sorry,而是thanks!谢谢你给我们这样的机会,这是在其他团队中难以想象的事情。我相信你也将亲眼看到我曾向你描述的关于结对编程的种种好处。另外,thanks to my partner canyue!和你一起工作真的很开心,我在你谨慎的约束下变得更专注也更有效率,而你也能在看我开发的时候学到更多的东西。Cool!   如果你也有类似的敏捷开发经历,不妨写在评论中与我们分享——无论是成功的经历还是失败的经历,我想都会很有参考价值。其实关于敏捷方法论(尤其是其中最著名的极限编程技术),我也有很多实践经验和想法,希望以后有时间能够在这方面也写些心得体会吧——不过当务之急,还是先把腾苦不堪的颈椎疼痛消灭掉吧!现在开车都成问题了……...[阅读全文]

posted @ | Feedback (18) | Filed Under [ Agile/XP ]