在Airwallex,领域驱动设计(DDD)方法被用来指导我们的工程师如何对复杂的业务问题和系统设计建模。在这篇博客中,我们提供了一个全面的工作流,我们使用DDD模式进行建模,然后对支付系统进行落地。
创新互联-专业网站定制、快速模板网站建设、高性价比乾安网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式乾安网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖乾安地区。费用合理售后完善,10年实体公司更值得信赖。
全球支付系统是复杂和不断变化的,涉及从订单、欺诈、通知、与各种支付方式的集成到清算和结算等广泛的板块。
在处理复杂的系统时,大多数开发人员可能会遇到一些一致的问题:
在Airwallex,领域驱动设计(DDD)方法被用来指导我们的工程师如何解决复杂的业务问题和系统建模。
然而,DDD只是各种模式的集合,很难将其应用于系统设计。在这篇博客中,我们提供了一个全面的工作流程,介绍了我们是如何在Airwallex应用领域驱动设计的,从中得到的经验教训,以及我们接下来要做什么。
领域驱动设计(由Eric Evans提出)是一组帮助基于业务领域的底层模型设计软件系统的思想、原则和模式。DDD有两个不同的空间,问题空间和解决方案空间。
在问题空间中,您使用战略模式定义系统的顶层的系统层次,这些战略模式关注域、子域和通用语言的分析。
在解决方案空间中,采用战术模式来提供一组设计模式,您可以使用这些设计模式创建领域模型。这些模式包括有界上下文、上下文映射、实体、聚合、领域事件、领域服务、应用程序服务和基础设施。这些战术模式将帮助您设计既松散耦合又具有内聚性的微服务。
下面是一个常见的案例:
一位顾客想在该商家的网站上购买一件价格为10美元的t恤。顾客可以用多种支付方式来支付这件t恤,比如Visa卡或微信钱包。在客户支付后,商家会从支付网关收到一个通知,显示客户的支付已经成功。然后,商家可以在Airwallex webapp中查看支付细节,包括购买价格、商家费用以及资金将何时进入Airwallex Global Account钱包。
下面是分析结果。
支付系统
付款处理:商家可以通过各种付款方式接受客户的付款。
金融:清算和解决商家的付款资金。
付款意向:商家创建的订单的价格,产品,客户等。
付款尝试:商家创建的交易以获得订单的客户。
付款方式:客户支付产品的方式。
付款结算:付款之 后钱进入商家钱包。
付款视图:汇总付款详细信息视图,包含与一笔付款相关的所有数据。
有界上下文(BC)限定了域模型的范围。根据对问题空间的分析结果,我们可以定义以下边界上下文:
支付网关: API网关,为商家提供restful API来创建或查看支付。
支付核心模块: 支付意图,方法资源管理。
支付适配器: 与一个外部的PSP集成,例如微信,支付宝,Visa,万事达等。
支付结算: 计算并结算商户每次支付的原则和费用。支付融合:支付明细汇总视图。
下面是生成的上下文映射的一个示例:
从上面分析的场景和通用语言中,我们可以确定以下聚合、实体、值对象和域事件:
根据我们的经验,领域服务为单个聚合使用业务逻辑服务,遵循单一责任。通常,我们将封装领域仓储、聚合修改和在领域服务中发布的领域事件。以PaymentAttemptExecutorService为例:
领域事件可以使系统更具有可扩展性,并避免任何耦合,且一个聚合不应该决定其他聚合应该做什么。
例如,当PaymentCaptureCommand命令将支付状态更改为已支付时,会发出领域事件PaymentAttemptCapturedEvent。在PaymentAttemptCapturedEvent的领域事件处理程序(EventHandler)中,我们可以在该业务逻辑上加上你想要的逻辑。例如,通知支付聚合有界上下文更新支付详情,通知支付结算有界上下文计算结算金额和费用。
在DDD模式中,基础设施层作用于将核心业务领域与技术实现细节分开。该层通常采用ACL (anti - corruption-layer)模式。以领域仓储为例:
领域仓储只定义接口功能,但实现细节应该隐藏在基础设施层中,细节上你可以使用PostgreSQL或MongoDB来保存数据。例如,在基础设施层中,PaymentAttemptPgRepository是基于PostgreSQL的特定实现,而toPO是一个转换器,用于将域对象PaymentAttempt转换为持久化对象。
现在,我们已经为支付系统定义了一组有界上下文,并在每个有界上下文中标识了一组实体、聚合和领域事件服务。下一步是从域模型到应用程序微服务设计。这里,我们选择将一个有边界的上下文映射到一个微服务。
采用DDD可以提供许多好处,例如,在所有团队之间进行清晰的沟通,以及在设计系统时使用成熟的模式来管理复杂性并提供更好的可伸缩性。
使用通用语言,我们可以实现更多的自描述类名和函数名。
使用聚合模式,我们可以实现清晰的边界和单一的职责。
使用领域事件模式,我们可以分割核心业务流程,减少聚合之间的耦合。
通过基础设施层和ACL模式,我们可以将核心业务领域模型与技术实现细节分离开来。通过限定上下文模式,我们可以派生出潜在的微服务候选对象。
在实践中应用DDD时,我们想要分享一些挑战和经验教训:
原文地址:
我们假定名字等于X,价格大于10。
那么是不是所有名称等于X价格大于10的amount总和大于Z就可以
假设你的总需是所有大于10的amount的和大于Z,那么显示什么,是显示所有的名称等于X,价格大于10的内容吗?那么如果所有amount之和不大于Z呢?是不是就不显示?价格小于10的计算amount吗?应该不计算吧
如果我上面没有说错,那么下面语句差不多能完成,语句未必能执行(没环境没办法测试,只能是起到一个借鉴的作用),我用的子查询,你可以尝试用表连接解决,那样可能更直观一些。
select name,price,amount from table where table.name in (select name from table where priceY group by name having sum(smount)Z) and table.priceY
这是腾讯系统的一种设定,数据迁移目前只支持 PostgreSQL 数据库的版本是9.3.x,9.5.x,同时9.3.x 不支持增量同步,9.5.x 需要通过在线同步插件才能支持。
腾讯都是可以直接从微信QQ里面下载,最重要的是没有平台或代理费用,而安卓版的COC的国服由昆仑代理,炉石由网易代理,代理费就像google play中谷歌拿走的那部分费用,因此在充值方面无可非议,不同的是,腾讯游戏充值运营(代理)都是自家的东西。
换句话说玩家使用的是与iOS相反的外部充值——微信或QQ支付,并且充值金额100%进了腾讯的腰包!但是在iOS充值的金额只有70%给了腾讯。
看你对精度的要求大不大。
如果你允许部分的精度丢失的, 那么可以用 Double.
如果你那一列, 是用来存储金额的, 不允许精度丢失的, 那么还是使用 BigDecimal 比较好!
Access是一种传统的桌面型关系数据库,数据库是有结构的数据集合,它与一般的数据文件不同,是一串文字或数字流。数据库中的数据可以是文字、图象、声音等。 关系式数据库由一系列表组成,表又由一系列行和列组成,每一行是一个记录,每一列是一个字段,每个字段有一个字段名,字段名在一个表中不能重复。如图1就是一张表。
图1
表与表之间可以建立关系(或称关联,连接),以便查询相关联的信息。Access数据库以文件形式保存,文件的扩展名是DB。Access 97数据库由六种对象组成,它们是表、查询、窗体、报表、宏和模块。
表(Table) ——表是数据库的基本对象,是创建其他5种对象的基础。表由记录组成,记录由字段组成,表用来存贮数据库的数据,故又称数据表。
查询(Query)——查询可以按索引快速查找到需要的记录,按要求筛选记录并能连接若干个表的字段组成新表。
窗体(Form)——窗体提供了一种方便的浏览、输入及更改数据的窗口。还可以创建子窗体显示相关联的表的内容。窗体也称表单。
报表(Report)——报表的功能是将数据库中的数据分类汇总,然后打印出来,以便分析。
宏(Macro)——宏相当于DOS中的批处理,用来自动执行一系列操作。Access列出了一些常用的操作供用户选择,使用起来十分方便。
模块(Module)——模块的功能与宏类似,但它定义的操作比宏更精细和复杂,用户可以根据自己的需要编写程序。模块使用Visual Basic编程。
数据库描述:数据库的主要作用是是存储数据,我们使用的所有软件都是需要数据库来支撑的,软件只是一个平台,它是没有存储数据的功能。所以必须有数据库来存储我们软件中所有的数据。一般软件使用的数据库有: Access、SQL Server、Oracle、DB、Informix、Sybase、PostgreSQL、MySQL。但是用的最多的是Access、SQL Server、Oracle、DB数据库。
例如:用友财务软件、金蝶财务软件、管家婆软件、速达软件、等一些企业管理软件都是用的SQL Server数据库来存储数据库的。无论是是在软件中做的凭证还是开的单据都是存储在数据库中的。我们从表面看见的商品名称、单位、数量、金额、说明、描述等信息都是存储在数据库中,查询的时候也是从数据库中读取出来的;
例如用友软件某数据库表存储的信息如下所示: