Skip to main content
added 1 character in body
Source Link
Peter Csala
  • 10.8k
  • 1
  • 16
  • 36

Orchestration vs Choreography

  • Whenever you want to execute a sequence of actions then you can pipe them through:
    • choreography: Each and every action knows who is the next in the calling chain
      • Or in other words, they know how to interact with each other
    • orchestration: There is a an orchestrator which chains the actions after each other
      • Or in other words, they don't know how to interact with each other
  • You have chosen the choreography which made your program harder to understand IMHO
    • None of your methods return anything rather they are calling each other
    • As a reviewer/maintainer it is harder to create a mental model
  • If you would compose your actions as an orchestration
    • then it would be much easier to follow the data and execution flows
    • Here is a (pseudo) example
async Task ExecuteCoreAsync(CancellationToken token) { var purchaseRequests = await GetPurchaseRequests(token); var accessToken = await RetrieveAccessToken(token); var purchaseIds = await ProcessPurchaseRequests(accessToken, purchaseRequests, token); await UpdateStatusOfPurchaseRequests(purchaseIds, token); } 

Problem domain decomposition

  • We can see that you have tried to split up the problem domain into smaller chunks
    • My problem here is that they are not on the same level of granularity
      • Compare MakeRequestsToRemoteService and UpdateData
  • MakeRequestsToRemoteService has multiple responsibilities
    • Retrieving access token
    • Issuing requests against downstream system
    • Calling update on database records
  • If you would try to aim for smaller composable chunks
    • then it is much easier to create actions with single responsibility
  • BTW: based on the shared code fragment it seems like it is unnecessary to retrieve access token whenever you start to process a purchase request
    • IMHO it would be enough to retrieve only once

Distributed transaction

  • According to my understanding your code is the glue between two subsystems (a database and a service) >> distributed
  • I assume that you want to guarantee that either you can update records in both systems or in none of them >> transaction
    • Let's suppose that for some reason your last action the UpdateData fails for a given purchase
    • That would mean the database is not updated but the other subsystem didis
    • Based onBecause of the purchase domain I assume that this inconsistency can cause problems
  • You could for example do a compensation action against the service to undo/rollback the change to heal the consistency across multiple subsystems
  • I would suggest read about SAGA pattern or Two/Three Phase CommitsCommit protocols

Orchestration vs Choreography

  • Whenever you want to execute a sequence of actions then you can pipe them through:
    • choreography: Each and every action knows who is the next in the calling chain
      • Or in other words, they know how to interact with each other
    • orchestration: There is a an orchestrator which chains the actions after each other
      • Or in other words, they don't know how to interact with each other
  • You have chosen the choreography which made your program harder to understand IMHO
    • None of your methods return anything rather they are calling each other
    • As a reviewer/maintainer it is harder to create a mental model
  • If you would compose your actions as an orchestration
    • then it would be much easier to follow the data and execution flows
    • Here is a (pseudo) example
async Task ExecuteCoreAsync(CancellationToken token) { var purchaseRequests = await GetPurchaseRequests(token); var accessToken = await RetrieveAccessToken(token); var purchaseIds = await ProcessPurchaseRequests(accessToken, purchaseRequests, token); await UpdateStatusOfPurchaseRequests(purchaseIds, token); } 

Problem domain decomposition

  • We can see that you have tried to split up the problem domain into smaller chunks
    • My problem here is that they are not on the same level of granularity
      • Compare MakeRequestsToRemoteService and UpdateData
  • MakeRequestsToRemoteService has multiple responsibilities
    • Retrieving access token
    • Issuing requests against downstream system
    • Calling update on database records
  • If you would try to aim for smaller composable chunks
    • then it is much easier to create actions with single responsibility
  • BTW: based on the shared code fragment it seems like it is unnecessary to retrieve access token whenever you start to process a purchase request
    • IMHO it would be enough to retrieve only once

Distributed transaction

  • According to my understanding your code is the glue between two subsystems (a database and a service) >> distributed
  • I assume that you want to guarantee that either you can update records in both systems or in none of them >> transaction
    • Let's suppose that for some reason your last action the UpdateData fails for a given purchase
    • That would mean the database is not updated but the other subsystem did
    • Based on the purchase domain I assume that this inconsistency can cause problems
  • You could for example do a compensation action against the service to undo/rollback the change to heal the consistency across multiple subsystems
  • I would suggest read about SAGA pattern or Two/Three Phase Commits

Orchestration vs Choreography

  • Whenever you want to execute a sequence of actions then you can pipe them through:
    • choreography: Each and every action knows who is the next in the calling chain
      • Or in other words, they know how to interact with each other
    • orchestration: There is a an orchestrator which chains the actions after each other
      • Or in other words, they don't know how to interact with each other
  • You have chosen the choreography which made your program harder to understand IMHO
    • None of your methods return anything rather they are calling each other
    • As a reviewer/maintainer it is harder to create a mental model
  • If you would compose your actions as an orchestration
    • then it would be much easier to follow the data and execution flows
    • Here is a (pseudo) example
async Task ExecuteCoreAsync(CancellationToken token) { var purchaseRequests = await GetPurchaseRequests(token); var accessToken = await RetrieveAccessToken(token); var purchaseIds = await ProcessPurchaseRequests(accessToken, purchaseRequests, token); await UpdateStatusOfPurchaseRequests(purchaseIds, token); } 

Problem domain decomposition

  • We can see that you have tried to split up the problem domain into smaller chunks
    • My problem here is that they are not on the same level of granularity
      • Compare MakeRequestsToRemoteService and UpdateData
  • MakeRequestsToRemoteService has multiple responsibilities
    • Retrieving access token
    • Issuing requests against downstream system
    • Calling update on database records
  • If you would try to aim for smaller composable chunks
    • then it is much easier to create actions with single responsibility
  • BTW: based on the shared code fragment it seems like it is unnecessary to retrieve access token whenever you start to process a purchase request
    • IMHO it would be enough to retrieve only once

Distributed transaction

  • According to my understanding your code is the glue between two subsystems (a database and a service) >> distributed
  • I assume that you want to guarantee that either you can update records in both systems or in none of them >> transaction
    • Let's suppose that for some reason your last action the UpdateData fails for a given purchase
    • That would mean the database is not updated but the other subsystem is
    • Because of the purchase domain I assume that this inconsistency can cause problems
  • You could for example do a compensation action against the service to undo/rollback the change to heal the consistency across multiple subsystems
  • I would suggest read about SAGA pattern or Two/Three Phase Commit protocols
Source Link
Peter Csala
  • 10.8k
  • 1
  • 16
  • 36

Orchestration vs Choreography

  • Whenever you want to execute a sequence of actions then you can pipe them through:
    • choreography: Each and every action knows who is the next in the calling chain
      • Or in other words, they know how to interact with each other
    • orchestration: There is a an orchestrator which chains the actions after each other
      • Or in other words, they don't know how to interact with each other
  • You have chosen the choreography which made your program harder to understand IMHO
    • None of your methods return anything rather they are calling each other
    • As a reviewer/maintainer it is harder to create a mental model
  • If you would compose your actions as an orchestration
    • then it would be much easier to follow the data and execution flows
    • Here is a (pseudo) example
async Task ExecuteCoreAsync(CancellationToken token) { var purchaseRequests = await GetPurchaseRequests(token); var accessToken = await RetrieveAccessToken(token); var purchaseIds = await ProcessPurchaseRequests(accessToken, purchaseRequests, token); await UpdateStatusOfPurchaseRequests(purchaseIds, token); } 

Problem domain decomposition

  • We can see that you have tried to split up the problem domain into smaller chunks
    • My problem here is that they are not on the same level of granularity
      • Compare MakeRequestsToRemoteService and UpdateData
  • MakeRequestsToRemoteService has multiple responsibilities
    • Retrieving access token
    • Issuing requests against downstream system
    • Calling update on database records
  • If you would try to aim for smaller composable chunks
    • then it is much easier to create actions with single responsibility
  • BTW: based on the shared code fragment it seems like it is unnecessary to retrieve access token whenever you start to process a purchase request
    • IMHO it would be enough to retrieve only once

Distributed transaction

  • According to my understanding your code is the glue between two subsystems (a database and a service) >> distributed
  • I assume that you want to guarantee that either you can update records in both systems or in none of them >> transaction
    • Let's suppose that for some reason your last action the UpdateData fails for a given purchase
    • That would mean the database is not updated but the other subsystem did
    • Based on the purchase domain I assume that this inconsistency can cause problems
  • You could for example do a compensation action against the service to undo/rollback the change to heal the consistency across multiple subsystems
  • I would suggest read about SAGA pattern or Two/Three Phase Commits