I'm learning about Dependency Inversion principle in Java, and the definition is:
- High-level modules should not depend upon low-level modules; they should depend on abstractions. 2) Abstractions should not depend upon details; details should depend upon abstractions.
And I have a piece of code from a REST API implementation and I want to know if this code represents an example of Dependency Inversion.
Rest Controller:
@RestController
@RequestMapping("/api")
public class EmployeeRestController {
private EmployeeService employeeService;
public EmployeeRestController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
@GetMapping("/employees")
public List<Employee> findAll() {
return employeeService.findAll();
}
...
}
Service Interface:
public interface EmployeeService {
public List<Employee> findAll();
public Employee findById(int theId);
...
}
Service Implementation:
@Service
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDAO employeeDAO;
@Autowired
public EmployeeServiceImpl(EmployeeDAO employeeDAO) {
this.employeeDAO = employeeDAO;
}
@Override
@Transactional
public List<Employee> findAll() {
return employeeDAO.findAll();
}
...
}
Entity:
@Entity
@Table(name="employee")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="first_name")
private String firstName;
...
}
So, I want to ask you if this code represents an example of Dependency Inversion principle, or it represents just the Dependency Injection design pattern?
For me, the controller class represents the high-level module and the service implementation represents the low-level module, and the high-level module depends on the abstractions because there is the EmployeeService
interface used in the EmployeeRestController
. And also the low-level module depends on abstractions because EmployeeServiceImpl implements EmployeeService
. Is this true?
But what is the difference between Dependency Inversion and Dependency Injection in this example? The fact that I declare private EmployeeService employeeService;
in the EmployeeRestController
represents Dependency Inversion. So if I declare directly the class EmployeeServiceImpl
in the EmployeeRestController
I don't have Dependency Inversion principle. And the fact that I inject the implementation of the EmployeeService
at runtime in the constructor represents Dependency Injection. Is that correctly?
But in the Service interface I'm using the Employee which is a class. So it means that in that case abstraction depends on details. So the second part of the Dependency Inversion principle is not satisfied. And because of that I don't have Dependency Inversion. Please tell me if it's true? Thank you!
Just Draw on the paper and you will get the idea
1.lets say you put the controller and Service in the package A, and you put the ServiceImpl in package B, in this case package B depends on package A, since service Impl refers to Service, and Service is in package A.
Using injection you are able to have service impl object in the controller but notice that controller does not know about impl(A does not know about B)
2.if there was no injection, the only way the controller could have service impl object is by referring to the impl class(in this case A knows about B which is bad )
so if we say that Package A is abstraction and package B is detail ,in the 1 point B depends on A (which is good)which means that detail depends on abstraction
But in the second point, A knows about B which means Abstraction depends on detail(not good)
So we achieved dependency inversion using injection