user4780495
user4780495

Reputation: 2912

Best design pattern for collection of objects

I have the following architecture:

         +-----------------+
         |   Collection    |
         |                 |
         |                 |
         |                 |
         |                 |
         +-----------------+
           |        ^
           |        |
  Create() |        |
           |        |
           v        | GetItem(B)
+------------+      |
|   Item A   |      |
|            |      |
|            +------+
|            |
+------------+

A class managing a collection of items, creates items. And these items may need other items from the collection.

The actual code is in python, and for now the Collection passes itself as a parameter to the created Item. As I see it, it is a bad practice. The only improvement I can see it to pass the few functions of Collection needed by the Item, instead of the whole instance.

For example:

class Collection:
    GetItem(self, id):
        ...
    CreateItem(self, id):
        item = Item(id, self) # <-- pass self
        ...

class Item:
    __init__(self, id, col):
        ...
        col.GetItem(...)

How can I avoid passing self as parameter? Or is it a common usage in Python?

More detailed example

 ┌──────┐            ┌──────────┐           ┌─────┐                              
 │Client│            │Collection│           │ItemA│                              
 └──┬───┘            └────┬─────┘           └──┬──┘                              
    │ UpdateItem(A, param)│                    │                                 
    │ ────────────────────>                    │                                 
    │                     │                    │                                 
    │                     │ Update(param, self)│  ╔═════════════════════════════╗
    │                     │ ───────────────────>  ║Need to update linked ItemB ░║
    │                     │                    │  ╚═════════════════════════════╝
    │                     │     GetItem(B)     │                                 
    │                     │ <───────────────────                                 
    │                     │                    │                                 
    │                     │        ItemB       │                                 
    │                     │  ─ ─ ─ ─ ─ ─ ─ ─ ─ >                                 
    │                     │                    │                                 
    │                     │                    │────┐                            
    │                     │                    │    │ UpdateItemB()              
    │                     │                    │<───┘                            
 ┌──┴───┐            ┌────┴─────┐           ┌──┴──┐                              
 │Client│            │Collection│           │ItemA│                              
 └──────┘            └──────────┘           └─────┘                              

Upvotes: 5

Views: 3384

Answers (2)

GhostCat
GhostCat

Reputation: 140467

A non-answer: given the current level of detail, recommending a specific pattern is the wrong approach! Coming from the DDD perspective, I am wondering if you should rather step back and should look at your model at a whole.

It looks like your are mixing up at least two responsibilities within your "collection" class:

  • knowledge to create objects
  • and to update them

DDD suggests to have factories that are responsible for creating objects.

And instead of thinking of a collection that provides access to all kinds of entries, you might rather define aggregates, and identify their root objects. Because you want to make sure that there is only one defined "path" to get to certain information.

In other words: you should strive to design a model that provides helpful abstractions for the real world elements you are dealing with. And your current implementation feels like it is something that evolved out of some technical ideas how to organize things. Thus the recommendation: step back and look at big picture.

Upvotes: 1

Jonathan Oron
Jonathan Oron

Reputation: 34

Seems like a classic place to user the composite pattern: https://sourcemaking.com/design_patterns/composite

Each instance can be a collection or an item and your client can use them interchangeably.

Upvotes: 0

Related Questions