小钢的架构思考:架构规划

原创文章,转载请注明:转载自Keegan小钢
并标明原文链接:http://keeganlee.me/post/architecture/20160509
微信订阅号:keeganlee_me
写于2016-05-09


小钢的架构思考:什么是架构
小钢的架构思考:架构规划
小钢的架构思考:架构设计


上一篇简单聊了下什么是架构,还将架构划分为三个阶段:规划阶段、设计阶段和构建阶段,构建阶段其实也是架构实现的阶段。其实,三个阶段的界限并不明显,而占比最多的是设计阶段;而且,规划和构建阶段其实也会有设计。也可能因此,当我们谈到架构的时候,更多是在谈架构设计。但仔细想想,三个阶段的划分确是合理的。本文先聊聊架构规划。

架构规划

架构规划做什么呢?我觉得主要是规划好下个阶段架构设计的边界。而影响架构边界的,其实就是需求。需求形成了对架构的约束条件,从而也对架构设计形成了边界。那么,有哪些需求呢?可以分为三大类:商业需求、功能需求和质量需求。

商业需求

商业需求是最高层次的需求,对其含义,我比较赞同温昱在《软件架构设计》中提到的解释:它关注从客户群、企业现状、未来发展、预算、立项、开发、运营、维护在内的整个软件生命周期涉及的商业因素,包括了商业层面的目标、期望和限制等。商业需求一般对架构的影响比较大,对架构产生限制的商业因素也比较多,在此列举一些比较常见的:

  1. 上市时间:上市时间限定了系统从设计、开发、测试到上市的时间边界。之前我跟进过一个垂直于大学生市场的应用,上市时间就要求在新生入学前,不然就会错过推广的最佳时期,预留给开发的时间只有两个月。因此,我们只好大部分重用前个项目的元素,包括重用服务端的一些模块,还包括客户端的架构和界面。当然,一般情况下,预留给开发的时间不会这么短,但也不会特别长。架构师需要根据时间长短,平衡各方面需求,做好架构选型。
  2. 成本预算:成本预算就限定了能使用的资源边界。不同架构的开发成本肯定不同,要满足更多功能需求和更多质量需求的架构成本也更高,在预算有限的情况下,只能权衡各种需求,优先满足重要程度高的需求。
  3. 人力现状:100人的开发团队和10人的开发团队,软件的架构会有很大不同。另外,开发团队人员所掌握的技术也会对架构选型有影响。例如,团队里还没有人会用React Native,那现阶段就不适合选择React Native作为App架构的技术基础。
  4. 与外围系统的集成:当需要与外围系统集成时,需要认真考虑集成方法,尤其是外围系统比较老的时候,集成难度可能更高。另外,外围系统的不可控因素一般也比较多,因此,对架构处理这些不可控风险的要求相对也高。
  5. 开放性:封闭的私有系统和开放式系统对架构的要求也不同,一个系统如果选择了开放,那对架构的质量要求更高,对安全性、扩展性、性能等质量属性都应该比封闭时高。
  6. 目标市场:目标用户10万、100万、1000万,不同级别的目标市场,架构也是大有不同。另外,大众市场和垂直的专门市场,架构也同样有区别,较大的专门市场一般都采用产品线的规划方案。
  7. 多端支持:现在移动端普遍支持Android、iOS、Wechat,管理端通常则支持PC Web,如果管理端也要支持Android、iOS、Wechat,或者移动端和管理端还要再支持WindowsPhone、黑莓,甚至再支持VR,则需要投入更多时间和人力,架构上相应也需要做出调整。
  8. 期望的系统生存期:从主观上说,谁都希望自己的系统可以生存很久,但生存期越长,意味着系统的可修改性、可扩展性、可移植性等需要更高。但是,受上市时间、成本预算等因素的制约,再加上软件本身的变化快,所以,客观上,一般也不会期望其生存期太长。当系统不能满足渐增的需求时,基本通过重构来解决。
  9. 阶段性计划:每一个大平台系统普遍都是分阶段完成的,因此,前期阶段的架构设计时就需要考虑好重用性、扩展性、伸缩性、移植性等特性。但因为每个阶段经过市场验证后,需求有可能会变化,所以又不能过度设计,否则就会造成设计浪费,还可能加大了后续阶段架构调整的难度。
  10. 国际化:如果走国际化路线,那架构上就要考虑好对多国语言的支持。
  11. 竞争对手:产品要比竞争对手优秀,那就要在一些关键的功能或质量上超越对方,也意味着在这些方面的架构需要投入更多。
  12. 法律法规:比如,对某些关键字要进行过滤屏蔽,这是天朝独有的,大家懂的。

商业需求多种多样,有些需求还可能会相互矛盾,比如,上市时间和成本预算就会和期望的系统生存期可能产生矛盾,期望的生存期越长其成本就会越高,需要投入的时间就会越多,那么,就有可能拖延上市时间。因此,做架构规划时,必须梳理清楚哪些需求是能够被满足的,能被满足的程度如何,需要在各个需求间权衡利弊。另外,商业需求因为是最高层次的需求,因此,相对于功能需求和质量需求,其优先级一般也比较高。

功能需求

功能需求描述了系统应该提供的服务,包括为用户提供的服务,也包括为其他系统提供的服务。而架构主要就是为功能服务的,而功能需求基本与具体的业务相关。因此,要做好功能需求这块的架构,就必须对该业务领域足够了解,这样才能更好地抽象建模。对功能需求的架构规划,主要就是建立业务领域模型。领域模型定下来后,下个阶段的设计必须与领域模型保持一致。

而对功能需求进行领域建模之前,还需先梳理下需求的优先级。因为受商业需求的影响,功能需求也需要权衡。比如,上市时间紧、成本预算低、人力资源也不是很充足的情况下,功能需求只能少不能多。而需要与外围系统集成的时候,也意味着这部分功能不需要自己实现了;但是,如果外围系统无法完全满足需求时,则还需要自己再实现缺失的需求。因此,现阶段需要满足哪些功能需求?需要满足到什么程度?这两个问题确定了之后才能更有效地进行领域建模。

领域建模主要就是要分析清楚每个领域模型和模型之间的关系。还是直接用一个例子来说明吧。假设现在要做一个支持O2O(Online To Offline)的电商平台,以下是经过梳理后的几个关键的功能需求:

  1. 商家可以在平台发布商品,可以是实体类商品,也可以是服务类商品。
  2. 实体类商品支持快递,服务类商品只能到商家门店兑换消费。
  3. 用户购买实体类商品时需提供收货信息。
  4. 用户购买每个商品时对应生成一个订单。
  5. 用户购买的是实体类商品时,可以查看商品的物流信息。
  6. 用户购买的是服务类商品时,可以用订单的兑换码到商家门店兑换消费。

根据以上需求,可以初步得到相关的领域概念有:商家、商品、实体类商品、服务类商品、物流信息、门店、用户、收货信息、订单、兑换信息。理清这些领域概念之间的关系之后,可以得到类似于下面的领域模型视图:

当然,这只是一个很小的例子,实际上的领域模型会比这个例子复杂得多。领域模型确定之后,系统中有多少业务领域、各领域概念之间的关系如何就一清二楚了。

质量需求

质量需求是三类需求中,需求层次最低的,但却是大部分架构师最关注的。纵览那么多架构技术,就会发现,大部分都是为了解决某个或某些质量属性优化的问题。

质量属性常见的有以下这些:

  • 性能(Performance):性能无疑是一个非常重要的特性,尤其在计算资源有限的情况下。但也无需过分追求高性能,从而牺牲其他更重要的特性。关于过度关注性能的问题,这篇文章说得很好:架构之路(二):性能
  • 安全性(Security):安全性一般会和性能相互制约,最明显的例子就是HTTPS,使用HTTPS提高了安全性,但性能就会有所牺牲。很难做到既满足高安全又高性能,因此需要根据具体需求平衡两方面的特性。
  • 可用性(Availability):也有人称为有效性,一般定义为:可用性 = 系统正常工作时间 / (系统正常工作时间 + 故障维修时间)。此定义就说明了可用性与系统故障有关,故障率高,可用性就低,故障率低,可用性才高。另外,高可用性还说明了系统对故障维修的时间也很短。
  • 易用性(Usability):易用性很容易和可用性混淆,可用性关注的是系统长时间无故障运行的能力,而易用性关注的则是系统易于使用的能力。
  • 鲁棒性(Robustness):也称为健壮性、容错性,是指系统在出现了用户非法操作、或软硬件的缺陷导致的异常情况下,系统依然能够正常运行的能力。比如说,系统在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件的鲁棒性。
  • 可伸缩性(Scalability):可伸缩性是指当用户量和数据量增加时,系统维持高服务质量的能力。比如,当并发量为1W时,系统响应时间为1秒,那如果并发量增加到100W时,只要通过增加服务器数量,而无需对代码进行修改即可达到系统响应时间依然为1秒,就说明该系统的可伸缩性高。
  • 互操作性(Interoperability):互操作性反映了本系统与其他系统交换数据和服务的难易程度。
  • 可扩展性(Extensibility):也称为灵活性,反映了系统应对变化的能力。在软件开发过程中,需求变更是常有的事,尤其在移动互联网时代,变化是非常频繁的,也因此,可扩展性是移动互联网产品重点考虑的质量需求。
  • 可理解性(Understandability):可理解性是指开发人员通过源代码和相关文档,了解程序功能、结构和运行方式的难易程度。遵从好的开发规范一般都可以提高可理解性。另外,单一职责原则运用得好,也能大大提高可理解性,所谓“简单就是美”,简单才容易理解。
  • 可测试性(Testability):简单点说,可测试性就是测试和诊断软件错误的难易程度。比如进行单元测试的难易程度。如果程序包含了复杂的处理逻辑、数据结构、模块关系,可测试性的设计更显得尤为重要。
  • 可复用性(Reusability):可重用性表明了一个软件组件可以在其他程序中使用的难易程度。一般需要将一个组件抽离成通用性的组件时,对可复用性的要求就会比较高。
  • 可移植性(Portability):可移植性表明了将软件系统从一个运行环境转移到另一个不同的运行环境的难易程度。
  • 可维护性(Maintainability):可维护性是指理解、改正、改动、改进软件的难易程度。我觉得,可维护性是保证一个软件系统能够长期生存的最重要的特性,没有之一。对一个可维护性差的系统,久而久之,不断变得牵一发而动全身,变得不可维护,慢慢只能宣布灭亡。

理想情况下,谁都希望所有属性都是高质量的,但谁都清楚这是不可能的事。要提高更多质量属性,实现的难度更大,需要付出的成本更高。而且,不同质量属性之间还存在制约关系,比如,提高安全性,一般就会减低性能;提高了性能,还可能减低了可维护性。因此,在实际做架构规划时,必须根据具体需求在各质量属性间权衡优先级。

写在最后

现在有不少公司,尤其是创业型的公司,为了快,直接从需求跳到开发,没有架构规划,也没有架构设计。这样的系统,就等于一栋没有打地基的建筑物,其风险自不用说。架构就是软件系统的地基。有一句话说得好,“基础不牢,地动山摇”。


扫描以下二维码即可关注订阅号。