Search code examples
domain-driven-designddd-repositoriesclean-architecturehexagonal-architecture

Can a DDD repository be stateful?


I’m designing a shipping application and trying to use Clean Architecture. I’m trying to figure out where to hold state of a Shipment object so that I don’t have to re-instantiate a new object every time a user clicks on a button in the UI. Here is the flow.

  1. User enters a delivery number in the UI
  2. UI Controller handles the UI event and instantiates an instance of the Use Case Interactor a. A repository instance in passed into the constructor of the Use Case Interactor
  3. The Use Case interactor instantiates an instance of Shipment by calling a Factory(e.g. CREATE_BY_DELIVERY). The factory calls the Repository to collect the data from the database.
  4. Delivery data is populated on the UI
  5. User then clicks a Rate Quote button
  6. UI Controller handles the button click event and calls the RATE_QUOTE method of the Use Case Interactor a. Does the Use Case Interactor need to call the Shipment factory again as in step #3 or can the Use Case Interactor get an instance of the Shipment object that was already created in step #3?
  7. Rates are displayed on the UI
  8. User then clicks the PROCESS shipment button
  9. UI Controller handles the button click event and calls the PROCESS_SHIPMENT method of the Use Case Interactor a. Does the Use Case Interactor need to call the Shipment factory again as in step #3 or can the Use Case Interactor get an instance of the Shipment object that was already created in step #3?

Should the state of the shipment object be an instance variable on the UI Controller, Use Case Interactor or the Repository? Ideally, I'd like to save it somewhere so I don't need to keep creating a new object every time a user clicks a button on the UI.

Thank you in advance!


Solution

  • Can a DDD repository be stateful?

    Yes, absolutely -- that was part of the point in the original description

    A REPOSITORY represents all objects of a certain type as a conceptual set (usually emulated). It acts like a collection, except with more elaborate querying capability.... For each type of object that needs global access, create an object that can provide the illusion of an in memory collection of all objects of that type.

    In other words, the point is to separate the application component from the implementation details of the collection. As far as the app can tell, the repository can be implemented as a stateful, in memory, key/value store.

    Ideally, I'd like to save it somewhere so I don't need to keep creating a new object every time a user clicks a button on the UI.

    As a matter of keeping your code easy to understand, you should probably just create a new object every time, and deal with the complications of caching only when you have a clear business case for it.

    That said, there's absolutely no reason that the implementation of the repository can't include a cache of recently used objects. You just have to be willing to invest in the cache invalidation strategy.

    Remember, Phil Karlton taught us years ago

    There are only two hard things in Computer Science: cache invalidation and naming things.