微服务业务体系内对复用的深度探讨

555次阅读  |  发布于4年以前

本文主要在微服务体系下重新探讨复用,侧重于讨论不同层级的复用条件和要求,以及落地节奏。

复用是一种计算机软件工程方法和理论。从表现上看,复用指对曾经编写过的代码加以利用,从而支撑新的功能或业务。提高复用度,不仅可以极大的节省研发资源,而且也能为系统带来更好的稳定性和可维护性。更重要的是,它能提升项目质量,带来技术进步,是驱动技术团队实现技术和效能良性循环的极佳途径。

根据维基百科,软件复用的主要思想是,将软件看成是由不同功能部分的组件所组成的有机体,每一个组件在设计编写时可以被设计成完成同类工作的通用工具。这样,如果完成各种工作的组件被创建起来后,编写一特定软件的工作就变成了将各种不同组件组织连接起来的简单问题,这对软件产品的最终质量和维护工作都有了本质性的改变。

从实践上看,复用不仅是指通过拷贝或引用原有代码来复用,而且更广泛的是,通过复用原有设计、逻辑、框架、服务等,让原有代码的能力可以有效被扩展,从而支持新功能或新业务,这一扩展也包含在微服务的体系下,某一服务支持更广泛的业务范畴。软件设计的经验、面向对象的原则,都可以作为方法论来指导复用的实践。

依据复用的定义,复用的程度可以从使用方的的角度被度量。此处,我们定义为复用结构体在业务体系内对各种场景、功能或业务范畴的支持次数。复用度提高意味着效能的提高,也意味着被复用结构体的影响范围扩大,对其代码质量要求也会提升。

1 复用的层次

复用有不同层次。我们依据可复用结构体的复杂性,从低到高依次划分为:代码复用、模块复用、服务复用、产品复用。可复用结构体的复杂性是指内部组织数量、层级、关联程度等特性。这一层次划分可以类比蛋白质、细胞、器官、动物,其内部封装的功能和复杂性随层次升级而提高。不过,每一层级的界限并非十分清晰,可以相互跨越。

代码复用

代码复用在此处窄化为函数、方法、或类的复用,代码是复用的最低层次,也是服务质量的基石。复用的代码通常无法脱离自身服务提供独立完整的功能,不具有模块的规模。

代码复用有很多成熟的经验和方法,如依赖设计原则、设计模式、分层等架构思想。比如实践开闭原则指导我们应当在不修改原有代码的前提下给程序扩展功能,原有的代码都属于被复用代码的范畴;依赖倒置原则可以有效指导我们复用顶层设计及逻辑;设计模式更是提供了一整套可操作的方法和套路,让我们更加方便简单地复用成功的设计模式和结构。分层架构思想也指导我们,在服务开发内部,通过对业务的分层与模块的正交分解后,底层的代码应当具有一定的可复用性。例如,阿里的编码规范里明确分层:Service 层,复用性较低,业务编排逻辑都得放进 service 中去做;Manager 层为通用业务处理层,是对 Service 层通用能力的下沉,如缓存方案、中间件通用处理,尽可能多的可复用业务逻辑层。

在微服务体系内,代码层次的复用往往可以被限制在单一服务内,所以其对代码质量的要求可以跟随团队的统一要求。但其对设计思想、设计能力的要求较高,应当成为团队内部高级研发的基本功,而对于低阶研发,这部分能力往往缺失,可以通过设计评审等方式来避免走偏。

模块复用

模块复用,也叫组件复用,模块是基于功能划分的单位。模块复用比代码复用高一层级,这是因为它通常可以提供较为独立的功能,模块由代码组成且由上层代码关联。

在系统开发中,把系统的各个功能模块正交分解后,底层模块在系统内被各种场景所使用,属于复用的范畴。同一公司或团队的业务体系内,业务相关性往往较大,业务相关的功能模块,其复用范围有一定概率突破本服务内,提供给其他服务使用,进一步提高其复用度。

业务无关的模块复用,通常可以为各个微服务统一提供 SDK,如分布式事务框架、一系列的依赖注入框架,它并不能形成独立的系统。这类复用的标志之一为较小规模的代码,可以直接放到 Github 开源,供其他公司或者业务场景使用。

优质的可复用模块,可以对单一微服务内部提供复用,来支持服务的各种扩展功能。也有可能脱离单一的微服务,在其他微服务间提供支持,模块一旦开发完毕,其他使用者就可以花费很少的精力就能在自身服务中集成该模块功能。脱离单一服务的可复用模块,由于影响范围的扩大,团队对其对代码和文档的质量要求较高,模块复用,应当成为团队有计划去追求的产物。

服务复用

微服务体系运维体系的强大便利为模块复用创造了一种变体,即服务复用。在微服务体系架构中,服务复用可以分为两种:

在公司业务体系中,服务的复用可以非常方便的扩展支持业务边界,这是由于服务复用封装度较好,通过接口与其他业务进行交互,对接操作往往简单方便服务复用。还有一个现象是,如果业务场景在不同的公司也较为广泛存在,往往会伴随有公司以其为主营业务生存,有专业的团队专注做此类产品,如直播消息服务,有融云等公司,日志统计服务,有友盟等公司。

服务复用和模块复用有一定可转换性,在对存储瓶颈充分预估前提下,我们倾向于优先考虑微服务,理由如下:

但同时也需要注意,微服务数据存储独立,意味着存储容量及性能可能成为整个系统的瓶颈,这需要充分预估;微服务封装彻底,对外使用 HTTP 交互,意味着功能在业务体系内为单点,其发生故障后,整个系统可能瘫痪,要做好降级故障预案,避免成为服务体系的瓶颈。

服务复用的复用度,也容易辨识,如进度服务,支撑多少个业务功能,就可以认为其复用度为多少。一个服务承担的职责越多,它被复用的可能性就越小服务复用应当恪守单一职责原则,服务复用和模块复用类似,对团队架构师及技术负责人要求较高,特别是要求架构师对和服务边界划分的能力较好,应当成为优秀团队及优秀架构师追求的目标。

产品复用

产品是对外交付的最终成果,研发为产品服务,产品复用是项目体系内,最大程度的复用,它需要来自产品团队或管理团队层面的支持。

产品复用对产品的多样性会有一定的限制,中低层次产品复用对产品形态要求较高。高层次产品复用,往往需要对需求的根源进行分析,得出一整套有创造性的解决方案,它也更有可能创造性的从根源解决需求问题,如推动广告营销平台,可以有效避免在产品各处侵入开发营销逻辑。产品复用往往需要产品团队的主导或介入,对技术团队而言,需要有较好的产品意识和创新意识,并具备和产品团队沟通并达成一致的领导力。

2 收益

复用带来的直接收益是沟通成本和研发成本的降低。可复用结构节约的资源量,大致等同于可复用结构的复用度,乘以原始设计、开发、测试人力的消耗。

更重要的是,由于复用带来的集中维护也会大大降低维护成本,缺乏复用,会导致同样的逻辑,实现各异,散落在业务体系随着迭代不断腐朽,将会对整个系统带来无法维护的噩梦。

复用带来的另一收益是稳定。部分服务实现复用后,已经基本上被归档,如音频服务的复用、计数服务的复用等,都已经展现出了极强的稳定性。业务的多变性是永恒不变的话题,与业务变化无关的稳定性使得团队可以集中力量应对变化需求。

复用是一个好的修行场所,它会带来团队、设计和认知能力的提升。每个复用组件的实现,需要其代码可靠,更容易被他人理解,强迫团队对好代码的认知提升。可复用的结构,对测试覆盖的要求、说明文档的要求,都和日常代码要求不一样,可以有效锻炼团队的每一个参与者。每个层次的复用,都有对不同能力的修炼,如代码的复用将提升对分层设计的能力提升,服务的复用直接单一职责认知的提升及封装变化的认知提升。

无论何种程度的复用,都会提高整个团队对软件设计原则和高质量代码的认知,这将使得团队走上良性循环。

3 落地节奏

复用的落地节奏中,有机会性的代码复用和有计划的代码复用两种,两者都不可偏废。

机会性的代码复用是指,开发团队在做需求或项目的过程中,通过自己的专业能力来判断其要开发代码或组件在其他业务需求中被复用的可能性,从而选择是否进行代码复用方式的开发,或者抽离为独立模块或服务。

有计划的代码复用,是指定期梳理业务开发团队从战略角度为了日后的开发能够复用代码而进行设计开发。这也包括对过往的存量代码进行盘点,主动进行推动重构开发,在重构的过程中,对已经明显表现出可复用的结构组织进行复用迭代。

开发团队业务需求繁重,团队进行复用度建设的初期,可以着力采用机会性的代码复用,以更好的贴合业务实际需要。有计划的代码复用有利于降低团队的负债和提高迅速应对变化的能力,需要团队管理者定期盘点,避免负债拖慢效率。当然复用也伴随有一定的代价,在业务快速迭代的过程中,如果处处着眼于未来开发,也将不可避免的增加当下成本,对其平衡的把控,是团队领导和架构师需要具备的能力。复用的认知、代码、知识、设计、文档等,都会形成团队内部所不可或缺的有形无形资产,有效支撑团队效能。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8