Crafting Robust Services: My Journey to HNG Internship
Building a robust service involves writing code that is scalable and maintainable. Achieving this demands creativity, problem-solving, and a relentless pursuit of efficiency. While much of this responsibility lies with the developer, the environment you're exposed to and the people you collaborate with significantly influence your proficiency in these areas. This is why I have chosen to join the HNG Internship (https://hng.tech/internship), a 10-week remote program that trains technology enthusiasts in the following areas:
Design
Backend Development
Frontend Development
Video Marketing
Data Analysis
DevOps
Product Management
Testing
I would recommend anyone out there trying to kickstart a career in tech to apply. After joining the internship program, you can make the most important decision in your career by joining the premium network (https://hng.tech/premium), where you will network with more engineers and get job offers.
Before I delve into what I intend to get from the program, I would love to explain a software engineering problem I recently encountered. This makes me really excited about being a part of the HNG Internship because I will have the opportunity to face more real-world engineering problems and collaborate with like-minded individuals and mentors to provide robust solutions.
Circular Dependency Injection
I was recently working on an Identity Verification platform built with the Spring Boot framework when my IDE, IntelliJ IDEA, warned me of a circular dependency injection. Though this problem might be simple to solve for experienced engineers, it actually took me a while to understand what was going on and how to resolve it.
Circular dependency injection occurs when two or more beans in the Spring container depend on each other, creating a cycle that prevents the normal creation and injection process. While this explanation is standard, it doesn't convey to a beginner why this might be a problem.
I think a better way to explain this is to consider each component in the software (bean, as called in the Spring ecosystem) as a person. Then picture four people in a queue such that the fourth person needs an item from the third person, who in turn needs the item from the second person, who himself needs it from the first person. Just like in a real-world scenario, there will be confusion if the first person comes up with an excuse that he himself is actually depending on the last person in the queue for the same item. So where do we get it now? ๐ก๐ก Thus, when something similar is present in our software, it becomes an issue.
For the purpose of making this article brief and to simplify the concept of circular dependency injection and how to resolve it, I will not be using the actual code sample for the explanation. So let's say you are working on a project and you end up with two services using each other as shown below:
javaCopy code
@Service
public class ProductService {
private final CustomerService customerService;
public ProductService(CustomerService customerService) {
this.customerService = customerService;
}
}
@Service
public class CustomerService {
private final ProductService productService;
public CustomerService(ProductService productService) {
this.productService = productService;
}
}
In IntelliJ IDEA, this will display the following message in the terminal when you try to run it, indicating that there is a circular dependency injection:
plaintextCopy code
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
โโโโโโโ
| customerService defined in file [C:\\Users\\USER\\Documents\\Coding projects\\CircularDependency\\Circular-dependency\\target\\classes\\com\\example\\Circular_dependency\\CustomerService.class]
โ โ
| productService defined in file [C:\\Users\\USER\\Documents\\Coding projects\\CircularDependency\\Circular-dependency\\target\\classes\\com\\example\\Circular_dependency\\ProductService.class]
โโโโโโโ
How to Resolve Circular Dependency Injection
Whenever you encounter this problem, it is most likely a design issue, and thus the best approach is to refactor your code. While there are several ways to break the cycle, such as using the @Lazy
annotation, the Spring Boot official documentation recommends setter-based dependency injection.
"One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only."
This method involves using setter methods, which eliminates the need for dependencies to be satisfied at construction time.
@Service
public class ProductService {
private CustomerService customerService;
public ProductService() {}
public void setCustomerService( CustomerService customerService){
this.customerService = customerService;
}
}
@Service
public class CustomerService {
private ProductService productService;
public CustomerService() {}
public void setProductService(ProductService productService){
this.productService = productService;
}
}
Setter injection not only resolves the issue of circular dependencies but also improves the flexibility of the application's dependency management, allowing for dynamic modification of dependencies after construction if necessary. You can check out the source code here .
Now, imagine a program where you are constantly solving more complex real-world software engineering problems like the one described above. I am confident that any HNG Internship finalist knows what they are doing. Thus, I urge all recruiters to follow the link https://hng.tech/hire to hire elite talent for their next project.
By the end of this program, I intend to improve my technical and collaborative skills, learn new technologies, and network with more experienced engineers in the industry.
Thank you for your time, and I hope to see you in HNG12! ๐๐๐