مهدی خانزادی
۲۷ مرداد ۱۴۰۵
The container is the warehouse of your application's services; the provider decides what goes into it and when. This part covers both patterns — how a container resolves a dependency graph on demand, how a provider organizes register, boot, and shutdown, and how danceable/container and danceable/provider split that work.
In this part we introduce the service container and the service provider — for dependency management and service lifecycle management.
One of the important patterns in designing large software is managing dependencies and managing the lifecycle of services. In the Danceable ecosystem this responsibility falls to two packages, container and provider, which together give you a simple, flexible, extensible structure for managing an application's services.
A service container is a design pattern responsible for managing an application's dependencies. Instead of every part of the program building the objects it needs, it asks the container to supply them.
Suppose a UserService needs a UserRepository to do its work, and UserRepository in turn depends on Database. Without a service container, you might have code like this:
On small projects this causes no trouble, but the more objects there are, the more complicated building and managing dependencies becomes.
With a service container, we register how each part is built just once:
Then whenever we need UserService, we simply get it from the container:
The container itself handles these steps:
UserService has already been built.UserRepository.UserRepository, it creates Database if needed.UserService and returns it.So we only place each part into the container, and the container works out for itself how to supply the dependencies.
These two concepts are often confused.
The danceable/container package plays exactly this role: a central place to register, build, and manage all of an application's dependencies.
A service provider is a concept used to organize the application's bootstrap and shutdown process.
If the service container is the warehouse of the application's services, the service provider is responsible for filling that warehouse and managing the lifecycle of those services.
Put simply:
Suppose your application uses these services:
With no service provider, all the code for registering and starting these services ends up in main.go:
As the project grows, main.go turns into the home of every startup operation and becomes hard to maintain. A service provider takes that responsibility out of main.go.
A service provider usually has three main responsibilities:
Every service provider goes through three main stages over the life of the program:
Suppose your project consists of several independent parts:
Each provider is responsible only for its own part. For example:
DatabaseProvider manages only the database.RedisProvider manages only Redis.LoggerProvider manages only the logger.Responsibilities are therefore separated, and adding or removing a service has little effect on the rest of the application.
The danceable/provider package plays the service provider role: it takes on managing the lifecycle of the application's services, determining which services are registered in the container at runtime, what work is done to prepare and start them, and how the resources they used are released and cleaned up when the program ends.