L'inversion de dédependance facile(et pas chère)

아, 독립적인 역전, 봐라, 이것은 종잡을 수 없는 파리, 공평한 지나가는 사람이다.특히 모바일 어플리케이션.Les arguments sont toujours Les mêmes:
  • Ça ajute trop de complexité
  • Ça bouffe des Resources et plombe les Performance
  • n'en a pas besoin de toute fa
  • Les frameworks c'est le mal absulu
  • Tu peux m'expliquer l'inversion de dépendance ?
    Fastoche, tu ouvres le gestionnaire de package nuget et tu installes AutoFac


    Et si on trouvait un moyen simple,efficace Et sans framework d'inverser les dépendences?

    반전 et 주입 의존


    Le but ici n'est pas de proposer un cours complett sur les principes d'inversion et d'injection de dédependences mais juste de présenter une astuce rapide,facile et pas chère pour effectuer une inversion de dependences avoiráaucun framework.
    Si vous ne connaisez pas ces principes,je vous inviteávous rendre sur votre moteur de recherche préféréet d'y saisir les mots clés suivants(pas tous en même temps,hein!):inversion de dépendance / injection de dépendance / dependency inversion / dependency injection / constructor injection / ioc di .
    Vous verrez qu'assez souvent cela Vous ramèneál'un ou l'autre des frameworksála mode.Et dans les cas les plus complements,c'est related de ne pas réinventer la roue.Mais dans une 응용 프로그램 이동판은 souvent besoin dequelque에서 de beaucoup에 간단한 sans'encomber d'un 프레임워크 ou d'une biblioth èque suppl é mentaire를 선택했습니다.

    Pourquoi une inversion de controlôle?


    Sans m'tendre sur le sujet,le but principal de l'inversion de contrôle est de ne pas laisser une classe dépendre d'autres classes.Elle ne doit dépendre quede leurs abstractions.
    L'application de ce principe a des conéquence assez variées mais qui vont toutes dans le sens d'un code plus propre et mieux structuré:

  • 존중원칙responsabilité unique: 추상류, 책임류, 내용류

  • Découplage:les classes ne sont pas liées entre elles

  • 모듈화: 비류 n'tant pas liée á une implementation particuli ère de ses dé dependentials,celle ciest facility 교환 가능.Une même classe pourra,par example,lire les données dans Une base Sql,un fichier json ou xml en fonction de l'implementation du service d'accès aux données injecté.

  • 테스트 가능:puisqu'on ne dépendpas d'une implementation concerète,on peutfacilite user dessimulacrespour effectuer des tests unitaires.
  • 거꾸로 lastuce que je vais vous présenter très bient ôt (je vous tiens en haleine!)nous allons passer les dépendences via le constructeur de la classe.
    L'intérêt est double:

  • Le code est lisible car la liste des dépendences d'une classe est directement dans la signature de son constructure:pas de suggest cachée dans Le code de la classe
  • nepeut pas oublier de passer une dé pendance á la classe puisqu'On en a besoin pour l'instancier
  • 에서
    Ici,les puristes auront sans doute les poils qui se dressent car ce que je vais vous montrer n'est pas au sens strict de l'injection de dédence,mais pour les cas simples,ça en présente tous les avantages.
    이것은 좋은 예이다.
  • 미집행 표준 편차
  • cas de besoin(테스트 장치에 적용되지 않음)에서 실시 가능성
  • L'inversion de contrôle pasápas


    파튼 대성당


    Partons d'une classe ne suivant aucun pattern particulier,la dédependance est directement instanciée dans le corps de la classe.빌크!
    public class MaClasse
    {
        private readonly MaDepdendance _maDependance;
    
        MaClasse()
        {
            _maDependance = new MaDependance();
        }
    }
    
    상상해 보세요. 이것은 실시간 교실MaDependancedépendeelle-même d'une autre classe,bienvenue au!
    덴마크는 유엔 총리다. 우리는 단지 간단하게 한마디 했을 뿐이다. 독립이라는 뜻이다.데세트 파송(De cette fa çon), 노트 오라(notre classe n'aura)에 책임감(la Responsibilité De l'instancier)을 더한다.Rien de bien Compliué.
    public class MaClasse
    {
        private readonly MaDepdendance _maDependance;
    
        // dépendance injectée via la constructeur
        MaClasse(MaDependance maDependance)
        {
            _maDependance = maDependance ?? throw new ArgumentNullException("Un message bien senti !");
        }
    }
    
    Mieux mais pas 무서워요.우리의 생활은 문제로 가득 차 있다.거꾸로 l'instant, toujours pas de dé couplage ou de modularit é dans le code.

    Dépendons de l'abstraction au liue de l'implementation


    Pour faire mieux,nous allons appigure stricto sensu le principle d'inversion de contrôle:dépendre d'abstraction au liu d'implementation.
    public class MaClasse
    {
        private readonly IMaDependance _maDependance;
    
        // On injecte une abstraction (interface) au lieu d'une implémentation concrète
        MaClasse(IMaDependance maDependance)
        {
            _maDependance = maDependance ?? throw new ArgumentNullException("Un message bien senti !");
        }
    }
    
    뭐 공부 해요?Le“I”pourinterface?
    Ce n'est bien entendu qu'une convention de nommage,mais en réalitéil s'est passéceci:
    // interface décrivant les membres à implémenter
    public interface IMaDependance
    {
        MaMethode();
    }
    
    // MaDependance implémente désormais l'interface IMaDependance
    public class MaDependance : IMaDependance
    {
        public void MaMethode()
        {
            // implémentation de l'interface
        }
    }
    
    Au liue de passer directement l'implementation concerète de la dépendence,nous avons passéson abstraction.조트!
    좀 쉬어.Sans l'aide d'un framework qui feraitça dynamiquement,il reste nécessaire de passer explicitement les dépendances au constructure de notre classe lors de son instancement.
    이중 문제:
  • Cela peut vite devenir très lourd si la classe a plusieurs dépendances
  • 단독 프로그램을 실행하고 있습니까?
  • Ajoutons une implementation par défaut


    Pour ajoter une implementation Pour défaut,nous allons simplement tirr parti du mot cléthisAppliqueéau constructure de la classe.thispermet,en effet,d'appeler un constructureápartir d'un autre constructure.
    public class MaClasse
    {
        private readonly IMaDependance _maDependance;
    
        // Constructeur acceptant un argument
        MaClasse(IMaDependance maDependance)
        {
            _maDependance = maDependance ?? throw new ArgumentNullException("Un message bien senti !");
        }
    
        // Constructeur vide, qui par appelle l'autre constucteur avec 'this'
        MaClasse() : this(new MaDepdendance()){}
    }
    
    De cette manière,le constructure vide appellera systemématiquement le constructur ayant la dépendance en argument en lui passant une implementation concerète.
    Nous obtenons donc deux manières d'instancier notre classe:
  • Avec le constructeur vide:la dépendance sera implémentée par défaut
  • Avec l'autre CONSTRUCTOUR:la dépendance sera implémentée manuellement par le dédeveloppeur
  • Nous avons donc atteint notre objectif premier avec un simple mot cléthisdu langage C#
    C'est bien,mais il subiste un problème:l'implementation par défaut est instanceciée en dur dans le code:
  • Si on suit les principesSOLID,une classe doitêtreéevolutional sans modification.Ici,ce n'est pas le cas:le jour oùon aura besoin de changer d'implementation par défaut,il sera nécessaire de modifier le code au niveau du constructureur.
  • Si plusieurs classes dépendent du même service,on risque simplement d'oublier de modifier le constructur de l'une ou l'autre des classes qui usinetMaDependance.
  • Trouvons donc un moyen de globaliser la correspondance entre une abstraction et son implementation par défaut.C'est-dire,qu'en pratique,pour une interface donneée on obtiene systemématiquement la même implementation.

    Prenons une bonne ré 솔루션


    Avec Xamarin.형식nul besoin de chercher très loin,leDependencyServicejouera ce r ôle á merveille.

    A strictement parler, le DependencyService sert surtout à la résolution d'implémentations natives (dans les projets iOS, Android...) pour les utiliser dans le projet commun Xamarin.Forms.

    En pratique, cela fonctionne très bien pour résoudre n'importe quel type.


    LeDependencyServiceexpose principalement trois méthodes:RegisterGetetResolve.Registerne souffre pas d'ambiguïté,c'est ici que nous enregistrerons notre implementation par défaut.
    Pour la simplicitéde la démonstration,et parce qu'en pratique ce sera souvent le cas,je prends la classeApp.xaml.cscomme point d'entrée Pour enregistrer mes dépendences.
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
    
            // On enregistre le type MaDependance pour l'interface IMaDependance
            DependencyService.Register<IMaDependance, MaDependance>();
    
            MainPage = new MainPage();
        }
    
        //[...]
     }
    
    Faites comme vous voulez,ce qui est important c'est de bien enregister les types avant toute use duDependencyServicedans le code,cela va de soi.GetetResolvesemblent fonctionner de manière identique,cependant la documentation affichée e dans Visual Studio nuancequelque peu leur 사용법:
    _Resolve: 종속성을 유형별로 해석하는 방법
    Get: 유형 T의 플랫폼별 구현을 되돌려줍니다_Resolvesemble mieux correspondreánotre besoin.
    public class MaClasse
    {
        private readonly IMaDependance _maDependance;
    
        MaClasse(IMaDependance maDependance)
        {
            _maDependance = maDependance ?? throw new ArgumentNullException("Un message bien senti !");
        }
    
        // On résoud le type avec le DependencyService
        MaClasse() : this(DependencyService.Resolve<IMaDependance>()){}
    }
    
    Désormais,notre classe ne Dépend plus D'aucune implication concerète,elle n'est plus qu'abstraction!
    Imagations que de nombreuses classes dépendent deIMaDependanceet qu'on ait besoin de changer l'implementation de la dépendence partout dans le code,il suffira de remplacer l'implementation enregistreée dansDependencyService.Register.
    Pour le reste,ça n'a pas change:Pour injecter une implementation différente il est nécessaire d'instancier la classe en passant explicitement la dépendence dans le constructure.Ce sera notamment le cas pour les simulares crésáfin de tests unitaires.

    결론


    Si l'inversion de contrôle est souvent confondue avec le framework qui la met en oeuvre,il s'agit en réalitéd'un principleálénoncéplutôtôt simple:une classe doit dépendre d'abstractions et non d'implementation.
    Et dans les cas simples,on peut l'appliker sans framework Et profiter de ses avantagesámoindre frais:découplage,modularité,testabilité.
    Je vous en ai présentéici une façon fort simpleábase d’interface,d'appeláun constructureur par défaut avec le mot cléthiset duDependencyServicede Xamarin.형식

    Pour un projet mobile, c'est souvent largement suffisant !


    Le 코드 소스


    Comme toujours,un petit projet d'Example sur monGitHub.Celui ci est minimaliste:un service,un ViewModel et un test unitaire.아들 seul intér êt est de dé montrer le fonctionnement de tout cela de fa çon un peu moins thé orique.

    Sylvain Moingeon 회사 / DITheEasyWayDemo


    프로젝트 수반물 주입 의존성


    DITheEasyWayDemo


    Projet d'Accomagment pour mon article concernantl'inversion de dépendance sous Xamarin.Forms
    View on GitHub
    뭐 공부 해요?

    좋은 웹페이지 즐겨찾기