6、 软件设计模式
软件设计模式描述的是应用软件设计原则所遵循的策略的问题。换句话说,一个软件设计原则是一个好的思想,而一个软件设计模式是你用于实现这种好的思想的工具。
软件设计模式的思想最初源于书籍《Design Patterns: Elements of Reusable Object-Oriented Software》。正是这本书为其它许多描述软件设计模式书的创作带去灵感。
例如,另一本书《The Head First Design Pattern》就以一种更易于理解的方式向人们介绍了GOF所著的书(即上面的那本《Design Patterns: Elements of Reusable Object-Oriented Software》)中所引入的设计模式。这本书中总共详细介绍了下列14种软件设计模式:
◆Strategy
◆Observer
◆Decorator
◆Factory
◆Singleton
◆Command
◆Adaptor
◆Façade
◆Template
◆Iterator
◆Composite
◆State
◆Proxy
◆Compound
另一本在软件设计模式方面较有影响的书是Martin Fowler的《Patterns of Enterprise Application Architecture》。这本书还拥有一个公司网站,其中列举了本书中所介绍的模式。此网站的网址是:http://www.martinfowler.com/eaaCatalog/。
软件设计模式提供给你按照模式的方式构建你的代码,从而使之更富于适应未来的弹性修改。例如,当构建本文中的论坛应用程序时,我们就使用了一种名字为 Repository的软件设计模式进行设计。Eric Evans,在他的著作《Domain-Driven Design》中这样描述Repository模式:
一个REPOSITORY把某种类型的所有对象描述为一个概念的集合(通常是模拟的)。其行为类似于一个集合,但是具有更细致的支持查询的能力。于是,符合相应类型的对象可以被添加或删除,而位于此REPOSITORY背后的系统则可以从数据库中添加或删除它们。
根据Evans的解释,Repository模式的一个主要的优点是,它能够帮助你实现“应用程序和域设计与存储技术,多种数据库策略,甚至是多个数据源之间的解耦。”换句话说,Repository模式能够使你的应用程序免于因数据库访问方式的不同而重新加以改变。
为了使我们的论坛应用程序从某一种特定的存储技术中独立出去,我们将在系统中引入上述Repository模式。因此,最终的此论坛应用程序的设计将能够支持我们可以在不同的数据访问技术(例如LINQ to SQL,Entity Framework或NHibernate)之间切换。
7、 测试驱动开发
我打算使用测试驱动开发原则构建本文中的MVC论坛应用程序。更具体地说是,在我编写任何应用程序代码之前,我将首先编写一个应用程序代码的单元测试。
测试驱动开发将会基于下列原因为你带来更高质量的代码:
(1)为你的代码编写测试能够提供给你一个适应于未来可能改变的安全网。
(2)为你的代码编写测试迫使你书写松耦合的代码。
(3)在正式书写你的代码前为你的代码编写测试将迫使你从一个用户的角度来观察自己书写的代码。
让我们更细致地分析上述每种特征的优点。
首先,单元测试提供你一个适应于未来可能改变的安全网。这是Michael Feathers在他的著作《Working Effectively with Legacy Code》一再强调的一个观点。事实上,他把遗留代码定义为“简单地编码而不进行测试”。
当你的应用程序代码被单元测试所覆盖时,你可以修改该代码而不必担心此改动会你的代码既有的功能。单元测试有助于使你的代码进行更安全的重构。如果你能够重构,那么,你可以使用软件设计模式修改你的代码,这将产生更好的适应未来修改的代码。
其次,遵循测试驱动开发将迫使你使用一种特定的方式书写代码。可测试的代码将趋于导致松耦合的代码。单元测试能够在各自孤立的代码单元中执行一个测试。为了构建你的应用程序以便使之可测试,你需要使用一种可孤立的组件方式来构建应用程序。
一个类与另一个类之间是松耦合的是指,当你改变第一个类时不必改变另一个类。测试驱动开发经常迫使你编写松耦合的代码,因为松耦合代码是经得起改变的。
最后,按照测试先行的方式书写代码将迫使你从一个用户的角度来观察自己书写的代码。通过首先编写测试的方式书写代码,会使你站在一个未来的有可能使用你的代码的开发者的角度进行工作。既然编写测试迫使你考虑另一个开发者(也许是未来的你自己)如何使用你的代码,那么,你最终编写的代码应该是设计得更好的代码。
8、 莫图眼前之利益更宜立足于长远
使用测试驱动开发原则构建软件在软件开发之初要求开发者付出更多的努力。尽管编写测试需要花费一定的时间;然而,其思想是,最初构建单元测试所要求付出的努力将会在未来获得丰厚的回报。
存在两种方式可以使你成为一名开发者。你可以成长为一个牛仔,也有可能成长为一个工匠。一个牛仔能够立即开始编码。也就是说,一个牛仔可以以很快的速度构建一个软件应用程序。然而,作为一个牛仔,其问题在于软件必须要进行长期的维护。
一个工匠则是很有忍耐性的。一个工匠总会精雕细琢地开发一款软件。一个工匠总是非常仔细地构建单元测试,并使之涵盖一个应用程序中所有的代码。因此,一个工匠要花费更长的时间才能创建成功一款应用程序。然而,此应用程序在创建后,却是易于后期的维护—更易于修改错误且更易于把新特征添加到应用程序中。
9、 总结
总之,我们的最终目标是构建一个MVC论坛应用程序,此程序能够经得起长时间的测试。它应该是不仅现在良好地工作,还应该在未来继续工作—即使是当有人需要对该应用程序进行更改之时。
我想利用微软ASP.NET MVC框架开发此论坛应用程序。原因在于,这个框架可以使我更容易地编写程序的测试代码。而另一方面,ASP.NET MVC框架本身就从设计之初提供了对测试驱动开发的最忠诚的支持。
【编辑推荐】