ThoughtWorks技术雷达(2013年5月)
技术
多年来,团队和组织都已经看到了围绕技术学科进行专业细分的危险性。当我们就高级应用听取专家的建议时,开发人员至少应当了解用户界面,数据库和数据科学等业界新宠的基础知识。当高级应用需要深入的专业知识时,我们要在所有开发人员使用基础统计分析理论和工具的领域,推动协作分析与数据科学,以此做出更好的决策,并在事情愈趋复杂时,开展与专家的密切合作。
技术趋势已经冲破了原本保护着企业IT网络的围墙,成为没有边界的企业。员工们频繁使用自己的消费设备通过云服务和Web API访问企业数据,而企业往往对此并不知情。随着设备不断扩散以及更多的应用程序迁移到云端,迫使企业重新考虑数据访问和网络安全的基本假设。
在云端搭建的开发环境意味着开发的基础设施能够外包,开发人员只需要一台笔记本电脑和网络连接。通过组合使用最佳的服务,如GitHub的私有资料库加上云端的Snap CI持续集成环境,你的团队也许永远都不再需要为自建IT基础设施而劳神了。
廉价或免费的视频会议工具,质量正在不断改善,选择也越来越多,让分布式团队有了一种全新的工作方式。即便团队分散在各地,全天候(Always-on)视频连通也可以帮助建立一种虚拟的临场感。事实上,这已经成为我们部分离岸交付中心的标配。我们还看到像ScreenHero这样的屏幕共享工具已经开始被广泛用于远程结对编程。但我们也必须警惕寻找银弹消除物理上同处一地的需求,毕竟没有什么可以替代面对面沟通时所产生的相互理解和情感交流。
一旦开始使用一件全新的工具,管理不同环境的部署,或者尝试着理解应用程序的行为为何在不同环境表现各异,对应用的配置就会成为痛苦的根源。作为最小化应用配置的拥趸,我们正尝试去保证应用能在最小配置下能够正常工作。
多数虚拟化技术都提供了通过加载镜像启动虚拟机的方法。在构建管道中要尽早创建虚拟机镜像作为构建产物, 随着它通过后续的测试套件对其进行提升,如此就能实现从测试环境到产品环境机器上的可靠部署 。此技术剔除了导致snowflake server*(注释)反模式的多数原因。
蓝绿部署(Blue-green deployment)是一种执行软件升级的模式。首先,将最新版本的应用部署到一个和当前产品环境完全一样的应用栈副本中。这样,当新版本的应用通过了相应的测试并得到了业务上的许可后,访问就可以被瞬间切换这个新版本的应用上。尽管这不是一项新技术,但基础设施自动化和云端资源使它值得被重新考虑。
以前,像Chef和Puppet这样的工具都缺乏对Windows的支持,导致构建简单的基础设施自动化任务都需要大量的Powershell脚本。所以,想要使Windows到达和Unix一样的自动化水平可谓困难重重。不过在过去的一年里,Chef和Puppet对Windows的支持得到了很大改善。这种支持与强大的PowerShell相结合,使得Windows基础设施自动化极为可行。
HTML5存储,也被称为本地存储或Web存储,是一种在现代浏览器里存储客户端数据的机制,其中也包括iOS和Android移动浏览器。 在几乎所有情况下,我们都建议使用HTML5存储,而不是cookie 。 HTML5存储最多可容纳5MB的数据,而cookie则被限制在4KB。 Cookie的数据在每一次请求中都会被发送,这会拖慢你的应用程序,并且有可能将数据暴露于不安全的HTTP连接中。 与此相反,HTML5存储只需要由浏览器来保证数据安全。 Cookie则只应该用来保存像session id这样的简单数据。
使用Promise进行异步编程是一项古老的技术,也被称为futures。由于JavaScript在客户端和服务器端的的广泛使用,它又再次得到了关注。这项技术消除了深层嵌套回调、标志位和轮询,同时得到了像jQuery库的一等支持。如果项目涉及到非常复杂的JavaScript代码库,团队就应该利用这项技术。
捕获客户端JavaScript错误,已经被我们的交付团队用来识别与浏览器或插件配置相关的影响用户体验的问题。在过去一年中,一些服务提供商业已开始对这一需求提供支持。除了将这些错误储存于应用数据存储中,一些Web应用还会将这些错误记录到网络分析工具,或像New Relic这样监测工具中,以减轻存储的需求。
随着HTML5模糊了传统本地应用和Web应用程序之间的界线,我们正开始试验移动设备上的持续交付。 如TestFlight服务可让你在一天内多次部署本地应用程序到实际设备上。对于全部或部分基于HTML5的应用程序,可以直接部署修改,而无需向应用商店提交一个新的应用。如果你的组织有企业内应用程序商店,就可以轻松的发布应用。我们注意到,当移动设备上的持续交付技术实现不断改进时,测试实践则相对落后。要取得成功,你需要更加专注于自动化测试,以确保应用被部署到设备上时能够正常工作。
我们越来越多的看到移动应用在开发和测试过程中工作良好,但在发布出去后却问题多多。移动网络的移动测试(Mobile testing on mobile networks)揭示了应用是如何在不同条件下运行的。你可能需要测试3G,LTE,或者故意使用一个访问超载的糟糕的WiFi网络。先获取目标环境下的网络性能,然后用延迟和丢包诱导工具去模拟相同的环境。 此外,使用像Wireshark这样的工具去检测你的设备和软件到底如何使用网络,有时也是必要的。
NoSQL数据存储正继续成为主流,但团队需要充分认识到对迁移数据库到NoSQL的需求。特别是使用隐式或动态schema,你可能会随着时间的推移需要重新配置数据。这里提供了几种方法:比如在部署新版本应用时进行显式地迁移,或者通过代码在加载和处理文档时进行动态迁移。
失败的测试揭示了产品代码中的bug。然而,针对其他属性进行分析性测试则可以揭示一些有趣的信息。 一个简单的例子是监测频繁失败的测试,然后在构建管道中尽早运行它们,从而快速得到反馈。同理,跟踪其他属性,如测试执行时间和耗时测试的比例,也可以为达成快速测试提供可操作的指标。
在以前的雷达中,我们曾经建议延长自动化验收测试的周期,在我们称之为语义监控(semantic monitoring)的阶段,不断在产品环境中运行这些测试。 现在我们仍然相信,这是一项使团队可以提前预测情况的重要技术。但现在, 尤其是在初创公司中, 我们还看到这种方法的一个变体, 就是在减少测试次数的同时,增加监控与自动报警。这使关注点从避免可预见的问题转移到对所有问题减少平均的恢复时间。
虽然单元测试和验收测试被广泛接受并作为标准的开发实践,但这一趋势还没有延伸到性能测试领域。目前,常用的测试工具促使测试人员养成编写一次性代码, 对点击进行脚本化的心态。 给予性能测试一等公民待遇,可以创造更好的测试,涵盖了更多的功能,引导出更好的工具来创建和运行性能测试,从而使得测试套件可以被维护,并能自我测试。
平台
PostgreSQL 正在逐渐成为SQL数据库中的NoSQL选择。版本9.2支持存储JSON格式的数据,并在其之上提供完备的查询功能。另外,PostgreSQL还提供了允许用户以键值对(key/value pair)的形式存储和查询数据的扩展。该扩展让你可以直接利用稳定的数据库底层存储和事务的能力, 而无需绑定在关系数据模型上.对于那些希望同时开发SQL和NoSQL应用,却又倾向于使用一套他们熟知的可靠基础设施的开发者而言,提供这一特性就再理想不过了。
网站的访问量即使再低,其产生的数据量也可能是巨大的。一旦你把各种分析结果,业务图表, 统计数据,用户资料以及对多设备的支持囊括进来,数据量可能会大到难以想象。许多组织使用数据仓库来存储从各部门收集上来的数据。这样做的挑战是数据仓库会变成一座“数据森林”。即使是获取及时的业务图表也已变成一种挑战,更别提在整个数据集上运行探索性查询了。而基于BigQuery之类的云技术对此会有帮助。它们即时付费的模式和可以运行任意查询的能力使你无需购买特殊的软硬件也能获得对数据的全面掌控。数据驱动的商业模式应该将数据送到决策者手中, 而不是隐藏在技术障碍和官僚主义中。
对于适用文档数据库模型的问题来说,MongoDB是当下最流行的选择. 除了易于使用和提供高可靠性的技术实现之外,开发社区及整个生态系统对其成功也贡献良多。我们也听说了一些团队抵受不住MongoDB流行的诱惑而产生了问题,比如并不适用文档数据库的应用, 又或者团队没有充分理解其内在的复杂性。然而若能用对, MongoDB已经在很多项目中证明了自己。
Redis 已经在多个ThoughtWorks项目中被证明是有用的工具。它被用作结构化的缓存或者跨越多个国家的分布式数据存储。
Hadoop最初的架构基于水平扩展数据,垂直扩展元数据的模式。 尽管slave节点可以从容的进行数据的存储和处理,管理元数据的master却是瓶颈,同时也限制了规模化网络的使用。Hadoop 2.0 重新设计了HDFS和Map Reduce框架的架构,以此来解决这些问题。现在,HDFS的命名空间可以通过使用同一个集群的多个name nodes来联合在一起,并且部署为高可用性(HA)模式。 MapReduce也被YARN取代了。YARN解耦了集群的资源管理和任务的状态管理,并且通过JobTracker消除了伸缩性和性能问题. 最重要的是,这些变化鼓励在Hadoop集群上开发除了MapReduce之外的分布式计算模型。
在过去的一年中,我们发现采用Elastic Search(弹性搜索)作为开源的搜索平台呈逐步上升趋势。Elastic Search基于Apache Lucene, 是一个可扩展的,多租户的, 支持水平伸缩的搜索解决方案。它允许索引复杂数据, 并可通过JSON获取。它支持从集群, 故障转移及备份中自动恢复各节点。Elastic Search可以通过基于插件系统的REST API来扩展,它提供了一个优雅的操作模型, 允许添加新功能, 或者改变现有行为。围绕着Elastic Search的社区是非常活跃的。一个证据就是已经开发出了包括Java、 C#、 Ruby 和 JavaScript 在内的多个客户端类库。
Node.js 是一个轻量级web容器。它在开发微服务, 移动服务端以及单页面web应用方面都是极好的选择。因为其天然的异步特性, 开发人员可以通过使用promise类库来简化应用代码。 随着在node.js社区promise应用的成熟, 我们期望看到更多为node.js开发的应用。 对那些不愿在产品环境中尝试node.js的团队, 用node.js来实现一些开发任务仍然值得考虑, 比如在浏览器之外运行JavaScript测试, 或者从类似CoffeeScript, SASS和LESS之类的工具中生成静态web内容。
Zepto.js 是一个轻量级的JavaScript类库。它的API与JQuery相同, 但并非100%兼容.因其压缩显著的文件大小, Zepto在开发响应式web应用方面颇有竞争力。
PhoneGap, 现在叫 Apache Cordova, 允许你使用HTML, CSS和JavaScript 来开发跨平台的移动应用。它通过一组JavaScript API对平台特定的本地代码做了抽象, 同时还保持了不同移动平台之间的一致性。Cordova支持非常多的平台, 包括iOS、Android、 Blackberry、 Windows Phone 以及 WebOS。
在云存储和云计算领域, 尽管AWS还在持续的增加功能, Rackspace Cloud 却悄悄发展为一名不可忽视的竞争者。部分用户会非常看重Rackspace更加周到的客户支持, 以及混合多种传统托管模型的能力。 我们并不为之而感到激动人心,因为Rackspace是我们的客户, 我们在参与该平台的开发过程中已经收获了许多乐趣。我们在另外多个客户的项目中已经成功地应用了Rackspace Cloud, 目前正期待着它能辐射到更多的地区。
开源OpenStack项目的发展可谓蒸蒸日上, 在最近几个月,它已经逐渐成为部署私有云的不二选择。 许多原来导致OpenStack难以使用以及运行不稳定的问题都得到了解决. 新功能也一直都在增加。显然,OpenStack联盟包括它的成员如Rackspace,Redhat,HP等都在不断为其添砖加瓦, 并以此作为自有的基于OpenStack的云服务基础。
在去年全球售出的手机中, 58%其实是老式的功能手机, 而非智能手机。 在很多发展中国家, 这一比例甚至更高。如果你的客户需要你为这些地区开发应用, 你需要考虑到这些限制。这些手机使用SMS和USSD作为用户界面。SMS是存在已久的发送消息的技术, 而USSD允许你通过安全会话来发送SMS之类的消息。你应该把SMS和USSD看做另外一个UI和UX的平台, 给予它们一等公民的待遇。
Vumi是一个可伸缩的开源的消息引擎。 它在移动设备上通过一些廉价的方式来完成通信。 Vumi帮助公司和它们的客户, 医疗服务机构和它们的病人, 政府和市民, 以及更多的团队之间通过SMS , IM 和 USSD进行交互. Vumi与电信公司进行了集成, 使你能够很容易的基于它构建应用, 而你只需要向运营商支付通信费。
“企业级”商业软件包提供的功能, 和实际需要的功能之间的差距正在拉大。这对面向互联网的应用来说更是如此。那些真正能够扩展自如的创新方案, 易于支持的现代技术如持续交付等, 都是实践者写给实践者的。它们肇始于许多互联网规模的公司, 而后作为开源软件得到了提炼。庞大的企业解决方案通常会阻碍高效的交付,因为这些方案经过长久累积,具有臃肿而繁琐的许可限制;它驱动出来的功能集来自于检查列表,依靠假想出来的脱离多数团队开发现实的需求。
工具
在上期的技术雷达中,我们谈到的嵌入式servlet容器。如今,这已经在我们的项目中广泛采用。像 SimpleWeb 和 Webbit 这样的工具在追求简洁和嵌入式的方向上更进一步,提供了未实现 Java Servlet 规范的原生HTTP 服务器功能。同时,最流行的 Java 应用服务器 Tomcat 在嵌入式安装中应用的逐渐增多,以及微软为 .NET 框架提供的自托管服务器,都加强了这一趋势。
D3 作为一个用来在浏览器上创建丰富可视化效果应用的 JavaScript 库,也在持续获得更多的关注。此前,使用 D3多少 显得有点底层, 比起那些更简单更有针对性的库,它需要更多的工作量完成常用的可视化效果。自从发布了上一次技术雷达,随着诸如用于图表的 Rickshaw 以及用于在浏览器中进行数据探索的 Crossfilter 等库的出现,使得 D3 比以前更容易使用了。
我们看到一些 JavaScript 框架正在拥抱基于浏览器的模板化的趋势,它们把更多的布局工作转移到客户端来做。虽然这种方法在很多情况下很有效,但它也会引入一些涉及缓冲、性能和搜索方面的运营问题。我们认为在使用这些工具前,需要仔细对这些工具进行评估,以确保满足目标部署环境的要求。
通过把 IObservables 和 IObservers 放到与 IEnumerables 和 IEnumerators 同等的地位上,.NET 上的响应式编程框架 Rx 允许开发者通过observable事件流的通用底层抽象,使用已有的 LINQ(Language INtegrated Query) 操作符,来查询和编写异步操作和基于事件的代码。
微软也发布了 RxJS 库把响应式编程的好处带到 JavaScript 中。整个 Rx 框架的开源,也使其在 Windows 富客户端应用和单页面 JavaScript 应用中发挥更大的作用。
一些 ThoughtWorks 的团队特别提到 Ruby 的 HTTP 客户端类库 Faraday 的实用性。它为各种适配器提供了通用的接口,并且和Rack 中间件有良好的集成。
针对第三方库的包管理系统继续在所有平台上获得认可,也都在不断添加新的功能。我们最近把 NuGet 和 Chocolatey NuGet 列入到技术雷达,也证实了这个重要的敏捷工程实践的先进性。
基于Windows的基础自动化应该采用,然而仍然要比在 Unix 上进行基础设施自动化要困难得多。Chef 和 Puppet 正在增加对 Windows 基础设施自动化的支持,同时也有正在研发中的像Octopus这种专门针对 Windows 的解决方案。Octopus 可以在自动部署 ASP.NET 应用程序和 Windows 服务时减少对 PowerShell 的依赖。它也可以与 NuGet 和 TeamCity 一起使用,以此创建一个完整的构建、打包、部署管道。
Puppet 和 Chef 都需要处理社区针对通用服务和任务而共享的module和manifest。Puppet Forge 和 Chef的Cookbook 资料库能在一定程度上解决这个问题,但结果是人们总是复制和粘贴这些脚本到自己的代码中,这样他们就不能享受到最近的错误修正和改进的好处。Puppet-librarian 和 Chef-librarian 通过让你更容易地声明自己的模块依赖关系,试图解决这个问题。其做法包括从这些社区网站取得已知版本的代码。
在分布式系统上的依赖关系管理非常复杂,这也是越来越多人在迁移到细粒度的微服务(micro-services)时所需要面对的问题。来自 Netflix 的 Hystrix 是一个实现了处理各种下游故障模式的 Java 类库,它提供连接的实时监控、缓存和批处理机制,以更有效地管理服务间的依赖关系。
不需要应用程序商店,TestFlight 和 HockeyApp让你能够管理移动应用程序的部署,让用户测试更容易。它们提供了崩溃报告和实际数据分析的能力。HockeyApp 支持 iOS、Andriod 和 Windows Phone 平台,而 TestFlight 只支持 iOS 和 Android 平台。我们已经成功地使用这两种工具来帮助移动应用程序的发布。这显然是一个快速发展的领域。
Frank是一个开源库,可以使用Cucumber 编写iOS 的功能测试,并在远程设备上执行。
以前在 iOS上,验收测试驱动开发非常麻烦,该库填补了一项重要的空白。
UIAutomator允许测试时对用户界面组件的细粒度控制,以及为在多个设备上的测试提供帮助,因此被认为是Android 用户界面测试方面最有前途的工具。
随着具有多种外形因素和像素密度的设备的兴起,呈现全尺寸高品质图标的问题已经变得非常重要。图标字体利用浏览器对WebFonts和SVG的支持,而不是使用缩放图像或维护不同的图标集,解决了这个问题。但当大量使用 SVG 时,需要注意移动设备的功耗问题和旧设备上的性能问题。
随着我们构建的系统比以往涉及越来越多细粒度服务,分布在越来越多的机器上,如何获得集中的信息以便更方便地识别和解决问题,比以往任何时候都更具挑战。Logstash已经成为一种解析和过滤日志再将它们转发到单一聚合节点的简单方法。虽然 Logstash 也提供了一些日志的搜索和过滤功能,但配合Graylog2使用,能提供更全面的日志查询和报告功能。
我们认为 Snowplow Analytics 在网络数据分析方面具有远大前景。它是一个开源网络分析平台,基于公开数据原则和云存储,并能从常规的网络分析中得出智能信息。
我们在 ThoughtWorks 的项目中看到对 PhantomJS 的兴趣,它是一个针对现实目标进行功能测试的 headless 网络测试工具。
Gatling 是另一个在自动化性能测试领域的新成员。它和 Locust 类似,都比传统的 JMeter 和 Grinder 更轻量级。Gatling 的DSL构建在Scala基础上,提供了易配置的数据源和响应断言等广泛的开箱即用功能。在需要个性化配置时,也可以很容易直接使用Scala 来进行扩展。通过 Highcharts 默认生成数据的各种动态视图的功能,更增加了它的吸引力。
许多已经迁移到敏捷工作方式的组织还在继续使用重量级的测试工具。这些工具并不适合快速发展的软件交付。重量级测试工具较陡的学习曲线及对专业技能和培训的要求,使团队很难使用这些工具来进行测试。通常这会导致随着其他团队的加入,对于每一个版本的发布都造成不必要的开销。这些工具昂贵的软件授权费用更加剧了这个问题。一些重量级的测试工具使用“模型驱动”的方法,试图精确地对应用程序的使用模式进行建模,但软件缺陷的误报却导致测试脚本昂贵的的开发和维护代价。其实我们经常看到一些简单的开源解决方案能以少得多的时间、精力和预算,给予对所要求的软件质量的信心。
基于语言的构建工具 Gradle 和 Rake 继续提供比Ant 和 Maven 等基于XML和插件的构建工具更细粒度的抽象和更灵活的长期解决方案。这使得它们在项目变得更加复杂时,还能保持优雅的增长。
我们继续看到尝试使用 TFS 作为版本控制系统的那些团队遭遇到生产力下降的问题。那些团队在实践作为持续集成核心部分的频繁代码提交时,发现TFS重量级的方式显著降低了生产效率。这往往导致团队更少地进行代码提交,导致产生诸多问题的代码合并。我们建议使用 Git、Perforce和 Subversion。
语言和框架
随着支持数据绑定、客户端模板和校验等功能的框架的蓬勃发展,单页面Web应用开发继续高歌猛进。在ThoughtWorks, 诸如AngularJS、Knockout和 Ember.js 这样的 JavaScript MV* 框架有着广泛的应用,且各有其倡导者和反对者。我们期望在此充满活力的领域有更多的创新。
随着基于Node.js的服务器端应用程序的持续增长,单页面应用和基于移动浏览器的应用渐渐融入主流, CoffeeScript 也因其能简化 JavaScript 代码而越来越多地得到采用。作为一种将源代码编译成 JavaScript 代码以供运行时执行的语言,CoffeeScript应用程序的调试难度备受关注。CoffeeScript 1.6.1 引入了 Source Maps 以帮助开发工具生产厂商解决这个问题,同时,像Dropbox 这样的著名技术公司也开始使用 CoffeeScript,我们预计它将获得更广泛的应用。
我们在新产品中对node.js的使用越多,对可靠的 JavaScript 包管理工具的需求就越迫切。Node Package Manager(npm)作为 node.js 应用的打包工具,是其生态系统的重要组成部分。对于要面对大量 JavaScript 或 CoffeeScript 代码的浏览器应用开发人员来说,应考虑使用 Require.js 组织代码结构以及在运行时装载依赖。
在客户端和服务器端,微框架正成为解决应用程序复杂度日益增加问题的新兴方式。Sinatra正是这一领域的先驱,它能够使用轻量级DSL在服务器端构建快速的、易于组合的服务。其它语言也有类似的框架,例如Java平台下的Spark、Python语言的Flask、面向Scala的Sclatra、基于Clojure的Compojure 和 .NET平台下的Nancy。
在.NET平台上,构建一个多样的、开源的Web开发生态系统始终步履维艰,原因之一就是对IIS和ASP.NET 框架的过度依赖。OWIN之于.NET平台,正如Rack之于Ruby 社区,它定义了一个开放的HTTP操作接口,从而将Web服务器从应用程序中解耦出来。我们为此激动不已,因为OWIN打开了一扇大门,使得在.NET平台下诞生简单的、可独立开发模块的Web开发工具成为可能。Nancy 正是一个利用这种可能性的完美例子。我们也希望它能促使人们在.NET平台下将web应用程序部署为单独的、自托管服务方面进行更多的实践。
最近发布的Play Framework 2.1.1 支持控制器依赖注入、异步、非阻塞I/O、Code - Reload工作流、数据库迁移、资源管道以及灵活的部署选项,这些特性对开发者产生了更大的吸引力。基于这个原因,Play重新出现在我们的技术雷达上,我们希望团队在 JVM 上构建 Web 应用程序和服务时,认真考虑选用 Play。然而需要提醒的是,Play 使用了函数式编程风格,在结合使用 Java 时, Play 会产生过多的静态方法,因此很难在运行中的服务器外围进行单元测试。
和 JavaScript、HTML 一样,CSS 是构建网站的核心技术。很不幸,CSS 本身缺乏一些关键特性,这导致代码具有高度重复性并且缺乏有意义的抽象。虽然 CSS3 旨在纠正其中的一些问题,但要等到大多数浏览器都正确支持 CSS3 ,恐怕还需很多年。幸运的是,通过 SASS,SCSS,LESS 这样的 CSS 框架可以帮助解决这个问题。基于这些框架的质量和相应支持,我们相信,除非需要细微的样式调整,手写 CSS 的时代已经一去不复返了。
CSS 框架简化了大规模 CSS 代码的开发,而无需每次都从头开始。面对琳琅满目的各种框架,选择一个支持持续增强与维护,而不仅仅是能够快速上手的框架就显得尤为重要。就这一点而言,基于 mix-ins 的框架如Compass,或者Susy这种有针对性的框架,将是更合适的选择。
Twitter Bootstrap 是一个流行的 CSS 框架, 它可以帮助你快速构建流畅的、具有响应式布局(responsive layouts)的精美网站。基于我们长期的使用经验,在此版技术雷达中,我们把 Bootstrap 从试用阶段移到了评估阶段。如果想要替换或定制应用程序外观,其与 HTML 标记的深度集成将成为需要面对的挑战。但这并不妨碍你选择Twitter Bootstrap,只是做决定时需要考虑到这些限制。
感谢张凯峰对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新 浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我 们,并与我们的编辑和其他读者朋友交流。