pam
pam

Reputation: 676

Python: communication between classes and design patterns

I have 4 classes that handle logic for a large project. I have Product that clients buy and i have to bill them. Nevertheless the price of those products is varying greatly according to many variables. I have create a class PriceGenerator that handles the pricing of the products, an Inventory class that checks if the 'Product' is still available and a 'Cart' class that contains a list of 'Product' for a total bill if the client buys many 'Product'

Class PriceGenerator:
    def get_price(*args)

Class Product:
    def prod_bill()

Class Inventory:
    def get_inventory(*args)

Class Cart:
    self.list_product = [product1, product2, product3,...]
    def cart_bill(*args)

my first option:

pg = PriceGenerator()
pd = Product()
inv = Inventory()
cart = Cart()

I could pass the PriceGenerator and Inventory as argument of Cart

def cart_bill(pg, inv, amount):
    bill = 0
    for prod in self.list_product:
        px = prod.prod_bill(pg)
        bill_p = px * min(amount, inv.get_inventory(product_args))
        bill += bill_p

Obviously as the number of methods grows in Product, it becomes very complicated to keep track of all the arguments you have to pass. you pass PriceGenerator and Inventory to Cart that are then passed to the product prod.prod_bill(pg), all those nested dependencies are very cumbersome to pass through all the objects and it makes the code much more complicated.

I could call pg and inv without passing it as arguments for example in Product as a global variable

def produce_bill(self):
    price = pg.get_price(product_args)
    inventory = inv.get_inventory(product_args)

but i really don't like not knowing what are the class/arguments required, necessary for the method.

As the project grows, what design pattern would you suggest?

Upvotes: 1

Views: 819

Answers (1)

soulmerge
soulmerge

Reputation: 75714

I would recommend implementing a context object containing anything that is relevant to your process. I am assuming this is about placing an e-commerce order in the following example:

class OrderContext:
    price_calculator: PriceCalculator
    inventory: Inventory
    cart: Cart

Now you can pass this object around for all operations that are involved in your process:

cart.add_product(context, product, amount)

This allows you to add/remove further bits to the context without modifying the signature of all your functions. The drawback is that this has the potential to massively increase the number of dependencies within your application (depending on how disciplined the programmers in your team are).

Upvotes: 1

Related Questions