python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

Circularly interrelated packages

Open Arseniy-Popov opened this issue 1 year ago • 1 comments

When using subcontainers to organize layers in an application, there likely won't be circular dependencies between them. However, with domains this is not the case.

@dataclass
class UserService:
    payments: "PaymentsService"

    def user_action(self):
        print("user action")
        self.payments.payment_action


@dataclass
class PaymentsService:
    users: UserService

    def payment_action(self):
        print("payment action")


class UserContainer(containers.DeclarativeContainer):
    payments = providers.DependenciesContainer()

    service = providers.Factory(UserService, payments=payments.service)


class PaymentContainer(containers.DeclarativeContainer):
    users = providers.DependenciesContainer()

    service = providers.Factory(PaymentsService, users=users.service)



class ApplicationContainer(containers.DeclarativeContainer):
    users = providers.Container(UserContainer, payments=???)
    payments = providers.Container(PaymentContainer, users=users)

What's there to do if in the outermost container I want to link packages with circular dependencies between them?

Arseniy-Popov avatar Nov 15 '23 04:11 Arseniy-Popov

I'm not the maintainer, but let me share my experience using this library...

One of the explicit benefits of containers.DeclarativeContainer is that it prevents circular dependencies. You end up with a tree of dependencies instead of a cyclical graph (spaghetti).

In our application, our Users service actually has no dependencies, so I'm wondering if you might restructure your application in this way.

If you need circular dependencies for some reason (we've run into this with libraries on occasion), using the @inject style of injection can work in conjunction with string identifiers.

philipbjorge avatar Dec 15 '23 16:12 philipbjorge