🎨
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. 其他

CQRS命令查詢職責分離

PreviousEvent Driven ArchitectureNextConcurrent並行相關

Last updated 2 years ago

Was this helpful?

CQRS(Command Query Responsibility Segregation)命令查詢職責分離 命令:對系統產生【影響】,但無結果 查詢:對系統【不】產生【影響】,但有結果


查詢
boolean isExist= File.exist(File);


命令
File.write("寫檔案");


目的

改善效能、擴充性、簡化

一般功能特性,多讀少寫。

改善效能:讀寫模型分離,讀模型降低框架使用,讀與寫不同資料庫,讀取資料擴可進行擴充,或是否是不同 連線方式 ,讀取使用JDBC原生程式,寫入使用ORM連線方式。

簡化:資料異動資料表與查詢資料表不同。

命令模型資料:學生、課程

Table
Column1
Column 2

課程

課程編號

分數

學生

姓名

學號

classDiagram
學生 o-- 課程 : 包含

學生 : 姓名 
學生 : 學號


課程 : 課程編號 
課程 : 分數

查詢模型資料表(每個學生最多兩個課程)

Table
Column1
Column 2
Column 3
Column 4
Column 5
Column 6

學生projection

姓名

學號

課程編號1

分數1

課程編號2

分數2

DDD

  • 命令EditPersonalInfoCommand

  • 查詢GetListQuery

  • 事件PersonalInfoChangedEvent

缺點:資料維護成為最大成本

投影:讀取資料模型與存取資料模型資料同步

  1. 事件驅動

    • 領域事件變更:

    • 訂閱追蹤領域事件(Event sourcing)

  2. 狀態驅動(透過狀態變更監聽 如:Hibernate :Event Listener)

    • 同步:反應速度快、增加處理時間、不容易拓展

    • 非同步:不會發生【阻斷】情況

範例

//命令
interface ICommand{

}
//命令處理
public interface ICommandHandler<T extends ICommand, Result> {
	Result handler(T cmd);
}
//學生電話變更命令
public class StudentChangeTelCommand implements ICommand {

	private String studentId;// 學號
	private String tel;// 電話

	public StudentChangeTelCommand(String studentId, String tel) {
		super();
		this.studentId = studentId;
		this.tel = tel;
	}

//變更學生電話命令執行
public class StudentChangeTelHandler implements ICommandHandler<StudentChangeTelCommand, Integer> {

	StudentRepository repository;

	public StudentChangeTelHandler(StudentRepository repository) {
		super();
		this.repository = repository;
	}

	@Override
	public Integer handler(StudentChangeTelCommand cmd) {
		return repository.changeTel(cmd.getStudentId(), cmd.getTel());
	}

}




public class ChangeTelUseCaseTest {

	StudentRepository studentRepository = new StudentRepository();
	StudentChangeTelHandler StudentChangeTelHandler = new StudentChangeTelHandler(studentRepository);

	@Test
	public void update_tel_withExistStudent_return_1() {
		ChangeTelUseCaseDTO dto = new ChangeTelUseCaseDTO();
		dto.setStudentId("S00001");
		dto.setTel("0911111111");

		ChangeTelUseCase changeTelUseCase = new ChangeTelUseCase(StudentChangeTelHandler);
		ChangeTelUseCaseOutput output = changeTelUseCase.command(dto);
		assertTrue(output.getUpdateSize() > 0);
	}

}