« Dependency injection » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
(2 versions intermédiaires par le même utilisateur non affichées)
Ligne 5 : Ligne 5 :
Les dépendances ne sont plus exprimées de manière statique dans le code mais déterminées dynamiquement à l'exécution.<br />
Les dépendances ne sont plus exprimées de manière statique dans le code mais déterminées dynamiquement à l'exécution.<br />
The DI delegates the creation of a service that an object consumes outside of this object.
The DI delegates the creation of a service that an object consumes outside of this object.
* classes are loosely coupled
* classes follow the single responsibility principle
* it becomes easier to mock the dependencies so to create unit tests
* by relying on abstractions instead of implementations, code can easily vary a given implementation
== [https://betterprogramming.pub/the-6-benefits-of-dependency-injection-7802b207ec69 Benefits of Dependency Injection] ==
{| class="wikitable wtp"
|-
| Maintainability || classes are loosely coupled and follow the single responsibility principle
|-
| Testability || easier to mock the dependencies so to create unit tests
|-
| Readability || single responsibility principle
|-
| Flexibility || easier to switch from an implementation to another
|}


= Exemple =
= Exemple =
Ligne 56 : Ligne 72 :
     }
     }
}
}
</kode>
== Reduce the number of parameter in the ctor by injecting a dependency object ==
<filebox fn='MyViewModel.cs'>
public MyViewModel(IMyViewModelDependencies dependencies)
{
    this.dependencies = dependencies;
    this.myService = dependencies.MyService;
}
</filebox>
<filebox fn='IMyViewModelDependencies.cs'>
internal interface IMyViewModelDependencies
{
    IMyService MyService { get; }
}
</filebox>
<filebox fn='MyViewModelDependencies.cs'>
internal sealed class MyViewModelDependencies : IMyViewModelDependencies
{
    public MyViewModelDependencies(IServiceLocator serviceLocator)
    {
        this.MyService = serviceLocator.GetInstance<IMyService>();
    }
    public IMyService MyService { get; }
}
</filebox>
<filebox fn='ServiceCollectionExtensions.cs'>
internal static class ServiceCollectionExtensions
{
    public static void AddViewModelDependencies(this IServiceCollection @this)
    {
        @this.AddTransient<IMyService, MyService>();
    }
}
</filebox>
<kode lang='cs'>
this.services.AddViewModelDependencies();
</kode>
</kode>



Version du 12 avril 2021 à 18:35

Définition

Implémente le principe de l'Inversion of Control.
Permet de découpler les dépendances entre objets.
Les dépendances ne sont plus exprimées de manière statique dans le code mais déterminées dynamiquement à l'exécution.
The DI delegates the creation of a service that an object consumes outside of this object.

  • classes are loosely coupled
  • classes follow the single responsibility principle
  • it becomes easier to mock the dependencies so to create unit tests
  • by relying on abstractions instead of implementations, code can easily vary a given implementation

Benefits of Dependency Injection

Maintainability classes are loosely coupled and follow the single responsibility principle
Testability easier to mock the dependencies so to create unit tests
Readability single responsibility principle
Flexibility easier to switch from an implementation to another

Exemple

Le MainViewModel veut utiliser le DataService mais ne veut pas:

  • de lien statique avec la classe DataService
  • prendre en charge sa construction

Dépendance entre MainViewModel et DataService

  • lien statique avec la classe DataService
  • prend en charge la construction de DataService
Csharp.svg
class MainViewModel
{
    private DataService _dataService;
    public MainViewModel()
    {
        _dataService = new DataService();
    }
}

Création d'une interface

  • plus de lien statique avec la classe DataService grâce à l'interface IDataService
  • prend en charge la construction de DataService
Csharp.svg
interface IDataService { }

class DataService : IDataService { }

class MainViewModel
{
    private IDataService _dataService;
    public MainViewModel()
    {
        _dataService = new DataService();
    }
}

Injection du service

  • plus de lien statique avec la classe DataService grâce à l'interface IDataService
  • un objet DataService est injecté dans le constructeur de MainViewModel
Csharp.svg
class MainViewModel
{
    private IDataService _dataService;
    // la création du service se fait en dehors de la classe qui l'utilise
    public MainViewModel(IDataService dataService)
    {
        _dataService = dataService;
    }
}

Reduce the number of parameter in the ctor by injecting a dependency object

MyViewModel.cs
public MyViewModel(IMyViewModelDependencies dependencies)
{
    this.dependencies = dependencies;
    this.myService = dependencies.MyService;
}
IMyViewModelDependencies.cs
internal interface IMyViewModelDependencies
{
    IMyService MyService { get; }
}
MyViewModelDependencies.cs
internal sealed class MyViewModelDependencies : IMyViewModelDependencies
{
    public MyViewModelDependencies(IServiceLocator serviceLocator)
    {
        this.MyService = serviceLocator.GetInstance<IMyService>();
    }

    public IMyService MyService { get; }
}
ServiceCollectionExtensions.cs
internal static class ServiceCollectionExtensions
{
    public static void AddViewModelDependencies(this IServiceCollection @this)
    {
        @this.AddTransient<IMyService, MyService>();
    }
}
Cs.svg
this.services.AddViewModelDependencies();

IoC frameworks