Learn
Best Practices
Dependency Injection

Prefer Dependency Injection over Explicit Import

Using explicit imports can lead to tightly coupled and less maintainable code, as the importing module becomes directly dependent on the imported module. This strong dependency can obfuscate the interactions between components, making them less modular and harder to test, understand, and refactor.

Dependency Injection allows for the inversion of control, wherein the dependencies of a component are 'injected' by an external entity, rather than being created by the component itself. This approach promotes decoupling between components, enhancing code maintainability, testability, and readability.

How to Implement

// Port
trait Talk {
    fn talk(&self) -> String;
}
 
// Service
struct SayHello {
    name: String,
}
 
impl Talk for SayHello {
    fn talk(&self) -> String {
        format!("Hello {}", self.name)
    }
}
 
// UseCase
struct UseCase {}
 
impl UseCase {
    fn handle<R>(&self, requirement: R) -> String
    where
        R: Talk,
    {
        requirement.talk()
    }
}
 
// Program
fn main() {
    let use_case = UseCase {};
    let service = SayHello {
        name: "World".to_string(),
    };
    let result = use_case.handle(service);
    println!("{}", result);
}