🎨
Andy開發紀錄
  • 關於
    • 自介
  • 設計模式
    • 觀察者模型
    • 有限狀態機
    • 裝飾器模式
  • 其他
    • Scrum敏捷式開發
    • SOLID設計
    • TDD驅動測試開發
    • Event Driven Architecture
    • CQRS命令查詢職責分離
    • Concurrent並行相關
      • Single Thread Execution
      • 共用元件設計
        • CountDownLatchWorkPool
        • IForkWorkService
      • Pattern
        • THREAD-PER-MESSAGE
        • PRODUCER CONSUMER
        • SINGLE THREAD
        • Guarded Suspension 守衛模式
      • IQueue
        • ListQueue
        • BlockQueue
        • OrderBlockQueue
  • 元件設計
    • Sql Help
      • SQL Help Generate
      • StringBuilderGenerator
      • SQL Generate
    • excel工具
    • BDD行為驅動開發
    • 多工設計
      • 多工自動調整Thread數量
    • 常用Design Patten實作
    • Telegram Bot元件
    • 代碼元件
    • HCP API元件
    • 文字解析元件
    • MockitObject
    • 資料驗證元件
    • Zip壓縮工具
    • Sql Code Generate
  • 讀書心得
    • Clean code第一章
  • side project
    • 後端服務
  • IDEA
    • IDEA 外掛推薦
    • IDEA 外掛開發
Powered by GitBook
On this page

Was this helpful?

  1. 其他

Event Driven Architecture

事件驅動設計

PreviousTDD驅動測試開發NextCQRS命令查詢職責分離

Last updated 2 years ago

Was this helpful?

行為松耦合制度,提升未來擴充性

姓名變更簡單範例

定義事件

  1. 已提交姓名變更事件

  2. 已驗證失敗事件

  3. 已變更姓名事件

graph LR;
    cmd(提交commmand) --> submit
    submit(已提交Event)-->ok(已完成姓名變更Event);
    submit-->fail(已驗證失敗Event);
  

事件監聽

當【事件發生】,驅動另一件事件

@Slf4j
@RequiredArgsConstructor
public class NamedEventChannel implements IChannel<NamedEvent> {

	private final ChangeNameUseCase changeNameUseCase;

	@Override
	public void dispatch(NamedEvent message) {
		changeNameUseCase.change(message);
	}

}

題目

  1. 身分證、變更後姓名必填

  2. 變更後姓名不得空白

  3. 姓名變更最多3次

定義聚合根

使用者【UserAggregate】


/**
 * 使用者
 *
 */
@Data
public class UserAggregate {

	private String id;// 統一編號
	private String name;
	private int changeNameCount = 0;// 姓名變更次數

測試Happy Path路徑

	/**
	 * 輸入正確性名,變更次數小於等於3,取得變更成功事件
	 */
	@Test
	void testCurrentNameAndCountLess3ReturnNamedEvent() {

		// GIVE
		SubmitNameUseCommand submitNameUseCommand = new SubmitNameUseCommand();
		submitNameUseCommand.setId(A123456789);
		submitNameUseCommand.setNewNmae(NEW_NAME);

		// WHEN
		UserAggregate userAggregate = new UserAggregate();
		userAggregate.setId(A123456789);
		userAggregate.setName(A123456789);
		userAggregate.setName(OLD_NAME);
		userAggregate.setChangeNameCount(0);

		Mockito.when(userAggregateRepository.findById(A123456789)).thenReturn(userAggregate);

		// THEN
		SubmitNameUseCase submitNameUseCase = new SubmitNameUseCase(userAggregateRepository);
		Event event = submitNameUseCase.submit(submitNameUseCommand);
		assertThat(event).isExactlyInstanceOf(NamedEvent.class);

		NamedEvent namedEvent = (NamedEvent) event;
		assertThat(namedEvent.getId()).isEqualTo(A123456789);
		assertThat(namedEvent.getNewName()).isEqualTo(NEW_NAME);
		assertThat(namedEvent.getOldName()).isEqualTo(OLD_NAME);
		assertThat(namedEvent.getChangeNameCount()).isEqualTo(1);

	}

撰寫提交案例

@RequiredArgsConstructor
public class SubmitNameUseCase {

	private final IUserAggregateRepository userAggregateRepository;

	Event submit(SubmitNameUseCommand command) {
		UserAggregate user = userAggregateRepository.findById(command.getId());
		if (user == null) {
			VerifiedFailNameEvent verifiedFailNameEvent = new VerifiedFailNameEvent();
			verifiedFailNameEvent.setMessage("帳號不存在:" + command.getId());
			return verifiedFailNameEvent;
		}
		return user.changeName(command);
	}

}

使用者行為操作

@Data
public class UserAggregate {

	private String id;// 統一編號
	private String name;
	private int changeNameCount = 0;// 姓名變更次數

	public Event changeName(SubmitNameUseCommand command) {
		try {
			this.checkchangeName(command);

			final NamedEvent namedEvent = new NamedEvent();
			namedEvent.setOldName(this.name);
			namedEvent.setNewName(command.getNewNmae());
			namedEvent.setId(id);
			namedEvent.setChangeNameCount(++changeNameCount);
			this.name = command.getNewNmae();
			return namedEvent;
		} catch (ApBusinessException e) {
			VerifiedFailNameEvent verifiedFailNameEvent = new VerifiedFailNameEvent();
			verifiedFailNameEvent.setMessage(e.getMessage());
			return verifiedFailNameEvent;
		}

	}