DDD实战篇:分层架构的代码结构

不同于其它的架构方法,领域驱动设计DDD(Domain Driven Design)提出了从业务设计到代码实现一致性的要求,不再对分析模型和实现模型进行区分。也就是说从代码的结构中我们可以直接理解业务的设计,命名得当的话,非程序人员也可以“读”代码。

然而在整个DDD的建模过程中,我们更多关注的是核心领域模型的建立,我们认为完成业务的需求就是在领域模型上的一系列操作(应用)。这些操作包括了对核心实体状态的改变,领域事件的存储,领域服务的调用等。在良好的领域模型之上,实现这些应用应该是轻松而愉快的。

笔者经历过很多次DDD的建模工作坊,在经历了数天一轮又一轮激烈讨论和不厌其烦的审视之后,大家欣慰地看着白板上各种颜色纸贴所展示出来的领域模型,成就感写满大家的脸庞。就在这个大功告成的时刻,往往会有人问:这个模型我们怎么落地呢?然后大家脸上的愉悦消失了,换上了对细节就是魔鬼的焦虑。但这是我们不可避免的实现细节,DDD的原始方法论中虽然给出了“分层架构”(Layered Architecture)的元模型,但如何分层却没有明确定义。

分层架构

在DDD方法提出后的数年里,分层架构的具体实现也经历了几代演进,直到Martin Fowler提炼出下图的分层实现架构后,才逐步为大家所认可。DDD的方法也得到了有效的补充,模型落地的问题也变得更容易,核心领域模型的范围也做出了比较明确的定义:包括了Domain,Service Layer和Repositories。

(Martin Fowler总结提出的分层架构实现,注意“Resources”是基于RESTful架构的抽象,我们也可以理解为更通用的针对外界的接口Interface。而HTTP Client主要是针对互联网的通信协议,Gateways实际才是交换过程中组装信息的逻辑所在。)

我们的核心实体(Entity)和值对象(Value Object)应该在Domain层,定义的领域服务(Domain Service)在Service Layer,而针对实体和值对象的存储和查询逻辑都应该在Repositories层。值得注意的是,不要把Entity的属性和行为分离到Domain和Service两层中去实现,即所谓的贫血模型,事实证明这样的实现方式会造成很大的维护问题。DDD战术建模中的元模型定义不应该在实现过程中被改变,作为元模型中元素之一的实体本身就应该包含针对自身的行为定义。

基于这个模型,下面我们来谈谈更具体的代码结构。对于这个分层架构还有疑惑的读者可以精读一下Martin的原文。有意思的一点是,这个模型的叙述实际是在微服务架构的测试文章中,其中深意值得大家体会。

这里需要明确的是,我们谈论代码结构的时候,针对的是一个经过DDD建模后的子问题域(参见战略设计篇),这是我们明确的组件化边界。是否进一步组件化,比如按照限界上下文(Bounded Context)模块化,或采用微服务架构服务化,核心实体都是进一步可能采用的组件化方法。从抽象层面讲,老马提炼的分层架构适用于面向业务的服务化架构,所以如果要进一步组件化也是可以按照这个代码结构来完成的。

总体的代码目录结构如下:

- DDD-Sample/src/
    domain
    gateways
    interface
    repositories
    services

这个目录结构一一对应了前文的分层架构图。完整的案例代码请从GitHub下载

可以看到实际上我们并没有建立外部存储(Data Mappers/ORM)和对外通信(HTTP Client)的目录。从领域模型和应用的角度,这两者都是我们不必关心的,能够验证整个领域模型的输入和输出就足够了。至于什么样的外部存储和外部通信机制是可以被“注入”的。这样的隔离是实现可独立部署服务的基础,也是我们能够测试领域模型实现的要求。

模型表达

根据分层架构确立了代码结构后,我们需要首先定义清楚我们的模型。如前面讲到的,这里主要涉及的是从战术建模过程中得到的核心实体和服务的定义。我们利用C++头文件(.h文件)来展示一个Domain模型的定义,案例灵感来源于DDD原著里的集装箱货运例子。

namespace domain{
struct Entity
{
    int getId();
protected:
    int id;
};

struct AggregateRoot: Entity
{
};

struct ValueObject
{
};

struct Provider
{

};

struct Delivery: ValueObject
{
    Delivery(int);
    int AfterDays;
};

struct Cargo: AggregateRoot
{
    Cargo(Delivery*, int);
    ~Cargo();
    void Delay(int);
private:
    Delivery* delivery;
};
}

这个实现首先申明了元模型实体Entity和值对象ValueObject。实体一定会有一个标识id。在实体的基础上声明了DDD中的重要元素聚合根 AggregateRoot。根据定义,聚合根本身就应该是一个实体,所以AggregateRoot继承了Entity。

这个案例中我们定义了一个实体Cargo,同时也是一个聚合根。Delivery是一个值对象。虽然这里为了实现效率采用的是struct,在C++里可以理解为定义一个class类。

依赖关系

代码目录结构并不能表达分层体系中各层的依赖关系,比如Domain层是不应该依赖于其它任何一层的。维护各层的依赖关系是至关重要的,很多团队在实施的过程中都没有能够建立起这样的工程纪律,最后造成代码结构的混乱,领域模型也被打破。

根据分层架构的规则,我们可以看到示例中的代码结构如下图。

Domain是不依赖于任何的其它对象的。Repositories是依赖于Domain的,实现如下:引用了model.h。

#include "model.h"
#include <vector>

using namespace domain;

namespace repositories {
struct Repository
{
};
...

Services是依赖于Domain和Repositories的,实现如下:引用了model.h和repository.h

#include "model.h"
#include "repository.h"

using namespace domain;
using namespace repositories;

namespace services {
struct CargoProvider : Provider {
    virtual void Confirm(Cargo* cargo){};
};

struct CargoService {
    ... ...
};
...

为了维护合理的依赖关系,依赖注入(Depedency Injection)是需要经常采用的实现模式,它作为解耦合的一种方法相信大家都不会陌生,具体定义参见这里

在测试构建时,我们利用了一个IoC框架(依赖注入的实现)来构造了一个Api,并且把相关的依赖(如CargoService)注入给了这个Api。这样既没有破坏Interface和Service的单向依赖关系,又解决了测试过程中Api的实例化要求。

auto provider = std::make_shared< StubCargoProvider >();

api::Api* createApi()  {
    ContainerBuilder builder;
    builder.registerType< CargoRepository >().singleInstance();
    builder.registerInstance(provider).as<CargoProvider>();
    builder.registerType< CargoService >().singleInstance();
    builder.registerType<api::Api>().singleInstance();

    auto container = builder.build();

    std::shared_ptr<api::Api> api = container->resolve<api::Api>();

    return api.get();
}

测试实现

有了领域模型,大家自然会想着如何去实现业务应用了,而实现应用的过程中一定会考虑到单元测试的设计。在构建高质量软件过程中,单元测试已经成为了标准规范,但高质量的单元测试却是困扰很多团队的普遍问题。很多时候设计测试比实现应用本身更加困难。

这里很难有一个固定标准来评判某个时间点的单元测试质量,但一个核心的原则是让用例尽量测试业务需求而不是实现方式本身。满足业务需求是我们的目标,实现方式可能有多种,我们不希望需要持续重构的实现代码影响到我们的测试用例。比如针对实现过程中的某个函数进行入参和出参的单元测试,当这个函数发生一点改变(即使是重命名),我们也需要改动测试。

测试驱动开发TDD无疑是一种好的实践,如果应用得当,它确实能够实现我们上述的原则,并且能够帮助我们交流业务的需求。比较有意思的是,在基于DDD建立的核心模型之上应用TDD似乎更加顺理成章。类比DDD和TDD虽然是不恰当的,但我们会发现两者在遵循的原则上是一致的,即都是面向业务做分解和设计:DDD就整个业务问题域进行了分解,形成子问题域;TDD就业务需求在实现时进行任务分解,从简单场景到复杂场景逐步通过测试驱动出实现。下面的测试用例展现了在核心模型上的TDD过程。

TEST(bc_demo_test, create_cargo)
{
    api::CreateCargoMsg* msg = new api::CreateCargoMsg();
    msg->Id = ID;
    msg->AfterDays = AFTER_DAYS;
    createCargo(msg);
    EXPECT_EQ(msg->Id, provider->cargo_id);
    EXPECT_EQ(msg->AfterDays, provider->after_days);
}

上面测试了收到一条创建信息后实例化一个Cargo的简单场景,要求创建后的Cargo的标识id跟信息里的一致,并且出货的日期一致。这个测试驱动出来一个Interface的Api::CreateCargo。

下面是另外一个测试推迟delay的场景,同样我们看到了驱动出的Api::Delay的实现。

TEST(bc_demo_test, delay_cargo)
{
    api::Api* api = createApi();
    api::CreateCargoMsg* msg = new api::CreateCargoMsg();
    msg->Id = ID;
    msg->AfterDays = AFTER_DAYS;
    api->CreateCargo(msg);
    api->Delay(ID,2);
    EXPECT_EQ(ID, provider->cargo_id);
    EXPECT_EQ(12, provider->after_days);
}

长期以来对于TDD这个实践大家都有架构设计上的疑惑,很多资深架构师担心完全从业务需求驱动出实现没法形成有效的技术架构,而且每次实现的重构成本都可能很高。DDD的引入从某种程度上解决了这个顾虑,通过前期的战略和战术建模确定了核心领域架构,这个架构是通过预先综合讨论决策的,考虑了更广阔的业务问题,较之TDD应用的业务需求层面更加宏观。在已有核心模型基础上我们也会发现测试用例的设计更容易从应用视角出发,从而降低了测试设计的难度。

关于预先设计

如果没有读战略篇直接看本文的读者肯定会提出关于预先设计的顾虑,毕竟DDD是被敏捷开发圈子认可的一种架构方式,其目标应该是构建架构模型的响应力。而这里给大家的更多是模式化的实现过程,好似从建模到代码一切都预先设计好了。

值得强调的是,我们仍然反对前期设计的大而全(Big-Design-Up-Front,BDUF)。 但我们应该认可前期对核心领域模型的分析和设计,这样能够帮助我们更快地响应后续的业务变化(即在核心模型之上的应用)。这不代表着核心领域模型未来会一成不变,或者不能改变,而是经过统一建模的核心部分变化频率较之外部应用会低很多。如果核心领域模型也变化剧烈,那么我们可能就要考虑是否业务发生了根本性的变化,需要建立新的模型。

另外不能忘记我们预先定义的模型也是被局限在一个分解出来的核心问题域里的,也就是说我们并不希望一口气把整个复杂的业务领域里的所有模型都建立起来。这种范围的局限某种程度上也限制了我们预先设计的范围,促使我们更多用迭代的方式来看待建模工作本身。

最后显然我们应该有一个核心团队来守护核心领域模型,这不代表着任何模型的设计和改动都必须由这个团队的人做出(虽然有不少的团队确实是这样落地DDD的)。我们期望的是任何对核心模型的改动都能够通过这个核心团队来促进更大范围的交流和沟通。检验一个模型是否落地的唯一标准是应用这个模型的团队能否就模型本身达成共识。在这点上我们看到很多团队持续通过代码走查(code review)的方式在线上和线下实践基于核心模型的交流,从而起到了真正意义上的“守护”作用,让模型本身成为团队的共同责任。

实践DDD时仍然需要遵循“模型是用来交流的”的这一核心原则。我们希望本文介绍的方法及模式能够帮助大家更容易地交流领域模型,也算是对DDD战略和战术设计的一点补充。


更多精彩洞见,请关注微信公众号:思特沃克

Share

面向变化的组织

[摘要]

科技狂欢的时代,市场响应力是决胜法宝,小型化、微型化的组织结构成为了这个时代的主旋律。很多企业争相效仿Google扁平的小团队集群组织结构,却发现组织反而越来越低效。本文结合企业服务化转型的案例,给出小型化组织治理的三条基本原则,相信你能从中得到启发。

组织结构的小型化

站在第四次工业革命的风口,每天被各种创新和变化刷新着,从我们的工作到我们的生活都在改变,“唯一不变的是变化”。这似乎是一个科技狂欢的时代,却给我们这些企业管理者带来了巨大的挑战。“自组织”的救赎并没有那么容易实现,现实是从有章可循变成了“定制化”多元管理。深知市场响应力是这个时代的决胜法宝,但庞大的组织结构却成为了沉重的掣肘,以至于我们开始怀疑过去辛苦打造的管理体系是否多余。小型化、微型化成了这个时代的主旋律,从Amazon到海尔,组织的架构和管理也在同样经历着颠覆。

随着微服务架构风格的流行,组织内部不可避免的产生了许多小规模团队,原来一个几十上百人的产品团队被拆分成了类似Amazon这样的“2个披萨饼”(6~10人)小团队。组织结构上也由之前的层级化职能团队变成了扁平的小团队集群。每个做这样调整的企业,都希望借助小团队的灵活性,跟上市场变化和科技创新的脚步。

组织的两种基本模式示意

当然这样的组织方式本身就带来了一系列的挑战,技术实践方面Martin Fowler已经通过微服务的定义文章做了很形象的叙述,还用了“你必须长这么高”(You must be this tall!)来比喻在技术实践方面所需做出的投入。

在组织管理方面,越来越多的挑战浮现,关于集群小团队组织和管理出现了各种各样的问题。把“自组织”当做银弹来回答这些问题,是行业里存在的一个不太好的趋势。在最近和Matin Fowler的讨论中,我们达成的共识之一是:与其说微服务是一种技术架构,还不如说是一种企业组织架构

组织原则:对齐业务

科技时代带来的最大变化就是对变化本身的认知。在上一个时代,变化被认为是高成本甚至是有害的,大家总是希望能够尽量减少变化,或者能够循序渐进地变化;而现在我们会认为变化是必然的,它会带给我们新的市场机会,甚至会引发颠覆式创新。 由于这样的认知变化,企业必须具备相应的灵活性,而扁平的小团队集群组织结构被不少企业(例如Google和韩都衣舍)证明是提供这种灵活性的有效组织方式。很多企业争相效仿,但会发现并没有得到预期的灵活性,反而做事情更为复杂了,以前一个接口部门变成了现在的多个团队。

作为咨询顾问,这两年经常接触到不少人抱怨划分成小团队后需求的实现成本增加很多,以前简单的业务需求现在要分解到很多“服务”团队才能完成。有的团队觉得这是技术问题架构设计前瞻性不够;有的团队觉得是管理问题——没有跨团队的协调机制。而我往往喜欢从组织入手,让团队从业务需求出发,分析为什么有那么多“集成”。

熟悉康威定律的同学可能已经理解我的用意了。以上团队出现的问题核心症结在于团队的组织结构和市场业务没有对应关系,大量的服务集成等同于把市场需求“翻译”适配到已有的组织结构。这样的痛苦在过去职能组织结构的时候就广泛存在,而错误的“服务化”只是把这种痛苦转换成了小团队之间的集成。

所以微服务化组织结构的核心原则是:小团队的组织结构应该和市场业务对齐,并跟随市场业务变化而改变

稍微实例化一下以上的原则,比如最近一个客户的电商团队,100人左右规模。开始时候划分成了10人上下的小团队,每个团队负责几个服务,其中有几个“重要”服务,如customer(客户)和catalog(目录)。在一段时间里,几乎所有的需求都要经过这两个服务,工作量很大,团队实际上也根本不是十几人,而是几十人。团队告诉我:撑过这段高峰期模型就稳定了,以后就可以真正“微服务化”了。

我用领域驱动设计的思想很快指出,就现在业务需求驱动出来的大量集成已经可以明确这些“重要”服务的划分是有问题的,新增加电子产品(比如点卡)的customer和之前的电商customer已经有不同的含义了,电子产品要求客户提供对应电子平台的账号和授权。按照上面的原则,不应该继续去扩充已有的customer服务,而应该重新分析新的业务模式下是否应该有新的服务(其中也包含新的customer模型)。

不同业务空间的Customer概念

以上的例子在很多走向服务化组织结构的企业里比比皆是,而遇到问题时大家更容易从看似明确的技术或管理手段入手。遇到这样的挑战时,别忘了康威定律。

管理原则:适应不确定性

《大教堂与集市》这本书中对比了两种不同的组织架构模式,很多特质也能够类比到单体架构和微服务架构之上。当微服务架构落地形成生态时(如Google),好比一个繁荣的集市,中央管理固然重要,但各个经营摊位却自主在为客户提供着琳琅满目的商品和服务。

作为一个企业,不太可能完全容忍集市一样的市场化,当然也有企业如海尔,把这种市场化更大程度上地引入到了内部。假设刚刚从过去职能层级组织结构转换到扁平小团队集群结构,这个时候管理者最大挑战,就是如何还能够获取过去“全面一致”的信息。管理者往往会告诉我他们感觉到随时可能失控,因为每个团队都没有统一的开发方法和流程。

很不幸的是,大多数从MBA课堂走出的企业管理者们都是管理“大教堂”建设的高手,却很难驾驭集市带来的“混乱”,但又都渴望着自己的企业能够有创新的环境。根据创新理论(Edge of Chaos),集市混乱产生创新的可能要远大于大教堂的整齐划一。那么在这个你不创新就被别人颠覆的时代,管理者就必须正视这个挑战。

管理的原则应该改变为:放弃对掌控全局的虚幻追求,拥抱不确定性带来的挑战和机遇

同样实例化一下上面的原则。一个300多人的大产品经理,自从转型成为扁平小团队结构后,他的会议比之前多了N倍,基本每天正常工作时间全部在开会。自己的产品方向和运营只能靠夜深人静的时候加班。他告诉我如果这就是所谓小团队要付出的代价,那么这事儿没法持久。

我首先肯定了他的观点,即如果作为产品经理都没有时间看产品方向和运营,那么模式上肯定是错了。进而询问最占用他时间的会议需要他做什么?答案是:“我需要知道XYZ信息才能保证计划的传达和理解”、“开会是已经同步各个小团队最高效的方式了”……。这里传递出来的,其实全部是希望掌控全局的急迫,和他表面上表达的赋权团队、打造自组织文化大相径庭。接下来,我们花了很多时间来讨论为什么一定要有拉通的计划、为什么要中央同步各个小团队……。当然,知行合一本身就是困难的——这位管理者最后带着更多的困惑离开了那次讨论。

对比组织结构的调整,管理者思想和方法的转型确实任重道远。我往往给出的建议是从小处着手,比如放弃给每人安排任务,让大家自己来选择;又比如在团队之间冲突时,放弃作为管理者的“拍板权”,让团队通过快速实验来验证哪种方式更好。另一位大师级同事Jim Highsmith在八年前就总结出了适应性领导力(Adaptive Leadership),十年后的今天仍是少有管理者能够真正践行。

合作原则:简化集成关系

微服务下小团队集群的结构,不可避免需要更多的团队合作。一个运作良好的微服务生态圈背后是一个紧密协作的小团队网络,而团队之间的合作就是这个网络里无形的手。合作很多时候是团队和团队在运营过程中实时发生的,并非是预先设定或中央控制的,这个时候如何高效合作就成了一个很大的挑战。

在共同满足业务需求的过程中,大多数的合作是由于实现过程中服务之间的集成关系产生的。如前面讨论组织结构时的案例,很多组织在转型后反而集成多了,造成交流沟通成本持续增高,最后不得不安装很多会议和流程来“协调”这样的合作。结果当然是响应力越来越差,小团队名存实亡。

在团队合作方面,《领域驱动设计》一书中提出的业务限界上下文的关联关系可以借鉴。服务划分强调从业务视角出发,限界上下文提供了很好的划分指导。由于每个服务对应一个小团队,那么实际上我们就建立了团队之间集成关系的模式。在微服务开始落地实施的时候,其中描述的基于领域模型耦合方式的关系模式,就变得十分重要了,因为这些模式本身也是团队之间的合作模式。

限界上下文关系模式要求矩阵(领域驱动设计,248页14.4)

上面的矩阵总结,告诉我们集成是高成本的,要尽量避免集成。同样道理在咱们团队合作的过程中,原则也是简化集成关系。在微服务架构下,显然右上角的“大泥球”(Single Bounded Context)和“共享内核”(Shared Kernel)是不推荐的;“独立自主”(Separate Ways)这种完全松耦合的关系是值得我们考虑的,但大多数情况下小颗粒度的服务之间还是会被不同的业务需求串联起来。

很多刚转型的企业会出现不少的“用户/供应商”(Customer/Suppier Teams)模式,主要是团队之间关系还是由更高层的领导在指挥,作为一个演进的合作关系应该更进一步向“开放主机服务”(Open Host Service)模式推进。现代的服务多是以API的形式更为规范的对外提供接口,所以其实在团队沟通方面的成本并非比领导中央决策高多少。

随着API规范的更进一步发展,如采用RESTful架构,很多时候服务团队之间只用做简单的翻译或遵从提供者的模型即可,耦合程度进一步下降,这个时候左下角的另外两种模式“防护层”(Anticorpution Layer)和“跟随者”(Conformist)就更为常见了。显然这两种模式集成关系更为简单,合作过程中调用服务的团队是不需要知道提供方的内部模型细节的,当然这个时候团队之间的信任关系也应该是相当高的。

结语

采用微服务架构后,自然会产生小团队扁平化组织结构,我们应该意识到在组织、管理、合作的原则及思维观念上都应该发生转变,忽略任何一个方面最终都会造成转型的失败。

  • 在组织结构上,团队划分要面向业务能力,持续提供市场价值。
  • 在企业管理上,管理者要拥抱不确定性,持续提升管理适应力。
  • 在团队合作上,考虑跨团队领域模型的耦合,持续简化集成关系。

无论我们是否采用微服务架构,组织想要持续响应外部变化、获得灵活性,就必须在组织级架构上“小型化”。组织管理上,我们必须适应和促进这样的架构落地和持续演进。起步必然是痛苦的,正如老子千年前指出“一生二 二生三 三生万物”,包容多样性是全局管理的精髓。

同海尔张瑞敏的认知一样,我认为有着这种全局视角基因的中国哲学,可能在这个时代的组织管理上大放异彩。


更多精彩商业洞见,请关注微信公众号:ThoughtWorks商业洞见

Share

DDD战略篇:架构设计的响应力

当敏捷宣言的17位签署者在2001年喊出“响应变化胜于遵循计划”这样的口号时,鲜有组织会真正把这句话当回事儿,甚至很多经验丰富的管理者会认为好的计划是成功的一半,遵循计划就是另外一半。然而在时下的第四次工业革命浪潮中,可能很多管理者已经不会简单满足于“响应”,而是选择主动发起变化了。不确定性管理成了这个时代的主旋律,企业的响应力成了成败的关键。

随着这种趋势的深入,架构设计这个技术管理领域也被推到了风暴边缘。“稳定”这个过去我们用来形容好系统的词语似乎已经失去原有的含义,很多人开始用“健壮”这个词语来形容好的系统。比如Netflix公司采用的Chaos Monkey机制随机主动关停线上服务而不会造成整个服务生态宕机的作法更多的是在测试系统的健壮性,保证不会因为某个局部的问题而造成全身瘫痪。

然而架构的健壮性却比较难于定义和测试,以至于很多时候咱们在架构设计上还是在追求稳定性。在一个典型的企业IT组织里,当你询问一位资深工程师架构设计时,往往会得到一张搭积木一样的“架构图”。

图的底层是各种数据存储(从经典的Oracle到大数据标配的Hadoop),图的中间是类似Kafka这样的消息管道和传统的ESB(消息总线),上层则是各种业务应用(包括各种Web应用和移动的APP)。

仿佛这是一个流行的“稳定”架构设计。

(示意:典型的IT系统架构图)

当询问这样的架构是否合理时,不少人会告诉你问题可大了:这不是云时代的服务化架构。原因是这个架构的大部分组件,如数据存储,都已经可以完全“托管”给云平台了。于是乎,很多企业架构师又开始寻找像过去ESB一样能够对接各种云平台的PaaS了,然后抱怨现在的PaaS没有当年的ESB“稳定”。

两个核心问题却很少被提及:

  1. 当年基于ESB集成的SOA服务化架构解耦出的组件不但没有提升效率,反而增加了系统后续修改的复杂度。
  2. 看似“以不变应万变”的架构并不能支撑多样化的业务需求,最后各个业务部门仍然有一套自己的IT系统,即便是画出来的架构图惊人的相似(多少次有人惊呼“这就是我们之前那个工作流系统~”)。

就这两个核心痛点,让我们一起来谈谈架构设计面临的挑战和应对方式。

什么是架构设计

由于软件设计是一个复杂度很高的活动,“通过组件化完成关注点分离从而降低局部复杂度”很早就成为了咱们这个行业的共识。前面提到的数据存储、消息管道等“模块”在某种意义上都是组件化的产物。这样的好处是在不同系统里遇到同样的功能需求时可以复用。在云服务崛起的今天,这样的组件以“服务”的形式更容易为我们所采用。

当然技术出身的架构师们在架构设计的时候或多或少都有一种“搭积木”的感觉。大家都非常关注Kafaka有哪些功能,K8S是不是比Mesos功能更全,以及Akka是不是稳定。就像走进一个家装公司,在选择了“套餐”之后有工程人员给你介绍地砖和木地板用哪个品牌更好。

回到咱们的第二个核心痛点,如果只是这样的搭积木,为什么咱们总是在面对新变化、新需求的时候发现需要新的组装方式或新的组件呢?这样的架构设计对比直接按照需求实现(不考虑架构)有什么优势呢?

这里我们应该回到架构设计的本质,即为什么我们要在代码实现前做设计。显然如果去掉设计这个过程,大家会说问题这么复杂,如何下手啊?所以设计首先是要解决问题的复杂度。于是有人做了一个架构,交给了一个团队去实现,很快发现实现的架构和设计完全是两张皮。当然原因很明确——缺少了交流和沟通,所以设计其次是要建立团队协作沟通的共识

假设我们产生了一个团队都达成共识的架构设计,大家都兢兢业业把设计变成了现实。一个长期困扰软件行业的问题出现了,需求总是在变化,无论预先设计如何“精确”,总是发现下一个坑就在不远处。相信很多技术人员都有这样的经历,结果往往是情况越来越糟糕,也就是我们常说的架构腐化了,最后大家不得不接受重写。这些经历让我们逐步明确了软件架构设计的实质是让系统能够更快地响应外界业务的变化,并且使得系统能够持续演进。在遇到变化时不需要从头开始,保证实现成本得到有效控制。

面向业务变化而架构

基于上面的架构设计定义,关键因素就是业务变化。显然这个时代的业务变化是很快的,甚至很多业务主动在变,不变则亡是很多行业目前的共识。变化速度给架构设计带来了很大挑战,一个移动APP可能需要在一周内上线,然而为了支撑这个移动APP的后台服务,平台发布窗口是每两个月一次。这样的不匹配在IT领域里是随处可见的现实,我们习惯性地认为后台天然就很重因此很慢,只可能在牺牲质量的情况下满足这样的速度。

然而事实上这样的健壮架构确实是存在的,看看身边现在无处不在的互联网,又有哪一个企业的架构比之复杂呢。互联网系统的组件是一个个网站,每个网站完成着自己的业务功能更新,从新闻发布到在线聊天。而各个站点又是紧密互联的,聊天网站可能把新闻网站拿到的信息实时推送给在线的用户。每个网站都是独立的小单元,面向互联网用户提供着一定的业务服务。好的网站也根据用户的反馈在不停升级和变化,但这样的变化并不影响用户使用其它的网站。

从互联网架构我们可以学到什么呢?从架构设计角度我认为以下三点是关键。

  1. 让我们的组件划分尽量靠近变化的原点,对于互联网来说就是用户和业务,这样的划分能够让我们将变化“隔离”在一定的范围(组件)内,从而帮助我们有效减少改变点。
  2. 组件之间能够互相调用,但彼此之间不应该有强依赖,即各自完成的业务是相对独立的,不会因为一方掉线而牵连另外一方,比如新闻网站挂掉了,聊天网站应该继续正常提供服务,可能提示用户暂时无法提供新闻信息而已。
  3. 组件在业务上是鼓励复用的,正是这样的复用才成就了今天的互联网,我们不会每个网站都去实现一个强大的搜索引擎。而被“复用”最多的网站显然会受到追捧,成为明星业务。当然架构上这样的网站必然是健壮的。

上面的三点毫无疑问都指向了业务,从业务出发、面向业务变化是我们现代架构设计成功的关键

架构设计的核心实质是保证面对业务变化时我们能够有足够快的响应能力。

这种响应力体现在新需求(变化)的实现速度上,也体现在我们组件的复用上,在实现过程中现有架构和代码变化点的数量也是技术人员能够切身体会到的。面对日新月异的数字化时代,组织的整体关注点都应该集中到变化的原点,即业务上,而架构应该服务于这种组织模式,让这样的模式落地变得自然。

对比之前的传统SOA架构,这个思路的变化是本质性的。类似工业总线(ESB)这样的组件化其实是面向技术的,希望通过技术平台的灵活性来解决业务变化的多样性。虽然短时间能够收到一定的成效,长期看必然把自身做成瓶颈,因为所有业务的变化最后都堆积到了这个技术组件来解决。这也回答了为什么实施了传统SOA架构的企业最后都发现响应速度其实并没有提升起来。

面向业务变化而架构就要求首先理解业务的核心问题,即有针对性地进行关注点分离来找到相对内聚的业务活动形成子问题域。子问题域内部是相对稳定的,即未来的变化频率不会很高,而子问题边界是很容易变化的,比如在一个物流系统中:计算货物从A地到B地的路径是相对固定的,计算包裹的体积及归类也是相对固定的,但根据包裹的体积优化路径却经常会根据业务条件而变化。

(子问题域的划分)

面对业务的变化也要求我们的架构必须是演进的,因为业务的变化点也会随着时间推移发生着变化。这意味着在一款较长生命周期的软件产品中,不会出现类似ESB这样的重型组件,相反的我们追求的是一些面向业务服务的轻量级组件,它们的持续演进也会造成老组件的合并,新组件的重新拆分。当然这也成了现代微服务架构成功的基础条件之一。

打造架构响应力的方法

如果认同了上述现代架构的真正意义,大家一定会问怎么才能打造这样的高响应力架构呢?

领域驱动设计方法DDD(Domain Driven Design)为我们提供了很好的切入点。这个2003年就总结出来的方法终于在10多年后重新走入了架构师的视野,而这一次大家已经意识到了这种方法在这个快速变化时代的重要性。DDD通过以下两个模式去有效解决了文章开始提到的两大痛点:

  1. 让团队中各个角色(从业务到开发测试)都能够采用统一的架构语言,从而避免组件划分过程中的边界错位。
  2. 让业务架构和系统架构形成绑定关系,从而建立针对业务变化的高响应力架构。

这两点是DDD的核心,也是为什么时下全球架构圈在进一步向DDD这个方向靠拢的原因。DDD明确了业务和系统架构上的绑定关系,并提供了一套元语言来帮助各个角色有效交流架构设计。

(DDD的基本方法)

在战略层面,DDD非常强调针对业务问题的分析和分解,通过识别核心问题域来降低分析的复杂度。在战术层面,DDD强调通过识别问题域里的不同业务上下文来进行面向业务需求的组件化。最后在实现层面利用成熟的技术模式屏蔽掉技术细节的复杂度。

在这里我们也希望通过第一届DDD China建立起一个架构设计人员的交流平台。期待更多的中国技术人员能够通过这个平台和世界一流架构大师们建立起沟通的渠道,不仅在战略层面,也在战术层面和所有人一起分享讨论关于DDD的一切。


更多精彩洞见,请关注微信公众号:思特沃克

Share

DDD & Microservices

Microservices(微服务架构)和DDD(领域驱动设计)是时下最炙手可热的两个技术词汇。在最近两年的咨询工作中总是会被不同的团队和角色询问,由此也促使我思考为什么这两个技术词汇被这么深入人心的绑定,它们之间的关系是什么呢?

服务于更高的业务响应力

首先从两个词汇的发明来看它们是没有因果关系的。DDD是Eric Evans于2003年出版的书名,同时也是这个架构设计方法名的起源。DDD的想法是让我们的软件实现和一个演进的架构模型保持一致,而这个演进的模型来自于我们的业务需求。这种演进式设计方法在当时看来还是比较挑战的,更为流行的解决架构设计复杂度的方法是分层:比如数据架构、服务架构、中间件架构等。MVC在互联网应用开发领域也基本成为了标配。

时间很快过了10年,Martin Fowler和ThoughtWorks英国架构师James Lewis坐下来一起分析了好几个能够持续演进的大型复杂系统,总结出了9大核心特质,然后用Microservices来定义了拥有这些特质的架构。之后由于Google、Netflix、Amazon等一系列明星企业都对号入座,Microservices开始风靡整个软件业。这时候很多人会问微服务架构是怎么设计出来的,业界人士会说DDD是一个好方法,其中也包括微服务定义者Martin Fowler,毕竟DDD原书的序是他给著的;)于是乎DDD开始在被定义10年后火了。

从我个人角度来看,如果真的需要找到因果关系的话,最根本的驱动力来自于科技时代对软件系统(数字化)响应力要求的不断提升,而系统的复杂度却随着业务的多元化而与日俱增。如何驾驭这样的高复杂度成了每个企业必须面对的挑战,以至于业界开始把这种模型总结为响应力企业Responsive Enterprise),而模型中总结的大部分原则都是为了更好的适应环境不确定性带来的高复杂度。

从业务视角分离复杂度

每个人能够认知的复杂度都是有限的,在面对高复杂度的时候我们会做关注点分离,这是一个最基本的哲学原则。显然在针对复杂业务场景进行建模时,我们也会应用此原则。这个时候去分离关注点一般可以从两个维度出发:

  • 技术维度分离,类似MVC这样的分层思想是我们广泛接受的。
  • 业务维度分离,根据不同的业态划分系统,比如按售前、销售、售后划分。

以上两个维度没有孰优孰劣之分,在处理复杂问题的时候一定都会用上,但为了能够高效响应业务的变化,微服务的架构更强调业务维度的关注点分离来应对高复杂度。这是显著区别于传统SOA架构的特质之一,比如诞生于传统SOA时代的ESB(工业服务总线)就是一个典型的技术关注点分离出来的中间件。随着业务的变化,我们也看到ESB成为了一个架构上的反模式,即大量的业务规则和流程被封装在了ESB里,让ESB成为了不可驾驭的复杂度之源,以至于破坏了SOA架构之前承诺的各种优势。当然Microservices架构并非是新一代SOA架构这么简单,已经有不少文章在讨论这个话题,本文就不在展开了。

所以从本质上作为一种架构设计方法的DDD和作为一种架构风格的Microservices都是为着追求高响应力目标而从业务视角去分离复杂度的手段。

如果这个时代你还觉得自己的架构不需要这种响应力,我建议你问问身边维护3年以上系统的朋友或同事们,他们会告诉你这是怎样的一种痛苦。实际上很多企业对这种响应力的追求已经很“疯狂”了,这也是微服务的两位定义者可能都始料未及的。

他们在定义文章中带着很强警告语气让大家慎用,但在这个科技时代,微服务架构实施的可能风险对比高响应力在未来可能带来的市场机会几乎可以忽略不计。一个Netflix的成功就足以让大部分企业毫不犹豫的选择微服务作为自身的架构风格。

业务和技术渐进统一的架构设计

如果Microservices和DDD在目标上达成了上文的统一,那么在具体做法上和以前有什么不同呢?

为了解释清楚这个问题让我们极简化架构设计为以下三个层面工作:

  • 业务架构:根据业务需求设计业务模块及交互关系。
  • 系统架构:根据业务需求设计系统和子系统的模块。
  • 技术架构:根据业务需求决定采用的技术及框架。

显然这三者在具体一个架构设计活动中应该是有先后顺序的,但并非一定是孰先孰后,比如一个简单的web应用,很多人会说MVC是标配了(首先确定了系统架构),或者有人说用RoR快(首先确定了技术架构)。在给定的业务场景里,也许这样的顺序是合理的。

架构设计工作分层及传统意义上的负责人

这个时候咱们增加复杂业务需求快速市场变化这两个环境变量,这个顺序就变得很有意思了。于是我们听到不少走出初创期的互联网服务平台开始“重写”他们的系统(从PHP到Java),很多文章开始反思MVC带来的僵化(臃肿的展现层)。经历了这样变迁的架构师们都会感同身受的出来为DDD站台,其原因就是“跳过”(或“后补”)业务架构显然表明设计出来的架构关注点并不在业务的响应力上,因为业务的可能变化点并没有被分析出来指导系统和技术架构的设计。

DDD的核心诉求就是能够让业务架构和系统架构形成绑定关系,从而当我们去响应业务变化调整业务架构时,系统架构的改变是随之自发的。

这个变化的结果有两个:

  • 业务架构的梳理和系统架构的梳理是同步渐进的,其结果是划分出的业务上下文和系统模块结构是绑定的。
  • 技术架构是解耦的,可以根据划分出来的业务上下文的系统架构选择最合适的实现技术。

第一点显然也是我们产生微服务划分所必须遵循的,因为微服务追求的是业务层面的复用,所以设计出来的系统必须是跟业务一致的。第二点更是微服务架构的特质:“去中心化”的治理技术和数据管理。 作为架构设计的方法,DDD的各种实践,包括最近流行的Event Storming(事件风暴)实际上都是促进业务和系统架构梳理的渐进式认知。

在一次DDD工作坊中,一位同事给出了“你们连业务故事都讲不清楚,还有必要继续做架构设计吗?”这样的经典评论。而DDD的整个方法也没有涉及具体的技术架构实现,这个选型的权利很多时候被“下放”给了真正的开发团队。

值得一提的是采用DDD这种架构设计方法并不一定就产生Mircoservices这种架构风格,往往会推荐用大颗粒度的服务来包含业务分析过程中发现的不确定点,以避免拆分后变化过度频繁带来的双向修改成本。

跨职能协作的架构设计

业务和系统的渐进认知改变了很多之前的架构工作模式,在采用DDD的过程中,很容易感受到业务专家的重要性。而如果还有人寄希望让业务能够一次性给架构师讲清楚需求,那我建议抱有这样希望的同学去亲身参加一次自己不熟悉业务领域的架构设计讨论。你会很容易得出结论“原来业务也不懂他要什么”。当然业务人员听说要参加某种(软件)架构设计方法时心里也一定是抵触的。

DDD成功运用的基础就是创造让业务和系统这两种不同认知模型逐步统一的环境。

业务架构和系统架构设计

所以“不幸”的是如果你不能建立一个跨业务和技术的新型架构设计小组,你的DDD实践就没有成功的基础,继而采用微服务架构可能就会是一场灾难。幸运的是这种跨职能组织结构已经是前文中“采用”微服务架构企业(如Amazon)的标配,你不必再论证这件事情的可实施性。剩下的关键就是如何能够让不同背景的人们协作起来。这也是大家可以看到DDD领域的下一个热点,类似Event Storming这样的模式化协作工作坊会更多的出现在大家的视线里。

永无终止的DDD和演进的Microservices

DDD是容易上瘾的,当大家发现原来通过这个建模过程业务专家更了解服务划分(系统模块),架构设计更懂业务需求,这种协作会成为常态。在这个tech@core的时代,这样的融合将成为企业的核心竞争力。

当然刚开始采用DDD方法的时候,请不要认为每个系统搞一次所谓的DDD工作坊就能够找到最佳的服务划分了。业务的变化是持续的,而每次业务架构变化必然牵动系统架构的变化。良好的领域架构绑定了业务和系统,让双方人员能够用统一语言交流,这件事情建立不易,而持续运作更难。

成功的DDD方法运用是贯穿系统的整个生命周期的,这个过程中业务和技术的协作是持续发生的。

Microservices的最后一个特质:“演进式”设计 – 也明确了设计是一种持续的活动。DDD提供了一种符合这个微服务特质的工作方法,让演进能够落地。值得一提的是就笔者最近的经验,这个演进过程中最难认知到变化的就是DDD里最显而易见的“统一语言”。当大家形成了一个业务概念-“客户”后,少有团队能够持续审视这个“客户”是否随着市场的变化而发生了含义的变迁。

对比传统的SOA,微服务的拆分也是动态的,禚娴静在自己的文章中描述一个系统采用微服务架构历程中服务拆分的演变。这里不会有一个ESB来以不变应万变,这种幻想在过去的10年里已经被数次打脸。DDD的好处是让业务和技术人员都能够在合作中理解这种变化,而不至于陷入业务人员抱怨技术架构不知所谓,技术人员觉得业务人员朝三暮四的尴尬。

你需要成为那个高个子!

Martin Fowler在Microservies的定义文章中画了下面的图,评论“你必须有那个高度”来隐喻微服务实施的能力要求。就架构建模方面来说我认为DDD应该是一个团队必须去掌握的,包括这个团队的业务人员和产品设计人员。

微服务前置条件示意

很有意思的是目前Service Design也是全球用户体验设计领域的一个热门话题,从用户视角出发去设计整个服务链条。比如时下热门的共享单车,一个成功的服务设计应该是从用户开始有用车需求触发到最后完成骑行缴费离开,而不仅仅是去设计一辆能够互联网解锁的自行车。

我们可以找到很多Service Deisgn和DDD在原则上的相似之处,比如用户中心和协同设计。借用上面的高个子说法:

在业务需求认知和跨职能协作方面你一定需要成为高个子!


更多精彩洞见,请关注微信公众号:思特沃克

Share

微服务化小团队集群的组织和管理

随着微服务架构风格的流行,组织内部不可避免的产生了许多小规模团队,原来一个几十上百人的产品团队被拆分成了类似Amazon这样的2 pizza(6~10人)小团队。组织结构上也由之前的层级化职能团队设置变成了扁平的小团队集群。每个做这样调整的企业都希望借助小团队的灵活性在这个科技时代跟上市场变化和创新的脚步。

(组织的两种基本模式示意)

当然这样的组织方式本身就带来了一系列的挑战,技术实践方面Martin Fowler已经通过微服务的定义文章做了很形象的叙述,还用了“你必须长这么高”(You must be this tall!)来比喻在技术实践方面所需做出的投入。

在组织管理方面,越来越多的挑战被识别出来,把“自组织”当做银弹来回答这样集群小团队组织和管理中的问题是行业里存在的一个不好趋势。在最近和Matin Fowler的讨论中,我们达成共识的一点是:与其说微服务是一种技术架构,还不如说是一种企业组织架构

希望通过本文与大家一起研讨这样服务化小团队集群的组织和管理方法。

组织原则:对齐业务

科技时代带来的最大变化就是对变化本身的认知。在上一个时代,变化被认为是高成本甚至有害的,大家总是希望能够尽量减少变化,或者能够循序渐进地变化;而现在我们会认为变化是必然的,是会给我们带来新的市场机会的,甚至是会引发颠覆式创新的。

由于这样的认知变化,企业必须具备相应的灵活性,而扁平的小团队集群组织结构被不少企业(例如Google和韩都衣舍)证明是提供这种灵活性的有效组织方式。很多企业争相效仿,但不少会发现并没有得到之前追求的灵活性,反而做事情更为复杂了,以前一个接口部门变成了现在的多个团队。

作为咨询顾问,这两年经常接触到不少人抱怨划分成小团队后需求的实现成本增加很多,以前简单的业务需求现在要分解到很多“服务”团队才能完成。有的团队觉得这是技术问题 – 架构设计前瞻性不够;有的团队觉得是管理问题 – 没有跨团队的协调机制。而我往往喜欢从组织入手,让团队从业务需求出发,分析为什么那么多“集成”。

熟悉康威定律的同学可能已经理解我的用意了,以上团队出现的问题核心症结在于团队的组织结构和市场业务没有对应关系,大量的服务集成等同于把市场需求“翻译”适配到已有的组织结构。这样的痛苦在过去职能组织结构的时候就广泛存在,而错误的“服务化”只是把这种痛苦转换成了小团队之间的集成。

所以微服务化组织结构的核心原则是: 小团队的组织结构应该和市场业务对齐,并跟随市场业务变化而改变

稍微实例化一下以上的原则,比如最近一个客户的电商团队,100人左右规模。开始时候划分成了10人上下的小团队,每个团队负责几个服务,其中有几个“重要”服务,如customer(客户)和catalog(目录)。在一段时间里,几乎所有的需求都要经过这两个服务,工作量很大,团队实际上也根本不是十几人,而是几十人。团队告诉我:撑过这段高峰期模型就稳定了,以后就可以真正“微服务化”了(很多同学可能都有同样的幻想~)。

我用领域驱动设计的思想很快指出,就现在业务需求驱动出来的大量集成已经可以明确这些“重要”服务的划分是有问题的,新增加电子产品(比如点卡)的customer和之前的电商customer已经有不同的含义了,电子产品要求客户提供对应电子平台的账号和授权。按照上面的原则,不应该继续去扩充已有的customer服务,而应该重新分析新的业务模式下是否应该有新的服务(其中也包含新的customer模型)。

(不同的customer概念)

以上的例子在很多走向服务化组织结构的企业里比比皆是,而遇到问题时大家更容易从看似明确的技术或管理手段入手。这里希望读到此文的各位在遇到这样的挑战时别忘了康威定律。 管理原则:适应不确定性

《大教堂与集市》这本书中对比了两种不同的组织架构模式,很多特质也能够类比到单体架构和微服务架构之上。当微服务架构落地形成生态时(如Google),好比一个繁荣的集市,中央管理固然重要,但各个经营摊位却自主在为客户提供着琳琅满目的商品和服务。

作为一个企业,不太可能完全容忍集市一样的市场化,当然也有企业如海尔,把这种市场化更大程度上地引入到了内部。假设刚刚从过去职能层级组织结构转换到扁平小团队集群结构,这个时候管理者最大挑战就是如何还能够获取过去一样的“全面”信息。管理者往往会告诉我他们感觉到随时可能失控,因为每个团队都没有统一的开发方法和流程。

很不幸的是大多数从MBA课堂走出的企业管理者们都是管理“大教堂”建设的高手,却很难驾驭集市带来的“混乱”。然而我们的管理者们又都渴望着自己的企业能够有创新的环境。根据创新理论(Edge of Chaos),集市混乱产生创新的可能要远大于大教堂的整齐划一。那么在这个你不创新就被别人创新颠覆的时代,管理者就必须正视这个挑战。

管理的原则应该改变为: 放弃对掌控全局的虚幻追求,拥抱不确定性带来的挑战和机遇

同样实例化一下上面的原则,一个300多人的大产品经理与我谈他的困惑,自从转型成为扁平小团队结构后,他的会议比之前多了N倍,基本每天正常工作时间全部在开会。自己的产品方向和运营只能靠夜深人静的时候加班。他告诉我如果这就是所谓小团队要付出的代价,那么他觉得这事儿没法持久。

我首先肯定了他的观点,即如果作为产品经理都没有时间看产品方向和运营,那么模式上肯定是错了。进而询问最占用他时间的会议需要他做什么?很有意思的是他的答案是“我需要知道xxx信息才能保证计划的拉通”、“开会已经同步各个小团队最高效的方式了”… 这里表达出来的行为全部是希望掌控全局的急迫,和他嘴巴里说出的赋权团队、打造自组织文化大相径庭,当然知行合一本身就是困难的。于是我们花了很多时间来讨论为什么一定要有拉通的计划、为什么要中央同步各个小团队 … 这位管理者最后带着更多的困惑离开了那次讨论。

对比组织结构的调整,管理者思想和方法的转型确实任重道远。我往往给出的建议是从小处着手,比如放弃给每人安排任务,让大家自己来选择;又比如在团队之间冲突时,放弃作为管理者的“拍板权”,让团队通过快速实验来验证哪种方式更好。另一位大师级同事Jim Highsmith在八年前就总结出了适应性领导力(Adaptive Leadership),十年后的今天仍是少有管理者能够真正践行。

合作原则:简化集成关系

微服务下小团队集群的结构不可避免的需要更多的团队合作。一个运作良好的微服务生态圈背后是一个紧密协作的小团队网络,而团队之间的合作就是这个网络里无形的手。合作很多时候是团队和团队在运营过程中实时发生的,并非是预先设定或中央控制的,这个时候如何高效合作就成了一个很大的挑战。

在共同满足业务需求的过程中,大多数的合作是由于实现过程中服务之间的集成关系产生的。如前面讨论组织结构时的案例,很多组织在转型后反而集成多了,造成交流沟通成本持续增高,最后不得不安装很多会议和流程来“协调”这样的合作。结果当然是响应力越来越差,小团队名存实亡。

在团队合作方面DDD(领域驱动设计)原书中提出的(业务)限界上下文(Bounded Context)的关联关系可以借鉴。服务划分强调从业务视角出发,限界上下文提供了很好的划分指导,即可以根据限界上下文来设计相关的服务边界。由于每个服务对应一个小团队,那么实际上我们就建立了团队之间集成关系的模式。Eric Evans用了一个子章节描述了不同的基于领域模型耦合方式的关系模式(248页14.4),并零散地叙述了几个模式的演进场景,很多读者可能都不会特别关注那个章节。然而在微服务开始落地实施的时候,这些模式就变得十分重要了,因为这些模式本身也是团队之间的合作模式。

(限界上下文关系模式要求矩阵)

Eric Evans通过上面的矩阵总结告诉我们集成是高成本的,要尽量避免集成。同样道理在咱们团队合作的过程中,原则也是简化集成关系。在微服务架构下,显然右上角的“大泥球”(Single Bounded Context)和“共享内核”(Shared Kernel)是不推荐的;“独立自主”(Separate Ways)这种完全松耦合的关系是值得我们考虑的,但大多数情况下小颗粒度的服务之间还是会被不同的业务需求串联起来。

很多刚转型的企业会出现不少的“用户/供应商”(Customer/Suppier Teams)模式,主要是团队之间关系还是由更高层的领导在指挥,作为一个演进的合作关系应该更进一步向“开放主机服务”(Open Host Service)模式推进。现代的服务多是以API的形式更为规范的对外提供接口,所以其实在团队沟通方面的成本并非比领导中央决策高多少。

随着API规范的更进一步发展(如采用RESTful架构),很多时候服务团队之间只用做简单的翻译或遵从提供者的模型即可,耦合程度进一步下降,这个时候左下角的另外两种模式“防护层”(Anticorpution Layer)和“跟随者”(Conformist)就更为常见了。显然这两种模式集成关系更为简单,合作过程中调用服务的团队是不需要知道提供方的内部模型细节的,当然这个时候团队之间的信任关系也应该是相当高的。

服务化转型小结

采用微服务架构后自然会产生小团队扁平化组织结构,我们应该意识到在组织、管理、合作的原则及思维观念上都应该发生转变,忽略任何一个方面最终都会造成转型的失败。

  • 在组织结构上,团队划分要面向业务能力,持续提供市场价值。
  • 在企业管理上,管理者要拥抱不确定性,持续提升管理适应力。
  • 在团队合作上,考虑跨团队领域模型的耦合,持续简化集成关系。

更多精彩洞见,请关注微信公众号:思特沃克

Share