I'm facing a design problem where i want to model the very same physical object in two different bounded context.

In order to describe my problem as precisly as possible, and even tho i'm aware this is only an implementation detail, i will start with my Event Sourcing mechanism. 

My events storage mechanism
---------------------------

*the following is widely inspired by Greg Young's CQRS document <https://cqrs.wordpress.com/documents/> (watch out for the PDF "building an Event Storage" section).*

I have **2 tables**, one called `Aggregates` and another one called `Events` (Note the plural form as these are tables, not objects!) which look like this :

### *Aggregates* Table

All my aggregates are stored in this table ; it has 3 columns (SO doesnt support the md table formatting so, sorry, i'll go for a list):

* `AggregateId` : basically this table's primary key. I'm using a Guid, as all my aggregates are using one.
	+ `AggregateType` : the fully qualified Aggregate's name.
	+ `CurrentVersion` : the current aggregate version. An integer that gets incremented every time an event get stored.

### *Events* Table

Every domain event issued by any Aggregates get stored in there ; it has got 5 columns :

* `AggregateId` : the foreign key to the aggregates' table.
* `SerializedEvent` : the domain event as it was issued by the aggregate but in a serialized form (eg. json)
* `Version` : An integer that gets incremented (for each given aggregate) every time an event get stored.
* `EventDate` : a datetime
* `UserName` : the user that issued the event's producing command

Example of a domain with 2 bounded contexts
-------------------------------------------

Now let's consider a merchant :

* A merchant **buys products** (that's the job of the purchase department, aka. supply chain department)
* A merchant **sells products** (that's the job of the sales department, in our case let say it's done on a website)

**The purchase department will consider a Product as following :**

* the product is purchasable by one or many suppliers
* the product has a purchase pricing grid, probably different from a supplier to another
* the product is stored in one or many warehouse where it is available (or not) in a given quantity
* the product is therefore subject to inventory

**On the other hand, the sales department will consider the product in a different way :**

* the product has a sales price (and maybe even a sales pricing grid)
* the product has guarantees, sales conditions...
* in an e-commerce context, it would even have publication's related attributes (like pictures, categories, descriptions, user vote and comments...) (so probably )

> 
> that sounds like 2 distinct bounded contexts, right?
> 
> 
> 

*Actually, Product, seen from the website point of view with its pictures, categories and votes attributes, sound to me like a third bounded context, but let's not debate about it for the example's sake...*

Let's now complete this domain example with the domain expert specification saying :

* "A product must have a name"
* "The supply chain department is the one responsible for adding products to the system"
* "As a consequence, the sales department NEVER adds products to the system but instead, it receives a NewProductAdded notification, informing him a new product is available for sales "
* (and probably some other rules like Sales Dptmt can only publish a product on the website once the supply chain Dpt. said this product was available in the ware house. )

And now i think we have a valid use case.

*NB : while i'm facing a very similar problem in a real project, this use case is purely abstract and inspired of this Codemotion conference slide <http://goo.gl/lMWSFZ>.*

1 product aggregate per BC => 2 distinct Product AR
---------------------------------------------------

So ok, in traditionnal design, I'd probably end up with a big `Product Entity` that would contain attributes related as much to the Sales point of view as to the supply point of view.

But I want to go for a DDD approach, and DDD says that I should protect my invariants within a bounded context.
So, the domain model of a product is different according to wether i'm within the Sales or in the Supply Bounded Context.

As far as i understood it, i should therefore have 2 entities :

* a Product Entity in the Sales BC
* and another Product Entity in the supply BC...

Still for the example's sake, we'll admit that those 2 Product entities were decided to be promoted to the range of aggregate root in their respective BC.

so to sum up we have :

> 
> 2 bounded context
> 
> 
> 1 product Aggregate per bounded context
> 
> 
> 

**But this is the very same product right?**

Designing the `Product AR` in the *Supply Chain BC*
---------------------------------------------------

*The following is widely inspired by :*

* *@codescribler's blog post : <http://goo.gl/UgYRqq>*
* *M. Verraes' conference : <http://goo.gl/iVrdZu>*

First, let's have a look at my abstract AggregateRoot class :

```
  namespace DomainModel/WriteSide;

  abstract class AggregateRoot
  {
    protected $lastRecordedEvents = [];

    protected function recordThat(DomainEvent $event)
    {
      $this->latestRecordedEvents[]=$event;
      $this->apply($event);
    }

    protected function apply(DomainEvent $event)
    {
      $method = 'apply'.get_class($event);
      $this->$method($event);
    }

    public function getUncommittedEvents()
    {
      return $this->lastestRecordedEvents;
    }

    public function markEventsAsCommitted()
    {
      $this->lastestRecordedEvents = [];
    }

    public static function reconstituteFrom(AggregateHistory $history)
    {
      foreach($history as $event) {
        $this->apply($event);
      }
      return $this;

    abstract public function getAggregateId();

  }

```

Basically, this class holds the ES mechanism.

Now let's have a look at its implementation for Product in the Supply Chain BC :

```
namespace DomainModel/WriteSide/SupplyChain;
use DomainModel/WriteSide/AggregateRoot as BaseAggregate;

Class Product extends BaseAggregate
{
  private $productId;
  private $productName;
  //some other attributes related to the supply chain BC...

  public function getAggregateId()
  {
    return $this->productId;
  }

  private function __construct(ProductId $productId, $productName)
  {
    //private constructor allowing factory methods
  }

  public static function AddToCatalog(AddProductToCatalogCommand $command)
  {
    //some invariants protection stuff
    $this->recordThat(new ProductWasAddedToCatalog($command->productId));
  }

  private function applyProductWasAddedToCatalog(DomainEvent $event)
  {
    $newProduct = new Product($event->productId);
    return $newProduct;
  }

  //more methods there...
}

```

The flow
--------

*The following is widely inspired by @codescribler's blog post : <http://goo.gl/yuIjzf>*

1. The UI (a user from the supply chain dpt.) has sent an `AddProductToCatalogCommand(/*...*/)` via the service layer (aka. command bus forwarding the command to its handler),
2. the handler has prepared the Product Aggregate (in other words, brought it to its current state by applying all previous events to it) and passed him the command over.
3. Given no exception was raised (in other word, the Aggregate handled the command properly), **we're now at the point where the handler is requesting the changes the aggregate just applied to itself.**

**The handler now persists the changes** in the database :

	* it inserts a new row in the `Aggregates` table :
	* AggregateId = ProductId
	* AggregateType = /some/namespace/Product
	* AggregateVersion = 0
	* it inserts a new row in `Events` table :
	* AggregateId = ProductId
	* Event = `ProductWasAddedToCatalog($productId)` (in a serialized form off course)
	* version = 0
4. Persitence went well, so **the handler forwards the event to the service layer** (aka. event bus forwarding the event to its handler**s**) for its subscribers to do their jobs.

> 
> here comes my problem!
> 
> 
> 

One of these subscribers is an event handler issuing a command for the Sales BC Product Aggregates.

```
namespace DomainModel/WriteSide/Sales;
use DomainModel/WriteSide/AggregateRoot as BaseAggregate;

Class Product extends BaseAggregate
{
  private $productId;
  //some other attributes related to the Sales BC, like sales price, guarantees...

  public static function AddAutomaticallyProductToCatalogSinceSupplyChainAddedIt(UpdateSalesCatalogCommand $command)
  {
    // some invariants' protection code here

    $this->recordThat(new ProductWasAutomaticallyAddedToSalesCatalog($command->productId));

  }
}

```

> 
> So now, what is my *$command->productId*?
> 
> 
> 

As Jimmy Bogard well summed it up in <http://goo.gl/QHBkSr> : *"Each Aggregate has a Root Entity [...] The root Entity has **global identity** and is ultimately responsible for checking invariants"*

Global identity is the key word.

So in my use case, **we have 2 disctinct Aggregates and we therefore should have 2 distincts AggregateRoot's Ids**.

It's even more obvious under the light of the event storage mechanism described above because if both ARs had the same Id, one would receive some events of the other while processing its `public static function reconstituteFrom(AggregateHistory $history)`

> 
> So 2 distinct Ids. But still it's the very same product right? How do i make that explicit?
> 
> 
> 

Possible solutions
------------------

After investigation, i come up with 3 possibles solution. I hope someone will be able to guide me into the right one...

### Solution 1 : Holding a reference

The sales BC Product Aggregate hold a reference to the supply chain Product Aggregate.

this would look like this :

```
namespace DomainModel/WriteSide/Sales;
use DomainModel/WriteSide/AggregateRoot as BaseAggregate;

Class Product extends BaseAggregate
{
  private $productId;
  private $supplyChainProductId;   //the reference to the supply chain BC Product AR...

  public function getAggregateId()
  {
    return $this->productId;
  }

  //more methods there...
}

```

### Solution 2 : Using a composite primarey key in the Event Storage

while i currently use the `AggregateId` column as primary key, i could use both `AggregateId` and `AggregateType`.

Since that would allow me to have both Product AR having the same ProductId, this looks like a smell to me ... Alone because of the concept of AR global identity would be ruined...

### Solution 3 : using a product *sub-entity* in both AR

Still from Jimmy Bogard's <http://goo.gl/QHBkSr>, " Entities inside the boundary have local identity, unique only within the Aggregate."

So i could model the sales BC Product Aggregate like following :

```
namespace DomainModel/WriteSide/Sales;
use DomainModel/WriteSide/AggregateRoot as BaseAggregate;

// **here i'd introduce my sub-entity**
use DomainModel/Sales/Product/Entities/Product as ProductEntity;

Class Product extends BaseAggregate
{
  private $_Id;
  private $product;   //holds a ProductEntity instance

  public function getAggregateId()
  {
    return $this->_Id;
  }

  public function getProductId()
  {
    return $this->product->getProductId();
  }

  //more methods there...
}

```

**While this would allow to keep both AR having the same productId, this doesnt really make sense to me since the only way to get an aggregate is by its AR's Id** (and not by the Id of any of its sub-entities).

Tho we could imagine having a sort of mapper on the Query side :

```
namespace DomainModel/QuerySide;

Class ProductMapping
{
  private $productId;
  private $salesAggregateId;
  private $supplyChainAggregateId;
  private $product;   //holds a ProductEntity instance

  public function getSalesAggregateId()
  {
    return $this->salesAggregateId;
  }

  public function getSupplyChainAggregateId()
  {
    return $this->supplyChainAggregateId();
  }

}

Class ProductMappingRepository
{

  public function findByproductId($productId)
  {
    //return the ProductMapping object
  }

  public function addFromEvent(DomainEvent $event)
  {
    //this repository is an event subscriber....
  }

}

```

Beside this ProductMapper, the query side would then only know about the ProductId. Seems all done ...
but this again doesn't look right to me. Can't really say why, it just doesn't !...

Conclusion
----------

This is a fake use case, and as such, it's probably debatable whether the 2 bounded contexts described above shoud be modelled as such or not.

But i hope i made my point clear, namely how to identify the very same physical object (in that use case, a Product) in 2 different BCs.

> 
> **Thx in advance for ur help!!!**
> 
> 
> 

*NB . While my first Post contained many linguistic misuses and therefore left out many opened doors to interpretation, leading to misunderstanding of the problem i'm trying to solve, i choosed to completly re-edit it. Tho for future reader to understand the previous replies and comments, i leave the first post version below*

==================================================================
==================================================================

### The question as asked Apr 18 at 11:51

let's start straight with the context (taken from this Codemotion conference slide <http://goo.gl/lMWSFZ>).

Domain expert is a merchant, he buys, sales and shifts Products. He's got :

* an e-commerce web site for sales purpose
* a supply chain department responsible for purchasing purpose
* a logistics department responsible for the shipping

So, we may consider having one Product Aggregate for each bounded context :

* **A Product Aggregate for for the sales context** that will hold properties like sales price, evtl. discount, customer friendly description, pictures, maybe some categories it belongs too etc..
* **A Product Aggregate for the purchase context** that will hold references to the suppliers and their purchasing conditions (eg. pricing by quantity, availabilities etc...)
* **An Item Aggregate for the logistics** context holding properties like size and weight (note that in this context, the aggregate's name is Item and not Product as the logistic department isnt concerned about wether it's a product or a packaging or a palett)

Domain expert also says :

* "the purchase department is the one that insert new Products to the system"
* "once the purchase department has inserted a new product in the system, it must be available for the others"

> 
> Now my question is simple :
> 
> 
> how do I reference each aggregate to each other, given it's in the end
>  "the very same Product"?
> 
> 
> Should Sales and Logisitics Aggregates contains an PurchasedProductId
>  ? I've been told to be very carefull with external references but ...
>  how else?
> 
> 
> 

**EDIT :**

this question must be seen under the light of an Events Storing pattern, where :

* every Aggregates get stored with its unique Id in an Aggregates Table (where rows are AggregateId, AggregateType, CurrentVersion),
* this unique Id get used as foreign key in an Events Table (that stores all the events that happened to the AR in 3 column : AggregateId, SerializedEvent, Version)

So, if the same ProductId should be used as @Plalx is suggesting it in its reply, the question becomes :

> 
> how can you have 2 Aggregates using the same Id whereas, by definition, an Aggregate is a self-containing Entity and, still by definition, an Entity must have a unique Id?
> 
> 
>