I understand well why and how to use a repository and the same applies to query objects, they all seem simple to understand as long as you need, for instance, objects that mirror exactly what is in the database.
But I can't seem to get my head around where exactly to fit the objects for a very specific structure I'm building right now.
I have products and categories, and they all have their repository.
My categories exist within a self-referencing parent-child structure.
I have products that belong to a category that don't have child categories.
Now I need to pull this data to put together a menu which will be like this:
Data:
- Kitchen (category)
- Cutlery (category)
- Knives (category)
- 3-piece knives set (product)
- Spoons (category)
- 3-piece spoons set (product)
- Appliances
- Coffee-Making-Machines (category)
- Nespresso Machine (product)
- Espresso Machine (product
- Blenders (category)
- Smoothie Blender (product)
- Coffee-Making-Machines (category)
- Knives (category)
- Cutlery (category)
Then I need a menu, which will be like this:
- Kitchen (this will be a link to see all its child categories)
- 3-piece knives set (this will a link directly to the product page)
- Nespresso Machine
- Smoothie Blender
- Another Category
- Another product 1
- Another product 2
- Another product 3
This will be a list of all top level categories in which the vendor has products in our marketplace, with a randomly selected list of products that are under that top level category regardless of the category level.
All fine, I got all that working. Now I'm just trying to understand where does this kind of structure fit in an architecture which has repositories that basically contain one object per table.
How do I match my repositories, which mirrors raw data into a totally different business object?
If someone could point me to a good article that tackle this problem, it would be great.
Repository pattern emerges in the context of DDD, and the best book to read on that would be the original Domain-Driven Design: Tackling Complexity in the Heart of Software
One of the things that Evans keeps saying over and over is that all of the concepts of the domain must be explicit.
What does your menu represent? Does it have a name in the domain?
Lets say it does, and it is the concept of "weekly promoted products", then you could make this concept explicit - and introduce a separate class for that, with a separate repository, that could read data from products table, and from categories table to come up with the list of promoted products.
Please note that according to Evans our domain and persistence models do not have to match, and we don't need to have a repository per domain object (specifically, we should only have repositories for aggregate roots, and references all other entities should be obtained by traversing the association from the aggregate root)
Alternatively, in a design, somewhat departed from DDD, you could place the selection of those promoted products in the product repository, pre-load the categories and just have a TopCategory calculation property on a product
Please note, that if the new entity "promoted products" is purely virtual, and you are only planning to do read operations, without mutating its state, then it makes a lot of sense to apply Command Query Responsibility Seggregation, and have a separate read model for "promoted products" outside of your main domain model.