英文原文:What to Use on the Microsoft Stack
Microsoft 技术栈最近有大量的变迁,这使得开发人员和领导者都想知道他们到底应该关注哪些技术。Microsoft 自己并不想从官方层面上反对 Silverlight 这样的技术,相对而言他们更喜欢让这种技术慢慢淡出人们的视线,否则局面可能会更加混乱。如果你想了解该问题的答案,那么可以查看“.NET 业务应用程序技术指南”这个小有名气的文档。该文档发布于去年早些时候,它深入探讨了 Microsoft 打算在哪些领域付出努力,我们应该回避哪些技术等内容。
下面这个概要图是我们探索 Microsoft 及其相关技术的一个很好的起点。
尽量早日放弃 Silverlight 和 Flash
虽然 WinForms 和 Web 表单这些旧的 .NET 技术依然占有一席之地,但是 Silverlight 和 Flash 这样的 RIA 容器绝对是出局了。正如下面图5-15 所展示的,Microsoft 并不想空等着 Silverlight 5 所计划的 10 年生命周期。他们已经打算在 2015 年底放弃 RIA 容器。
高端应用程序更倾向于完全使用本地技术;而低端应用程序则期望 HTML5 的能力持续发展。尽管没有将开发人员推向具体的某一种技术,但是对于这种转变我们必须要注意的事情是:
移动
Windows 8 商店有三个相等但是不同的选项
就 Windows 8 商店应用而言,Microsoft 过去一直不愿意将开发人员推到某一种具体的技术栈上。这个政策现在也没有发生变化;在 .NET/XAML、C++和 JavaScript/HTML5 这些技术之间选择的首要标准是开发人员最熟悉哪种技术。
除此之外,他们还提到了C++,因为它具有性能优势。可重用性并不是很受关注的一个点,因为这三个平台都能够在 Windows Phone 和 Windows 桌面之间共享代码和资源。
本地选项适合 Windows Phone
Windows Phone 推荐的技术是 .NET 和C++。再次重申,需要注意一下 C++ 的性能优势,但是他们说的最多的还是开发者应该使用自己更加熟悉的技术。
尽管 Windows Phone 兼容 PhoneGap/Apache Cordova,但是这并没有被提及。推测起来原因可能是他们认为在小设备上 PhoneGap 的性能比起 .NET 或者 C++ 要差。在 2013 年度的 Build 大会上性能无疑是最重要的话题,超出了诸如一般可用性、可视化设计和深度 OS 集成等其他话题。
移动 Web:都可以使用,除了 Web 表单
如果你想选择一种能够在所有移动设备上运行的、基于 Web 的解决方案,那么有多种选择。使用 Modernizer 的 ASP.NET MVC 是基线推荐方案,你能够使用它创建单页面应用程序(ASP.NET SPA)。Microsoft 对 SPA 的看法是它更像是一种设计模式而不是技术,同时 Microsoft 还极力推荐使用 Knockout 和 Breeze 这两个类库。
为了快速地装配 CRUD 风格的应用程序,LightSwitch 被列了出来。虽然该框架几乎没有对 HTML 渲染进行控制,但是却可以让开发人员不必为各种各样的屏幕大小构建布局,减少了工作量。
ASP.NET Web 页面是为移动 Web 提供的第四个选项。它基于 Razor 语法,为开发者提供了与 PHP 和传统 ASP 等脚本语言相似的开发体验。
指南中并没有提及比较老的 ASP.NET 渲染工具箱——Web 表单。虽然该技术依然在积极的开发中,同时从理论上说它也能够渲染设备特定的 HTML,但是在实践中 Web 表单并没有发挥其真正的潜力。它所渲染的 HTML 和 JavaScript 好像比较低效,此外其高级功能所必须的 view state 能快速地压垮一个手机的网络连接。
服务
因为大部分应用程序都依赖于外部的数据存储和处理,所以服务器端开发依然是一个非常重要的考虑因素。Microsoft 认为现在有 6 种可行的技术选项。
首选:ASP.NET Web API
根据 Microsoft 所提供的信息,新项目的默认选择应该是 ASP.NET Web API。如果要开发遵循 REST 风格的服务,或者需要兼容“Akamai、Windows Azure CDN、Level3 等”Internet 缓存,那么可以使用该技术。
开发者在使用 Web API 的时候应该关注 OData 和 JSON,前者标准化了 REST 端点的暴露方式。
第二选择:WCF
与 Web API 相比 WCF 被认为是一种更加灵活的选项,因为它并没有与任何特定的传输协议或者消息格式绑定。例如,你能够利用 TCP 或者命名管道和二进制消息提升性能。缺点是 WCF 使用起来比较困难,特别是当你想要以 JSON 或者其他非基于 SOAP 的格式暴露数据时更是如此。
WCF 是面向企业设计的,理念是 RPC 风格的通信。虽然它也可以使用面向大众的 REST 风格的设计模式,但是这并不是该场景下的首选项。
WCF 和 OData
如果你的主要工作是 CRUD 风格的服务层,同时想要使用 WCF 技术栈,那么 WCF 数据服务是一个不错的选择。它与 ASP.NET Web API 共享 OData 类库,并且通常会与 Entity Framework 结合使用。
Workflow 服务
Workflow 服务是 Windows Workflow 与 WCF 的结合。使用它的原因只有一个,那就是你的服务内部已经使用了 Windows Workflow。Microsoft 认为没有让你选择这个选项的其他原因。
使用 SignalR 进行双向通信
如果你仅想使用基于 .NET 的客户端,那么 WCF 为良好的双向通信提供了很多选项。但是如果你想要的是能够同时支持 .NET 和基于 Web 的客户端,那么 SignalR 是一个非常不错的选择。
根据 Microsoft 提供的信息,SignalR 甚至能够扩展到上百万用户。Web 客户端喜欢使用 WebSockets,但是可以在必要的时候自动地回退到旧的模式,例如长轮询。
SignalR 还有一个针对 .NET 客户端的类库,允许 Web 和本地客户端共享服务。
LightSwitch,另一个 OData 提供者
Microsoft 对 OData 的喜爱程度夸张到我们几乎难以用语言来描述。到现在为止,我们已经看到了用于 WCF 和 Web API 的 OData,但是这并没有结束。尽管通常情况下我们使用的是 LightSwitch 的客户端,但是很显然我们还可以使用它的服务器端能力快速地生成一个服务层。
Microsoft 宣称 LightSwitch 不需要任何编码,但是同时也警告说这样会丧失灵活性。
中小型企业应用程序指南
Microsoft 为中小型企业编写指南时一直遵循如下目标:
通俗点说,它的意思就是“让事情变得更快,成本更低”。Microsoft 提供的这个具体的指南取决于你喜欢什么样的展示模式。
中小型企业 Web 应用程序
对于快速而随意的 CRUD 风格的应用程序而言,Microsoft 推荐的首选平台依然是 LightSwitch。LightSwitch 最初被描述为一个针对非专业程序员的工具。许多人将它看作是一个访问的多层替代。但是随着现在 Microsoft 更多的将其作为一个服务于需要快速推出应用程序的 IT 部门的工具,这个愿景似乎也已经消失。
接下来要讲的是 Web 表单。是的,令人尊敬的 Web 表单依然是新项目推荐使用的技术。Microsoft 将其看作是一种折中技术,介于易用但是有限制的 LightSwitch 和复杂的 ASP.NET MVC 之间。Web 表单包含丰富的数据表格等功能,它依然能够非常好的适用于企业内部的应用程序。
此外还提到了 ASP.NET Web 页面,但仅仅是简单介绍了一下。如果你认为 Web 表单所提供的渲染能力依然无法满足自己的需求,那么可以选择 ASP.NET MVC。但是 Microsoft 针对其较长时间的学习曲线提出了警告。
构建 Windows 桌面程序
虽然所有基于 C++ 的 GUI 工具集(例如 MFC 和 ATL/WTL)都不在列表上,但是最初的 .NET UI 工具集 WinForms 以及 WPF 依然被认为是可行的选项。这两者都支持现代的理念,例如数据绑定和 async/await,同时都能够使用 WCF 或者 SignalR 进行双向通信。
在 WPF 和 WinForms 之间做出选择之前需要考虑下面几点因素:
首先是难度。比起 WPF 来 WinForms 更容易理解,甚至对高级开发者也是如此。WinForms 使用非常简单的数据绑定,同时更喜欢传统的 MVC 或者 MVP 机制。而对于 WPF 而言,用户在能够正确地使用 MVVP 模式之前需要学习一个复杂的数据绑定框架。成功地使用 WPF 还需要了解资源字典、转换器、ICommands 和 XAML 模版引擎方面的知识。
另一方面,如果你还打算把 Windows Phone 或者 Windows 8 商店作为目标平台,那么你需要学习如何使用 XAML。在这种情况下,从 WPF 入手会让你更有可能在不同的平台之间共享代码。
与常见的 WinForms 应用程序相比,WPF 灵活的渲染引擎渲染的外观更漂亮。当然这也是有代价的,在同等条件下 WPF 应用程序通常比 WinForms 应用程序运行的慢。
顺便提一下 LightSwitch 桌面客户端。好像它并不能提供任何可以在桌面客户端中使用的东西,所以似乎没有太多的理由选择它。
应该避免使用客户端—服务器模式
当 Microsoft 谈到“客户端—服务器”的时候,他们实际上指的是那些直接与数据库通信的应用程序。尽管他们承认这依然是一个非常常见的模式,但是他们还是希望新项目使用 3 层设计,在客户端和数据库之间创建一个服务层。与直接访问数据库相比,这提供了更好的可伸缩性,同时还提供了一种可以绕开防火墙及其他障碍物的方式。另外它允许将应用程序移植到数据库驱动不可用的平台上。
"现代化" —放弃 Windows 桌面
对于如何“现代化”桌面应用程序 Microsoft 提供了很多建议。下面的建议大部分是有关于做好将应用程序迁移到其他平台上的准备的,但是即使你并没有打算放弃 Windows 桌面,这些指导对你而言依然是有一定用处的。相关建议的摘要如下:
Android 和 iOS 平台上的 .NET
Microsoft 正在和一些合作伙伴一起努力,以帮助用户实现现代化。下面是针对每一个合作伙伴所必须说的内容:
边注:Microsoft 正在积极推动 Xamarin 和 MonoCross 的事实最终应该会平息一直流传的 Microsoft 打算控告 Mono 制造商的谣言。
大型、关键业务应用程序指南
对于大型企业以及它们的关键业务应用程序而言,焦点不再是成本和生产率,而是复杂性管理和服务的质量。下面的指导方针并不适合数据驱动或者 CRUD 风格的应用程序,从事这种工作的开发者应该参照中小型企业指南。这些指导方针适用于有许多相互联系的部分同时有大量独立子系统的系统。
企业 Web 应用程序
Microsoft 对于这一点的态度是明确的,他们认为关键的 Web 网站应该使用 ASP.NET MVC。唯一的架构问题是是否应该在它上面使用单页面应用程序设计模式。
不推荐使用其他 Web 技术,例如 Web 表单和 Web 页面。因为它们不具备 MVC 的控制性和可测试性,这反过来限制了可获得的服务的质量。
企业桌面应用程序
对于小型应用程序,Microsoft 的推荐列表中依然包含 WPF 和 WinForms。这种场景下他们还增加了 C++ 和 Win32/MFC。Microsoft 推荐在可以与 Microsoft Office 相比的这种大型、长期项目中使用C++。这里的一个假定是 AutoCAD 和 Paint.NET 在规模方面是不同的。
企业 Windows 商店/Windows Phone
对于这一场景,Microsoft 给出的建议类似于“新兴应用程序模式”部分所给出的建议,除此之外并没有其他内容。这样的态度并没有给用户灌输太多的信心,但是也没有彻底地放弃平台。
模式和实践
在指南的最后,Microsoft 并没有继续讨论产品,而是花了大约 20 页左右的篇幅讨论模式和实践。
控制反转
Microsoft 在讨论依赖注入和控制反转容器上花费的大量时间简直令人惊讶。他们列出了 9 个单独的控制反转容器,其中最主要的一个是非附属于 Microsoft 的社区运行的项目。应该注意的是,他们列出的许多框架并不是真正意义上的 IoC 容器,而是依赖注入框架。
Microsoft 并没有在这一部分清晰地表述出自己更喜欢组合根(一种 DI 模式)还是更喜欢服务定位(一种 IoC 容器模式),所以用户对这两者的疑惑依然存在,这相当令人沮丧,因为正如 Mark Seemann 所说:他们在本质上是对立的。
Microsoft 使用了“单一职责模式”证明依赖注入的使用。例如,他们说 SRP 可能会导致一个类的构造函数中有 15 个依赖。为了“解耦”这些依赖,他们建议从构造函数中移除这些依赖,然后使用控制反转容器进行注入。
Microsoft 还提到应使用面向切面的编程添加一些其他的间接层,并且进一步注入依赖。
边界上下文和复杂性管理
为了控制复杂性,Microsoft 花了几页讨论“边界上下文”的概念。据 Eric Evans 所说,它的基本思想是将应用程序分成更小的部分,各部分之间使用有限的共享。下面的例子有 4 个独立的栈,它们使用不同的后端和一个共同的 UI。
Microsoft 在这一部分的建议非常有道理。对于被识别出来作为关键任务的边界上下文,你可以使用更加昂贵的命令、查询职责分离(CQRS)或者领域驱动设计(DDD)模式以及完全的自动化测试。同时,辅助性的边界上下文可以使用轻量级的、CRUD 风格的架构。当然,遗留代码会有它自己的仓库,在那里它们会被隔离并被慢慢替代。
通信和防护
如果想要在边界上下文之间共享信息,那么 Microsoft 推荐尽可能地使用异步消息。这样每个部分就能够独立工作,即使某个部分失败了也不会影响其他部分。对于简单的场景,命名管道和 Microsoft 消息队列是比较容易的选项,而更复杂的系统则需要一个服务总线。Microsoft 提到了 Windows Server 服务总线、Windows Azure 服务总线以及 NServiceBus,但是并没有说更喜欢哪一个。
边界上下文暴露的所有服务都应该有一个防护层对其进行保护。就像应该对参数进行检查以保护公共函数一样,边界上下文的防护层可以让底层的数据存储免受畸形消息的侵害。这一层会验证进入的消息,执行所有必要的转换,并且确保坏数据会被处理和存储。用户可以使用普通的 .NET 代码实现,但是对于复杂的、有很多频繁变化的业务规则的场景,Microsoft 推荐使用规则引擎和集成平台,例如 BizTalk。
处理遗留代码
处理遗留代码的第一步是为其创建一个外观层。该外观层应该使用现代的技术,例如持续的、可扩展的缓存,并且应该隐藏旧代码使用的所有模式。随着时间的推移,遗留代码将会被置换,外观层会被重定向到新的服务层。
结论
Microsoft 推荐使用所有的 .NET 本地、Web 和通信框架,浏览器端的 Silverlight 和 .NET Remoting 除外。在一些场景下他们还推荐使用 C++ 和 JavaScript。像 VB 6 和传统 ASP 这样的旧平台根本没有被提及,所以依然在使用这些技术的公司应该尽快地迁移到新技术上。
不出所料,Microsoft 继续强调了依赖注入,特别是它们与 ASP.NET MVC 及 Entity Framework 的结合。企业试图集成现场和云架构的趋势让 BizTalk 这个一度被认为已经死亡的技术看到了再度焕发生机的希望。
关于作者
Jonathan Allen 从 2006 年开始就一直在为 InfoQ 撰写新闻,他现在是 .NET 专栏的责任编辑。如果你想为 InfoQ 撰写新闻或者教育性的文章,可以联系他:jonathan@infoq.com。