- DDD はアーキテクチャに重点を置き、ビジネスに重点を置いています。– モノリシックアーキテクチャによる迅速な検証
- DDDデザインパターン
- 貧血モデル
- 充血モデル
- 防食層
- DDD 4 層アーキテクチャ仕様
- DDD モノリシック アーキテクチャとマイクロサービス アーキテクチャの分離
- ローカルの単一 SPI プラガブル拡張ビジネス モデル
- Nacos プラガブル拡張機能のビジネス モデル - サービス コードとしてのサービス名
- DDD 明確なアーキテクチャ – ドメイン ウェアハウスを構築してドメインの再利用を実現
iQiyiの投げ銭ビジネスにおけるドメイン駆動設計(DDD)の実践
https://blog.csdn.net/weixin_45583158/article/details/114312926
DDD はアーキテクチャに重点を置き、ビジネスに重点を置いています。— モノリシックアーキテクチャによる迅速な検証
DDDデザインパターン
1. 貧血モデル
- POJOには用事がない
- ビジネスはサービスに引き継がれます
2. 充血モデル
- DAOの責任とビジネスマッピング
- DO は DB マッピングを担当します
3. 防食層
- BusiSafeService のカプセル化とカプセル化
- Kafak は AduitMessageProducer をカプセル化します
- 金額計算口座振替サービス
- 単一オブジェクトの状態動作をエンティティ (Entity) でカプセル化します。
- ドメイン サービスはマルチエンティティ ロジックをカプセル化します
変更前
public class PaymentController{
private PayService payService;
public Result pay(String merchantAccount,BigDecimal amount){
Long userId = (Long) session.getAttribute("userId");
return payService.pay(userId, merchantAccount, amount);
}
}
public class PayServiceImpl extends PayService{
private AccountDao accountDao;//操作数据库
private KafkaTemplate<String, String> kafkaTemplate;//操作kafka
private RiskCheckService riskCheckService;//风控微服务接口
public Result pay(Long userId,String merchantAccount,BigDecimal amount){
// 1. 从数据库读取数据
AccountDO clientDO = accountDAO.selectByUserId(userId);
AccountDO merchantDO =
accountDAO.selectByAccountNumber(merchantAccount);
// 2. 业务参数校验
if (amount>(clientDO.getAvailable()) {
throw new NoMoneyException();
}
// 3. 调用风控微服务
RiskCode riskCode = riskCheckService.checkPayment(...);
// 4. 检查交易合法性
if("0000"!= riskCode){
throw new InvalideOperException();
}
// 5. 计算新值,并且更新字段
BigDecimal newSource = clientDO.getAvailable().subtract(amount);
BigDecimal newTarget = merchantDO.getAvailable().add(amount);
clientDO.setAvailable(newSource);
merchantDO.setAvailable(newTarget);
// 6. 更新到数据库
accountDAO.update(clientDO);
accountDAO.update(merchantDO);
// 7. 发送审计消息
String message = sourceUserId + "," + targetAccountNumber + "," + targetAmount;
kafkaTemplate.send(TOPIC_AUDIT_LOG, message);
return Result.SUCCESS;
}
}
変更後
public class PaymentController{
private PayService payService;
public Result pay(String merchantAccount,BigDecimal amount){
Long userId = (Long) session.getAttribute("userId");
return payService.pay(userId, merchantAccount, amount);
}
}
public class PayServiceImpl extends PayService{
private AccountRepository accountRepository;
private AuditMessageProducer auditMessageProducer;
private BusiSafeService busiSafeService;
private AccountTransferService accountTransferService;
public Result pay(Long userId,String merchantAccount,BigDecimal amount){
// 参数校验
Money money = new Money(amount);
UserId clientId = new UserId(userId);
AccountNumber merchantNumber = new AccountNumber(merchantAccount);
// 读数据
Account clientAccount = accountRepository.find(clientId);
Account merAccount = accountRepository.find(merchantNumber);
// 交易检查
Result preCheck = busiSafeService.checkBusi(clientAccount,merAccount,money);
if(preCheck != Result.SUCCESS){
return Result.REJECT;
}
// 业务逻辑
accountTransferService.transfer(clientAccount,merAccount,money);
// 保存数据
accountRepository.save(clientAccount);
accountRepository.save(merAccount);
// 发送审计消息
AuditMessage message = new AuditMessage(clientAccount, merAccount,money);
auditMessageProducer.send(message);
return Result.SUCCESS;
}
}
DDD 4 層アーキテクチャ仕様
- ドメイン層: システムの中核であり、外部依存性を持たずにビジネス機能を純粋に表現します。
- アプリケーション層: ドメイン オブジェクトを調整し、ビジネス シナリオを整理および形成し、ドメイン層にのみ依存します。
- ユーザー インターフェイス (ユーザー インターフェイス): ユーザーとの対話を担当します。ユーザーのリクエストを理解し、ユーザーの応答を返します。アプリケーション層のみに依存する
- インフラストラクチャ層: ビジネスとデータの分離。ドメイン層に永続化サービスを提供し、他の層に一般的な機能を提供します。
アダプターは各サービス層を分離します
DDD モノリシック アーキテクチャとマイクロサービス アーキテクチャの分離
//TODO 单体架构与微服务架构只需要切换一个服务实现类即可,对各领域的核心是没有影响的。。
//@Resource(name = "LocalAsyncBusiService") //基于SPI实现的单体架构消息处理服务
@Resource(name = "NacosAsyncBusiService") //基于Nacos实现的微服务消息处理服务
private AsyncBusiService asyncBusiService;
ローカルの単一 SPI プラガブル拡張ビジネス モデル
@Component
public class BusiServiceRepositoryimpl implements BusiServiceRepository {
private List<GsService> busiServices = new ArrayList<>();
@PostConstruct
public void loadBusiServices() {
if (busiServices.isEmpty()) {
final ServiceLoader<GsService> gsServices = ServiceLoader.load(GsService.class);
final Iterator<GsService> iterator = gsServices.iterator();
while (iterator.hasNext()) {
busiServices.add(iterator.next());
}
}
}
public GsService getGsService(String serviceCode) {
for (GsService gsService : busiServices) {
if (serviceCode.equals(gsService.serviceCode())) {
return gsService;
}
}
return null;
}
}
Nacos プラガブル拡張機能のビジネス モデル - サービス コードとしてのサービス名
@Resource
private DiscoveryClient discoveryClient;
//1、去Nacos上获取服务实例。
List<ServiceInstance> instances = discoveryClient.getInstances(serviceCode);
//1-1、如果服务不存在,直接返回不支持的serviceCode
if(null == instances || instances.isEmpty()){
logger.error("ServiceCode["+serviceCode+"] is not support yet.");
return;
}
StringBuffer requestUrl = new StringBuffer("http://");
ServiceInstance serviceInstance;
//随机找一个实例
if(instances.size()==1){
serviceInstance = instances.get(0);
}else{
Random random = new Random();
int index = random.nextInt(instances.size());
serviceInstance = instances.get(index);
}
//接口路径固定请求 SERVICE_SUFFIX
requestUrl.append(serviceInstance.getHost()).append(":").append(serviceInstance.getPort()).append(SERVICE_SUFFIX);
DDD 明確なアーキテクチャ – ドメイン ウェアハウスを構築してドメインの再利用を実現
https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/
具現化された形式の
メッセージ コントラクト層: 多くの MVC プロジェクトの開発プロセスでは、データを送信する POJO が DTO、VO、BO、DO などのさまざまなオブジェクトに分割され、異なるメソッドが使用されることが常に規定されています。各技術レベルの目的、その目的は、各層のデータがより純粋であることを保証し、外部データの影響を軽減することを試みることです。