How to get ID in create when applying CQRS?

Language AgnosticCqrs

Language Agnostic Problem Overview


My take on CQRS is when followed strictly your commands don't return anything (return type void), so my example is really straight forward: How do you retrieve an ID when creating something?

For example, when creating a credit card transaction it seems rather important to return a transaction ID, or when creating a customer it would be much easier if you got the customer you created or the customer ID back so a browser could navigate automatically to that customer page for example.

One solution could be to first ask for an ID and then create the customer or transaction with that ID, but it seems pretty weird.

Does anyone have any experience with this or know how it should be done in the most effective way? Maybe I have misunderstood something?

Language Agnostic Solutions


Solution 1 - Language Agnostic

CQRS is all about fire-and-forget, and since GUIDs are very reliable (low risk of collision) there is no problem sending in a GUID that you generate your self.

The steps would basically be:

  1. Create your command
  2. Generate and assign your identity (GUID) to it
  3. Fire the command
  4. Return the identity earlier generated

Read more about GUIDs on Wikipedia

Solution 2 - Language Agnostic

Integer id's / GUIDs / byte arrays of any size can be reliable enough at practice, but they all do not correspond to the theoretical requirement (collisions happens), while valid theoretical solution exists and can be applied most of the time.

I'd formulate the solution as: in the equal-level system co-operation one's identity should be guaranteed by the system of a higher level. Higher-level system is the one which manages the lifetime of co-operating systems.

Example:

class John
{
    private readonly int id;

    public John(int id)
    {
        this.id = id;
    }

    public void UseSite(Site site)
    {
        site.CreateAccount(id, "john");

        site.SetPassword(id, "john", "123");

        /* ... */
    }
}

class Site
{
    public void CreateAccount(int humanId, string accName) { /* ... */ }

    public void SetPassword(int humanId, string accName, string pwd) { /* ... */ }

    /* ... */
}

class Program
{
    static void Main(string[] args)
    {
        Site s = new Site();

        // It's easy to guarantee the identity while there's only one object 
        John j = new John(4);

        Console.ReadLine();
    }
}

Program is the higher-level module. It is responsible to use John and Site correctly. Providing John with an unique identifier is a part of this responsibility.

You will find that it is impossible or very hard to deal with the identity of some real-life systems, like a human. It happens when these systems are on the same level as your system. Typical example is a human and a web-site. Your site will never have a guarantee that the right human requesting the page. In this case you should use the probability-based approach with a reliable hash.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomas JanssonView Question on Stackoverflow
Solution 1 - Language AgnosticRobin OrhedenView Answer on Stackoverflow
Solution 2 - Language AgnosticastefView Answer on Stackoverflow