Làm thế nào để tạo gốc tổng hợp mới trong CQRS?


10

Làm thế nào chúng ta nên tạo gốc tổng hợp mới trong kiến ​​trúc cqrs? Trong ví dụ này tôi muốn tạo AR2 gốc tổng hợp mới giữ tham chiếu đến AR1 đầu tiên.

Tôi đang tạo AR2 bằng phương pháp AR1 làm điểm bắt đầu. Cho đến nay tôi thấy một vài lựa chọn:

  1. Phương thức bên trong AR1 createAr2RootOpt1Tôi có thể gọi new AR2()và lưu đối tượng này vào db ngay lập tức bằng cách sử dụng dịch vụ miền có dấu vào kho lưu trữ.
  2. Tôi có thể phát ra sự kiện trong gốc tổng hợp đầu tiên, vd. SholdCreateAR2Eventvà sau đó có câu chuyện phi trạng thái phản ứng với điều này và đưa ra lệnh CreateAR2Commandsau đó được xử lý và thực sự tạo ra AR2 và phát ra AR2CreatedEvent. Trong trường hợp sử dụng nguồn sự kiện SholdCreateAR2Eventsẽ không được bảo tồn trong cửa hàng sự kiện, vì nó không ảnh hưởng đến trạng thái của gốc tổng hợp đầu tiên. (Hoặc chúng ta vẫn nên lưu cái này trong cửa hàng sự kiện?)

    class AR1{
        Integer id;
        DomainService ds;
    
        //OPTION 1
        void createAr2RootOpt1(){
            AR2 ar2 = new AR2();
            ds.saveToRepo(ar2);
        }
    
        //OPTION 2
        void createAr2RootOpt2(){
            publishEvent(new SholdCreateAR2Event());    //we don't need this event. Shoud it still be preserved in event store?
        }
    }
    
    class AR2{
        Integer id;
        Integer ar1Id;
    
        void handle(CreateAR2Command command){
            //init this AR with values and save
            publishEvent(AR2CreatedEvent());    //used for projections afterwards and saved inside AR2 event store
        }
    }
    
    class Saga{
        void handle(SholdCreateAR2Event ev){
            emitCommand(new CreateAR2Command());
        }
    }
    

Đó là cách thích hợp hơn để làm điều này?

Câu trả lời:


2

Tôi nghĩ rằng lựa chọn đó không. 2 là giải pháp, với một sửa đổi nhỏ nhưng quan trọng: AR1không nên phát ra một sự kiện mà mục đích của họ là tạo ra AR2, thay vào đó nó sẽ phát ra một AR1WasCreatedsự kiện. Sự kiện này nên được duy trì trong cửa hàng sự kiện, vì nó là một sự kiện quan trọng đánh dấu sự ra đời của AR1. Sau đó, một Sagadanh sách cho AR1WasCreatedsự kiện và tạo một lệnh để tạo AR2: CreateAR2Command.

Lựa chọn số 1 là rất sai. Bạn không bao giờ nên tiêm loại dịch vụ tên miền đó vào một Aggregate. Aggregatesnên thuần túy, không có tác dụng phụ nào khác mà tạo ra các sự kiện.

PS Tôi không bao giờ phát ra các sự kiện từ hàm tạo của Aggregatevì có sự phân biệt giữa việc tạo một thể hiện của một đối tượng (theo nghĩa ngôn ngữ lập trình) và sự tạo ra (sự ra đời nếu bạn muốn) của một Aggregate. Tôi chỉ phát ra các sự kiện từ một handlephương thức (khi xử lý a command).


Bạn có ý nghĩa AR1WasCreatedgì? Có nên AR2WasCreatedkhông? Ngoài ra, nếu tôi sử dụng logic của bạn, tôi phát ra sự kiện AR2WasCreatedtrước khi nó thực sự được tạo ra? Và việc lưu sự kiện này trong nhật ký sự kiện của AR1 có vẻ có vấn đề, vì tôi thực sự không cần dữ liệu này trong AR1 (nó không sửa đổi bất cứ điều gì trong AR1).
Bojan Vukasovic

OK, 3 năm sau. Nó đi AR1WasCreated-> SAGA (có quy tắc nếu A1 được tạo rồi tạo A2) -> CreateAR2Command-> AR2WasCreated.
Bojan Vukasovic

@BojanVukasovic Tôi rất vui vì nó đã hoạt động như tôi đã viết :)
Constantin Galbenu

2

Làm thế nào chúng ta nên tạo gốc tổng hợp mới trong kiến ​​trúc cqrs?

Mô hình sáng tạo là lạ .

Udi Dahan có một số điều hữu ích để nói về vấn đề chung: Đừng tạo Rễ tổng hợp . Điểm cơ bản là tổng hợp không bật ra khỏi hư không và có ngôn ngữ miền mô tả cách chúng xuất hiện, cần được ghi lại trong mô hình miền của bạn.

Trường hợp nó có xu hướng bị xoắn là thực thể trong mô hình miền của bạn đang xử lý lệnh không phải là thực thể được sửa đổi bởi giao dịch. Điều đó không sai; nó thật kỳ lạ (so với trường hợp bạn yêu cầu một thực thể tự sửa đổi.

Cách tiếp cận thứ hai của bạn cũng OK. "Các sự kiện mà chúng tôi nêu ra mà không thực sự lưu vào cơ sở dữ liệu" đôi khi được gọi là "sự kiện miền"

Ý tưởng cơ bản là, trong cùng một giao dịch, trình xử lý lệnh tăng sự kiện, di chuyển dọc theo xe buýt đến một trình xử lý sự kiện cho phép tập hợp thứ hai tự tạo. Bạn có thể có được sự gắn kết mã tốt hơn, có thể.

Lưu ý: trong các hệ thống nguồn có sự kiện, bạn thường không sử dụng các sự kiện theo cách này.

Trong trường hợp sử dụng nguồn sự kiện ShouldCreateAR2Event sẽ không được bảo tồn trong cửa hàng sự kiện, vì nó không ảnh hưởng đến trạng thái của tổng hợp gốc đầu tiên.

Lưu ý: tên sự kiện thường ở thì quá khứ - ShouldCrateAR2 có lỗi chính tả.

Có, nếu bạn chỉ ném một sự kiện lên xe buýt đồng bộ để chạy mã từ xa, thì bạn không nên lưu sự kiện đó vào sổ ghi chép. Nó chỉ là một chi tiết thực hiện ở quy mô này.

Hay chúng ta vẫn nên lưu cái này trong cửa hàng sự kiện?

Tránh sửa đổi hai luồng sự kiện khác nhau trong cùng một giao dịch. Nếu sáng tạo này cũng thể hiện sự thay đổi đối với AR1, thì câu trả lời thông thường sẽ là sửa đổi AR1 trong giao dịch này, với một thuê bao không đồng bộ với các sự kiện chịu trách nhiệm bắn lệnh để tạo AR2.

Xử lý lệnh tạm thời giúp rất nhiều ở đây.


cảm ơn về câu trả lời. Một điều nữa không rõ ràng 100% - sau này nếu tôi phải sử dụng AR2 làm đối số cho AR1 thì tôi nên vượt qua điều này như thế nào - vì CQRS nói rằng AR chỉ nên được sử dụng để viết và không truy vấn. Nhưng tôi không có lựa chọn nào khác ngoài việc sử dụng AR1.doSmthn(AR2 param)vì mọi phép chiếu đọc mà tôi tạo không có dữ liệu hoàn chỉnh tôi cần (chỉ AR2 có dữ liệu hoàn chỉnh).
Bojan Vukasovic

> "Có, nếu bạn chỉ ném một sự kiện lên xe buýt đồng bộ để chạy mã từ xa, thì bạn không nên lưu sự kiện đó vào sổ ghi chép." Tôi nghĩ rằng việc lưu nó có giá trị thực sự ở chỗ bạn biết rằng quá trình đã được khởi động để điều gì đó xảy ra, bây giờ bạn cũng có thể theo dõi thời điểm này thực sự hoàn thành. Nhưng tôi đoán nó phụ thuộc vào trường hợp sử dụng
Chaosekie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.