First time i encounter Circular dependency
Table of contents
1. The problem
In the last semester while working on my Laravel project, i encountered a problem which led to a memory leak whenever i call an API that interacts with my OrderService
class:
class OrderService {
public function __construct(private MomoService $momoService, private VnPayService $vnpayService){}
}
In the above code, class OrderService
injects two dependencies MomoService
and VnPayService
by using constructor injection method (this is dependency innjection concept). Whenever i call OrderService
, Laravel will look in its Service Container
and find or create the instance of each MomoService
and VnPayService
. This process is called Inversion of control, i won't have to write something like MomoService ms = new MomoService()
. The VnPayService
looks like this:
class VnPayService {
public function __constructor(private OrderService $orderService){}
}
VnPayService
is bound to OrderService
. This is where the memory leak occured. My code creates a loop when OrderService
depends on VnPayService
and VnpayService
depends on OrderService
. The result is when my API calls OrderService
, OrderService
calls VnPayService
, VnPayService
calls OrderService
and BOOM my laptop freezes due to memory leak.
This problem is called Circular Dependency or Circular Reference. A circular dependency occurs when two or more components or classes depend on each other or depend on itself.
2. How do i fix the problem
Honestly, i currently don't have enough knowledge and experience for this kind of design pattern problem :"). So hopefully i will have the ability to solve this in the near future.
After i figured out what caused my laptop freeze, here are some thoughts that come first in my mind to solve the problem:
- Do i need to separate VnPay and Momo services from my
OrderService
?
Each VnPay and Momo service contains about 150 lines of code, so i think it is a good practice to make these two become independence. While this project is relatively small and just for university, i want myself to be ready for real world problems. Payment service is much more complicated in real life (i supposed).
But in the end, i choose to merge those services to one OrderService
because i don't have time : ).
- My plan
Encountering this problem has motivated me to dive into world of design patterns. I think my problem is too small to apply a pattern or any real world concepts for it. But it's worth to give it a try in design pattern field. I plan to gain a basic understanding of design pattern and do more projects, especially more complicated back-end services.
Remember that problems come first, not patterns come first. In my opinion, the best way to learn design pattern is just create more complex problems and then start refactoring to apply the appropriate patterns.
3. Nice topic to read
Vietnamese- A student is dealing with a circular dependency issue in his university project