zoukankan      html  css  js  c++  java
  • 《软件框架设计的艺术》试读:2.1 分布式开发

    无绪的模型需要利用全世界范围的软件项目中大的组件模块,以装配的方式来开发应用程序。要尽可能多地复用,而不要从零开始编写软件,这样就可以保证产品团队能将重点集中在软件的独特功能上,即应用程序的具体业务逻辑上。这样,开发人员就无需花费时间去创建和编写基础设施,重用现有的框架和由第三方提供的功能库即可。相信现在不会有人因为自用的原因去写一个SQL数据库服务器软件,而是会使用一些商业或者开源的数据库。创建一个私用的数据库可以说是一种低效的资源浪费。对于软件技术的其他领域也是如此。Web服务器、编程语言及其功能库、集成开发环境还有富客户端程序框架①都已经有设计良好的组件可供使用了。就像活动板房,只需将其各个组件从架子上拿下来,组装到一起,并根据需要适当抛光即可。这种模式极大地缩短了软件产品的开发周期。

    在组装应用程序的时候,需要将各个独立的模块整合在一起。这些模块之间需要相互通信,通常来说,是通过定义好的API来完成的。每个组件的API都能增加你迈向无绪的步伐。不必了解组件内部机制,只阅读该组件的文档,调用其API就能够使用该组件的功能。利用API可以避免去了解第三方组件的细节。

    抽象也会泄漏天机

    API可以被看作是对功能和组件内部实现的抽象。通常来说,外部人员只要了解抽象即可,但在某些情况下,一个API也可能会“泄漏”内部组件实现中的一些信息。来看一个文件系统抽象的例子。通用的文件系统将文件和目录以树状的层次结构组织在一起。在获得一个资源以后,可以访问其内容②,或该资源的子资源。资源的内容通常是使用流方式③来提供的。现代操作系统几乎都使用了这种方式来支持对文件内容的访问。这样在开发时,程序员就不需要去关注实际的存储和文件系统的类型。在读取文件时,不需要知道该文件是放置在硬盘驱动器、光盘、闪存盘中,还是网络上。不同的存储介质以这种通用的抽象提供了一致的处理方式。

    然而有时候,API却会把这些具体实现的相关信息泄露出来。比如说,在读取闪存盘上的内容时,可能会因为用户拔下了闪存盘而使得正在访问的资源突然消失了。或者在使用网络存储的时候,可能会因为网速很慢或者网络性能差,使得文件资源的访问有很长时间的延迟。在这种情况下,开发人员不仅要了解抽象的信息,可能还要了解具体实现的部分内容。

    但从“针对性无绪”的角度来说,这样做也是可以接受的。这种通用的API只是一个基本的抽象,它提供服务,只要用户不在意网络延迟,或者移去闪存盘时引起的崩溃。如果你在意,还有一些高级的方式来检测处理这些情况。因此文件系统API可以让程序员做到无绪,而且也不会影响我们在必要情况下深入了解系统信息。任何一个对外提供功能的API都应该做到这一点。

    一个典型的应用程序不仅仅是由一个或者几个类库组成的。当今开发的应用程序,会用到全世界开发人员提供的很多开源功能库,这些开源贡献始于Unix内核、C语言基础功能库和命令行工具。发展至Web服务器和Web浏览器,以及Java实用程序,如Ant、Tomcat、JUnit和JavaCC等。事实上,每个类库都有自己的API ,因此每个写这种软件的人都在从事API的设计,不论他自己意识到没有。

    对于各种Linux发布版来说,将模块集合在一起打包,然后发布出去,这是常见的一种组装方式。软件是由不同的人编写的,然后再通过编译、打包,最终整合在一起。通常,不同Linux版本的发行商只需要写一个中心管理器的模块,用来提供质量保证,让所有选中的软件都可以正常运行。对于大部分供应商和用户来说,这种方案行之有效,能够降低创建Linux分发版本的成本。这种模式还有一个成功的案例,就是Mac OS X系统,它是在一般FreeBSD Unix版本上添加了一些由Apple公司开发的功能模块。

    分布式开发自有其特殊之处。最大的不同就是,整个程序的源代码已经不再完全处于开发人员的控制之下,而是散布于世界各地。与完全基于内部代码仓库④中的源代码来构建一个程序相比,这种构建软件的方式是明显不同的。

    我们需要认识到,在这种开发模式下,产品的开发进度是无法全面掌控的。软件的源代码和开发人员都散布在全世界,而且开发人员各有自己的进度安排,所以项目领导者对此无法一一掌控。猛一听,感觉项目完全不可控,但真实情况并不像乍听起来那样危险。任何一位项目领导者,只要其带领的团队超过50人,那么他一定明白,所谓的全面掌控往往只是一种理想状态。在开发过程中,考虑到时间、资源等因素,有时不得不砍掉某个功能或者发布一个老一点的版本⑤。对于分布式开发模式来说,每个人在使用功能库的时候都可以自由选择使用老版本还是新版本。

    事实上,要设计良好的API,开源并不是唯一驱动力。商业组织也提供了大量共享的功能库和框架。还有不少公司提供了一些现有标准的具体实现产品,如各大数据库厂商的产品都支持SQL标准,还有一些厂商提供了自己的API⑥。带有自由许可证方案(liberal licensing schemes)的开源运动已经成为组件的首要来源,这些组件可以作为可复用构件来使用。最终用户知道很多开源软件方案,不需要支付任何费用即可使用。而且开源软件没有许可权的限制⑦,这对于开发人员来说也是很重要的。很容易就可以根据自己的需求来找到一个组件,然后把这个组件用作自己应用程序的一部分。迟早会有人这么去做。这也说明每一个开放源代码的组件迟早都应该有一个API。这些通用的组件是由各类程序人员开发的,可能是刚开始做项目的大学生,也可能是能够投入大量时间在某个项目的开发人员,还有可能是某些公司专门雇用的开发人员,他们看到了开源软件的商业机会。这些开发者有着不同的开发技巧,不同的开发方式。无论如何,设计优秀的API是一件非常重要的事,因为API是无绪使用库的开始。类库和框架这类东西自然是越多越好。但要想让无绪重用能够成功,就必须让API体现库的内在功能。这就是为什么API的设计如此重要,成为本书写作的主要动机。

    ① 即Rich Client Platform,缩写为RCP。——译者注

    ② 如果是文件,就访问文件内容,如果是目录,就访问其子资源。——译者注

    ③ 在Java中,即常用的InputStream和OutputStream。——译者注

    ④ 这里的代码库其实就是暗指常用的版本管理系统。——译者注

    ⑤ 指到了指定版本发布时间,可能最新的版本尚不能稳定或者目标没有达到,所以不能正式发布,只能将前一个内部的稳定版本发布出来。——译者注

    ⑥ 如JDBC和ODBC都需要对外API。——译者注

    ⑦ 原书是这样说的,但事实上,开放源码并不是意味着就可以免费使用,很多开源软件都是双协议,对开源软件或者非商业软件都是免费的,但商业用途并不免费,如著名的Ajax框架Ext,所以原书中说的并不是很准确。

    ——译者注
  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/shihao/p/2146376.html
Copyright © 2011-2022 走看看