深入理解领域驱动设计中的聚合
作者 | 嵩华来源 | 阿里技术公众号聚合模式是 DDD 的模式结构中较为难于理解的一个,也是 DDD 学习曲线中的一个关键障碍。合理地设计聚合,能清晰地表述业务一致性,也更容易带来清晰的实现,设计不合理的聚合,甚至在设计中没有聚合的概念,则相反。聚合的概念并不复杂。本文希望能回到聚合的本质,对聚合的定义和实操给出一些有价值的建议。一 聚合解决的核心问题是什么我们先来看一下在 DDD Reference 中关于聚合的定义。将实体和值对象划分为聚合并围绕着聚合定义边界。选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制。这是典型的“模式语言”,说明了聚合是什么,聚合根(aggregation root)是什么,以及如何使用聚合。但是,模式语言的问题在于过度精炼,如果读者已经熟悉了这种模式,很容易看懂,但是最需要看懂的、那些尚不够熟悉这些概念的人,却容易感到不知所云。为了能深入理解一个模式的本质,我们还是要回到它试图解决的核心问题上来。在软件架构领域有一句名言:“架构并不由系统的功能决定,而是由系统的非功能属性决定”。这句话直白的解释就是:假如不考虑性能、健壮性、可移植性、可修改性、开发成本、时间约束等因素,用任何的架构、任何的方法,系统的功能总是可以实现的,项目总是能开发完成的,只是开发时间、以后的维护成本、功能扩展的容易程度不同罢了。当然现实绝非如此。我们总是希望系统在可理解、可维护、可扩展等方面表现良好,从而多快好省的达成系统背后的业务目标。但是,在现实中,不合理的设计方法有可能增加系统的复杂性。我们先来看一个例子:假设问题领域是一个企业内部的办公用品采购系统。企业的员工可以通过该系统提交一个采购请求,一个请求包含了若干数量、若干类型的办公用品(称为采购项)。(1)主管负责对采购申请进行审批。(2)审批通过后,系统会根据提供商不同,生成若干订单。(3)对同一个问题,存在若干种不同的设计思路,例如以数据库为中心的设计、面向对象的设计和“正确的 OO”的 DDD 的设计。如果采用以数据库为中心的建模方式,首先会进行数据库设计——我确实看到还有许多团队仍然在采取这种方法,花费大量的时间进行数据库结构的讨论。为了避免图表过大,我们仅仅给出了和采购申请相关的表格。结构如下图所示:图1 数据库视角下的设计如果直接在数据库这么低的设计层次上考虑问题,除了数据库的设计繁琐易错,更重要的是会面临一些比较复杂的业务规则和数据一致性保证的问题。例如:如果采购请求被删除,则相应的和该采购请求相关的采购项以及它们之间的关联都需要被删除——在数据库设计中,这种约束可以通过数据库外键来保证。如果多个用户在对具有相关关系的数据进行并发处理,则可能涉及到复杂的锁定机制。例如,如果审批者正在对采购请求进行审批,而采购提交者正在对采购项进行修改,则就有可能导致审核的数据是过期数据,或者导致采购项更新的失败。如果同时更新某些相关联的数据,也可能面临部分更新成功导致的问题——在数据库设计中,这类约束则需要通过 transaction 来保证。确实,每个问题都是有解决方案的,但是,第一,对于模型的讨论过早地进入了实现领域,和业务概念脱开了联系,不便于持续地和业务人员协作;第二,技术细节和业务规则的细节纠缠在一起,很容易顾此失彼。有没有一种方案,可以让我们更多的聚焦于问题领域,而不是深陷到这种技术细节中?面向对象技术和 ORM(对象-关系映射)有助于我们提高问题的抽象层级。在面向对象的世界中,我们看到的结构是这样的:图2 传统OO视角下的设计面向对象的方式提高了抽象层级,忽略了不必要的技术细节,例如已经不需要关心外键、关联表这些技术细节了。我们需要关心的模型元素的数量减少了,复杂性也相应减少了。只是,业务规则如何保证,在传统的面向对象方法中并没有严格的实现约束。例如:从业务角度来看,如果采购申请的审批已经通过,对采购申请的采购项进行再次更新应该是非法的。但是,在面向对象的世界中,你却没法阻止程序员写出这样的代码:...
PurchaseRequest purchaseRequest = getPurchaseRequest(requestId);
PurchaseItem item = purchaseRequest.getItem(itemId);
item.setQuantity(1000);
savePurchaseItem(item);语句 1 取得了一个采购申请的实例;语句 2 取得了该申请中的一个条目。语句 3 和 4 修改了采购申请条目并保存。假如采购申请已经审批通过,这种修改岂不是可以轻易突破采购申请的预算?当然,程序员可以在代码中加入逻辑检查来保证一致性:在修改或保存申请条目前总是检查 purchaseRequest 的状态,如果状态不为草稿就禁止修改。但是,考虑到 PurchaseItem 对象可以在代码的任何位置被取出来,且可能在不同的方法间传递,如果 OO 设计不当,就可能导致该业务逻辑分散到各处。没有设计约束,这种检查的实现并不是一件容易的事情。让我们回到本质思考:采购项如果脱离采购请求,它自身的单独存在有价值吗?——没有价值。如果没有价值:名义上看起来对采购项的修改,本质上是对采购项的修改吗?还是本质上其实是对采购请求的修改?如果我们认可“修改采购项也是修改采购请求”这个结论,那么我们就不应该分开来研究采购项和采购请求,而是应该如下图所示:图3 用聚合封装对象我们把“采购请求”和“采购项”组织到一起,看做一个更大的整体,称为“聚合”。这个聚合内部的业务逻辑,例如“采购申请审核通过后,不得对采购申请条目进行更改”,应內建于聚合内部。为了实现这一目标,我们约定:对采购项的一切操作(增加、删除、修改等),都是对采购请求对象的操作。也就是说:在 DDD 的世界中,从来就不应该存在 savePurchaseItem() 这种方法,而应以 purchaseRequest.modifyPurchaseItem() 和 purchaseRequestRepository.save(purchaseRequest) 取代之。在新的对象关系中,采购申请负责“把守关隘”(即“聚合根”),采购条目成为了聚合的内部数据。由于聚合现在已经是一个整体,与其相关的操作只能通过采购申请对象进行,业务一致性就可以得到保证。这事实上也是关于对象之间关系的更精确的描述:虽然采购申请和采购项都被建模为对象,但是它们的地位是不对等的。采购项是从属于采购申请的对象,它们只有是一个整体才有意义。聚合的本质就是建立了一个比对象粒度更大的边界,聚集那些紧密关联的对象,形成了一个业务上的对象整体。使用聚合根作为对外的交互入口,从而保证了多个互相关联的对象的一致性。合理使用聚合,可以更容易地保证业务规则的一致性,减少了对象之间可能的耦合,提升设计的可理解性,降低出问题的可能性。所以,通过把对象组织为聚合,在基本的对象层次之上构造了一层新的封装。封装简化了概念,隐藏了细节,在外部需要关心的模型元素数量进一步减少,复杂性下降。但是,封装边界的引入也引发了一个新的问题,例如:商品信息也是采购项的有效部分,应不应该把商品也放入“采购请求”这个聚合呢?提交人和审批人是不是也该放入聚合呢?如果要便利地获得业务规则的一致性,那岂不是把一切存在业务关联的对象都应该放在一起更好?如果有些对象应该放入聚合,有些不应该放入聚合,那么是否存在一个清晰的指导原则?本文在下一节回答这个问题。二 聚合划分的原则聚合作为 DDD 的对象体系中的一层,也同样应该遵循高内聚、低耦合的原则。本文认为,聚合边界内的对象应满足如下的启发式规则:生命周期一致性问题域一致性场景频率一致性聚合内的元素尽可能少1 生命周期一致性生命周期一致性是指聚合边界内的对象,和聚合根之间存在“人身依附”关系。即:如果聚合根消失,聚合内的其他元素都应该同时消失。例如,在前述例子中,如果聚合根(采购请求)不存在了,那么采购项当然也就失去了存在的意义。而商品、作为申请人的用户等对象,和采购请求之间则不存在此关系。可以用反证法来证明生命周期一致性:如果一个对象在聚合根消失之后仍然有意义,那么说明在系统中必然需要存在其他方法访问该对象。这和聚合的定义相矛盾。所以聚合根内的其他元素必然在聚合根消失后失效。违反生命周期一致性,也会同时带来实现上的严重问题。让我们一起看一个例子:其中 User 对象的生命周期和采购申请不一致。现在假如有两段程序代码并行执行:代码 1(例如采购申请的修改)获得了某个采购申请的对象,对该对象进行了修改,进行保存。注意由于 User 对象嵌入到了 PurchaseRequest 中,User 对象也会被同时保存。r = purchaseRequestRepository.findOne(id);
//...一些修改
purchaseRequestRepository.save(r);代码 2(例如是用户管理),获得了该对象对应的审批人的信息,也进行了修改。User user = userRepo.findOne(r.getSubmitter().getId());
//...一些修改
userRepo.save(user);这将会导致一种完全不可接受的后果:对于 User 对象的修改不确定性!因此,对于那些说不清楚是否应该划入同一个聚合的对象,不妨问一下:这个对象如果离开本聚合的上下文,是否还有单独存在的价值?如果答案是肯定的,该对象就不应该划到本聚合中:Submitter/Approver 对应的 User 对象脱离了 PurchaseRequest,仍然有单独存在的理由。Product 对象脱离了 PurchaseRequest,是可以单独存在的。所以以上两个对象都不属于采购申请这个聚合。2 问题域一致性第二个原则是问题域一致性。事实上问题域一致是限界上下文(Bounded Context)的约束。聚合作为一种战术模式,所表示的模型一定会位于同一个限界上下文之内。虽然原则一说明了对象的生命周期一致性可作为聚合划分的依据,但是什么是”一个对象脱离另外一个对象是否有存在的意义“,有时候可能会存在争议。例如:如果采购申请被删除,那么根据此采购申请生成的订单是否有价值?(由于订单这个例子可能会陷入另外一种争论,它可以从业务流程上规避:只要订单存在,采购申请就不能删除),让我们换一个非常近似的例子:一个在线论坛,用户可以对论坛上用户的文章发表评论。文章显然应该是一个聚合根。如果文章被删除,那么,用户的评论看起来也要同时消失。那么评论是否可以属于文章这个聚合?现在让我们来考虑评论是否还可能有其他的用途。例如,一个图书网站,用户可以对图书发表评论。如果只是因为文章删除和评论删除之间存在逻辑上的关联,就让文章聚合持有评论对象,那么显然就约束了评论的适用范围。一目了然的事实是,评论这一个概念,在本质上和文章这个概念相去甚远。所以,我们得到了一个新的、凌驾于原则 1 之上的原则——不属于同一个问题域的对象,不应该出现在同一个聚合中。对 DDD 熟悉的朋友可能知道,这在 DDD 中对应于限界上下文这一战略模式。限于文章篇幅,我们在此不过多展开。图4 问题域一致性由于聚合根无法保证聚合之外的一致性,所以我们需要依赖”最终一致性“来实现聚合之间的一致性。例如,在文章删除的时候,发送一个文章删除的消息。评论系统接收到文章删除消息之后,删除文章对应的评论。3 场景频率一致性依赖于前述两个原则已经能够区分出大多数聚合。但是,仍然会存在一些比较复杂的情况。例如,考虑软件开发中的“产品”和“版本”以及“功能”的关系。“产品”和“版本”算不算是同一个问题域?——这几个概念之间的关系可能就不如“文章”和“评论”那么清晰。不过不要紧,我们仍然有一个启发式规则来规避这种模糊性。这就是“场景频率一致性”原则。场景(scenario)是业务用例的具体化描述,反应了用户使用系统达成业务目标的方式。我们可以观察这些场景中涉及的领域对象操作,如对领域对象的查看、修改等。场景操作频率的一致性是同一聚合内部对象的一个关键表征。经常被同时操作的对象,它们往往属于同一个聚合。而那些极少被同时关注的对象,一般不应该划为一个聚合。以下图所示的“产品”、“版本”和“功能”这三个概念为例来说明。产品确实包含了很多功能,这些功能通过一系列的版本发布。但是,在产品层面的操作,例如查看所有的产品列表,却并不需要关心特定功能的详细信息,也不需要了解特定的某个版本信息。我们做版本规划的时候,确实会用到功能列表,但是大多数时候我们并不会去查看功能详情,更加不可能在做版本规划的时候修改功能描述。图5 不合适的聚合根据这一原则,我们划分出了如下的三个聚合:图6 更合理的聚合基于场景一致性划分聚合,对于实现也有很大好处。不在同一个场景下操作的对象,放入同一个聚合意味着每次操作一个对象,就需要把其他对象的所有信息抓取到,这是非常没有意义的。从实现层次,如果不紧密相关的对象出现在同一个聚合中,会导致它们经常在不同的场景中被并发修改,也增加了这些对象之间冲突的可能性。所以:操作场景不一致的对象,或者说如果一个对象在不同场景下都会被使用,应该考虑把它们分到不同的聚合中。4 尽量小的聚合聚合出现的本质是解决一致性问题带来的复杂性。因此,那么凡是不破坏以上三个一致性的情况,都没有必要把它们放到同一个聚合中。仅仅由一个业务概念(即领域模型中的类名及属性以及后面马上提到的 Id 对象)构成的聚合在面向对象的世界中是大多数。根据上述分析,在采购申请的例子中,采购申请、采购申请的一些属性(如状态、提交时间等)以及采购项属于一个聚合。但是,商品、用户这些不能属于采购申请这个聚合。这些聚合之间如何关联起来呢?我们引入一种新的值对象来解决这个问题,如下图所示。图中也顺便标记了各对象是值对象还是实体对象。图7 精化后的聚合封装在采购请求这个聚合中,除了采购请求聚合根是实体对象外,其他对象,包括作为对外引用的 Id 对象都是值对象。对应的代码如下:Id 值对象的引入是一个值得讨论的问题。首先,Id 值对象的引入能断开聚合,能加快查询的速度,但是它不可避免的会导致某些场景下,需要对信息进行第二次查询,而且无法利用 ORM 的 EagerFetch/LazyFetch 加载机制的遍历。这是一种损失吗?简单地回答是:不是损失。不要贪图不属于一个聚合的对象层次嵌套带来的所谓便利——它引起的麻烦要远远多于带来的益处。这类问题应该由外部服务,例如应用层服务来完成。其次,为了断开聚合而额外引入的 Id 值对象,还能算是领域模型或者是 “统一语言” 的一部分吗?我对这一问题的解释是:这是 DDD 的实现机制的一部分,它属于领域模型,但是请把可见性控制在开发团队。没有必要和业务人员沟通这些概念。仅仅使用问题域识别出的实体、值对象、领域服务和领域事件和业务人员进行沟通。Id 值对象、资源库和工厂以及聚合、聚合根这些概念留给实现人员自己理解和在实现中使用就可以了。它们仍然是领域模型的一部分,它们的存在也仍然是统一语言的一部分,但是正如视图可以有选择地忽略部分信息一样,这些概念应该在和业务人员的沟通以及业务描述时忽略。第三,请注意这个 Id 对象引用的只能是其他聚合根的 Id。由于只有聚合根才可能会被外部引用,所以聚合根的 ID 应该做到全局唯一。聚合内部的对象,无论是实体对象还是值对象,都只需要保证内部的 ID 唯一即可。三 实现方面的考虑1 资源库、工厂面向聚合定义工厂(Factory)模式、资源库(Repository)模式都是 DDD 在实现维度的模式。尽管在 DDD Reference 给出的模式关系图中,工厂、资源库除了与聚合之间有连接之外,与实体之间也有连接,甚至工厂和值对象之间也有连接,但是,本文认为,这些连接的强度是不同的,价值也是不同的。工厂模式的存在显然是为了分离对象的构造与使用,但是在 DDD 的上下文中,它包含了更深层面的意义。聚合内部的对象直接的关系可能是复杂的,业务一致性是需要保证的,那么使用工厂来构造聚合对象是一种更好的对复杂性的封装。诚然,工厂模式对于非聚合跟的复杂的体对象和值对象的构造也有价值,但这只是设计或者实现层面的事情,和业务模型扯不上什么关系。尽管聚合的工厂和一般对象的工厂都是以工厂模式同名,但是 DDD 以聚合为基本单位设计的 Factory 对于简化系统的复杂性具有更重要的意义。从设计约束上,在聚合以外,只应该有一个工厂对外可见,那就是聚合的工厂。(领域事件的 Factory 也是有意义的,领域事件离本文的话题稍远,暂且不做讨论)。资源库模式也绝非只是意味着持久化,更不是数据库访问层,所以不要误解。资源库更重要的意义是:资源库是聚合的仓储机制,外部世界通过资源库,而且只能通过资源库来完成对聚合的访问。资源库以聚合的整体管理对象。因此,从设计约束上,一个聚合只能有一个资源库对象,那就是以聚合根命名的资源库。除此之外的其他对象,都不应该提供资源库对象。图8 聚合和资源库2 代码结构与聚合保持一致细心的读者肯定已经发现了,在上图中包的组织方式也是和聚合一致的,并且使用了聚合根的名字作为包名。这是我本人组织代码时的惯用方式,把聚合作为代码的一个层级(之上当然存在其他层级,例如限界上下文、模块等),把所有属于该聚合的实体(包含聚合根)对象、值对象、资源库、工厂等都放入到同一个代码包中。代码结构和领域模型的结构高度一致,可以降低表示差距,更好的管理对象世界的复杂性。3 聚合不可跨越部署的边界部署的边界是一个复杂的话题,本文仅就和聚合有关的内容进行讨论。首先,如果系统采用了微服务架构,应该保持部署边界和限界上下文边界的一致——不要让部署的粒度大于限界上下文的粒度,这样可以带来更好的业务灵活性和可伸缩性。其次,从服务的最小边界上,不可让最小边界小于聚合的粒度,否则会带来大量的数据的一致性问题——因为微服务之间的一致性一般需要通过最终一致性来保证,如果聚合跨越了部署边界将会是一致性的灾难。曾经在某些书上看到一些关于关于微服务划分的不甚合理的建议,例如把对每一个对象的增删改查都做成一个服务。这种建议在我看来是错误的。4 聚合改进了系统性能和可伸缩性很多人会为 ORM 机制中低效的查询所困扰。为什么会这样?看一下前面的例子就明白了。我们为前述的不正确的聚合的例子加上 Spring JPA 的 Annotation:由于缺乏聚合的概念,或者不正确的做了一个超大的聚合,那么每次对 PurchaseRequest 的查询,都需要从系统抓取大量的对象,耗费了大量的计算资源——也许 User 自己也是一个超大的对象呢?“拔出萝卜带出泥”,性能自然不可能好。也许有读者会说,我不用 Eager Fetch,我可以用 Lazy Fetch 啊。是的,这确实对性能上更好一些,但是不幸的是,数据访问的上下文将不得不一直保留,系统出错的概率大大增加,也给分布式设计带来了不便。小的聚合就完全没有这个问题了——在这种情形下,每个涉及访问的对象(事实上就是聚合)不可能很大,而所需的数据又恰如其分的都在,数据完整性和业务完整性就有了保障,还可以方便地进行水平扩展,性能和可伸缩性也就同时得到了满足。四 总结建模是我们理解现实世界,简化问题复杂性的方法之一。聚合作为领域建模的一个层次,通过恰如其分的边界,实现了信息隐藏、提高了抽象层级,封装了紧密关联的业务逻辑,保证了系统数据的一致性,改进了系统的性能。本文讨论了聚合的定义和价值,概括的说:聚合是面向对象的世界中建模的一个层次。它隐藏了细粒度对象,约束了对象之间的耦合。聚合是一致性的边界,是对具有紧密关联关系的对象的封装。聚合封装了实体对象和值对象,并且采用其中最重要的一个实体对象作为聚合根。聚合根作为聚合的唯一外部入口,保证了业务规则和数据的一致性。本文也探讨了关于聚合识别的四条启发式规则,具体是:生命周期一致性问题域一致性场景频率一致性聚合内的元素尽可能少从实现角度,资源库、工厂的粒度应该和聚合的粒度一致,代码结构和部署结构也可以和聚合对齐。实现和领域模型保持一致,这也是领域驱动设计作为正确的 OO 的目标和价值所在。【2021阿里巴巴研发效能峰会】开放报名6月23日,阿里巴巴合伙人、IBM副合伙人、德勤云服务首席架构师、PMI业务副总裁等,近30位海内外大咖分享效能趋势和实践,云原生、低代码、智能化、未来架构、DevOps、数字化转型1200分钟精选干货汇聚,和你一起感知行业技术水位,洞悉未来发展态势。点击这里,免费预约吧~
「技术人生」第4篇:技术、业务、组织的一般规律及应对策略
往期技术一号位方法论系列文章:「技术人生」第1篇:什么是技术一号位?「技术人生」第2篇:学会分析事物的本质「技术人生」第3篇:解决问题的规律总结本期文章篇幅较长,建议收藏阅读。背景本期文章将接上期《「技术人生」第3篇:解决问题的规律总结》继续探讨技术、业务、组织的一般规律及应对策略。需要注意的是,以下内容为个人实践结果的总结和分析,受限于个人能力和经验有限,在描述规律的过程中,可能会存在维度的缺失;或者当前描述的规律所涉及的维度并不是某些读者认知中的重点,因为事物不同的维度在不同角色和级别的人的认知中重要程度不同,即:PD和研发对于同一件事情的侧重点不同;P6到P11对于同一件事情,很大概率看重的侧重点不同,我们特别欢迎不同层次的同学分享你眼中的规律出来指引其他人实践。而对于今天本文接下来要讨论的内容,需要大家辩证地去看待,并且在讨论初始需要重新对齐当前事物的讨论范围:当前对组织、业务和技术的规律的探讨,限定在“技术团队leader带领研发团队负责某个业务或负责某个业务的一部分”的情况下,“技术”一词指代研发人员使用的信息化技术;“业务”一词指代研发人员使用信息化技术解决的问题域的统称,“组织”一词指代技术团队 Leader 带领的团队(可能是跨团队的组织)。同时仍然需要注意的是:上述范围中提到的组织、技术、业务没有加上“规模”相关的限制,可以理解为,任何规模都符合下面探讨的规律,即我们探讨的是一般规律。同时,不同规模,即团队规模、业务规模、技术深度本质上都是特殊条件,特殊条件的存在可能会触发特殊的规律,但是还是那句话,特殊规律存在并不影响对一般规律的讨论。并且受限于本人当前实际的实践情况,不同规模所触发的特殊规律并没有全部都直观感受过(实践缺失),也没有看过类似的书籍(理论输入缺失),所以不在本文内进行相关特殊规律的探讨。不排除未来有了更多的实践会来完善,同时更欢迎有实践经验的人整理总结成规律分享出来。上述范围中提到的分析问题的主体是技术 leader,所以对于其他角色类型的同学而言,探讨之后形成的结论需要辩证地去理解,可能有很大部分都是相通的(注意不是相同,而是相通,意味可以相互借鉴),但是同时也有一部分是不适用的,是和探讨的主体本身的特殊性相关的。而这种特殊性对于其他类型的角色并非没有意义,恰恰相反,这可能是比较宏观地、直接地了解另外一种角色的非常有效的途径。即运营一号位或产品一号位或业务一号位可以看到技术一号位所负责的事情中的一般规律和特殊规律,而一般规律大概率相通,而了解特殊规律是理解彼此差异性的在宏观层面的认知。业务的发展规律及应对策略业务的发展规律业务的生命周期如下图所示:看图时,需要注意以下内容:图中的曲线仅用于定性分析,非定量分析的精确图表,因此生命周期中各阶段的长度、和业务规模、利润规模的比例关系也都是示意型的,而非精确的比例关系。不同的业务,生命周期长短可能不同,各阶段持续的时间也不同,业务方期望各阶段持续时间长短也不同,需要具体问题具体分析。不同的业务,利润出现的时间和业务生命周期的阶段对应关系不同,利润规模和生命周期各阶段对应关系也不同,需要具体问题具体分析。在此基础上,我们简单用语言讲清楚业务发展过程是怎样的:启动期启动期可以粗略分为立项期和验证期。立项期一般都是业务侧如PD或者运营发起,要做很多事情,例如围绕业务产生的价值是什么、目标客户是哪些、如何交付给客户、如何收取对应的费用继而维持业务运转下去,这个过程往往还需要结合大环境的要求补充更多细节,即当前事物的主要矛盾次要矛盾的分析解决要符合大环境的主次矛盾,即当前事物发展规律遵循于事物所属大环境的发展规律,因此需要结合组织战略、组织价值、业务所属大业务的战略目标等一系列大环境的要求来完成立项信息的准备。如果继续探讨,就会涉及到这个探讨事物的本质分析,我们后面有精力的情况下会新开文章去分析,本篇内容不再展开。这个阶段的主要作用就是通过合理的业务模式设计拉通各方对新业务的认知,获取组织的支持。优秀的技术一号位会在这个阶段就介入进来,为业务发起者,通常是业务一号位,提供必需的技术视角的分析和支持。验证期一般是在立项通过后。主要是通过快速的产品原型的实现,证明业务模式是行得通的,证明业务或产品是能解决客户问题,并且目标客户群体的客户代表是愿意为这种产品付费的。这个阶段一般会投入大量的研发人员来做对应的信息系统来支撑业务的运行。研发团队一般从这个阶段开始做深度介入,并且相较其他角色的团队而言,研发团队在该阶段是主角。发展期当启动期内完成了价值证明之后,接下来的重点就是如何将单个客户验证的业务模式快速地规模化复制到更多的客户场景中,从而能够让业务在一定时间内完成业务规模的爆发。研发团队在这个阶段会主要处理系统完备性的问题,因为涉及到越多的客户,新的共性的场景就会越多,为了承接规模化的用户而需要补充对应的业务场景的支撑。这些补充的业务场景,往往是技术系统核心领域的补充以及支撑。同时,这个阶段的主角不再是研发团队,意味着研发团队的表现逐步从主要行动方逐步转变到幕后成为基础参与方,而其他团队如运营、PD、销售、客服等团队会共同入场相互协同构成当前阶段的主角。所以研发团队除了支持客户本身的业务需求外,还承担着业务上下游协作角色的需求的信息化任务,这一点往往是新手技术一号位可能会忽视的点。平台期当业务通过规模化复制推广形成一定规模以后,增长会逐步受限于目标客户群体规模,规模增长达到上限,逐步趋于平缓,同时利润曲线也应该在此阶段之前转正并且在当前阶段达到最大。这个阶段追求的不再是规模化增长,而是开始继续追求利润的最大化,降本提效往往变成该阶段的主旋律,而很多业务环节和参与方也往往会在“降本”提出以后,出现较多的矛盾,出现较多的问题,本质上是之前的几个业务阶段中留下的隐患,即:为了达到业务目标而采用了看似当时合情合理但是实际上对整体有害的方式。这个问题看似是短期利益和长期利益的冲突,但是对于技术一号位而言,需要寻找既能满足长期利益又能兼顾短期利益的方案,并且一定是以长期利益为主旨的,作为主要做事原则的,而不能反过来。其他的业务参与方应该保持同样的认知,并以之作为实际行动原则。业务进入平台期之后,随着整个业务进入成熟周期,很多流程逐步完善,组织支撑逐步形成体系,这套配套的组织和流程能让业务继续平稳地发展下去,并且尽可能维持成熟期的长度,但是同样也会带来新的问题,即组织僵化后,业务对市场、客户的变化的感知敏感度下降;针对客户、市场变化的决策被延迟或者阻滞;最终结果就是业务当初产生的价值不再能够满足目标群体的要求,如果不做任何调整和干预的话,业务进入衰退期是必然的。这个阶段,业务和技术都不是破局的关键,而是组织本身。衰退期业务进入衰退期没啥好说的,技术团队需要考虑的一个问题就是,业务经历完整的生命周期而做没了是自然规律,那么对应的技术是否也需要随着业务的消亡而消亡?如果技术和业务耦合度太高,那么业务消亡自然会牵连技术,而导致后续新的业务无法利用起来。所以不论从哪个方面考虑,都需要在技术设计和实现过程中,将技术体系进行系统性的、结构性的分层,底层的通用技术和通用的业务服务本身要做到业务无关,而业务相关的部分要构建成通用的业务领域,确保业务变化以后,领域仍然是可用的,因为业务领域本身是业务内核的反馈,只对业务本质相关的事情负责;而最上层的和产品展示层相关的内容都约束到最上层的业务应用中,业务应用中对产品的展示和交互负责,对场景化的技术需求负责。消亡期如果业务进入消亡期没啥好说的,及时转身止损,投入合理的资源善后即可。各阶段的主要矛盾次要矛盾分析在整个业务开展过程中,不同阶段的主要矛盾不同,不同的矛盾需要用不同的方式解决。我们这里只探讨最基本的情况,为的是寻找规律。在实际业务的开展过程中,很可能业务属于某个阶段,但是在其他条件的作用下,主要矛盾发生了变化,这一点并不意味着我们今天讨论的内容没有意义,因为矛盾的普遍性和矛盾的特殊性本身都是客观存在的,不能因为特殊性而忽视普遍性,当然也不能因为了解了普遍性,就不再关注特殊性。启动期:前半段有无是主要矛盾,业务价值证明是次要矛盾;后半段业务的价值证明是主要矛盾(业务是否可行),业务规模化发展、大规模获取收益是次要矛盾。发展期:业务规模化复制从而高效创造商业价值是主要矛盾,业务成本控制和价值变现效率是次要矛盾。平台期:业务成本和价值变现效率是主要矛盾,其他问题是次要矛盾(组织等)。衰退期&消亡期:业务进入平台期,如果不能够基于过去的业务求变求新适应新的市场环境,则业务很快会衰落,则业务的可持续发展就成了业务的主要矛盾。各阶段的应对策略及如何打破规律3.1 从总体上看如何打破规律业务生命周期的各阶段并不是一定必须要串行的,也不是有明确的界限的,所以对于某些业务,可以多阶段并行推开。比如业务一号位可以从一开始就基于过去的业务经验和组织经验提供业务保障的流程和规范,在业务进入平台期之前即具备相关的组织保障能力;技术一号位可以在开始即构建良好的架构设计,关注业务特征,了解业务特征对技术架构的影响,也了解不同业务阶段对技术架构的影响,从而在起步阶段即完成整体设计,从而让架构设计具有前瞻性,同时基于实际情况逐步推进架构向终态的演进。简而言之,就是:既然知道了后面哪些事情必须要干,那么在最开始的时候在解决主要矛盾的时候就顺手逐步干掉,而不是非要反复地踏入业务倒逼技术架构改变的圈子里面。在生产力有限的情况下,可以加速某些阶段,压缩这些阶段持续的时间,但是永远要知道它是无法跳过的。作为业务一号位或者技术一号位,要知道在不掌握更高的生产力的情况下,业务每个生命周期都是不可跳过的,主观能动性不能让某个阶段凭空消失,加人进来也不能让某个阶段凭空消失,都只能是用资源成本来换时间。要么就是压缩那些投入期的环节;要么就是延长那些回报期的环节,但是无论如何不能改变这些环节原本的生命周期。所以当决策者发现主观能动性和砸人进去都不好使,都不能达到你想要的效果的时候,很大可能不是团队执行力不够强,而是做执行的人生产力不够高,至于为什么生产力不够高,是受到了生产关系的制约,还是本身在生产力方面的投入不足所以积累有限,那就要具体问题具体分析了。当然还有一种可能,就是决策者自己不知道自己做的事情的客观规律是什么,主观认知上达不到这个高度,所以只能出于个人意愿和想象来提出不切实际、不符合规律的要求。当然,辩证地去看,即便是这种最极端的情况出现了,也最终还是因为生产力不够先进,如果足够先进了,再夸张的要求、再不切实际的要求其实都能实现。在生产力很先进的情况下,可以跳过某些阶段,或者延续某些阶段的持续时间,但是要关注高生产力带来的成本问题。在生产力提高到一定程度的时候,业务生命周期内的某些环节可以借助生产力跳过,而这种跳过并不是这个环节凭空消失了,而是已经被高级的生产力做掉了。例如可以利用成熟的中间件服务来解决分布式系统中的各种问题,而不需要重复重新做一遍。先进的生产力本身形成也是有其自有的生命周期和阶段的,在初步出现阶段,先进生产力带来的各种成本肯定是高的,甚至会高到无法大规模推广,而随着先进生产力本身不断发展,随着周围环境对先进生产力的适配,先进生产力的使用成本逐步下降到合理的范围内。因此在决定使用先进生产力影响业务生命周期的某些阶段的时候,需要关注投入的成本。随着生产力的提升,生命周期的每个阶段依然可以继续细分为多个阶段,并且生产力越高,参与业务的各方可以控制和干预的业务生命周期的粒度就会越细,可以控制的维度也越多。如何理解这句话呢?首先要明确究竟什么是生产力。生产力不是单纯地指技术人员掌握的技术,而是以 “劳动者”——就是指人、“劳动资料”——就是指人使用的工具、“劳动对象”——就是指被人使用工具改变的对象为要素,构成的概念。所以生产力的提升包含了人的提升、人使用的工具(对于研发同学而言就是技术,对于PD或运营同学而言就是你们的工作方法论)的提升。所以当人变得更强、工具变得更先进以后,可以改造的对象的粒度就越小,可以改造的对象的维度也就越多。这是普世的一般规律,想想物理上化学上随着生产力的提升人类可以改造的对象的维度和粒度是如何演变的。而这个规律在业务上的体现就是技术能力更强、PD运营方法论更先进更适合业务的团队,能够感知并控制业务的更多的维度,业务的发展周期也会拆解地更细。这一点其实是最和我们日常工作最为息息相关的一个规律。我们可以利用这个规律来针对“生产力不够先进的业务”构建结构上的优势,例如在业务的“启动期”,生产力落后的一方在解决系统有无问题时,而生产力先进的一方已经同时在着手解决塑造品牌形象等问题。这些问题看起来不是主要矛盾甚至都算不上次要矛盾的维度的事情,之所以在同样的业务发展阶段,两种团队解决的问题完全不一样,原因就是在于生产力的差异,即:落后的一方在当前阶段解决主干问题时,先进的一方已经解决了主要矛盾并完成了多轮“由主到次”的解决过程,而每一轮“由主到次”的过程,都是拓宽问题维度、拆分问题粒度的过程。这种优势是结构性的,比时间上发力更早而形成的先手优势更高级,也更难被追上。同样的,这个规律也会在技术上同样起到作用,下面在探讨技术的一般规律的时候,会提到这个规律的具体体现。3.2 从具体的发展阶段上看整体应对策略启动期:尽可能利用现有积累或与三方合作加速或跳过启动期。发展期:具体问题具体分析,与特殊规律有关。平台期:做好孵化新业务的技术准备和业务准备,避免业务进入衰退期以后组织随着业务消亡而价值降低。消亡期:利用转型或孵化新业务构成第二业务曲线,从而在宏观上看到当前组织的业务规模没有发生衰退。4 从整个业务发展的规律来看,技术一号位需要具备哪些能力从业务发展规律来看,技术一号位的能力大多数和做业务相关,同时和宏观的技术架构及落地把控能力相关,具体如下:分析业务本质的能力,即能看清业务内部主要矛盾次要矛盾,能根据业务内部和外部环境的相互关联和相互影响来判断业务未来的发展趋势。分析业务各参与方的核心利益诉求,能够合理利用商业模式尽可能多的平衡各方利益诉求,并从技术系统上针对这种业务模式给与支持。分析业务各参与方的核心利益诉求,能够使用指标分别体现各方的核心利益诉求,并且能够以体系化的维度将指标拆解,避免看问题的片面化;同时能够分阶段理清不同阶段的重点指标并在技术支持上予以倾斜,避免看问题静态化。在业务初期,能够结合业务的问题域,完成合理的业务领域建模;并且结合市场调研及业务发展趋势,合理设计系统架构,体现出架构的前瞻性和扩展性。同时要开始做技术生产力上的长线投入,借短期业务需求落地长期技术规划。在业务中期,逐步完善业务支撑维度,全方位构建支撑体系。将支撑体系解决方案化,并且将业务支撑解决方案跨业务复用。同时利用业务初期投入的生产力的提升,来推动业务发展。在业务末期,能够完成技术侧的沉淀,并且有能力孵化出新的技术产品。技术的演进规律及对应的应对策略对于技术一号位而言,技术领域是本职领域,探讨技术领域的规律时,要充分结合组织、业务对技术的影响来谈。因为组织特征、业务特征共同决定了技术特征。在我们开始谈一般规律时,先把“技术”这两个字讲清楚,不是要讲概念,而是要讲这两个字在不同语境下的侧重点,然后分别从不同的视角来探讨他们具备的规律。我们常见的研发过程分类来看,一种是业务研发过程,一种是技术研发过程。两者在某个层面遵守同样的一般规律,同时也因为各自受生产对象的不同而分别有“各自的一般规律”。注意,这里讲“各自一般规律”是指讨论范围分别限定在各自的话题之内,而在更大的技术范围上看,它们则是特殊规律。为了能清晰地讲清楚业务研发过程中的技术和技术研发过程中的技术究竟有什么一般规律,我们先明确二者之间的辩证关系,统一大家的认知,为后面的讨论扫清障碍。从本质上讲,所有的研发过程都是业务研发过程,技术研发过程只是业务研发过程的一种特殊情况。业务研发过程服务的对象,是客户的业务人员,要解决的问题域集中在广泛的客户业务领域上;技术研发过程服务的对象,是客户的技术人员(请辩证地、广义地理解客户,不要狭隘的理解客户二字),要解决的问题域集中在狭隘的技术领域内。即:业务研发过程的内核是业务问题,技术研发过程的内核是技术问题,而技术问题是一种特殊的业务问题。业务研发中的技术处理的对象是一般的客户业务需求;技术研发中的技术处理的对象是特殊的技术需求。技术研发过程中的技术的特殊性在于需求不是直接来源于客户在业务开展过程遇到的业务问题,而是来源于客户在业务开展过程中遇到的特殊领域的、专业的技术问题。技术研发过程中的技术的一般性在于不管需求从哪来,需求类型是什么,需求有什么特征,都属于广义的业务需求,因此技术研发领域中的技术也同样遵守业务开发领域中的技术所遵守的一般规律。业务研发过程和技术研发过程在一定的条件下和特殊的阶段是会相互转换的:业务研发过程不断由主到次地解决问题,最终问题的领域会聚焦在单一技术问题上,变成技术研发过程;而技术研发过程不断由主到次地解决问题,最终会在进行对外价值传递时变成业务研发过程。所以业务研发过程的主要问题是对外传递业务价值,次要问题是技术在某些领域的先进性;而技术研发过程恰恰相反,其主要问题是在当前技术领域的先进性,其次才是本身价值的对外传递,因为其价值本身是基于它自身的先进性的。这就是业务研发和技术研发的对立统一的过程,相互演变的过程。当然这个演变过程不是发生在个人身上的,而是发生在组织身上的,并且随着这个过程的演变,组织内部也会分化演变,即:业务研发团队内部最终会出现专门做技术攻坚的小团队;技术研发团队内部也最终会出现专门做业务产品的小团队;这一演变规律,为所有研发人员选择团队提供了宏观的指引,要辩证地看待做业务和做技术,如果想做技术,在业务团队一样能做;如果想做业务,在技术团队也一样可以;问题就在于你个人是否能看到当前组织的技术、业务演变趋势,机会往往就出现在业务研发过程向技术研发过程转变的时候,或者技术研发过程向业务研发过程转变的时候。业务需求对技术领域的综合度、广度的要求,构成了业务研发过程中的技术的特殊性;技术需求对技术领域的专业度、深度的要求,构成了技术研发中的技术的特殊性。对以上内容的认知对齐以后,我们就可以分别探讨业务研发过程中的技术有什么样的一般规律、技术研发过程中的技术有什么一般规律了。1 技术的演进规律1.1 业务研发过程中的技术的规律受业务复杂度和业务生命周期的影响,业务研发过程中的技术整体呈现模型复杂、支持维度多的特征,因此“复杂业务模型的领域设计”、“横跨多个业务生命周期的技术架构演进”、“多维度全方位支撑、保障、驱动业务发展”是三个明显的特点。从单个业务生命周期来看,业务研发过程涉及到的技术从单一维度向多维度演变;除了要使用技术完成业务的数字化,还需要从研发效能、运营效能、稳定性建设、业务风险控制、财税法支撑等方面进行技术上的支撑(这些支撑,很多都是业务上下游参与方不感知的),随着业务逐步进入成熟期,应用从单体应用向微服务转化;技术的发展趋势,从简单的“把业务跑起来”,逐步形成全方位支撑业务发展的技术解决方案。技术本身也从满足“有无问题”的粗犷模式,逐步演进到解决“降本提效问题”的精细模式,这是一个由主到次的过程,也是生产力提升的一个过程。这就是业务研发过程中的一般规律。如果一个研发团队同时负责多个业务,那么在做业务的过程中,逐步会形成一些多个业务都会复用到的业务服务,这些业务服务领域相对独立,功能通用,各种业务都需要用到,最终逐步形成业务中间件。例如文件服务(基于OSS封装或其他存储服务封装)、在线签约服务、权限服务、消息中心、待办中心等等。这个过程本质上就是业务研发过程中,技术“从单维度应用演变为多维度的解决方案”的基础上,继续从“单业务适用演变为多业务复用”的过程。如果一个研发团队或技术一号位先后负责多个业务,那么某个业务本身的领域知识不再那么重要,“如何在没有任何业务背景和经验的前提下完成复杂业务领域建模”变成了技术一号位需要重点构建的核心能力之一。因此业务研发过程中,关于业务建模的方法论是众多技术中的一个非常重要的维度,特别是对于支撑多个不同业务的人而言,该维度的能力是核心能力,是区别于技术研发人员的核心差异点之一。当然由于业务研发过程和技术研发过程会有转换,所以不同情况下的核心维度会发生变化,需要具体问题具体分析。以上提到的规律是和组织的生命周期相关的,组织稳定,就能沿着单个业务发展的生命周期完成技术从单维度应用到多维度应用的积累;组织有能力承接多个业务,那么就会自然而然地走上解决方案复用的道路,而解决方案的复用带来的好处就是生产力提升以后反哺业务,能够加速业务的某些阶段的发展。同时,要看到技术演进的过程和其宿主——即技术人员所在团队有关,所以A组织具备了什么样的能力,不代表B组织也会具备同样的能力,如何拉通各组织之间的生产力,在技术的多组织复用的基础上,确保各组织的创新性和独立性,是最顶层的技术一号位的核心命题之一。不同于技术产品,很少有团队能走完业务研发过程中的技术演进过程。往往是成熟业务的团队才可能走完整个过程。例如淘系的星环目前就是处于整个过程的比较靠后的阶段。那么再往后还有么?再往后,就会继续遵循事物演变的规律,当前的主次矛盾解决以后,新的主次矛盾会出现,所以随着资源和时间的持续投入,过去不是主干的问题,会在现在成为主干问题被解决,随着问题域的不断细分,技术领域也会随之不断聚焦,最终演变为技术研发过程。所以其实星环是从业务研发过程中演进或孵化出来的技术产品。这一点(业务研发过程和技术研发过程的相互转变过程)在之前已经讲过了,不再重复展开。1.2 技术研发过程中的技术的规律技术研发过程中的技术,与业务研发过程中的技术相比而言,同时具备“技术性”和“业务性”。前者是其特殊性,使之有别于业务研发过程的技术;后者是其一般性,是其和业务研发过程的技术相同的部分。技术研发过程中的技术,在“业务性”方面,有自己的生命周期,整体会按照以下规律发展:按照“能用——易用——产品化——商业化——商品化”的路径演进。是从满足使用需求,到最终能够做标准化的价值交付的演进过程。技术研发过程中的技术,在“技术性”方面,也有自己的生命周期,整体会按照以下规律发展:由浅入深,由主干到旁支,随着持续不断的投入,技术命题的深度变深,粒度变细,成本也更大,最终会在投入与产出的平衡中演进暂停,形成阶段性的先进性。而这个过程,和技术场景支持的业务规模息息相关,二者是相辅相成的,即业务规模带来了技术演进的动力,增加了投入的成本,同时技术演进也支撑了更大的业务规模,带来更高的收益。2 如何利用规律或打破规律理论最大的用处,是提前对事物构建一个理性的、全面的、动态的认知,从而指导对该事物的实践过程。我们花费了这么多的篇幅来尝试分析清楚技术的规律,如果仅仅停留在理论上,那就失去了它应有的价值。下面我们就简单选几个技术人员日常最关心的几个问题,看看如何从规律的角度来分析解答,具体如下。2.1 提到的技术规律对一般的研发同学有什么启示认识到生产力形成的过程是和团队的生命周期相关的,成熟的团队生产力相对较高,技术沉淀更深入,但是由于多次的由主到次的迭代,所以一个成熟团队,需要投入精力的领域往往在技术体系上的粒度较细,面较窄,整体更深入;而新成立的团队往往生产力的积累上比成熟团队差,但是面更广。因此一般的研发人员在挑选团队的时候,要看自己当前处于什么样的阶段,是处于积累期,还是处于已有一定积累,需要在广度上做扩展:前者适合去成熟团队,后者适合去新兴团队。当然,也要认识到业务生命周期和团队生命周期之间的关系。成熟的团队做的业务往往是比较稳定的,换言之,已经稳定的业务一般是由一个比较成熟的团队来支撑的。即使这类型的团队开展了新的业务方向,但是基本盘依然是成熟业务,因此团队稳定性高。但是在这种团队中,一般情况下新加入的员工做的都是比较边缘的事情,因为核心的主要的事情已经有人在做了,并且已经做到了一定的成熟度。新兴团队做的业务往往是新立项做的,不论业务在战略上有多重要,都无法改变它不是当前时间段的主干业务的现实,所以业务能否做成、团队能否稳定存在是一个需要考虑的问题。因此一般的研发人员在挑选团队的时候,也要考虑团队的稳定性,如果觉得稳定性最重要的,那就去核心业务部门,这样的团队相对而言比较稳定,但是要注意做的事情可能是比较细碎比较边缘的;如果是认为施展个人才华更重要,那就选择去新兴团队做新的业务,机会多,虽然开始事情比较杂,但是都是业务的重点,唯一需要考虑的就是团队的稳定性,即业务可能失败而团队被调整。认识到技术研发过程和业务研发过程的客观转换规律。一般比较成熟的技术团队,技术研发过程已经逐步经过多次迭代,在技术先进性和技术深度上已经完成了阶段性的目标,在成本和支撑的业务场景没有骤变的情况下,大概率不会继续投入,而会逐步将重心调整到整个技术的对外输出上,因此会变成以业务研发过程为主;一般比较成熟的业务团队,业务研发过程逐步完成了对应阶段的业务使命,而继续发展下去生产力就会变成制约业务继续增长的瓶颈,所以除了业务能力建设以外,还会投入更多资源进行技术能力的建设,因此团队主要研发过程会从业务研发过程转变为技术研发过程。因此一般的研发人员在挑选团队的时候,要结合自己究竟想做业务还是想做技术,然后根据目标团队当前的实际情况来看该团队究竟处于哪个研发过程中,而不是只看团队是否是技术团队或业务团队。非常实际的例子就是,在技术团队中,有大量的研发人员做的都是业务功能的开发,而和技术团队真正的核心技术领域关系并不大;在业务团队中,有一些研发人员做的事情并不是真正的客户业务需求,而是在做相关领域的技术深度建设。所以在转岗的时候,不要看团队的类型是什么,而是要看团队当前处于哪种研发过程中。2.2 从技术的发展规律来看,如何选择广度或是深度目前来看,技术已经出现了很多大领域的划分,从单纯的编程语言到基于编程语言构建的技术栈,再到大数据、算法这类专业技术域,再到各个场景业务领域的基础技术如电商、广告、社交等,并且随着整个技术体系的发展,越来越多的细分领域的投入也在逐步饱和,整个技术栈的深度和广度都已经到了单个研发个体无法完全掌握的程度。所以对于很多初级技术人员首先面临的问题就是:我该怎么选我的成长路径。究竟是先深度还是先广度,一般情况下,我们都是讲先把基础打好,这是前提,也是未来深度究竟能多深、广度究竟可以多广的决定性因素。那么基础究竟打到什么程度?我个人的感觉和实践是:一定要在某个技术领域达到专家的程度,然后再去考虑究竟是横向扩充广度,还是纵向发展深度。这些是个人内在的要求。另外一个方面就是,技术人员所在的团队类型也和发展模式有关,如果是业务研发团队,技术的广度是必然的要求;如果是技术研发团队,那么技术的深度也是必然的要求。这些是外界环境的要求。在回答究竟是深度优先还是广度优先的时候,要结合个人内在的驱动力和外在团队的要求,眼光放长远去选择即可。2.3 从技术的发展规律来看,如何在做业务的过程中有突破做业务的时候,绝大多数人都是在不停地处理业务需求,并且往往陷入恶性循环:需求越做越多,越做越急,却最终越做越慢。本质原因是把业务发展和技术发展作为二元对立的过程来看的,做业务需求的时候就认为要赶快做完,PD、运营没有给留出做技术的时间所以就不做了;而在有时间做技术的时候却又一心想把各种高大上的东西用起来,满足个人的技术成长欲望、消除自己在技术上积累缓慢的焦虑。但是事实上,做业务开发和做个人技术成长是一个统一的过程。首先就是要求技术一号位能够分析清楚业务发展的趋势,提前在架构层面完成对应的前瞻性的设计,然后就是借着做业务需求的机会来做架构落地。不要觉得这是理想主义纸上谈兵,这是可以实操的,并且可以练习实践的。它究竟是不是纸上谈兵在于你个人,而不在于这个理论和方法。我在自己的小团队内的要求就是,每次迭代技术规划落地和业务需求要3-7开,假如一个迭代十个需求,其中三个一定是技术长线规划的需求。简单来说就是技术和产品需求严格遵守一个原则,首先“你打你的,我打我的”,其次“你的就是我的,我的最终也是你的”,这就是把业务需求研发和技术研发有机地统一在一起的模式。本质上就是业务规划和技术规划双线并行,两条腿走路,同时技术规划为业务长期发展打基础,借助业务需求来阶段性落地长期的技术规划,从而最终业务需要更先进的技术能力的时候,技术已经做好了相关的准备。所以说,想在做业务的过程中有突破,第一件事情就是要在认知上改变过去业务需求和技术发展对立的错误观念,要在思想上把做业务需求和做技术统一起来,而不是对立起来。道理很简单,难在你有没有去实践,而下面就是具体的实践方式。当我们掌握了业务研发中的技术发展的规律的时候,就能提前知道每个业务阶段整体的对技术的要求是什么,就能完成提前的布局。单体应用的开发阶段,就将代码以领域驱动设计的方法论为指引划分为不同的领域模块,在做微服务拆分的时候,直接按照业务领域做拆分即可;在启动阶段即在满足“有无”的时候,不再是过去那种无脑地堆代码,而是结合下阶段业务发展周期对架构的要求,对长期架构设计进行最短路径地落地:即我设计好完整的架构以后,启动期需要哪些能力,我就只按照架构设计落地哪些功能,其他没有业务需求用到的部分,一律只保留代码框架不做具体的逻辑实现即可。同时,当业务已经稳定以后,可以去主动推动业务技术在不同业务上的复用,提前把跨业务复用的部分形成业务中间件对外推广,这部分目前看,是全集团的一个空白区,难度不小,机会也不小。最后,一定别忘了技术是第一生产力,不仅可以支持业务、保障业务,更应该驱动业务发展(我知道怎么做,并且有实践,会在其他文章里面讲清楚,这里不再细说了),同时,除了围着业务转以外,自己也可以作为孵化器来孵化出技术产品,这些,都是做业务的过程中,利用我们分析掌握的规律来创造“不可能”,创造突破。2.4 从技术的发展规律来看,如何在做技术的过程中有突破从技术的发展规律来看,做技术的过程中怎么突破,其实有很多可以讲,但是由于篇幅有限,我们今天只挑最困扰技术人员的一个点来分析——做技术的人最大的困扰,就是我做的东西怎么能让更多的人都愿意用起来。技术产品本质上是所有研发人员的生产力的代表,而先进的生产力能够给“创造特殊条件,打破规律” 提供可能性,但是最重要的一点就是,要知道生产力的应用是需要付出成本的。生产力可以改造某事物的维度越多、改造某事物的粒度越细,生产力的使用就越复杂、成本越高。想要让自己做的非常先进的技术能够被更多人使用,最短的路径,就是把技术的使用成本降低,这个成本包括学习曲线是否陡峭、资源投入是否太高、产品易用性、技术支持的完备性等等这些维度。所以能看到很多沉淀多年的技术团队在产出技术系统或工具的时候,配套支撑做的非常好,这一点就是为技术产品的推广降低了成本,从而让大范围的使用成为可能性。这个点,就是利用了上面提到的一些规律得出的结论。如果你所在的团队做出了非常棒的技术产品,但是推广使用不佳,那么不用犹豫,从降低它的使用成本入手完全没毛病并且一定能改变现状有所突破。3 从整个技术的发展规律来看,技术一号位需要具备什么样的能力从主观上认清日常常见的两种研发过程的辩证关系,从宏观上看清两种研发过程的对立统一面、相互转换的过程、转换过程发生的条件。能够利用该认知,在恰当的时间推动两种过程的转换,从而在宏观上达到外部环境对研发团队的要求。从主观上认清自己负责的事情需要的是哪种研发过程,针对不同的研发过程阶段进行针对性的梯队建设,避免团队人员配置单一化,导致无法顺利完成整个过程的转变,或无法支撑对应的业务或技术产品的研发。人为造成成员和做的事情的不匹配既影响业务也影响个人成长。当然,凡事要辩证地去看,有意识地培养团队成员去匹配不同的研发过程,需要让对应的人员也有同样的认知,了解不同的转变的价值是什么,变被动为主动。在实际行动上能够宏观感知技术演进脉络,在某些节点上能够按照发展规律进行对应的布局。在执行上,能够长期规划和短期需求有机地、辩证地结合起来,不让团队走弯路。组织的演进规律及应对策略1 组织符合的一些规律组织是一群人的统称,在阿里巴巴,这群人是有情有义的,一起做一件有价值有意义的事情。探讨组织,既要从宏观层面研究它的规律,还需要从微观层面研究组成它的人,而在研究人的时候,不是单纯地研究个体差异,而是再从宏观的角度研究群体特征。除了人以外,组织还有它的使命、愿景;有约束组织内人的规章制度,有共同相信的企业文化,还有奖惩机制,最终基于人、业务、规则、文化、奖惩共同构建了组织的运转模式。同样的,由于受限于本人个人实践经验的局限和理论输入的匮乏,所以讨论的内容需要大家辩证地去看。1.1 组织的构建和运转符合什么规律组织的构建和运转,本质上是围绕着组织和事、组织和人的辩证关系展开的。关于组织的生命周期的规律任何组织都是为了完成某个使命而存在的,即组织的存在是为了完成某件事情,不存在一个不为了做某个事情的组织。组织的生存周期和其使命的生命周期是一致的。要合理的区分“组织使命”和组织在“某阶段的主要矛盾”,主要矛盾的生命周期和组织的生命周期的关系是辩证的:如果一个组织的存在就是为了解决上级组织的某个阶段的主要矛盾的,那么它很可能会因为主要矛盾的解决而消亡;如果一个组织的存在不是为了上级组织的某个阶段的主要矛盾而存在,而是为了上级组织的使命的一个维度存在的,那么这个组织就不会因为它当前解决的主要矛盾消失而消亡。对于实际工作中,我们能感知到的大多数的组织部门都是以后者的形态存在的,即:其使命是上级组织的使命的一个维度;而那些为了某个具体的事情临时成立的项目组则是属于第一种类型的组织,这种组织的生命周期注定与其负责的事情的生命周期绑定。当然,所有的事情都需要辩证地去看,如果把项目组的使命定义为完成所有某类型的项目,那么组织的生命周期就脱离了具体的项目的绑定,变成了常见的组织部门。这一点对于实际工作还有更大的指导意义:组织是培养人才的环境,为了尽可能降低组织变动带来的人才的流失,一个组织应该尽可能地把自己的存在绑定在上级组织的使命的一个维度上,那么只要上级组织的使命没有调整,下面组织的稳定性是能够保证的;对于项目型的团队,也要让自己的使命和具体项目解绑,让项目的完结变成组织的前进基础,而不是消亡的号角,这样不论是哪种组织,内部的人员对于大环境的感知就是稳定的,有安全感的。越大的组织,其要完成的使命越大,越抽象、内涵越广泛、维度越多;越小的组织,其要完成的使命越小,越具体,内涵越聚焦,维度越单一。团队规模和使命大小是存在辩证关系的。组织和其使命的匹配过程,是一个运动的过程,不是静态的过程:要完成大使命的组织,开始可以很小,随着逐步的发展,组织会扩充到与其使命一致的规模;要完成小使命的组织,开始虽然可能很大,但是随着逐步的匹配过程,组织会逐步缩小到对应的规模,所以很多组织为了维持规模会寻找更大的使命。整个过程是动态的,也是辩证的、发展的。实际上,规模大的团队不一定因为其使命小就被缩小,更大概率会因为其规模大而被赋予更大的使命。在我们实际工作中,所有的组织都期望自己人越多越好,都在拼命的扩招,这是符合一个组织想要生存下去的客观规律的。在顶层设计者的考量过程中,就要充分考虑到这一点,辩证地看待团队规模的问题,拼命招人的团队不一定应该继续招人,人少的团队也不能因为现在做的事情看起来没有收益而约束其规模,真正要确保的是团队规模和其需要完成的使命大小的匹配。关于“组织与事情”的运转相关的规律组织通过愿景来明确长期的工作方向,愿景是受使命驱动的。愿景是组织在一个阶段内的长期的综合的高维度的指标,是组织在较长时间段内的工作目标,即:在什么时间点上,什么样的指标,达到什么样的值。这个目标往往是战略层面的,是某种布局完成后达到的效果。一般情况下,实际上决策者期望的是某种局势的形成,局势形成后目标自然完成,而不是真的只想要这个指标。体现愿景的指标往往是多维度的,并且是和使命的维度相匹配的。愿景需要从各个维度去拆解,从而支撑对应维度的使命。维度的拆解和重要性也符合主要矛盾次要矛盾的规律,也符合事物演进的规律,维度的重要性会随着时间和环境的变化而变化。任意规模的组织,都是有其愿景的,愿景的生命周期应该和使命的大小匹配;规模越大的团队,其使命越大,愿景的时间不要设定太短,要体现愿景的长期性,要认识到除非掌握了跨代的生产力,否则不可能短期即能完成大的使命;而规模越小的团队,其使命越聚焦,愿景的时间不要设定太长,要体现愿景的及时性。这里需要注意的是,要能区分愿景和目标的区别,愿景是一个阶段内的一系列目标的结果和集合,因此要辩证地理解愿景的设定时间的长短和目标的设定的时间的长短之间的关系。大团队肩负大使命,愿景太短证明战略分析不够宏观,眼光不够长远。目标时间太短则连续性不足,要把短的目标拆解到下级团队,在上级团队的目标上要体现出长期性,要能体现出战略的定力。小团队肩负小使命,愿景太长则证明规模和使命不匹配,战略执行落地灵活性不足。目标时间太长则需要继续拆解来保障执行落地的及时性,从而保障战略的灵活性。所有组织的行为最终都需要组织成员来执行,现阶段人是组织的组要成员,不排除未来不是。组织的运转机制中,除了宏观的使命愿景,还和微观的组织成员有极大的关系,因此人以及对人的约束和奖惩就是接下来讨论的重点了,但是不能只看到下面要讨论的内容而忽略上面讨论的内容。1.2 组织的成员符合什么规律组织内的成员一般都是企业员工,所以我们使用员工一次来简化“组织内的成员”的表述。员工的本质是什么定义员工是组成组织的基本个体,以某种形式构成和其他人协作的模式,以该模式为基础进行组织使命的履行。员工以完成分配的工作来产生价值,并以此取得回报。性质员工同时有“组织性”和“个人性”。员工在组织内部扮演某些角色,这些角色带来的核心利益诉求会影响他的日常工作行为和决策偏好向有利于完成角色赋予的使命,则我们把这种情况称为员工在组织内的“组织性”。同时员工本人对其个人核心利益诉求的追求,也会影响他的日常行为和决策偏好,因此我们把这种现象称为员工在组织内的“个人性”。即:当员工的行为及决策偏好主要受到组织角色的核心利益诉求驱动时,员工体现出的是组织性;员工的行为及决策偏好主要受个人核心利益诉求驱动时,员工体现出的是“个人性”。一个员工的组织性和个人性是共同存在的,不是割裂的,共同构成了员工日常工作行为和决策偏好的驱动力。员工与其他员工因为角色的不同而产生的核心利益诉求的冲突,是组织内常见的管理者与普通员工的对立统一关系的由来,也是HR与普通员工的对立统一关系的由来。员工的个人核心利益诉求和组织核心利益诉求的冲突,是员工与组织之间对立统一关系的由来。所以,一般情况下,员工与员工的对立统一关系是基于其组织内角色的矛盾的;员工与组织的对立统一关系是基于个人与组织之间的矛盾的。如果对立激化,要知道问题的根源在哪,要能辩证地分析情况,做出合理的缓解对立的举动,而避免在问题没有搞清楚的情况下就采取某种措施。员工的成长过程的本质(内在分析)员工在组织内扮演某种角色,并且随着员工或环境的变化,角色会发生变化,员工承担的角色逐渐变多,代表着员工处理的事情的维度变多,并最终在某个时间段完成由量变到质变的变化,由低一级的角色转变为高一级的角色。在讨论这个量变到质变的过程时,我们需要对“同一维度的角色在持续时间上的量变”和“同一纬度的角色向更多维度上的量变”有一个辩证的认知。员工扮演角色的量变到质变的变化过程,是员工成长(晋升)的本质规律。外在的员工在组织内的角色的变化只是员工成长的外在现象,本质是员工成长了,对事物的把控维度变多,对事物可操作的粒度变细。这也是为什么阿里内部讲不同级别的员工做事的演进轨迹是“点-线-面-体-局-势”,这是维度变化的体现,当然也要清晰地认知到,“点-线-面-体-局-势”没有体现出人对事物可操作的粒度变细的过程。员工的成长,是由认知的升级开始的,以实践为基础的,同时实践会继续影响认知,从而带动新的实践,从而形成了成长的过程。本段内容会在其他文章中展开论述,这里只列出最基本的规律和过程,对于“员工成长到下一个层次”给出一个科学合理的解释,而不再是只谈现象不谈本质的各种“水到渠成”的说法。这些说法都只是在从表象上描述客观现象,而非事物本质的描述和传递,所以为什么这类信息都需要读者有悟性,根本原因在于它们看问题是表面的、片面的,而非深刻的、全面的、理论的。需要注意的是,对于同一个员工而言,他所扮演的角色与角色之间不是单一互斥存在的,而是叠加在一起对员工产生影响的。员工在组织内存在的形式宏观层面员工是构成组织的最小单位,单个员工在组织内以某种角色进行日常的工作,与其他若干员工以某种形式构成小的组织,小的组织与其他若干小的组织构成更大的组织,如此循环往复最终形成了完整的组织形态,这是以自底向上的认知过程看到的,这也是大多数人的认知视角。而从自顶向下的认知过程来看,我们就可以发现组织结构和组织使命的辩证关系以及两者之间相互影响的过程,可以看到组织结构与组织使命的维度和拆解粒度是匹配的。维度代表了一个事物的多面性,粒度代表了一个事物的可拆解性。所以在一个大组织下的不同组织之间,组织角色对应使命涉及的维度,组织层级深度和粒度代表了事物的可拆解粒度。这是组织结构的一般规律,也是和组织使命的辩证关系。我们实际工作中,存在很多和这个一般规律不匹配的现象,最终具体案例具体分析来看,无外乎有两种情况,要么是组织设计不按规律办事,最终肯定会受到规律的反噬;要么是符合了某些特殊条件,触发了特殊规律,这部分我们在探讨一般规律和特殊规律的时候已经讲过了,这里就不展开讨论了。所以从这个角度来看,当一个组织结构变化频繁的时候,说明组织使命发生变化,是顶层设计者在依据最新的发展规律做出调整,因而组织结构随着组织使命做调整,这其实是组织健康的表现,说明顶层设计者在战略上是勤奋的。当然战略上的勤奋也是一个辩证的事情,太勤奋了说明过去的战略决策思考不足,有很多没考虑到的维度,所以现实情况发生某些事情,倒逼战略不得不在原来的基础上做调整;不太勤奋说明对实际情况响应不够敏捷,对事物所处的环境的变化或者事物本身的变化感知的敏锐度不够,只能等到非预期的变化造成了一定伤害才去做处理。这个辩证关系其实还有更多内涵,比如组织形式的复杂度和战略的决策、执行、调整之间存在的规律以及如何在组织设计上避免这个规律引发的负面问题,受限于个人能力和实践有限,所以这里就不展开讨论了。微观层面任何一个子组织,一定是由一个管理者和若干名普通员工构成,从微观层面探讨员工在组织内存在形式的规律时,员工与管理者的对立统一的辩证关系是一个绕不开的话题,不过从目前的实际实践经验来看,管理者对组织结构规律的影响要大于普通员工。所以我们这里把讨论的重点集中在管理者的分析上。可以理解为,在组织微观层面的规律中,管理者是矛盾的主要方面,管理者和员工的对立统一关系是矛盾的次要方面。管理者的组织性对组织的影响管理者在组织层面扮演了双重角色,其一是组织业务顶层设计的执行者,承担着完成组织使命的责任,把被分配到的业务做好;其二是组织架构顶层设计的执行者,承担着维系组织架构和运转机制的责任,把组织内的人培养好。所以管理者的业务、组织双重角色是其内部特征,影响着外部的组织结构,同时外部组织结构的规律也会影响管理者,这就是管理者和组织之间的辩证关系和互动的过程的概述。如果一个管理者不能平衡好业务角色和组织角色,就会出现很多问题,这些问题的最直接被影响的群体就是该管理者负责组织内的普通员工。比如实际工作中有的管理者是顾做事,不顾培养员工,员工从资产变为资源;如果有的管理者只管人事,不管业务,实际上是主次不分,本末倒置,团队无法在业务上有产出,实际上是团队无法履行它自己的使命,那么团队本身的存在也就会被人质疑了。上面分析的都是管理者的“组织性”,别忘了管理者也是员工,也具备我们之前提到的“个人性”。“个人性”与管理者的个人核心利益诉求息息相关,很多时候提到个人核心利益诉求,会觉得人心千变万化无法进行讨论,这里我们需要忽略矛盾的特殊情况,讨论矛盾的普遍情况,即忽略矛盾的特殊性,抓住矛盾的普遍性来讨论群体的共性。所以作为一个正在履行职责的正常的管理者,“维持或扩大其在管理上的范围,延长在该角色下做事的时间,从而在此基础上谋求其他个人核心利益诉求”是这个群体的共性,所以不论他个人核心利益诉求究竟是什么,从整体来看其个人核心利益诉求是基于管理者的角色来实现的。这也是管理者这个群体,组织性和个人性的对立统一关系中的统一一面的体现。对管理者的组织性和个人性有了辩证的认知以后,我们才能理解管理者在组织内的行为模式,才能知道这种行为模式是如何影响组织的,如何最终形成规律的。管理者的个人性对组织的影响管理者自身的组织性对所在组织存在影响并形成规律以外,管理者自身的个人性也对组织有影响并形成规律。我们知道,任何事物的解决都是由主到次的,其实在人的方面也是符合同样的规律:“管理者与其团队内员工的互动也符合由主到次、由重要到普通的特征”。不论在什么样的组织结构里,扁平化也好,立体化多层级也好,管理者在协作时间、精力分配、利益分配方面都是向核心成员倾斜的。也就是说,任何一个团队,形成一定规模以后,一定有一部分人和该团队的领导走的更近,协作互动更多,利益分配也更被照顾。不要把这个现象粗浅地归类到中国人的人情世故上,或者中国人的文化上,而是中国文化传承时间久,各种组织形态和现象都能被不同时期的人看到,并且得出各种受限于当时哲学理论限制下的讨论。所以这种现象不是中国人或中国文化特有的,这个现象的根源不是中国文化(当然文化对于现象的广泛传播是有作用的,要辩证地去看这个过程,不是根源不代表没关系,有关系也不意味着是根源),而是管理者追求代表了个人性的核心利益诉求时必然会出现的现象。我们简化讨论的前提条件,复现这种现象形成的过程,从而得到一般规律:管理者组建团队,假设所有员工与管理者事先皆无利益关系,团队组建成功后,开始履行团队使命。团队接到任务以后,管理者会评估员工的能力,把最重要的事情交给有能力搞定这个事情的成员,随着团队做的事情足够多,能够看到综合能力强的那些员工做的重要的事情越来越多,而这些员工做的事情也越来越重要,最终这些员工在评定绩效的时候也比其他普通员工更高。随着事情由主到次的解决,那么团队做的事情的维度就会变多,粒度会变更细,需要更多的人投入,逐步就会继续演进出现更多小的团队,去解决对应维度的事情。这个过程继续在小团队里面循环往复。我们可以看到,这个规律对于普通员工的意义就是,做事情不论大小都要体现出来能把事情彻底搞定,表现出对事情的把控力和胜任的能力,这里千万要注意,把事情做完,不等于体现对事情的把控力和胜任的能力,这是绝大多数普通员工的思维误区;对于管理者而言,这个规律的意义就是要做好平衡,要做好不同层次的员工的针对性培养,否则就会被外界误以为管理者用人唯亲,会被认为团队不公平。单纯从现象来看,如果管理者在组织成员培养上不作为的话,或者只培养能力最强的人,那么不论本心是不是有意不公平,也实际上造成了客观上和事实上的不公平,所以管理者难在这里:不作为既是在构建不公平的环境。实际工作中,会有各种各样的情况,大多数人也会觉得刚才讨论的内容太理想化了,很多情况没讨论到,其实这里要结合我们之前讨论的一般规律和特殊规律来看待:实际工作中的各种现象,都是基于一般规律之上,附加了一些特殊条件,比如某人是管理者的小舅子,比如某人是管理者的老同学,这些都是可能触发特殊规律的条件,但是本身再怎么特殊,也是符合一般规律的,所以把一般规律摸清楚,再根据特殊情况探讨各种特殊规律,才能对事物有完整的认识。有一本书详细地论述了管理者做事的逻辑,理论自成体系,但是其背后是符合马克思主义哲学的,也是符合矛盾论的,也是符合我们今天讨论的这个规律的。这本书的名字叫《独裁者手册》,感兴趣的同学可以看下,这里不再展开论述了。员工在组织内的价值体现的规律员工在组织内部的价值体现的规律,和员工个人成长规律匹配,有对应的关系,并且形成了一定的规律。基本价值员工在组织内投入法定长度的时间和精力来完成日常工作,构成了员工在组织内的基本价值。基本价值的衡量标准一般掌握在顶层设计者的手中,并且最终会在组织内全员中间形成一致的认知。不同组织对基本价值的考核条件不同,所以对员工基本价值的回报逻辑不同。比如不同行业、不同类型的公司对于基本价值的衡量可能都是工作时长,但是时间长度不一样;也可能是销售量,但是销售量的具体数值也不同。员工个人产生的附加价值员工在创造基本价值的过程中,通过个人的综合能力、协调能力、创新能力、坚持不懈等等个人特质,创造了更多附加价值的情况,就产生了对应的附加价值。优秀的组织会承认并且认识到员工附加价值的重要性,并且有能力识别员工的附加价值并给与对应的回报。组织也应该激发、促进更多的员工在产生基本价值的过程中产生更多的附加价值。通过团队产生的价值管理者、或者能力较强的员工,可以通过其带领的团队或协调的一些员工产生基本价值以外的价值。即在个人的基本价值、附加价值的基础上,带领团队创造出远超团队成员的基本价值以及附加价值总和的价值,这部分可以理解为依靠团队或团队合作的力量来产生的价值。这部分价值是组织的主要价值,是主要的组成部分,是组织主要价值的来源。优秀的组织需要具备评估“通过团队协作产生的价值”中各参与者的贡献的比例,并且给与对应的合理的回报。如果做不到,可能会影响到员工对公司环境公平性的体感。通过各种不可简单复制的综合因素产生的价值一些具备特殊能力的人,掌握大量组织资源,能够提前看到行业发展趋势,看到大环境的变化规律,利用规律创造了远超组织协作创造的价值,这类型的价值就是通过各种综合因素产生的价值。这种价值可以理解为组织在发展过程中的各种红利,可遇而不可求。优秀的组织具备良好的环境,来培养能够创造这类型价值的员工。这些规律对于普通员工而言,最大的指导意义就是看到个人对组织产生的价值的类型和上限,如果只是为了回报而来,那么途径要么是提升个人能力,通过创新来创造更多个人附加价值;要么提升个人能力,协调个人性和组织性的辩证关系从而能够在业务发展的过程中成为管理者,利用团队来创造更大的价值;或者对于能力更强、掌握更多组织资源的人而言,通过预测业务发展趋势、提前布局,或者开创没有竞争者的业务来让组织享受到某种规律的红利。其他任何途径获利,都是不符合规律的,是会被规律反噬的。员工与组织的对立统一关系员工个人性和组织性存在着对立统一的关系,绝大多数是统一的,但是统一的层次是高级还是低级,取决于员工本身的个人核心利益诉求和组织角色核心利益诉求是否是互惠互利的。二者互惠互利,则是高层次的统一,统一是主旋律,对立虽然存在但未被激化,统一的关系持续时间长;二者相互冲突,某一方长期受损,则是低层次的统一,对立是主旋律并逐步被激化,统一只是最低程度的统一,当对立加剧到一定程度,则统一关系结束。对于个人而言,受益最大的做法,是把个人性和组织性有机地结合起来,这是效率最高的选择。因为当两种核心利益诉求有机地结合在一起的时候,员工做出的行为和决策偏好在满足个人核心利益诉求的同时能有益于组织核心利益诉求,同时组织受益后会反哺员工对员工产生有益的影响。如果一味地以个人核心利益诉求为优先,损害组织核心利益诉求,那么这种统一关系非常脆弱,会因为违反了组织的制度而终结;同样,如果一味地以组织的核心利益诉求为优先而不顾个人核心利益诉求,那么这种统一的关系非常短暂,会因为个人利益受损而无法长久。组织工作的核心要围绕着如何让员工的个人性和组织性能够有机地、平衡地结合在一起。所以会出现规章制度、企业文化以及奖惩机制,来从不同的角度让大多数员工的个人性和组织性维持在高层次的统一上。1.3 组织的制度、文化、奖惩符合什么规律对于任何一个组织,在组织上的顶层设计,永远都围绕着人以及人和人之间的协作机制,这二者是一体两面。由于实践经验和背景知识都不足以支撑探讨制度、文化、奖惩机制的本质,因此本章节仅仅进行一些简单的理论上的分析,而不进行严谨的理论论述证明。组织制度组织的规章制度约定了组织内所有人的权利义务以及行为规范和准则。从目前个人的分析来看,规章制度具有基础性、片面性、滞后性等特征。规章制度是组织运转机制的基础和前提,这一点决定了它的基础性。规章制度无法对组织成员的每个人的每个行为都事无巨细形成条例,即规章制度无法针对成员个体的特殊性进行规范约束,而只能针对组织成员的一般性进行规范约束,这一点构成了它的片面性。规章制度的片面性决定了它对员工行为约束或引导有限,因此给企业文化和价值观留下了发挥作用的空间。规章制度的产生机制决定了它的滞后性,即无法提前对没有发生过的事情进行定义或约束,都是由事物发生并对组织利益形成影响并现象逐步扩大的情况下,才会通过规章制度来进行定义或约束。规章制度的滞后性决定了它需要被按照实际情况进行调整,同时由于规章制度的基础性决定了调整的幅度不会太大,更多是补充性质的。组织文化如果说规章制度是组织内人与人之间的协作机制的基础骨架,是刚性的部分,那么企业文化价值观就是解决制度无法解决的那些问题,是填充在骨架内的柔性的部分。组织文化的内核是组织宣扬的价值观,决定了组织内成员决策偏好及行为偏好,而一定群体范围形成的行为偏好就会逐步形成文化现象,即成为组织文化。由此来看,组织无法通过规章制度约束员工由其个体的特殊性产生的行为,但是可以通过构建共同认可的价值观来引导员工个体的特殊性产生的行为,使之形成一定的偏好。组织文化价值观在组织成员协作过程中发挥重要的作用。由企业文化价值观构成的共性的认知,本身就携带了很大的信息量,因此组织成员之间的言语、行为的解读和理解更大概率不会被误解,提升了协作过程中的沟通效率,从而在协作方面发挥了制度无法发挥的作用。组织文化价值观也引导着组织成员个体本身的决策偏好和行为偏好。我们看下价值观的定义:价值观是基于人的一定思维感官之上而作出的认知、理解、判断或抉择,也就是人认定事物、辩定是非的一种思维或取向,从而体现出人、事、物一定的价值或作用—— 百度由此可知价值观对于人的行为的影响是公认的,这部分不再展开论述了。我们知道价值观在个人决策过程有很大的影响,但是要认清这种影响的能力边界,即它究竟在哪方面能够发挥作用,却又不能在哪些方面发挥作用。当个体面对复杂的问题时,价值观可以影响决策的偏好,但是价值观本身不能帮助人把复杂的问题进行拆解,更不能让人看清复杂问题背后的本质。也就是说,如果我们把“解决问题”分为三个步骤:“1. 弄清问题本质是什么 —— 2. 给出解决方案 —— 3. 决策使用哪种方案解决问题”,那么价值观只能在第三个阶段发挥作用,即决策者在已经搞清楚复杂问题的本质之后,面对多个解决方案时,价值观会让他选择某种符合其认同的价值观的方案来解决问题。而决策的基础:复杂问题的本质以及对应的多种解决方案的定制是价值观无法发挥核心作用的。所以,我们在日常工作中,不能拿价值观来作为分析问题、解决问题的方法论,而是要清晰地认知到它的能力边界。否则就会出现看似符合价值观但是错的一塌糊涂的决策,而问题并不是出在价值观上,而是在于决策的基础:即对问题本质的认知、解决方案的定制就是有问题的,这是因,决策错误是果,而价值观是“背锅者”。就目前实际实践经验来看,当前组织内部,即阿里巴巴内部,虽然有完善的制度、优越的企业文化和价值观,但是缺少的是广泛形成一致认知的分析问题本质(这个是决策的基础)的方法论。也就是说,我们现在能通过制度约束员工行为,也能够通过组织文化和价值观让员工决策和实际行为表现出一定的偏好,但是唯独在员工明确决策的基础和前提这个环节没有任何官方的手段来形成有效的干预。其结果就是,大多数人在面对复杂的问题时,各自结合各自的实践经验和理论认知提出自己的看法,而往往大多数在这方面又受经历、学识、角色、利益相关影响而各有不同,所以很多人说的话各有各的道理,但是往往都是片面的,只讲到了一个复杂事情的一方面,或某几方面,而不是全面的、客观地、理论的认知。越复杂的事物,涉及群体越多,涉及的核心利益诉求的类型越多,平衡越困难,所以问题越复杂。如果业务决策者对事物的认知无法把握本质,那么在进行复杂问题的决策时,往往和实际情况是有偏差的。为什么要花费这么多篇幅针对企业文化价值观的能力边界进行分析讨论?就是因为我们所在的组织在这方面有很强的优势,而这一优势往往会让很多人觉得有些事情交给“价值观”就好了,对价值观形成了惯性依赖,凡事向价值观要答案。但是正确的做法是,问题的分析和拆解必须交给科学的方法论,而决策才要交给价值观。所以,对于需要做业务或组织决策的人而言,必须掌握一种科学的方法论。当然,我们还需要辩证地理解价值观在问题本质探寻过程中的作用,虽然不能发挥核心作用,但是能够起到一定的保障作用,确保业务在战略上,方向不偏,在战术执行上,动作不变形。奖惩机制我们看到了组织价值观和文化的巨大作用和其能力边界,同时我们要有清晰的认知:组织内员工对组织价值观的认同依靠的不是宣传,真正对价值观的认同起到关键作用的是奖惩机制。价值观的宣传工作做得再多,只是能够让组织内的成员知晓其内容,所以组织文化价值观的工作重点不在于宣传,而在于设计合理的奖惩机制来引导价值观的认同。合理的奖惩机制,能够避免员工铤而走险,也能引导员工从善如流。如果奖惩机制出了问题,不符合价值观的行为最终会受益,而符合价值观的行为非但不被奖励反而会受损,那么价值观最终会变成墙上的标语,而奖惩机制的刺激下,会催生出畸形的企业文化。这一点,我们当前的组织正在经历这个过程,为了保证本文的严肃性,具体案例不再进行详细分析了。做组织工作的同学,特别是人力部门和一线的管理者(技术一号位一般都是管理者),要清晰地知道当前的奖惩机制对组织文化和价值观的巨大影响力。求仁得仁,不恰当的激励机制是在自毁长城,而问题不在长城本身:我们的组织价值观并无过错,错的要么是决策的前提有问题,要么就是奖惩机制在背后捅刀子,最终给员工的体感就是价值观变成了PUA的借口。而对于一线员工而言,坚持正确的事情是最好的选择,因为长远来看,一切错误均将被修正。2 从整个组织相关的规律来看,技术一号位需要具备什么样的能力对员工的个人性和组织性要有清晰的认知,帮助团队成员构建一个科学的个人成长观,帮助团队成员分析当前其个人所处的阶段特征,主要矛盾及次要矛盾,并将个人核心利益诉求和组织及业务的核心利益诉求有机地结合起来,从而形成高层次的统一关系。对组织和业务的对应关系要有清晰的认知,能够根据业务发展趋势构建梯队合理的组织阵型。比如业务进入了平台期,随着主次矛盾的解决,新的维度和一些细节会变得更重要,那么就要及时地组建对应的团队或者调整团队阵型来支撑新的维度或继续深入细节的研究。而不是技术和团队能力制约了业务发展以后再去分析问题再去被动地解决问题。对组织制度、组织文化价值观、奖惩机制有科学清晰的认知,由于技术一号位一般承担管理职责,作为管理者的一员,认清自己在组织顶层设计的执行过程中的职责及其占日常工作的比重,合理平衡业务事务和组织事务,避免只顾技术或业务,而忽视了组织工作。总结本文讨论了解决问题的一般规律,即由主到次,随着多次由主到次的发展和演进,问题需要被解决的维度变多,可被操控的粒度变细。同时探讨了这个规律在技术、业务、组织上的体现,从而让技术一号位能够从理论上、以宏观的视角看清日常工作息息相关的事物的发展规律,从而为顺应规律办事或者创造条件打破规律提供理论依据。扫码查看更多中间件技术干货和案例:
预算管控服务(库存和产品账平台)的DDD设计案例
一. 背景 本文预算管控服务建设作为一个DDD设计的例子介绍,目标是是呈现一次DDD设计的过程,为了减少绘图和描述的工作量,文中会对预算管控业务需求和功能做简化。请重点关注设计的流程,这是我们想传达的重点,忽略设计细节的合理性。另外,对于预算管控服务来讲,不一定要用DDD来进行分析设计,基于传统的数据驱动就完全可以满足需求,但作为介绍DDD实施过程,预算管控是一个不错的例子(不需要画太多的图)。在这里我们不讨论什么类型项目合适DDD,可以参考:大致的共识为复杂度高的业务适合DDD。而复杂度一般体现在:业务流程长业务场景多业务概念多业务系统干系人多业务系统需要长期维护且持续有变更业务背景需要设计一个适用于本地生活场景的资源预算规划和管控服务,业务需求上主要包括两方面的用例:品牌发放权益需要有一定的限额,不能无限制的发放。包括品牌、门店、活动、人群、权益等维度个人消费者参与活动领取权益有次数的限制,不能无限额领取或使用。包括在活动、品牌、门店、商品等维度目前各业务线针对以上需求,各自实现了部分能力,整体上看较零碎、不完善、不统一。本次目标是设计一个统一的平台为各业务方提供基础能力二. 战略设计2.1 业务梳理2.1.1 业务定位&目标分析协同分析阶段,需要各干系方共同参与,如,业务运营,业务产品,运营产品,平台架构,业务系统方的技术等。目标:聚焦业务需求和平台定位,确定平台的能力范围和服务方式输出需求文档:提供一个统一的记账能力,以平台的方式为各个系统提供记账服务。主要功能:记账销账各维度的查账库存创建库存扣减、查询库存缩扩容细化要求:作为平台能为客户提供逻辑上的数据隔离,即A产品方默认不能访问B产品方数据。如需要访问需要经过授权同意作为平台需要提供同步记账能力和异步记账能力,并提供明确的“能力范围”承诺作为平台需要为产品方提供方案避免重复记账除记账之外,需要提供对应的销账能力需要提供常用的记账周期(账期),如时账,日账,周账,月账,季度账,年度账,终身账。需要提供自定义记账周期(账期)的能力需要提供一单多账记账能力,即一张单据,需要同时记录日账和终身账需要提供多维度的查账能力,如按产品方,记账主体,产品,账期时间,以及基于这些维度的组合条件查账需要提供批量查账能力,如主体下单一产品的批量账期时间,主体下的批量产品的单一账期时间,及其它可能的批量组合技术上需要保证账单存储和记账动作的事务技术上需要保证分库分表的数据存储均衡性技术上需要尽量保证分库分表的数据库读写均衡分布,对可能出现的数据倾斜场景,需要给出明确的说明,和使用限制性规范能提供性能基准承诺,由测试团队对典型场景压测给出《平台性能报告》,作为平台对外服务的一部分库存的创建,扣减,查询,扩容,缩容(缩容量不能少于剩余库存)库存冻结,解冻库存管理主要功能:库存创建库存扩容库存缩容库存扣减库存回补库存查询细化要求:满足去UMP的所有要求(去UMP为一个内部项目,各种限定型规则在此不细列)2.1.2 业务抽象可视化通过事件风暴或四色建模法来可视化。我们这里选择事件风暴法。过程主要涉及识别领域名词(示意,不包括全部)识别领域命令(示意,不包括全部)这里列了主要的命令场景分析:主要是识别发出命令的主体是谁,如C端消费者,B端消费者还是某个系统。主要是通个主体在具体Usecase中去串联命令对于领域对象(对应领域名词)的影响。串联业务流程完成领域分析识别领域事件在命令发出后对一个领域对象(聚合根)将产生影响,往往对内(聚合根)会生成数据或发生状态变更;对外(向其他聚合根)发送消息或触发事件。这些事件是业务专家重点关心的结果这里是先识别领域事件,还是先识别命令可以根据设计者的习惯和熟悉度,自行选择最后,整合命令,领域对象和领域事件的关系,得到业务梳理的输出文档(实际命令可能比图中多,如库存冻结和预扣等):2.2 统一领域语言(示意,不包括全部)2.1章中几个阶段是一个来回讨论的阶段,通常需要经过很多轮的修改和妥协,以至于早期列出的领域名词、领域事件和命令远多于上面的图例,但最后大家需要统一确定其中关键的领域名词、领域事件,并统一领域语言,在后续的讨论和设计阶段均使用统一语言建模。这里我们用下面的统一语言仅示例产品账:术语描述记账主体(principal)(mainPrincipal)(subPrincipal)记账主体(id),如,抽奖活动中的消费者记账,则为cid账单(accounting document)(accounting doc)名词,一次记账请求提交的数据为一条记录。指产品方提交给记账平台的原始单据数据记账(keep account)动词,记录record的过程销账(write off account)动词组,记账的反向操作金额(amount)记账的数量账(account)按账期 统计的在该周期内的数额总和相关数据账期(account cycle)账期(会计周期)的类型,如,日账,月账,终身账等账期值(account cycle value)账期值。如对于自然日类型的账期,账期值可以是“20210415”代表4月15这天的账记账类型(operate type)操作类型指,记账或销账2.3 限界上文识别最后,当领域名词、领域事件和命令都统一并清理好之后,我们需要圈定合适领域出来,这里要注意,并没有统一的最佳答案,圈定原则只是遵循现实世界的松紧耦合关系,某些场景下可能有多种选择,本例较简单,示例如下2.4 问题子域识别在战略设计阶段的最后,按“一个子域负责解决一个独立业务价值的问题”的原则,将限界上下文划分到不同的问题子域(Subdomain)中,同时还需要从更大的域视角来俯览全局,并按照以下三种类型进行标注:核心域(Core Domain):是当前产品的核心差异化竞争力,是整个业务的盈利来源和基石,如果核心域不存在,那么整个业务就不能运作。对于核心域,需要投入最优势的资源(包括能力高的人),和做严谨良好的设计。通用子域(Generic Subdomain):该类问题在界内非常常见,所以很可能有现成的解决方案,通过购买或简单修改的方式就可以使用。支撑子域(Supporting Subdomain):该类问题解决的是支撑核心域运作的问题,其重要程度不如核心域,又不属于通用子域,具备强烈的个性化需求,难以在业内找到现成的解决方案,需要专门的团队定制开发。问题子域,是对业务问题的进一步澄清和划分,同时也是对于资源投入优先级的重要参考,相对限界上下文来说,问题子域是对业务问题更大粒度的划分,是在限界上下文识别后与问题域匹配的一个过程。通过对于子域进行识别、划分和类型标注,团队能够实现软件架构在业务边界上的内聚和解耦,便于逆向应用“康威定律”。在 DDD 的概念中,限界上下文和问题子域是两个不同维度的概念,限界上下文可能只是真实问题子域的一部分表达,也可能限界上下文中的一些领域名词超出实际问题子域的范围,理论上来说没有绝对的依赖关系。需要根据实际需求和成本综合考虑,既要保证便资源分配的合理,又要在降低落地成本的同时保证后期演进的适度兼容。问题子域识别过程的产出物,如下图所示:2.5 限界上下文映射(示意,不包括全部)这里只示例产品账的。明确限界上下文映射关系,是为了更明确各context之间的关系,在IDDD中给出了9种关系,在本例种只涉及到3种,实际项目中可能比这个复杂的多,尤其是涉及集成和遗留系统的场景。明确contex之间关系,有助于后续保证系统之间的依赖关系,为后续架构模式的补充模块做好准备。三. 战术设计3.1领域建模3.1.1 领域对象提取(聚合/实体识别)偷个懒,这里只示意产品账的实体和部分值对象3.2 业务服务识别业务服务识别,是为后续系统实现进行的基于业务边界的模块拆分分析,常见的拆分方法有:基于限界上下文进行拆分:每个限界上下文为一个服务,优点是每个服务都很小,代码量少;缺点是拆分粒度太细,导致服务数量过多,增加架构设计的复杂度和运维成本。基于子域进行拆分:每个子域为一个服务,优点是服务数量相对较少,架构复杂度和运维成本相对更低;缺点是拆分粒度在某些场景下会非常大,导致单个服务变成“小单体”,增加开发成本和代码分层复杂度。通过对于业务服务进行划分,团队能够获得对软件架构模块拆分的直接指导,并且还能够依据“逆康威定律”依据架构结果进行开发团队的划分和组建。下面是预算管控子域的服务拆分示例子域服务预算管控子域库存服务产品账服务3.3 业务服务接口识别单独对业务服务的接口能力进行识别,是符合面向接口编程原则的,提前定义服务的概要设计方案,可以让后续团队成员更快开展工作,也方便后续接口的详细设计这里提前识别服务接口,是为了避开技术实现细节的影响。我们在基于具体技术实现的情况下设计接口,通常会干扰领域驱动的设计。我们试想下基于swagger文档,设计API时,我们是否容易保证API的归属正确领域服务。所以提前的概要识别和设定很重要下面是库存和账服务接口识别示例:子域聚合根/实体接口能力读写账上下文账单记账写账本单主体单产品单账期查账读单主体批量产品单账期查账读库存上下文库存创建库存写扣减库存写缩扩容库存写查询库存读四. 技术实现在完成了战略设计和战术设计之后,就可以考虑具体的技术详设,这个阶段会设计到具体的架构模式选择,架构风格和基础技术,存储等的选择。包括且不限于:架构风格选择,单体,soa,微服务,restful,rpc,webservice,ODATA等架构模式选择,传统分层,六边形,简洁,洋葱等补全组件,如rpc客户端,mtop,gatway,acl等,这里要分清应用层,,基础设施和领域技术框架选型,技术栈,服务治理体系API设计,openapi,swagger,blueprint等领域模型类设计,参考领域模型设计类图持久化选择,这里要考虑哪些需要存储RDB,哪些用Nosql,哪些只需要内存中。在上例产品账中的账本就不需要持久化应用层设计模式选择,因应用需要,或运营策略需要支持能力要考虑合适的模式支持考虑其他需求的实现,易测试性,性能,易维护和运维,安全等在本例里只示例产品账的领域模型参考: 其中账本(accountbook)不需要持久化,其他领域对象均需要持久化五. 总结最后需要时刻提醒的。没到最后实现阶段之前应该杜绝提前考虑技术细节和技术实现,否则很容易偏离DDD
为什么你应该关心领域模型?
作者简介:张刚,软件工程博士,阿里云云效资深技术专家,ALPD方法学核心成员。读者福利:前往:https://developer.aliyun.com/topic/course/alpd 免费领取阿里爆款架构师课程《DDD高手进阶12讲》(原价98元)。引言领域模型是重要的概念。但是,真正了解并能熟练运用它的人并不多。这实在是殊为可惜的一件事情。软件开发中的许多问题,例如需求难于沟通,软件难以演化,都和领域模型紧密相关。更关键的是,掌握这个概念并不难。通过练习,一个团队只需要一两个小时,就可以习惯领域模型的建模思路,并且开始从中受益。那么,什么是领域模型?如何理解领域模型的本质?为什么领域模型能给软件开发带来巨大帮助?如何表达它,如何应用它?本文将依次展开这些概念。什么是领域模型?首先我们来看什么是领域模型。领域模型定义了领域内的关键的概念以及这些概念之间的关系。为什么要强调“领域内”?是因为模型(或者说概念)只在它所处问题空间中才有意义。这分为两种情况:1)一个概念只在某个特定领域有意义。例如,“应收账款”,就只是在财务领域,更严格的说是会计领域才有意义。2)一个概念必须通过领域限定,才有具体的意义。例如,“轨道”这个概念,它可能是天文学领域的行星运动轨道,也可能是铁路领域的火车轨道,必须得先限定领域,这个概念才有真正的价值。关键信息1:领域模型最重要的是概念,领域模型也被称为概念模型。虽然有人说“领域模型是领域内的概念的可视化表示”,但是, “可视化”并不本质,虽然它也重要。相比较而言,“概念”才是根本。关键信息2:“语言的边界就是思想的边界”—— 一个好的领域模型,必然承载了有用的知识。对一个不熟悉特定领域的人来说,理解概念,往往是进入一个领域最快的方式。例如,小时候的儿歌:太阳大,地球小,地球绕着太阳跑。地球大,月亮小,月亮绕着地球跑。它就可以认为是一种概念模型的表达。在这个模型中,包括了3个概念实体:太阳,地球和月亮。而太阳和地球的关系是地球绕着太阳运动,地球和月亮的关系是月亮绕着地球运动。用一张图画下来就是:这张图其实是UML的对象图,当然即使你不熟悉UML,就是作为线框图,也能很容易理解。同样,在各种业务领域,都有自己的关键概念。这些概念的表达也不一定是图。例如,刚才所讲的会计领域,我们可以使用一张表来表达下列的几个关键概念:会计主体(本方)->对方应收账款货物已经发给对方,但是尚未收到货款应付账款已经收到对方货物,但是尚未支付货款预收账款已经收到对方货款,但是尚未发货预付账款已经支付对方货款,但是尚未收到货物通过这样一张表格,相信即使对会计领域不甚了解对小伙伴,也能快速掌握相关的知识。如果我们更进一步,能够理解到,应收和预付,本质上是本方的债权,而预收和应付,本质上是本方的债务。用一张图表示就是:在这里我们使用了UML类图来表示。对于不熟悉UML的小伙伴,可能需要解释一下三角形箭头的意思,它代表“是一种”,例如,应收账款是一种债权。更严格的,如果一笔应收账款的帐期已经很长,例如5年,那么这种账款有很大概率已经收不回来了,所以需要计提坏账。有一些通用的坏账计提策略,例如:一年以内5%,一到二年20%,二到三年50%,三年以上100%等。所以,面向刚才的应收账款,我们可以用下面的图来表达这样的概念:图是一种视图,它不需要面面俱到。例如,本图中,并没有显示一切和会计科目相关的信息,而只是集中于坏账的计提。其中,我们在应付账款和坏账之间引入了一个新的符号,认识UML的小伙伴知道我们表达的是”应收账款中包括坏账“。图中的帐期、金额等,我们成为“属性”,用于详细的说明应收账款、坏账这些概念还包括哪些内容。由于领域模型本质上传递的是概念,是知识性的信息,所以,对于软件开发的场景来说,把这些知识显式化,能快速对齐不同角色、不同参与方之间的概念,加速沟通,避免误解。领域模型是重要的业务资产领域概念沉淀业务知识,而且非常稳定。一家在某个领域深耕多年的企业,和一个新入行的企业,差别是什么?差距可能是多方面的,但是最大的差距应该是“认知”。——所以我们常常会看到,新入行的企业追赶深耕多年的企业的办法,常常是去成熟的的企业高薪“挖角”。按道理说,挖来的这些人既不能把原公司的客户带来,也不可能把原公司的系统带来,那么本质上他们给新企业带来了什么呢?他们对新公司最大的帮助,是对特定领域的认知。在业务领域,认知非常值钱,而且非常稳定。我们也会看到,一些在某个领域建立了优势的企业,特别是咨询类企业,单靠业务领域的咨询,就能给企业带来客观的收入。如果有良好维护的领域模型,那么领域模型就是这些认知沉淀的最佳位置所在。更重要的是,尽管业务常新,但是领域模型却相当稳定。我们以商品交易为例。我们知道买家、买家、商品、交易这些概念,都是商品交易领域的核心概念。这些概念并不会随着业务的演进发生剧烈的变化,无论是B2C业务,C2C业务,C2M业务,拼团业务还是秒杀业务。不同的业务,体现的只是对这些业务概念的不同组织方式。当然,真正的领域模型要远远比上述概念复杂的多。我们这里只是举一个简单的例子,说明领域概念的稳定性。领域模型的跃迁和生长当然,我们说领域模型稳定,并不是说它一成不变。优秀的领域模型都一定会持续生长,甚至有时候会发生本质的跃迁。一旦一个模型被推翻,我们会认为,我们对某个领域的认知,一定发生了非常本质的跃迁。例如,前述的儿歌“太阳大,地球小,地球绕着太阳跑。地球大,月亮小,月亮绕着地球跑。”并不是一开始就是这样认知的。无论中外,在几百年前,我们都曾经认为,地球是宇宙的中心,太阳、月亮都是绕着地球运行的。那么,这个模型画出来就是下面这个样子:地心说对象图地心说到日心说,是我们宇宙认知到巨大进步,以为日心说模型彻底否定了地心说模型。在软件领域也是这样。我曾经经历过几次领域模型跃迁的场景,每次都伴随这业务认知的巨大进步。当然,在现实生活中,跃迁并不多见。更多的时候都是在原有的模型上稳定发展,逐步增入各种新的概念和各种细节。模型的生长过程,本质上也是业务能力积累的过程。稳定的领域模型带来软件的适应性需求是不稳定性的,而领域模型是稳定的,这启发我们,如果以领域模型为中心去构造软件,那么我们就会构造出很多稳定的积木块。新的需求,就可能通过这些稳定的积木块,通过不同的搭建方式,形成丰富多彩的应用。在这种情况下,我们的软件对于变化的适应力最强,开发成本最低。领域模型存在于哪里用类图表示领域模型UML类图是表达领域模型的非常好的工具,虽然并不存在如何表达领域模型的标准。因为在UML中,“类”并不简单是软件设计中的“类”,它代表的其实是“概念”,所以,把类图用在领域模型的表达上,是非常恰切的。而且,UML已经约定了概念和概念之间的关系,例如:类、属性、关联、关联的多重性、泛化、聚合、组合、依赖等等。对于不熟悉UML的人来说,使用UML也完全没必要有什么心理负担。UML是一个高度灵活的结构,它具有渐近的能力。你没有必要掌握所有复杂的概念才开始工作,根据我的经验,只要一开始能把类(代表概念)、类的属性和它们的关系描述出来,最多再知道多重性怎么表示,就足以应付大多数的场景。有些小伙伴有面向对象的经验,在这里会纠结于要不要对“方法/操作”进行建模。在“领域模型”是一种“业务概念”这个上下文中,方法是完全多余的东西,暂时不需要在这个阶段进行建模。我认为在实现阶段补足它们更合适。在交流和文档中使用领域模型领域模型写在纸上并不是最关键的。作为概念模型,它反映了这个领域的最重要的概念,也构成了表达业务概念的词汇。所以:最好的领域模型,应该时刻存在于团队成员的心中,存在于日常的交流活动中。为了做到这一点,我对自己的团队和辅导过的团队,都有一个要求,这个要求也被成为交流活动中的“统一语言”:任何在需求描述中出现的概念,都必须出现在领域模型中。如果需求描述中存在概念之间的关系,领域模型中也必须有这个关系这个要求看似简单,实际做到会比较困难。特别在刚开始的时候,团队成员可能并不适应这种做法,常常就忘记了这个准则,需要经常纠正。但是一旦习惯,大家会发现,在日常交流活动中,因为所有的概念都已经显式化,误解大大减少,共识更容易达成,导致的后果就是最后团队成员,都会非常自觉的维护“统一语言”的做法。出于同样的原因,编写文档时,使用领域模型作为统一语言也成了一个非常自然的结果。在代码中使用领域模型由于领域模型已经被显式化,所以如果能够在代码中使用领域模型,那么代码就会获得更好的易读性。由于领域模型和代码对应的更加一致,那么在领域模型发生演进时,代码就会变得更容易演进。在这方面,领域驱动设计给出了一组完备的模式,可以帮助架构师和开发人员自然地把领域模型转化为代码。本文中我们并不准备展开这些模式。在此,暂时先请读者们记住下面的结论,后面会有更深入的讨论:代码和问题域之间的表示差距应该尽量缩小,领域模型是连接现实世界和数字世界的最佳桥梁。使用领域模型作为代码中的业务概念的基本表达元素,可以大幅提升代码的易读性,也可以更好的支持业务的演进。领域模型来自哪里领域模型反映了关键的业务认知,但是认知并不会凭空建立。能够一上来就洞悉一切本质的,要么是这个人是天才,要么说明这个领域已经是一个非常成熟的领域,已经无需探索和发现。大多数时候,认知都来自于业务场景的启发。所以,领域模型建立的过程,往往是伴随着需求分析同步产生的。我画了下面这张图,来说明领域模型和业务场景之间的关系:也就是说,领域模型是在业务场景的激励下逐渐完善的。而且,反过来因为对领域的认知更加深刻,领域模型还有助于新的业务场景的发现。探索和发现最好不要一个人独自进行。更多地时候,应该尽量进行集体建模。集体建模不仅仅利于探索和发现,而且它也有助于达成对于关键业务概念的共识。集体建模的最好工具并不是UML的电子化工具,使用白板,在开放空间中的讨论,往往能够收到最好的效果。由于领域模型表达的是概念,所以对于概念及时地分解和抽象,是领域建模的基本功。当然,现实中受过严格的分解和抽象训练的人并不多,特别是很多业务人员往往都缺乏这方面的能力。我在实际工作中,观察到具有面向对象经验的开发人员,经过一定时间的练习,可以很快掌握这方面的技能。所以,如果有一些具有经验的开发人员参与建模,往往可以获得质量更高的模型。常见误区领域模型的概念产生于90年代的面向对象社区。在那个时候,业务变化还不像今天这样频繁,迭代的思想也还没有完全成熟,业务人员和技术人员也没有像今天这样密集的交流,所以,无论是从参考书上,还是实践上,领域模型的概念都难免留下早年做法的影响。其中,有若干误区,在实践中是应该尽量避免的:误区1: 从开发视角进行领域模型的建模常常有技术人员问:“领域模型和ER图有什么关系?” 对这个问题最直接的回答就是:“没有关系”。固然,我肯定知道在有了领域模型之后,设计ER图会更简单,或者对于一个还缺乏领域模型的遗留系统,研究数据库结构可以带来有效的输入,但是它们的立足点是完全不一样的。领域模型一定要从业务视角去看,因为领域模型反映的是业务认知。一旦在领域模型中掺杂了技术的概念,不仅仅是因为它不够纯粹,更重要的是它已经堵死了从业务视角对领域模型进行演进和纠正的机会。因为没有软件背景的业务人员,是不可能去看一个充斥着技术概念的模型的。统一语言无法建立,领域模型带来的价值就已经损失了一大部分。此外,从开发视角进行建模,往往还会忽视业务人员的参与。而实践一再表明,资深的业务人员在领域建模时,往往能提出深入的洞察。所以,从开发视角对领域模型进行建模绝对不可取。误区2: 建立庞大的领域模型当我们说“领域”的时候,并没有限定一个“领域”应该有多大。究竟是“航空”作为一个领域,还是“航空”中的“订票”是一个领域?当你考虑到“领域的核心是认知”,这个答案就变得非常清楚了。领域越大,越不利于建立认知和共识。我们应该这问题域,把大的领域划分为小的领域,然后逐个建立这些小的领域的领域模型。那种整整一面墙的领域模型,往往都是不可取的。 误区3: 重文档,轻交流和共识领域模型的核心在于建立共同的共识,所以,如果只是把领域模型作为一种“制品”,作为某个阶段的“输出”,这是非常不合适的。领域模型需要作为交流工具。“统一语言”是避免该误区的重要方法。误区4: 不把领域模型显式化很多人认为自己是有“认知”的,甚至是有“领域模型”的,但是,如果你问他们模型在哪里,这些要么就是在某个项目曾经有过一些讨论,但是现在已经不知所踪,要么就是虽然文档还在,但是团队的概念表达依旧混乱。没有显式化,没有把领域模型写下来,没有形成团队口口相传的知识,那么这种模型,并不真正存在。除了“统一语言”,我们还有一个非常简便的检验方法,就是看这个团队如何给新人介绍自己的系统。因为领域模型反映了基本的业务概念,是一个非常好的新人培养工具,但凡真正有“领域模型”的组织,是不可能不把领域模型拿出来做介绍的。总结本文我们主要介绍了领域模型的基本概念及重要度,领域模型对于“统一语言”的价值以及领域模型应用的常见误区。总结一下要点:领域模型的本质是概念和认知,它定义了领域内的关键概念以及这些概念之间的关系相对于业务的多变,领域模型相对稳定,优质的领域模型可以低成本的支持业务,领域模型也是统一语言的基础,能有效提升沟通效率领域模型来自于业务滋养,领域模型生长的过程,也是业务认知建立的过程,协作建模是更有效的建模方法在你的团队中,有显式的领域模型和共同的业务认知吗?它在指导日常的交流和开发工作吗?如果还没有,让我们开始吧。课程推荐:《DDD高手进阶12讲》本文内容源自阿里云云效推出的《ALPD云架构师系列——DDD高手进阶12讲》。这是一门阿里内部的爆款课程,获得数千阿里工程师口碑推荐,值得每位开发者反复学习。或PC端前往如下链接获取课程,免费领取阿里爆款架构师课程《DDD高手进阶12讲》(原价98元)https://developer.aliyun.com/topic/course/alpd
如何成为云原生时代的卓越架构师
本文作者:张刚,阿里云云效资深技术专家,ALPD方法学核心成员。立即学习:https://developer.aliyun.com/topic/course/alpd软件开发的本质困难1986年,软件工程巨匠Frederick Brooks撰写了一篇著名的论文《没有银弹》。他在文章的开篇写道:在未来的10年以内,不存在任何单一的方法和技术,能够10倍以上的提高软件开发的生产力。这个论断在当时就引发了巨大的争议。至今,《没有银弹》仍然是一个被经常拿出来讨论的话题。不过,这篇论文的真正价值远不限于此,继续读下去,就会发现,。停留在是否存在10倍以上生产率的讨论是不够的。真正值得关心的,是Brooks对原因的论断。我把其中的重要观点概括如下:软件开发的困难有两类,一类是本质(Essential)困难,一类是附属性(Accidental)困难。本质困难是和软件的本质紧密联系在一起的,所以这类困难无法通过工具或者语言等加以解决。例如,软件解决的问题是现实世界的问题,如果现实世界的问题本来就是复杂的,那么无论任何工具,都不可能消除这种复杂性。附属性困难是和我们采取的工具或者方法相关的。例如,软件需要被通过某种语言实现,软件需要被编译、被部署,软件可能被实现为缺陷,这些都和具体的实现方法相关。这一类困难,可以通过工具、方法和技术的提升得以改善。本质困难包括软件的复杂性,不可见性、可变更性和符合性(指软件开发还需要遵从诸如法律法规、外部系统等不受主观意志决定的因素)作为一名在软件开发行业工作了20年的架构师,《没有银弹》关于本质困难和附属性困难的论述给了我巨大启发。多年以来,我一直都把“管理本质困难、消除附属困难”作为软件开发活动的座右铭。特别有意思的是,最近我发现,作为一个主要工作在业务系统上的架构师,在云原生渐成趋势的时候,架构师的职责已然发生了改变。而这个变化,恰恰和“管理本质困难、消除附属困难”密切相关。业务架构当然也是架构师的重要职责。业务和技术已经深度融合,业务对响应速度的要求和开发质量的要求越来越高,同时在云原生时代,服务化几乎成为必然选择。而无论是业务响应能力、开发质量和服务化,都和业务规划能力密切相关。这不就是最重要的“管理本质困难”的方面嘛!领域驱动设计,虽然Eric Evans的同名书籍写于2004年,多年以来,在技术社区也有较大影响。但是为什么最近几年热度突然大幅上升,变得特别受关注呢?这是因为,我们的业务终于越变越复杂,到了如果没有恰当的方法,就不能很好的管理的地步——这也恰恰暗合了DDD一书的副标题“软件核心复杂性应对之道“。微服务和云原生在服务方面的划分等,也是关键的助推因素。成为云原生时代的架构师在今天的业务环境下,能更好地利用好云原生基础设施,更好地进行业务规划、高效高质地分析和管理领域模型,用领域模型指导架构设计和开发实践,是云原生时代架构师的重要技能。这次云效和阿里云开发者学院联合推出的《ALPD云架构师系列——领域驱动设计》课程也正是围绕着这个主题展开。ALPD全称Advanced Lean product development,它是阿里云云效团队提出的云原生时代的研发新范式,它整合了技术、工程、协作、创新4类实践,并提供高效解决方案。上面2幅图分别是ALPD方法和支撑体系图,我们希望ALPD及其解决方案可以帮助企业和开发者,实现10倍效能提升——10倍的响应速度,10倍的过程质量,10倍的有效价值交付。在本次课程中,我们将为大家带来 ALPD方法体系中的领域驱动的架构和实践 部分的内容。能通过这一次的对外整理,将知识和经验分享给社区开发者小伙伴,也是非常开心的事情。ALPD云架构师系列课程——DDD高手进阶在课程整理中,我们把课程分成了如下章节:01|领域模型的本质是业务认知02|案例分析:高质量领域模型提升业务灵活性03|高质量领域模型源自持续演进04|案例分析:梳理业务概念,发现领域模型05|从模型到代码:领域驱动设计的构造块06|聚合:保证业务完整性的单元07|领域驱动设计的分层模型和代码组织08|核心域、通用域和支撑域09|基于业务能力和业务场景拆分子域10|守护领域边界,构建自治服务11|限界上下文映射的模式12|使用微服务构建领域资产其中每讲都保持了15分钟左右的篇幅,以聚焦于一个比较内聚的主题。1-4讲,讨论领域模型的一个基础概念,包括什么是领域模型?为什么要关心领域模型?如何进行基本的领域建模?5-7讲,主要关心领域模型为中心的软件实现,具体对应于领域驱动设计的战术模式,例如实体对象、值对象,领域服务、领域事件构造块及聚合、资源库和工厂这些跟业务完整性密切相关的部分。8-12讲,关心领域模型为中心的架构设计,具体对应于领域驱动设计的战略模式,比如说子域、限界上下文、限界上下文映射等方面的话题。最后的12讲,我们把微服务跟领域资产之间的关系也做了讨论,微服务是当前一个重要话题,如果对领域驱动设计关注不足,也会影响到微服务和云原生的实施。在整个课程中,没有晦涩难懂的概念,我更希望能通过简明的案例让学员轻松理解领域驱动设计的核心思想和关键实践。希望你也能通过学习这个课程,可以从本质出发,更好地理解DDD并付诸实际项目实施。点击下方图片或文末链接,加入《云架构师系列课程——DDD架构实战》的学习之路吧!当然,领域建模和领域驱动设计仍然是需要长期刻意练习的技能,课程中的内容也还只是抛砖引玉,在后续的实际工作中希望你能持续应用和提升,不断精进,成为云原生时代的卓越架构师!立即学习:https://developer.aliyun.com/topic/course/alpd
「技术人生」第2篇:学会分析事物的本质
作者:贺科学技术一号位不是岗位,更多的是技术人员在公司中做事的一种心态,这个系列的文章适合所有想要对日常工作“知其然更知其所以然”的技术人,借助理论工具的指引,结合自己的实践经历,悟到自己的收获,从而加速成长的过程。大道理千千万万,有缘者得之真谛践于其行而非流于其表。未来一段时间,阿里巴巴中间件公众号会持续发布系列文章,欢迎关注。往期技术一号位方法论系列文章:「技术人生」专题第1篇:什么是技术一号位?背景生活中每时每刻都在发生着各种各样的事情,有些与己相关,有些看似毫无瓜葛,不论事情大小,总需要分出一部分精力,或多或少,对事情进行处理解决。在处理这些事情的过程中,在和某些人接触时,总能感觉到他们对事物的认知要更深刻,更全面,听其言如同醍醐灌顶,观其行胜读十年书。这样的人解决问题往往一针见血,事半功倍;而在和另外一些人沟通时,则可能会感到对方对某个事情的认知其实流于表面,解决问题往往抓不住重点,做的很辛苦却多是无用功。那么究竟是什么造成了两种人对事物认知的差异?是否有什么途径或者方式能够消除这种差异?作为技术研发人员,总面临着各种各样的需求,总会有前人不断强调技术的复用,强调代码的重构,可是往往是倒排的截止日期逼迫研发更快上线临时需求,造成线上拣不干净的满地鸡毛,同时留下一身还不完的技术债务。为什么面对一定会变的业务需求,研发人员似乎永远跟不上需求变化的节奏?很多时候大家本能的会怪罪产品经理没有想清楚,那么有没有人思考过,和我们每天配合的产品经理或者运营人员,究竟是什么东西没想清楚,从而导致了我们研发同学自己不断地返工?他们没想清楚的事情,我们是不是从来就没想过?这些事情,我们该不该想,能不能想清楚,有没有好处?研发人员需要掌握什么技能来应对永远都在变化的业务需求?作为系统架构师,在面对复杂业务系统时,开局往往操作猛如虎,三年规划五年演进,可是经过若干年的建设,往往只是遗留下众多见招拆招的祖传代码,新的需求需要在旧的业务逻辑的缝隙里面找“解法”,一线开发人员不仅要避开“牵一发动全身”的各种弯弯绕绕,可能连架构本身也已经变得模糊不清了,更不用提架构的演进。这一切都会逐步失控下去直到某一天达到临界点再来一次推翻式的重构,让混乱重新回到原点,开始新一轮的技术债务周期,当然,系统一定是 2.0 或者 3.0了(目前还没见过 4.0 的系统)。可是当年说好的架构可扩展性呢,说好的抽象程度高呢?架构本身究竟和业务有什么关系,架构的演进又和业务的发展有什么关系,如何才能让架构师打破“架构设计和演进过程被现实反复打脸”的魔咒?作为研发团队 leader,带着自己的人做需求交付,一边忍住亲自下场写代码的冲动不得不做着项目管理的事情,一边又可能被下面的人怀疑技术能力;各种倒排的截止日期仿佛一条条排着队催债的红线,眼看着这些红线圈着自己团队的黑着眼圈的兄弟,在一个又一个的坑里面像炮灰一样摸爬滚打,而自己只能像一个大号的外包资源经理一样对这种局面在实际行动上束手无策,在思想上除了觉得要不断加人之外感觉无力回天。如何才能让团队成员在做业务的过程中不再是资源一样被消耗而是像资产一样自我增值?如何才能利用对业务发展趋势的预测打破规律提前布局,在战略上掌握主动性,从而在战役上既能先于对手做出稳定的产品,又能有足够的时间打磨产品从而提升用户的使用体验?不同角色的技术人,不论在工作还是在生活中,面临的这一系列老生常谈的问题时,或许都希望能有一抹就灵的万金油,打一发银弹出去,就能够留下广为业内传唱的人月神话。可是在现有的生产力条件下,技术人员既没有万金油,更不存在银弹,而且人月神话永远都是神话。所有的事情,所有的问题,想要被解决,都要回到最初的原点:这件事情的本质是什么?也就是说,我们日常工作中的事情的起点不是使用什么工具解决问题,而是先认清这件事情 —— 认清一件事情的本质,是所有后续行动的前提和基础。做业务需求分析也好,做架构设计画架构图也罢,计算机语言和技术栈的选择以及相关整体解决方案的构建是一方面,而“基于对业务本质的理解进行的业务建模并结合业务发展持续演进”是极其重要的、却往往被忽视的另外一个方面。日常工作中,很多研发人员往往把注意力集中在各种计算机语言及其技术栈上,大家会花时间翻看各种技术书籍,探究各种技术方案背后的原理,然后通过业务实践提升个人技术能力,所有的促进个人成长的事情几乎都是围绕着“技术”两个字展开,但是,特别是对于常年从事业务研发的同学而言,大家是否意识到,除了“技术”以外,还需要掌握“业务”相关的知识,而其中,探究事物的本质,是最基础最核心最先需要被掌握的技能,没有之一。它是战略层面构建业务大图的基础,是排兵布阵发起关键战役的基础;也是战术层面分析业务需求的基础,做架构设计的基础,做业务领域建模的基础。技术一号位需要掌握的所有工具和方法论,所有的起点都是它,所有的理论工具和方法论最终都是它在某个领域内的应用、投射和简化。什么是事物的本质事物本质的哲学定义抽象地探讨事物的本质,涉及到了哲学层面,目前本人不具备相关的能力来进行详细的理论论证,这里就直接摘抄马克思主义哲学关于事物本质和现象的对立统一的论述,来看哲学层面的事物的本质是什么:本质是事物的根本性质,是事物自身组成要素之间相对稳定的内在联系。—— 《马克思主义哲学原理》(第五版,陈先达、杨耕著)本质是事物的根本性质,是事物自身组成要素之间相对稳定的内在联系,是由事物本身所具有的特殊矛盾构成的。—— 百度百科唯物辩证法的宇宙观主张从事物的内部、从一事物对他事物的关系去研究事物的发展,即把事物的发展看做是事物内部的必然的自己的运动,而每一事物的运动都和它的周围其它事物互相联系着和互相影响着。事物发展的根本原因,不是在事物的外部而是在事物的内部,在于事物内部的矛盾性。任何事物内部都有这种矛盾性,因此引起了事物的运动和发展。事物内部的这种矛盾性是事物发展的根本原因,事物和事物的互相联系和互相影响则是事物发展的第二位的原因。—— 《矛盾论》毛泽东研究问题,忌带主观性、片面性和表面性。所谓主观性,就是不知道客观地看问题,也就是不知道用唯物的观点去看问题。这一点,我在《实践论》一文中已经说过了。所谓片面性,就是不知道全面地看问题。—— 《矛盾论》毛泽东事物本质与现象的对立统一分析1、本质和现象是对立统一关系。任何事物都有本质和现象两个方面。世界上不存在不表现为现象的本质,也没有离开本质而存在的现象。本质和现象是统一的,但二者又有差别和矛盾。本质从整体上规定事物的性质及其基本发展方向,现象从各个不同侧面表现本质;本质由事物内部矛盾构成,是比较单一、稳定、深刻的东西,靠思维才能把握;现象是丰富、多变、表面的东西,用感官即能感知。假象从否定方面表现事物的本质,给人一种与事物完全相反的印象,掩盖着本质。假象的存在明显表现出本质和现象的矛盾。因此不能简单地把现象与本质等同起来。—— 百度百科2、事物的本质与现象是对立统一的,这是客观辩证法,把这种辩证法运用于人的认知过程,就要求人们既不能脱离现象去空谈事物的本质,也不能停留在事物的现象上,而要透过现象抓住事物的本质。(本文作者批注:透过现象看本质,这句话谁都懂,但是究竟怎么才能做到,是本文尝试给出的。)为此,要在实践的基础上观察大量的现象,尽可能多地占有感性材料,这是认知透过现象抓住本质的前提条件。(本文作者批注:这就是“没有调查就没有发言权”的理论依据。)在观察社会问题时,一定要学会区分本质与现象,要抓住本质与主流,这是其一。其二,有了观察到的大量现象,占有了真实的感性材料,并不等于抓住了事物的本质,要透过现象抓住本质,就必须对大量的现象、真实的感性材料,以及它们之间的关系进行分析和研究,这就需要掌握科学的方法。(本文作者批注:《马克思主义哲学原理》中并没有讲明需要掌握的科学的方法究竟是什么,而这一点,恰恰是本文作者结合实际实践经验尝试给出的,同上一个批注。)其三,事物的现象错综复杂,而且事物的本质有一个逐渐暴露,逐渐展开的过程,所以人们对事物本质的认知不是一次完成的,而是一个不断深化的过程,是一个由片面到全面、由不太深刻到深刻的过程。—— 《马克思主义哲学原理》(第五版,陈先达、杨耕著)了解了哲学层面的本质与现象的对立统一关系,有的读者可能会问,这和业务研发有什么关系?我这里只举一个看起来非常小但是实际上问题很大的例子:我们所做的新零售业务,整个流程涵盖了供应商、平台、渠道客户、合作伙伴和消费者这些不同的业务参与方,整个业务可以让供应商入驻平台,给平台上的渠道客户供货,从而让渠道客户自己的用户能够以积分或者积分加现金的方式购买商品。某天产品经理提了一个需求,说要“在供应商控制台中增加一个删除按钮,删掉供应商不想看到的商品”。看似非常简单的一个需求,在商品列表里面增加一个删除按钮,应该很快就能上线,但是实际上,删除商品这个动作背后真正的业务含义和场景并不是简单的技术上的把商品数据软删除,而是“停止供货”——供应商要删除的商品很大概率已经签过在线协议,以某个价格供货给某个渠道客户,这个时候研发人员如果按照需求无脑删除商品数据,就会造成已经在售卖甚至在参加运营活动的商品突然无法购买,造成渠道客户的损失或引发舆情。所以,研发人员沟通完需求要进行技术方案评审时,被我驳回,要求相关的同学完成业务场景的分析和讨论,补全删除按钮背后的完整业务流程,将“删除”按钮的名称修改为“停止供货”按钮,并且针对已经不在任何渠道销售的商品单独提供筛选项,而不再在供应商商品管理列表里面默认展示。所以整个需求原本就是一个删除按钮1天的工作量,实际上分析清楚产品需求背后的业务场景和真正的业务含义以后,就变成了一个涉及到了停止供货的在线审批流程、供货协议更新、渠道在售商品下架等等一系列联动的复杂业务需求,技术方案的复杂度和原来相比更复杂,排期更长。作为业务的技术负责人,如果不能把握业务需求背后的本质,类似这种情况会层出不穷,所有快速上线的临时方案最后都要随着需求的深入而重新投入人力和精力进行重做,这方面的成本往往会转嫁在一线研发同学身上。探究事物本质的方法抽象的哲学定义并不能给我们提供透过现象看本质的实际操作方法,但是却指明了事物本质的组成和关键点。我们可以基于哲学上的定义和《矛盾论》全文以及本文中特别引用内容可知,如果想要分析清楚一个事情的本质,就是要客观地去分析事物,梳理它内在的主要矛盾和次要矛盾,同时需要梳理外在的它和它所处环境内其他事物的相互联系和相互影响。内在要分析研究目标事物的组成部分和对应的对立统一关系,从而得出对应的主要矛盾次要矛盾,理清矛盾的主要方面和次要方面。需要注意的是,相关的分析是建立在事物的某一维度上,在事物发展的某一阶段上的,随着事物的发展,相关的分析可能会出现变化。事物的内在决定了事物的本质。如下图所示:外在要分析在一定环境下,研究目标事物和其他事物之间的相互关联关系和相互影响。事物的外在通过事物的内在关系和影响来影响事物的发展。这一点可以简单思考一个问题:一把普通的锤子可以打破一面普通的玻璃,根本原因在锤子还是在玻璃?如果觉得根本原因在锤子的读者,可以继续思考:一把普通的锤子可以打破钢化玻璃么,可以打破防弹玻璃么,可以打破钢铁么?如下图所示:通过以上的示意图和对应的分析说明,我们可以了解到在分析问题本质的过程中的所有关键因素,关于详细操作步骤和说明指引,在本文第四章节会给出模板,方便大家在实际工作生活中使用。分析事物本质对技术一号位的必要性业务研发,特别是复杂业务系统的研发,实现产品经理提出的业务需求仅仅是其表象,其真正本质内涵,是使用技术手段将解决某一特定问题的逻辑数字化,利用计算机技术对客观事物做数字化的建模,以尽可能贴近事物本质的方式进行逻辑和数据的运转,从而完成现实和虚拟的映射,解决对应的问题。作为研发团队的技术负责人,如果对业务的认知的起点是产品经理输出的产品功能文档,对业务的理解来源于源源不断的业务需求,不能认清业务的本质,不能看到未来的一些可能的发展趋势,那么这样的技术负责人其实只能做到了响应业务的需求,永远无法真正的在技术架构和解决方案上支撑业务的发展,更遑论使用技术驱动业务发展了。这也是“技术一号位” 和 “研发团队 TeamLeader”的最大的区别,前者是业务的共建者,利用技术背景和专业技能辅助业务一号位推进业务的发展,本质上是在扮演决策者的角色,而后者只是研发资源的协调者和项目进度的把控者,本质上是在扮演执行者的角色。面对非常复杂的事情的时候,我们需要能够有合理的理论工具来支撑自己,将复杂的情况主干脉络理清楚,然后分析它为什么现在会是这样,过去是什么样的,在什么条件下,未来会发展成什么样,然后再分析哪些关键部分是我们可以通过实际行动影响的,从而通过影响关键部分来引导事物未来的发展方向。以下内容就是面对复杂问题的时候,基本的分析操作流程。分析事物本质的操作步骤事物内在分析1、明确事物讨论的范围明确问题讨论的范围非常重要,同一件事情,在不同的范围内讨论,得出的结论可能完全相反,原因并不是我们使用的理论工具有问题,而是随着讨论范围的扩大,讨论的事物本身的组成和外界的相互联系和相互影响都会变化,所以就会有不同的,甚至是相反的结论出来。所以为了解决某个固定的问题,我们首先要确定的就是这个问题的范围是什么,它所处的环境是什么,讨论的问题的场景是什么。这些是展开所有的分析的基础,如果多人讨论的情况下,不把这部分内容对齐,就会非常容易导致讨论的时候各方论点风马牛不相及。2、分析事物内部组成及其存在形式在明确好事物的范围以后,我们需要分析清楚这个事情中的各个组成部分,每个组成部分是以什么样的形式存在的。3、分析事物内部各组成成分所扮演的角色及其职责事物的每个部分,在这个事物中,都扮演了某种角色,这个角色是某个部分的职责和行为的抽象,所有的行为都体现着该部分的核心利益诉求。4、分析各角色在职责限定下的核心利益诉求在分析完事务内部各组成的角色以后,接下来就是分析该事物内部组成在对应角色的要求下的核心利益诉求了。需要注意的是,在讨论核心利益诉求的时候,需要结合场景,明确讨论范围,否则所很多事物最终的核心利益诉求都会被过渡抽象化,但是很多时候一个问题是一个具体的、有范围的利益诉求展开的。只泛化地讨论经过抽象后的利益诉求,既不方便分析矛盾点,又不能具体的解决实际问题,所以在讨论对立统一的时候,明确核心利益诉求要限定范围和场景,不能一味只做抽象,只去看矛盾的普遍性而不看矛盾的特殊性。事物组成 1核心利益诉求讲清楚该事物组成 1 的核心利益诉求是什么核心利益诉求的由来分析讲清楚该事物 1 的核心利益诉求为什么是这样的事物组成 2核心利益诉求讲清楚该事物组成2的核心利益诉求是什么核心利益诉求的由来分析讲清楚该事物 2 的核心利益诉求为什么是这样的事物与外界相互关联相互影响的分析以毛泽东的《矛盾论》中的理论为依据,我们要想分析清楚事物的本质,还需要分析清楚它和外界其他事物的关系,因此我们会针对这部分内容作简要分析。事物所处的大环境是什么从影响事物本身的多个维度去分别梳理,从而能够建立起来一个多维度的大环境的画像。事物所处的大环境内的关键事件是什么分析每个维度发生的关键事件,这些事件可能和事物内部有各种关系。事物所处的大环境内的关键事件对事物内的影响是什么分析每个关键事件对事物内部的影响是什么。事物所处的大环境未来可能有哪些变化简单预测大环境中每个关键事件未来可能演变的走向,从而分析未来可能对事物本身的影响。事物内部对立统一分析明确讨论范围和场景再次明确讨论事物内部对立统一的范围。基于事物各方核心利益诉求,分析各方之间的对立统一关系基于之前分析的事物各方的核心利益诉求,进行两两分析,分析每2个组成事物时间的对立统一关系,在必要的时候,可以继续分析三方、四方的对立统一关系。我们需要明确的是,所有的对立统一都是在围绕着核心利益诉求展开的,核心利益诉求的满足有低级的方式,也有高级的方式,如果各方的核心利益诉求是通过低级的方式满足的,那么说明各方的“统一”处于低水平的状态;如果各方的核心利益诉求是通过高级的方式满足的,那么说明各方的“统一”处于高水平的状态。基于分析出来的对立统一关系,确定当前阶段主要矛盾次要矛盾基于已经分析清楚的对立统一关系,明确当前事物现阶段的主要矛盾次要矛盾。基于当前阶段的主要矛盾次要矛盾,分析矛盾主要方面次要方面明确主要矛盾和次要矛盾以后,就要看下,矛盾主要方面是什么,次要方面是什么,分别给出解决办法即可。并且确定矛盾主要方面以后,就要优先解决矛盾主要方面,而不是哪个简单先解决哪个,或者最起码要讲清楚在主要矛盾方面做了哪些事情来缓解,否则就会给人造成一种感觉:解决问题隔靴搔痒,不切中重点。1、矛盾的主要方面的分析和解法2、矛盾的次要方面的分析和解法事物发展规律的预测和干预我们面对非常复杂的事物的时候,为什么要费很大的力气去分析它的组成,分析它的主次矛盾?就是为了能够在非常复杂的局面下看清它未来可能的走向,从而提前做好一些准备,甚至主动做一些事情,从而让事情按照我们的预期来发展。1、基于当前主次矛盾的分析,分析主次矛盾的解决办法分析解决办法,确定如何解决主要矛盾,次要矛盾。在解决主要矛盾和次要矛盾的时候,要遵守至少一个非常明确的原则:当前事物的主要矛盾和次要矛盾需要遵循其所在环境的主要矛盾和次要矛盾的演变规律。2、预测演化轨迹和事物发展趋势,寻找可以影响事物发展趋势的关键点,利用规律打破规律就一般的规律来看,对于任何一个事情而言,如果我们期望统一大于对立,把对立的激烈程度降低,那么整个事务的对立统一情况应该从低水平状态向高水平状态发展,即从可能伤害某一方的核心利益的状态,逐步演变为不损害任一方的核心利益诉求,在此基础上寻找合理的方法和模式,满足各方核心利益诉求。在整个演进过程中,开始是统一的模式或形式会起到决定性作用,但是随着统一的水平逐步变高,模式起到的作用释放殆尽以后,往往就需要从生产力来着手,利用生产力的提升来解决模式无法解决的问题,或者是让模式更精细化,或者是催生出新的模式基于更高生产力的模式,从而继续推动统一朝着更高的水平演变。就我们日常具体的事情来看,主要做到以下几点进行分析即可:预测事物在主次矛盾不被干预的情况下的发展趋势,判断趋势是否有利于我们的预期的达成。寻找事物的关键点,判断改变关键点对事物发展趋势的影响,从而让事情向我们期望的方向演变。分析事物本质的案例分享以下内容,是本人利用该方式进行复杂业务的分析的案例。1、在没有做任何调研,只依靠 “流量变现” 几个字,结合自己做的电商业务,进行脱离实际业务的单纯的理论分析,这个分析主要的作用就是让毫无任何业务背景和经验的我,能够在理论上看到业务和技术演进的大脉络,从而为后续的调研、架构设计和最终的系统落地提供整体方向性的支撑。为什么要这样做,因为未来很可能接手的业务是毫无经验的,如何能够把业务做好,这是基础之一。2、在做了大量的调研的基础上,继续按照该方式分析流量变现中的某一个业务参与者他的核心利益诉求,并根据核心利益诉求进行关键业务指标的拆解,从而在业务开展过程中以此指标及其拆解后的指标指引业务的发展。案例详情,请大家在 阿里巴巴中间件 公众号后台回复“一号位”,获取详细信息。扫码查看更多中间件技术干货和案例:
「技术人生」专题第1篇:什么是技术一号位?
技术一号位系列文章介绍研发人员经过一段时间的成长和积累(3-5年),往往需要带领团队或者小组承担更大的责任。很多扮演了 teamleader (TL)角色的“管理新人”,在带人做事遇到困难的时候会陷入纠结:要不要放弃这个发展路线继续做一个单打独斗的技术“老人”?特别是在一些环境中,管理新人本身面临着陌生的领域和挑战,如果没有领路人,单纯依靠自己去实践感悟,往往会走很多弯路。所以本文作者结合多年实践经验,以及结合很多经典理论的输入,总结出了“技术一号位是什么”、“普通研发人员如何一步步成长为技术一号位”、“作为技术一号位需要掌握哪些理论工具来支撑日常工作”等一系列能够引导技术人员升级认知的理论工具。同时需要强调的是,技术一号位不是岗位,更多的是技术人员在公司中做事的一种心态,这个系列的文章适合所有想要对日常工作“知其然更知其所以然”的技术人,借助理论工具的指引,结合自己的实践经历,悟到自己的收获,从而加速成长的过程。大道理千千万万,有缘者得之真谛践于其行而非流于其表。技术一号位方法论系列文章计划:《什么是技术一号位》《技术一号位的方法论【理论篇】—— 如何分析事物本质及分析事物本质的必要性》《技术一号位的方法论【理论篇】—— 解决问题的规律概述》《技术一号位的方法论【理论篇】—— 解决问题的规律在技术、业务、组织方面的应用》《技术一号位的方法论【理论篇】—— 浅谈技术人员如何成长为技术一号位》《技术一号位的方法论【业务篇】—— 什么是业务,以及业务运转需要哪些方面的支撑》《技术一号位的方法论【业务篇】—— 什么是指标,如何构建业务指标》《技术一号位的方法论【业务篇】—— 如何画业务大图、产品块图、兵力投放大图、战役大图》《技术一号位的方法论【技术篇】 —— 浅谈如何做复杂业务系统的领域驱动设计》《技术一号位的方法论【技术篇】 —— 浅谈如何做复杂业务的数字化》《技术一号位的方法论【技术篇】 —— 浅谈如何做稳定性建设》《技术一号位的方法论【技术篇】 —— 浅谈如何做业务风控能力建设》《技术一号位的方法论【技术篇】 —— 浅谈如何让技术支撑、保障、驱动业务发展》《技术一号位的方法论【技术篇】 —— 浅谈如何做分布式系统建设》《技术一号位的方法论【技术篇】 —— 浅谈如何做秒杀》《技术一号位的方法论【技术篇】 —— 浅谈如何快速掌握陌生技术领域知识》《技术一号位的方法论【技术篇】 —— 浅谈一些常见技术问题的解决模式》未来一段时间,阿里巴巴中间件会持续发布系列文章,欢迎关注。前言什么是技术一号位、有哪些关注点、怎么做技术一号位?做了研发团队的技术 leader 以后,要处理的事情非常多,如果对自己扮演的角色没有一个清晰的认知,就会出现该做的事情没有做,不该做的事情投入了过多的精力,造成实际行动和结果既不匹配上级的要求,又不匹配下级的期望。特别是对于刚开始带领研发团队的新人 leader 而言,角色的转换和适应的过程,增加了认清自己的角色本质的难度。今天我们抛开纯技术团队的同学不谈(其实本质一样),只讨论业务研发团队的同学,如何以技术一号位的角色来做事。如何识别自己是不是技术一号位在开始谈如何做事之前,首要任务是判断自己是不是技术一号位,而要判断之前,首先要明确判断标准,跳出思维误区。这里我们列出一些常见的思维误区。以下是常见认知误区:带人的是技术一号位,不带人的不是技术一号位。级别高的是技术一号位,级别低的不是技术一号位。以上的认知误区,错误地把是否带团队、技术等级的高低和是否为技术一号位关联起来。虽然事实上带团队的业务研发同学成为技术一号位的概率更大,但是本身这两者不是划等号的关系。那么什么是区分是否为技术一号位的决定性因素呢?很简单:对一个具体的业务而言,你作为该业务的直接技术参与者,是否处在技术领域责任链的最顶端。这句话翻译过来就是,对一个明确的具体的业务而言,多种角色的同学一起合作的时候,你是否是技术序列的最终责任人,即:谁承担对应的责任,谁就应该扮演对应的角色。当产品经理、运营、研发共同做一个业务的时候,某个研发同学独自或者带领其他几个研发同学,或者带领跨 BU 的研发团队,共同支撑 PD 的业务需求。那么这个研发同学就是这个业务的技术一号位,不论他是否带不带人,也不论他带的人在行政上是否从属于他。一般来说,负责单一业务的研发团队 leader 一般就是这个业务的技术一号位;负责多业务线的研发团队的 leader 的下属,是每个业务线的技术一号位,而研发 leader 本身是更高层面业务的技术一号位。所以,做业务开发的技术同学,不论是什么层级,带不带人,都可能是某个具体业务的技术一号位的。这一点非常重要,只有认清这个事情以后,业务研发同学才能在做业务的时候,明确下来自己除了需要写代码以外还需要做什么,关注什么;这些关注点需要做到什么程度,才能对上满足期望,对下不让团队走弯路、不和下属抢功。当你经过以上判断以后,确定自己是技术一号位时,恭喜你,你已经不再是一个仅仅需要写代码的研发同学了。很多研发同学眼中还是只有写代码这一件事情,如果以这种方式做业务,那么就会发现业务过程会有各种没有做到位的事情,会在做业务的过程中“交很多学费”,甚至会因为自己的能力不够而拖慢业务发展。虽然成熟的研发团队可以通过完备的研发过程管理,来避免个人能力不够而对业务产生太多负面影响,但是本质上强制的规定和“上级要求”只是在依靠行政管理手段在强制一个人做这些事情,并没有唤醒他的创造力和责任心,反而会被认为是“工作琐事”。这些“工作琐事”本质上是需要他扮演的角色来负责的,但是由于他没有意识到自己实际上已经是这样的角色了,而仅仅把自己停留在“研发”的定位上,把“写代码”当做核心任务,这样一来,会让研发同学对那些看起来 “和写代码无关但是是技术一号位必须做的事情” 非常抵触。这种抵触情绪发生的时候,leader 再强调 Ownership 也都没有太多效果,因为不是他不负责任,而是他没有意识到,这是他应该负责的事情。当他的心态和认知转变以后,一些原来看起来不怎么负责的人会变得负责(不排除有人本身就是不负责的人,那么这样的人不是良好的技术一号位的候选人,主管要有识别能力)。作为业务开发同学,一定要仔细认清辨别自己实质上是不是一个业务的技术一号位,而不用考虑自己的层级,不用管自己是不是业务其他参与者的 leader。当你意识到自己是这个业务的技术一号位的时候,就要迅速切换角色,从原来自己给自己的定位 “写代码的、搞技术的” 转变为 “某个业务的技术一号位”,开始进入角色,发挥出你的价值。这也是很多研发同学通过做业务能迅速成长的原因,抛开技术上的成长之外,他比其他研发同学接触了很多 “做事情需要思考并为之行动” 的维度,这些维度的丰富是普通业务研发同学很难看到、很难感觉到,因此更难悟到的。不排除有悟性高的研发同学能够自己悟到,但本质还是由于他所处的环境、他面临的问题在逼迫他做出思考,然后为之实践。如果一开始就知道自己做事情要找准自己的角色和定位,那么就会少走很多弯路。分析你所在环境的局势当你意识到自己是一个业务的技术一号位的时候,不用过多怀疑自己究竟是还是不是,而是要本着“就当自己是”的心态来进行接下来的工作实践和思考。需要大家明确的一点是,任何一个工作角色,都有对应的责任,也都有履行对应责任的方法论。我们要做的,不能再像过往做普通研发的时候那样懵懵懂懂去做事,听“需求”指挥,而是要开始寻找或总结一些方法论,要自顶向下地对业务有一个清晰的认知,知道自己比过去多了哪些维度的事情要关心,知道接下来会面临什么样的挑战,要知道自己在挑战中应该扮演什么样的角色,采用什么样的手段去解决业务在不同阶段一定会出现的各种问题。在开始所有的思考之前,先要做一件事情,就是分析你目前所处的环境的局势。业务方面你的大团队的业务大图是什么你负责的业务的大图是什么你负责的业务大图是否和大团队的业务战略匹配你负责的业务和大团队的业务看似没有契合点的时候,你的leader跟你对焦以后的结论是什么这个业务对客户的价值是什么这个业务对组织的价值是什么这个业务对你个人的价值是什么这个业务是否会在未来承担社会责任,会有怎样的社会价值这个业务目前处于什么阶段,是刚开始,还是已经成型等待发展,还是已经发展一段时间需要业务规模这个业务目前存在最大的问题是什么协作方面谁在配合你一起做这个业务和你一起做业务的同学中,分别有哪些角色,他们会在哪些方面和你有交集和你一起做业务的其他角色的同学,是否对业务大图的理解和你一致和你一起做业务的其他角色的同学中,谁是业务的负责人;或者关键角色的人员是否对自己是业务负责人有感知业务上下游的同学段位怎么样,是否能在实际落地过程中跟上你的节奏业务一号位的KPI是什么,你的KPI是什么,你们两人的KPI是否方向一致,你的KPI是否能支撑他的KPI团队研发方面现在是否有一个研发团队支持你一起做这个业务和你一起做业务的研发团队是否在行政上从属于你你带的团队人员每个人的特点是什么,有什么短板,在这个业务里面负责什么事情研发团队里面谁是你的接班人研发团队里面谁能补充你的短板研发团队里面,每个人做事都有什么个人的想法?个人的成长目的研发团队里面的每个人对业务大图是否了解,认知是否一致,目标是否一致如果你本身已经是专家级别以上了,那么下面这些维度可能是需要你继续深入思考的:业务方面业务的愿景是什么业务的愿景在不同时间维度上拆解以后的关键业绩指标是什么为了实现不同时间维度的关键业务指标,你准备投入什么样的资源?投入的资源之间相互怎么配合?相互配合的原则是什么这个业务现在做是否合适?现在做不合适的话,需要在什么时候做合适这个业务现在做不合适的情况下,哪些因素让你觉得现在做不合适让你觉得现在做这个业务不合适的因素中,哪些因素是可以通过人为干预让它不再是阻碍性的,哪些是可以通过人为干预增加它对业务的积极作用业务的现状及瓶颈问题业务问题的技术解法业务发展趋势业务竞合分析业务发展策略业务的终局畅想团队方面团队的使命是什么团队推崇的价值观(做事原则)是什么当前团队的人才梯队是否合理当前团队的人才储备方向是否完备当前支撑业务的团队是否未来依然能够支撑业务的发展当前团队不能继续支撑业务的战略规划的情况下,需要做怎样的调整协作方面业务是否可以向其他BU借力,或者借力于其他BU当前的业务是否和其他BU可以相互配合形成某种合力的优势当前业务和其他业务如何配合来完成未来的布局从而获取对应的优势未来的布局落地后,想要形成什么样的局势局势形成以后,对完成组织愿景,履行组织使命有什么决定性帮助找准自己的定位,明确自己的定位的含义当理清楚自己所处的环境以后,知道业务是什么情况,和自己配合的人又是什么情况以后,需要知道自己扮演的角色究竟意味着什么。从我个人的经验来看,技术一号位是负责使用技术能力解决业务问题,提供稳定可靠的技术支撑,确保业务安全合规低风险地健康发展,并通过技术或业务创新来推动业务发展;负责向业务各方提供各种必要的技术支撑,通过合理的数据分析为业务决策提供依据;通过对技术领域的积累和发展,通过业务领域的理解和落地影响业务决策;负责构建梯队完整、能力全面、制度完善的技术团队来支撑业务发展。应该有什么样的工作原则和要求1、以业务一号位的视角思考,辅助业务一号位构建合理的业务大图。2、以技术一号位的角色保障业务落地,协助业务一号位实现业务的客户和组织价值。3、掌握和业务建设过程中各种角色的上下游协作者合作的专业能力:在产品方面具备基础的产品规划和设计能力;在业务方面具备有一定深度的领域知识,或者具备相关的方法论可以快速向领域专家完成领域知识的学习。在商业化方面能够提供合理的商业化模型设计,包含提供合理的计费维度和技术成本清单。在产品运营方面能够了解常见的基础运营手段和方法论,能够结合运营策略给运营同学提供准确的专业知识的支撑。在客户沟通方面,能够有良好的倾听能力,理解客户的诉求,辩证地转换为系统改进的动力。在技术方面在公共技术服务的基础上完成全维度技术能力建设,考虑技术的投入产出比,不能只做架构或只做核心代码的实现。在团队方面能够建设合理的人才梯队,储备必要的技术领域人才,推行组织文化,确保成员对做事的风格和原则理解一致,有行之有效的方法论帮助不同层次的同学找到成长的突破口。履行技术一号位的职责具体需要感知哪些事情及其要点下面这张图从大方面上列出了一个技术一号位需要感知哪些方面的事情(图中未列出产品运营、售前售后等一系列其实很关键的方面,但是如果技术一号位负责的业务是有商业化需求的,则还是需要关注这些维度的事情的)。这些事情是必须知道,但不是必须亲自做的,要能够借助团队的力量完成该完成的事情。下面是具体从业务、技术、团队角度来详细理清楚技术一号位需要感知的事情及其要点:业务方面(后面会有单独的文章详细解释业务方面怎么做)建大图定方向找打法撑业绩技术方面1、技术选型业务需要什么样的技术能力支撑需要的技术能力集团或其他BU团队已经具备了并且可以被你复用如果不能复用,差异点在什么地方如果不能复用,差异点不是方向上的根本问题,是否可以通过共建或提出合理需求来完成复用如果不能复用,不能共建,是否可以使用开源项目如果不能复用,不能共建,需要自研,需要个人具备什么样的技术背景,需要团队具备什么样的技术积累团队或组织是否已经有了相关的基础框架或效能提升工具业务是否需要考虑数据安全问题,组织或团队是否有安全防护相关的积累可以复用业务是否需要考虑业务风险问题,组织或团队是否有业务风险控制的积累可以复用业务一般情况下都需要数据服务做业务运行期的运转情况的监控和后期业务决策的支撑,组织或团队是否有相关的积累可以复用技术投入产出比2、系统架构设计1)业务场景在技术侧映射出来的特征是什么,对技术侧的影响是什么?一般而言,不同的业务场景会体现出不一样的技术特征,对技术反应出不同的需求。面向B端客户的传统企业级应用,通常情况下对稳定性要求高,对数据安全要求高,需要保证业务操作结果和实际数据匹配。业务流量不大,系统用户对用户体验不如C端用户敏感。针对这类系统,往往通过简单的单体应用做高可用部署即可,使用单一数据库并通过数据库保障业务数据变更的事务,界面契合客户业务。面向C端客户的互联网应用,通常情况下对流量承载能力要求高,对数据安全要求高,对用户体验敏感,对稳定性要求高,业务流量巨大,特殊的业务场景会出现特殊的流量峰值。针对这类系统,往往需要构建分布式系统做大流量高并发高可用系统架构建设,自顶向下分层优化,从终端层的静态资源CDN化,到应用层的前后端分离,应用逻辑和底层服务分离,再到核心业务层的微服务架构建设,从服务发现服务治理,到无状态应用的规模化部署,从大量基础中间件的使用,到大量公共业务服务的构建,每一层都需要做好对应场景的优化和架构设计。2)如果业务会在某个发展阶段涉及到大用户流量,对应的系统技术架构是什么样的?大流量高并发高可用系统架构业务流程异步化使用限流手段确保系统不被突发大流量压垮使用降级手段确保下游系统不可用时能够快速失败避免请求堆积造成系统无法接受或响应外部请求使用逻辑隔离或物理隔离手段确保多租户模式下各租户互不影响使用合理的资源调度策略确保不同规模的租户享受同等技术服务水平使用合理的资源使用策略确保成本维持在合理水平使用合理的监控手段提前发现系统承载能力的变化,及时通过扩容或缩容来应对系统流量变化使用分库分表或根据业务需求采用合适的NoSql数据库来支撑海量数据持久化使用缓存抵挡大流量对数据库的压力使用分布式锁处理高并发业务场景下的公共资源抢占问题使用幂等服务屏蔽高并发场景下的重复请求使用分布式事务服务确保业务数据的最终一致使用负载均衡承接业务流量,分配给后端应用服务器,避免单点风险使用同城双机房来规避单机房风险使用异地多活技术来规避单个城市的不可抵抗风险3)如果业务非常复杂,领域众多,那么采用什么样的架构更合适?业务复杂的情况下,采用微服务架构4)如果确定要采用微服务架构来支撑复杂业务,那么领域划分和每个微服务是否匹配,微服务拆分粒度是否合适?如果是单体复杂业务应用拆分为微服务,则应该按照业务领域来拆分,拆分后通过服务接口对外提供标准服务。如果是开始就确定要做成微服务架构,那么要先做领域划分和建模,然后大的复杂的领域单独形成业务服务,公共依赖的领域做成服务,使用合理的服务治理框架,选择合理的服务通信协议,构建业务系统。3、业务建模业务领域知识学习。业务领域建模,使用领域驱动设计完成战略设计(领域上下文的划分和上下文之间的协作模式的确定)和战术设计(领域内的实体、值对象、领域服务、实体工厂、仓储层、数据持久化层的设计)。业务建模是否合理,是否采用了合适的方法论来应对不同复杂规模的业务?面对复杂业务,是否有完整的领域设计和匹配当前阶段的落地路径?针对复杂业务,不需要最开始即按照完整的业务模型做落地,而是根据实际业务需求和时间进度合理定制业务模型的落地计划,既确保需求能按时完成,又确保代码落地始终在业务模型设计范围之内而没有腐化。4、研发落地略5、项目管理项目目标完成时间想要取得的结果项目成员关键里程碑风险预警多方协调沟通日常进度追踪6、项目复盘1)质量保障代码扫描代码评审研发单元测试团队业务需求沟通及评审测试用例编写测试用例评审基础功能测试验收上线发布验证灰度测试线上验收测试自动化冒烟测试每日自动化测试2)稳定性建设关键业务流程日志打点全业务链路跟踪系统技术指标监控系统业务指标监控告警自动化告警恢复关键业务场景预案建设关键业务场景预案执行值班响应机制3)风控建设业务风险点定义业务风险点识别业务风险点级别定义业务风险点分级处理业务风险点报警业务风险点触发趋势实时业务风险控制离线业务风险扫描业务风险点诱因分析团队方面成员 1v1 沟通成员优劣势分析成员做事意愿分析成员角色定位对焦成员能力梯队聚焦方法论的探讨与实践帮助不同的人看到自身不足,定制不同的成长规划根据不同人的优劣势和做事意愿,安排调整合理的事情和责任范围,激发做事的主动性,为其发挥出创造力营造良好的环境业务大图的解读和 KPI 的设定工作原则和工作要求达成一致认知明确团队要什么,不要什么,推荐怎么做,不推荐怎么做要创新不要墨守成规要思考不要苦劳要打破思维定式和束缚,不要自我设限要 Ownership,不要推脱如何成长为技术一号位目前还不是技术一号位的业务发开同学,虽然现在的岗位只负责一小部分,但是本质上来讲,只要你负责某个事情,那么不论这个事情大小,你都是这个事情的技术一号位,只是由于事情的难易程度和规模大小,导致很多可能需要做的事情其实并不需要做,但是这些问题并不妨碍你知道技术一号位要做什么,应该怎么做,更不妨碍你以技术一号位的心态去做事。先确定好心态的问题以后,接下来就需要一些可以被实践检验的方法论来帮助大家打破自己层级的束缚,完成自我突破,从而在成长的基础上获得负责更重要的事情的机会,通过做好更重要的事情来获取更更重要的事情的机会,这样一定会在某个阶段,你负责的事情,需要完全以真正的技术一号位的角色去落地,那么那个时候扮演技术一号位的角色也就是水到渠成的事情了。作者介绍:贺科学(晨末),毕业于北京科技大学,工作10年,在企业级应用架构及研发方面有长期积累。擅长分布式系统架构,擅长复杂业务的领域建模及开发落地,掌握领域驱动设计及开发相关方法论,有实际成熟线上产品案例;2014年入职阿里云,先后参与或主导过阿里云控制台、阿里云容器服务、资源编排服务、云分期等云服务的建设。目前带领小型团队负责新零售业务相关的研发工作,累计C端用户过亿,承接阿里巴巴集团内外众多流量业务的积分兑换实物商品业务。除业务以外,个人精力也投入在“复杂业务系统落地过程数字化”这一命题上,目前有一定思考和实际积累。实际工作中有3年带团队全面独立负责复杂业务系统的经验,所以在技术一号位的工作方面有相关的实践和思考。联系邮箱:kexue.hkx@alibaba-inc.com。扫码查看更多中间件技术干货和案例:
业务团队如何统一架构设计风格?
作者 | 木沉来源 | 阿里技术公众号首次上线应用,面对业务框架搭建你是否曾感到无从下手?维护线上应用,面对大量历史包袱你是否正避坑不及深陷泥潭?为何同样是业务应用,不同人的设计风格千差万别?为何最初的设计经过多个迭代后总是面目全非?新人来到团队,怎样才能快速了解业务,不被大量技术细节折磨?如果你也有这些困扰,希望本文能提供些许帮助。一 初衷1 细节割裂架构业界的成熟应用框架有很多。无论是SpringMVC/SpringBoot还是SofaBoot,都对工程结构给出了明确的规范约定,职责边界看似非常清晰。但在实践中,再简单的业务应用都避免不了业务逻辑分散各处,打破module边界出现隐式耦合的现象。分散的业务细节必然导致应用架构的割裂,如果没有持续的重构调整,最终总会变得复杂臃肿(当然,是持续有新需求的前提下),老人沉默新人流泪,只能依靠天降猛男重做2.0。究其原因,个人认为主要在于:框架灵活性过高:应用框架给出的是工程规范,而非业务设计规范,为开发者保留了非常大的灵活性,一个业务功能可以有很多种实现方式。架构约束力不足:业务架构的搭建和维护是在不同时段由不同人分别投入的结果,设计思维的不同,自我要求的不同,项目进度压力的不同,都会对应用的现状产生影响。若以法律和道德的关系做类比,通用框架约束了技术编码的“法律”底线,而设计原则就是开发人员对自身的“道德”要求。在简单的业务场景下,满足需求是第一优先级,设计能力的诉求并不突出。但在多方协作的业务团队下(真实情况大多如此),没有统一的“道德标准”,将很难形成合力完成复杂项目。《Java开发手册》(阿里巴巴Java开发规约)在推进编码标准的道路上迈出了很大一步,极大提升了工程人员的专业素质,大大提高了“道德共识”。那么在业务架构设计的领域里,是否至少能在某个问题域内,也建立一套面向业务研发同学的“设计规约”。2 技术沉淀流失另一方面,进入阿里巴巴后,自身研发经历虽然并不多,但接触过不少优秀设计。这些产出无论是否最优方案,都体现出了技术同学对优秀设计的美好愿望和强大落地能力,也确实在一定的历史时期内高效地保障了业务发展。然而,令我困惑的是,尽管每个业务项目和业务产品都能沉淀出一些可复用的组件或框架,参与研发的同学也能总结出一套面向未来需求的设计原则和实践经验,但这些财富始终难以维护和传承。可能的原因有(对前端/测试/数据/平台等研发经历不太了解,这里仅针对一线业务研发):坚持设计成果而非设计原则:有成功经验的研发同学,倾向于用曾经的架构设计来套用当下的业务场景。这种思路本身没有对错,但如果钉不配锤,往往会在短期内引入大量额外成本,反倒丧失了原本的设计优势。面对具体问题域,只有坚持一贯的设计原则,在需求分析的过程中结合诸多因素进行动态权衡,才能打造真正符合当下和未来需求的设计。喜欢造新轮子而非持续重构:研发同学的设计原则和代码洁癖可能是一种“玄学”,对前人代码的不待见倒是更具确定性的常态,其实这不难理解。即使都是DDD流派,方案沟通时也未必互相认可;即使经过让步对架构设计达成一致,编码实现的风格也是各领风骚。理解前人的设计思路和代码癖好更重要,还是按时完成业务需求更重要?按自己擅长的设计风格重写更简单,还是在他人的“过时”设计上持续重构优化更简单?靠文档传承而非工具化复用:对新人来说,文档里的再多建议和快速上手指南,都比不上一个开箱即用的工程DEMO;在成熟应用上持续开发的人,不会因为历史文档上大写的注意事项就抵抗住临时代码换取早点下班的现实诱惑,除非应用工程中有编译/部署失败的强制约束让你不得不放弃。相比于缺少“设计规约”导致的低效协作,已经沉淀的“规约原型”被轻易抛弃更加令人可惜。业务研发的日常工作,本质上是拆解问题域的复杂性,用分层解耦/工具化/平台化/业务抽象的多种思路将子问题逐个击破。如果部分子问题已被很好解决,为何不站在前人肩上?放弃造不造新“轮子”的纠结心态吧,或许我们更需要搭“积木”的心态。二 思路:业务架构设计规约结合蚂蚁链-应用技术团队近年来的技术实践,我们试图从自身需求出发,搭建一套或许能满足更多业务场景的业务架构设计规约。重点说明下,本文是从有限的问题域出发提出的解决思路,不奢求成为通用解决方案。如果其他业务线也有类似的痛点,希望能有些许借鉴。标准:统一业务设计框架,用标准化架构简化技术细节沉淀:从业务场景中持续沉淀“积木”重构:持续重构“积木”,减少重复建设集成:基于业务服务编排引擎快速集成1 标准——减少细节理想情况下,业务技术只需关注领域建模,但现实中却不得不考虑更多通用的技术细节。以供应链金融场景下简化版的应收账款发行流程为例,需要考虑的有:领域建模:应收账款领域模型及其行为的设计流程编排:流程模型的设计及发行流程的状态机设计数据转换:领域模型<->数据模型及流程模型<->数据模型的双向转换并发控制:业务锁机制的设计业务幂等:流程中各业务环节的幂等控制异常处理:异常捕捉,错误码约定监控报警:摘要日志,异常日志,边界日志其他在以上未完全列举的几项中,除了“领域建模”以外,基本都是与具体业务无关,但对于一个稳定可靠的业务应用不可缺失的部分。如果能建立一套标准化的框架方案,用统一的规范解决掉业务无关的大量细节,是否就能让业务技术同学真正的专注于“领域建模”?2 沉淀——能力复用沉淀和复用是技术群最常出圈的几个词,可见认同度之高。能力复用不局限于形式和粒度,能够切实降低技术成本,提高业务扩展性,就是不错的沉淀,可作为“积木”供后续使用。以蚂蚁链应用技术团队场景为例,近年来沉淀的能力包括但不局限于:技术类工程规范系列:约束编码规范和边界接口定义风格,日志打印,异常处理,仓储行为,状态机等等读写分离机制:屏蔽交易类需求与查询类需求对数据模型的设计冲突,降低设计复杂性,提升查询性能和灵活性业务类网银核身:提高网银核身签名在不同业务流程中的扩展性合约上链:提高智能合约对接在不同业务流程中的扩展性平台类配置中心:灵活定义和管理业务流程需要的各类配置项产品中心:平台功能打包和隔离,实现业务流程的全局视图3 重构——持续优化沉淀来源于业务需求,却常常落后于新需求。对于设计者以外的人来说,维护他人的“积木”常常会踩到不少坑,反倒不如自己重写。这也是为何每个团队都在说沉淀,但能够横向复用,甚至在同一个团队内持续复用的能力都少之又少。虽然这个现象没有完美解法,但个人建议采取以积极的心态看待这些“积木”:分析历史背景,了解“积木”出现的技术和业务背景明确该能力能够解决的问题,和不适用的场景分析当下业务需求,是否可以重构该能力后直接复用与创作者沟通,评估重构落地方案这里没有强调重构复用和重写这两种方案的ROI对比,是因为个人看来,即使前者成本更高,重构的过程对个人技术成长和团队文化统一都是有利的。相对于不断推翻和发明新“积木”,持续优化的过程,是对自己和他人经验的不断回顾和反思,看清历史的坑,才能避免新风险的出现。4 集成——灵活搭建标准能够落地,除了有足够趁手的“积木”库外,更重要的一点,是要有灵活便捷的“粘合剂”,以完成业务功能的快速搭建和灵活调整。在供应链金融的场景下,业务需求主要体现为各种各样的业务流程,比如发行/转让/清分等等。为了简化“积木”搭建,灵活复用底层能力,我们基于以下目标,设计了面向业务的服务编排引擎:标准化:遵循设计规约,将业务无关的通用技术细节屏蔽插件化:对“积木”友好,可持续沉淀和复用新能力业务化:面向业务,有业务描述能力的流程编排配置化:通过配置即可完成流程编排,最好能做到可视化配置5 产品——业务大图“积木”+“粘合”能够满足技术落地的低成本高扩展,但从业务视角,还需要一个全局大图来描绘业务线的全域能力和功能流程。本文中暂不涉及。三 实践——业务架构标准方案如前所说,只靠文档形成的共识,对技术没有足够的约束,极难维持。因此,我们基于上述规约的各项原则,搭建了一套标准化的业务架构设计方案,通过组件化工具化的方式约束业务应用,形成团队共识。一个标准的业务应用架构如下:1 组件——规范技术细节通过组件化约定,约束通用技术细节的行为,包括但不局限于:交易模型描述业务流程的核心交易模型,用于管控状态推进,维持与业务模型的关联。仓储行为数据持久层的通用行为,包括锁定查询/插入/更新/普通查询等。事务模板定义事务边界,确保模版内业务逻辑的事务一致性;支持幂等能力。通用业务模板定义业务逻辑边界,无事务性保障,但包含了异常处理/日志埋点等通用能力。通用查询模板定义查询逻辑边界,与通用业务模板类似,但主要面向单项/批量/分页等查询场景。消息对消息中间件的简单封装,适配业务应用规约,降低配置成本。调度对调度中间件的简单封装,适配业务应用规约,降低配置成本。服务开放api组件规范对外服务能力,通过注解识别服务定义和服务实现,自动生成接口文档,描述接口参数/返回/业务域/错误码等等。其他——日志/异常处理/请求参数/返回类型这里不做展开。以上是所有业务应用都会遇到的技术细节,用组件屏蔽细节的思路也没有复杂之处,我们想要表达的重点是:尽可能沉淀和复用技术组件,尽可能使用他人的成果,不要重复搭建,把重心放到业务上!2 领域——专注业务建模再次强调,对业务技术来说,业务建模是核心,业务建模是核心,业务建模是核心!本文的初衷和方案都是为了让开发解放出来,直面核心业务的设计和思考。本小节仅给出领域产出的基本要求,后续在【案例分析】再做详述。领域实体建模的核心是抽象出领域实体及其关联关系,不同的业务场景和设计思路,会有很大差异,最终会体现为一到多个领域模型。需要明确在不同业务流程下,各交易模型内需要包含的领域模型(比较抽象,后续在【案例分析】再做详述)。领域仓储定义数据模型,及其与领域模型的对应关系(各种converter)。基于上文提到的仓储组件,配置数据库表和连接,实现锁定查询/插入/更新/普通查询等业务行为。领域服务基于业务行为,抽象出原子化的领域服务能力。该服务无需关注数据仓储,无需关注业务流程,仅抽象出领域实体的原生能力。以上文中提到的应收账款模型为例,至少需要包含:应收账款的创建应收账款的拆分/流转应收账款的销毁等等基本行为。交易实体用于承载交易流程的业务实体,上文中交易模型的业务实例,内部关联一到多个领域实体。交易仓储用于管控交易实体以及内部各领域实体的仓储行为。3 服务编排引擎 —— 积木+粘合但凡涉及复杂业务流程的应用,都需要引入流程引擎来编排状态机的流转。业界有很多成熟的流程引擎框架,也有很多足够可用的简化版本。但如前文所说,这类通用引擎的优点也是其最大的弱点:过强的灵活性无法对设计风格形成约束,大量业务细节会分散在不同状态节点间,不直观也难维护。从自身需求出发,我们设计了面向业务的服务编排引擎,以遵循业务设计规约的方式约束技术,以直观的形式描述业务流程。与传统流程引擎相比,其业务友好性主要体现在:约束业务模型:需明确指定业务交易模型/状态及仓储定义,遵循业务设计规范托管仓储行为:只需配置业务模型及仓储实现,无需再关注数据持久化的时机和细节编排领域服务:通过转接层,将领域服务开放到引擎中自由编排。领域的原子能力是引擎编排的最小执行单位灵活增减状态:流程中的状态迁转和业务行为均可被灵活插拔支持“积木”扩展:将可复用的领域服务组合打包,形成固定模式,作为“积木”在其他流程中重复使用总的来说,服务编排引擎基于通用组件屏蔽技术细节,重点专注于业务行为的编排和复用,对“积木”进行“粘合”,以编排出符合业务需求的业务流程。四 总结本文从业务技术团队的现实痛点出发,尝试以业务架构设计规约(理论标准)结合业务架构标准方案(工程约束)的思路统一团队的技术风格,将技术同学从细节中释放出来,专注于技术能力的积累和对业务价值的思考。希望传达的想法有:用标准约束技术细节:降低业务设计的灵活性,也是为了减少成本用技术工具而非文档推行标准:持续沉淀的组件,胜过没有约束力的文档持续重构而非造新轮子:正视自己和他人曾经的产出,持续改进能带来成长重视业务建模:好好思考业务和行业吧,用DDD武装自己,提升建模思维和能力篇幅所限,【案例分析】后续另开一篇再做详述。文中一些不成熟的想法,也欢迎多多指正。阿里云开发者社区世界读书日,来读书吧4月23日是第26个世界读书日,阿里云开发者社区推出“记录阅读之路,影响同行之人”活动,6位阿里技术人为同学们分享他们看过的好书,开发者藏经阁也推出了最受大家欢迎的电子书。点击链接:https://developer.aliyun.com/topic/worldreadingday?utm_content=g_1000264434,推荐曾经影响你的书,来一起读书吧~
框架来解决优雅重试-spring retry
重试的意义To make processing more robust and less prone to failure, it sometimes helps to automatically retry a failed operation, in case it might succeed on a subsequent attempt. Errors that are susceptible to this kind of treatment are transient in nature. For example, a remote call to a web service or an RMI service that fails because of a network glitch or a DeadLockLoserException in a database update may resolve itself after a short wait. 这句话来至于spring-retry的github文档. 总之一句话就是 (为了使处理更加健壮,减少失败的可能性,有时候自动重试失败的操作会有所帮助).有时候等等估计一会就成功了...code demo: https://github.com/WangJi92/spring-retry-example遇到的问题最近做项目需要进行同步数据(定时任务),一定要同步成功,不然对于业务会有影响,偶发性的会出现调用接口失败,失败并不是特别多,大概的流程如下:1、循环的进行远程调用,同步数据。2、记录一下调用失败的记录。3、休眠一段时间4、继续循环调用失败的记录5、如果在调用失败、通过钉钉告警 人工二次调用进行修复。try {
// 1、foreach do remote invoke
// 2、record list error invoke
// 3、sleep some time
TimeUnit.MINUTES.sleep(5000);
// 4、foreach do remote invoke error record
// 5、record error again and ding talk robot alarm
} catch (InterruptedException e) {
}这里也做了一些优化:
将之前的递归调用远程->然后报存数据转换为通过递归转队列,来一个处理一个报错,方便记录调用失败的数据,同时不至于有一个失败所有的之前调用都没有保存且占用内存空间。
增加记录失败,然后休眠一段时间进行补偿,还是不成功,钉钉告警通知。
由于偶发性的会出现调用接口失败,失败还是比较低,上线后没有收到过补偿之后都修复好勒缺点:实现不够优雅,如果第二次还是失败怎么办?可复用的成本比价低,每个业务都需要写一遍这种增强可靠性的业务逻辑。重试需要什么?出现什么场景需要重试(重试源头)? 抛出xxx异常或者返回结果为x 需要重试。重试的策略是什么(RetryPolicy)? 无限重试?最多重试几次、指定的时间范围内可以重试、或者多种重试策略组合。重试的要休眠多久(BackOffPolicy)?每次都休眠固定的时间、第一次1s 第二次2s 第三次4s 、随机的休眠时间。兜底方案(Recover) 如果所有的重试都失败了、兜底方案是什么?有点类似限流,最差返回你系统繁忙的界面。这些都是重试框架需要解决的问题,需要通过定义模型去解决以上的问题spring retryspring retry提供了注解和编程 两种支持,通过异常失败是否需要重试。提供了 RetryTemplate 支持,类似RestTemplate,使用非常的简单方便基本使用Spring Retry 的使用和原理Spring-Retry定制化你的RPC重试核心概念RetryPolicy 重试策略SimpleRetryPolicy 最大次数+特定异常
TimeoutRetryPolicy 超时时间
CircuitBreakerRetryPolicy 熔断+重试
MaxAttemptsRetryPolicy 最大重试次数BackOffPolicy 退避策略FixedBackOffPolicy 固定时间
ExponentialBackOffPolicy 指数退避策略
ExponentialRandomBackOffPolicy 指数随机退避策略
...RetryCallback 业务回调入口RecoveryCallback 兜底回调入口RetryTemplate 执行操作使用,RetryCallback 执行业务逻辑 ,RecoveryCallback 兜底。public interface RetryOperations {
<T> T execute(RetryCallback<T> retryCallback) throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
throws Exception, ExhaustedRetryException;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
RetryState retryState) throws Exception;
}RetryListener 重试监听器RetryContext 重试上下文业务流程spring retry 提供了编程式和Aop 注解 两种方式 通过编程式更好理解。// 获取原始的对象
RetryTestService targetRetryTestService = (RetryTestService) AopTargetUtils.getTarget(retryTestService);
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(2)
.fixedBackoff(DELAY_TIME)
.retryOn(RemoteAccessException.class)
.traversingCauses()
// 非必须
.withListener(retryListener)
.build();
Integer responseBody = retryTemplate.execute(new RetryCallback<Integer, RemoteAccessException>() {
@Override
public Integer doWithRetry(RetryContext context) throws RemoteAccessException {
// 调用业务
return targetRetryTestService.retryTestService();
}
}, new RecoveryCallback<Integer>() {
// 垫底方案
@Override
public Integer recover(RetryContext context) throws Exception {
// 兜底调用业务
return targetRetryTestService.recover((RemoteAccessException) context.getLastThrowable());
}
});
log.info("programmingRetry retryTestService response result is {}", responseBody);如下图所示: 执行业务调用 回调 RetryCallback,如果发生了异常,通过RetryPolicy 查看是否可能重试,如果可以重试进行退避休眠策略,如果不行 进行兜底方案调用。
常用注解幕布:https://mubu.com/doc/5Oq1BHmS4Ba#m@Retryable 通过注解定义重试策略+退避策略@Recover 兜底方案,如果都不成功尝试兜底
第一个参数异常,后续的其他的参数和真实调用保持一致,返回值一致即可。@Retryable(value = RemoteAccessException.class,
// 退避策略 休息 5秒继续
backoff = @Backoff(DELAY_TIME),
// 重试策略 最大一个两次 包含第一次
maxAttempts = 2,
// 兜底方案 全部失败 调用当前类中的兜底方法
recover = "recover"
)
public Integer retryTestService() {
int count = invokeCount.getAndIncrement();
String url = "http://localhost:8080/unstableApi/500";
if (count % 2 == 0 && count % 5 == 0) {
url = "http://localhost:8080/unstableApi/200";
}
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
} catch (Exception e) {
log.info("try get unstable api failed", e);
throw new RemoteAccessException("500", e);
}
return 500;
}
/**
* 作为恢复处理程序的方法调用的注释。合适的恢复处理程序具有Throwable类型(或Throwable的子类型)的第一个参数和与要从中恢复的@Retryable方法相同类型的返回值。Throwable第一个参数是可选的(但是没有它的方法只有在没有其他参数匹配时才会被调用)。后续参数按顺序从失败方法的参数列表中填充
*
* @param e
*/
@Recover
public Integer recover(RemoteAccessException e) {
String stack = Arrays.toString(Thread.currentThread().getStackTrace());
stack = stack.replaceAll(",", "\n");
log.info("recover is begin : 堆栈 \n {}", stack);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/unstableApi/200", String.class);
log.info("remote response is {}", responseEntity.getBody());
return Integer.parseInt(Objects.requireNonNull(responseEntity.getBody()));
}深入理解spring retry支持有状态和无状态两种方式。一般理解使用无状态。
【这个理解了好久才理解了】
对于有状态的可以通过代码实践去理解: spring-retry-example无状态:
无状态就是当前线程继续处理,spring retry 通过获取到异常后继续在当前线程重试。有状态:
类比http,http 调用是无状态的,为了增加访问状态可能增加cookie 标识一个人的访问,当前的多次访问是否是一个人;
spring retry 中有状态我这么理解,多次调用不直接的在当前线程重试,将异常抛出,标识为【当前方法参数+方法名称】,记录下当前失败的key对应的记录。
下一次在继续调用对于相同的key可以进行失败统计,如果达到目标失败次数,会调用失败处理的兜底回调org.springframework.retry.RecoveryCallback 进行记录。
spring retry 中的 stateful 如何使用?@CircuitBreaker 是一种有状态的+具有熔断功能 是一个特殊的 @Retryable 可以这么理解由于有状态出现异常直接抛出,第二次调用会记录相同key的失败记录,这里会根据失败次数+熔断,下次调用是否活着兜底方案。总结多实践实践、才更好的理解,更多参考demo 理解。
通过学习spring retry 理解了框架将相关概念收拢,开发者只需关注核心的逻辑层即可。和写业务类似的,领域建模、内聚业务,单一职责。spring retryguava-retryhttp://kriszhang.com/spring-retry/https://blog.csdn.net/a742172349/article/details/106199939Spring retry有状态重试
闲鱼社区如何快准稳的完成无缝数据迁移
作者:闲鱼技术——长明背景:在内容社区中,内容标签用来辅助说明内容,内容标签对内容分发和理解具有重要作用,能够帮助内容社区将对的内容分发到对的人。目前闲鱼会玩社区的标签分为分类和属性标签两种,两种标签的用法不同,但是目前二者都是存在于同一个标签系统中,目前会有如下问题:易出错,靠人为去辨别分类标和属性标,难免会出错,出现漏打,错打难拓展,属性和分类属于不同的业务域,有各自独有的特性,现状无法让二者独立拓展为了解决以上问题,现在要将原标签系统拆分为分类系统和属性系统,具体来说,会将属性标从原标签系统中拆分到属性系统,然后将原标签系统作为新分类系统。整个过程,不仅需要迁移底层数据,还需要将属性服务从原标签系统迁移到新属性系统。现状:如下图所示,闲鱼会玩社区对属性标签依赖非常之多,除了自身的业务系统之外,还有图中标蓝的算法、搜索、数据等也会依赖。迁移过程中需要保证这些上层依赖不受影响。另外,业务方希望能够尽早启用属性系统,尽快提高打标效率。总结起来,迁移过程中面临了如下的挑战。快,短时间内迁移完成,尽早使用新属性系统稳,依赖众多,在迁移时需要保证属性服务可用,不影响上层业务,用户无感知准,迁移最最最基本的要求就是要保证数据正确迁移方案:我们按照影响面从小到大的顺序,制定了 1.底层存储同步、2.建设隔离层、3.业务读写迁移、4.依赖迁移、5.启用新属性系统共五步。其中依赖是指搜索、算法和数据,这些依赖影响面较广,迁移需要更加慎重,需要有己方业务迁移正确这个前提作为保证。因此依赖迁移需要单独列为一部分,且放在己方业务迁移完成后进行。迁移中的每一步迁移需要保证上一步正确,且出现问题,每一步都可以回滚回上一个正确状态。为了保证数据的一致性,我们全程都有数据校对服务。迁移过程1. 存储迁移整个迁移过程,我们首先先从底层存储开始同步,为了保证原标签系统和属性系统中的属性标签相同。实现这个目标需要从两方面做起,一方面是全量同步,就是将全部数据同步一遍。一方面是实时增量同步,一旦有新的属性标签被写入原标签系统中,那么属性系统中也要同步一份。这个套路比较固定。下面是我们全量同步的数据处理过程。其中同步任务我们直接使用了 阿里云 提供的 scheduleX 分布式任务工具。全量同步过程中要注意,控制同步速率、配置告警、做好异常记录和完成进度记录。控制同步速率是需要避免把依赖服务系统打挂,影响其他正常业务。配置告警是为了及时发现异常,及时排查。其中异常记录是为了排查问题的,必然要记录的。完成进度记录也是非常重要的,一旦出现问题,修复完了要继续时,可以直接从上次记录的同步位点开始同步。讲完了全量同步,下面讲一下实时增量拆分的过程,数据流过程如下图所示。即一旦触发了原标签系统变更,会实时将属性标的变化同步到属性系统。2. 隔离层建设屏蔽迁移细节做了存储迁移,那么现在属性系统和原标签系统中的属性标相同了,下面可以做业务读迁移了。业务迁移,这是迁移过程中工作量最大最复杂的地方,需要梳理清楚依赖很多。经过梳理发现,多个应用多个业务场景都在使用原标签系统。假如逐个迁移改造,一方面重复性工作比较多,需要重复验证的功能点多,另一方面,迁移细节无法统一管理,一旦有问题,需要逐个应用修改。所以在做业务迁移之前,我们做了一件事情,就是将散落在多个应用的读写原标签系统的操作都收归到了一个 jar 包中,然后在该 jar 中统一控制读写切换。jar 包相当于一个隔离层,隔离了上层业务和属性标签的存储逻辑。这样上层业务系统不必关心属性标是从原标签系统读取的抑或是从属性系统中读取的,只管从隔离层提供的方法中读取即可。有了隔离层统一管理,可以同时统一迁移,减少不必要的重复工作。具体的变化从 a 图变换到 b 图。接口适配由于分类系统和属性系统两种标签的业务语义和功能不同,内容中台对这两个系统的领域建模也不同,对应的数据服务接口能力也不同,为了让上层业务对此无感知,我们保持原服务接口不变,在隔离层做了对于分类系统和属性系统两个系统的适配。3. 业务读写迁移读迁移前置工作做完之后,我们开始具体的读迁移。读迁移是最好做的,可以先按照比例切流,逐步放量从属性系统中读取属性标,一旦发现有问题,那么直接将流量切回读原标签系统 ,没有问题,就直至全量。写迁移写迁移是很难一刀切的,一方面,即使是经过了梳理,还是可能会有遗漏的地方。另一方面,还有部分依赖方的写入(比如内容中台的标签写入)不在我们这边,暂时无法迁移。假如己方业务的写迁移了,那么己方业务只会写到属性系统 ,而没迁移的依赖方只会写到原标签系统。这会造成原标签系统和属性系统的属性标数据不一致。这导致两方面的问题,一方面,影响依赖方读,依赖方读的还是原标签系统,读取不到属性系统上的属性标。另一方面,两方不一致的话,如果属性系统出现问题,那么写无法即时回滚到原标签系统。因此在迁移过程中,还需要保证原标签系统和属性系统上的属性标时刻是相同的,在存储拆分中,已经有了 原标签系统-> 属性系统的同步链路,现在还需要将只写入属性系统的属性标同步回原标签系统。那么现在有 原标签系统->属性系统 和 属性系统 -> 原标签系统 两条同步链路。如果不做任何控制的话,明显会出现同步死循环原标签系统->属性系统->原标签系统。解决这种双向同步死循环的一般办法是加标志,用标志标识这次数据变更是源自哪一方,当发现自己的更新消息回流到了自己这里,那么就不再更新,这样就切断了更新的死循环。4. 依赖方迁移当己方业务能够保证无误的时候,那么可以做依赖迁移了。依赖方一般为算法、搜索和数据等。链路分为实时链路和离线链路。对于实时链路,这部分工作因为有了前面的业务读迁移,可以复用;对于离线链路,提供好离线数据表给到相关依赖方,让他们按时迁移完成即可。5. 启用新属性系统依赖方也迁移完成后,经过一段时间的观察,没有问题,便可以使用新的属性标签系统来打标了。启用新系统打标的之后,便不再需要 原标签系统->属性系统 的同步链路了,可以停止。后续再观察一段时间后,确认使用属性系统无问题后,便不再有将读写切回原标签系统的必要了,可以再切断 属性系统 -> 原标签系统 的同步链路,至此迁移完成。6. 数据校对任务在整个同步过程中,还要有对账任务来实时查看同步的数据是否正确。如果发现数据不正确,要及时找到原因,修正,然后做好数据矫正。总结本次迁移排除依赖方迁移所用时间外,共计两周。迁移过程中属性服务正常。零客诉舆情。迁移后,数据零差异。最后捋一下本次迁移中的经验点迁移过程中,如果服务依赖众多,可以用隔离层来隔离依赖对迁移的感知。双写,过程中避免出现同步死循环,可以通过给更新消息加标志避免。