dependency injection: išmoktos pamokos
TRANSCRIPT
Dependency Injection: išmoktos pamokos
Gediminas GeigalasUAB Baltic Amadeus
gedgei.wordpress.comba.lt
enjoyIT.lt
Turinys
• Problemos• Sprendimai• Patarimai• Rekomenduojama
medžiaga
Sąvokos
•Dependency Injection (DI) - priklausomybės perdavimas priklausančiam objektu
• IoC konteineris; konteineris – įrankis objektų ir jų priklausomybių medžiams kurti
•Composition Root (CR) – vieta, kurioje sukuriamas objektų ir jų priklausomybių medis, pvz.:•var instance = container.Resolve<T>()
Programavimas be DI
Spaudžiam F5
#1: DI yra naudingas
•Viešos priklausomybės•Lengvesnis perpanaudojimas•Lengvesnis testavimas•Lankstesnis gyvavimo trukmės valdymas
#2: DI galimas ne visur
•Reikalaujama konstruktorių be parametrų•Nepateikiami plėtimo taškai•Pavyzdžiai:•ASP.NET WebForms Page•RoleProvider•Windows Workflow Foundation
...bet norim jį naudoti
•Ką daryti, jeigu technologija nepalaiko DI?•Facade pattern•Service locator *
#3: Konstruktoriai tampa dideli•Dažniausiai naudojamas constructor injection•Priklausomybių skaičius tampa didelis•Sudėtingesnis palaikymas
Neprivalomos priklausomybės•Log‘inimas ir kiti cross-cutting concern•Keičiam į property injection•Local default•Null Object pattern
Facade Services
•Single Responsibility Principo taikymas•Grupuoja kelias priklausomybes į vieną
#4: Nenaudoti DI esybėse
•DI naudojimas esybių klasėse nerekomenduojamas•Naudoti „servisinėse“ klasėse• Jeigu esybei reikalinga service klasė, ji gali būti perduodama metodo parametrais
#5: Primityvai taip pat priklausomybės
•Priklausomybė nebūtinai turi būti sudėtingas objektas•Primityvai tinkami visiems DI būdams
Konfigūracijos parametrai
•Nekviesti [Web]ConfigurationManager klasių tiesiai•Priimti parametrus per konstruktorių arba property•Kūrimo/registracijos metu nuskaitomos ir panaudojamos konfigūracijos reikšmės
* CR konfigūracijos demo
#6: Ne viską galima sukurti iš anksto•DI atskiria objektų kūrimą nuo jų panaudojimo•Ką daryti, jeigu objekto sukūrimas yra sudėtingas ir neturėtų būti atliekamas viso medžio kūrimo metu?•Factory pattern•Func<T>•Lazy<T>•Nepamirškite sunaikintisukurto objekto!
#7: Nevisada reikalinga abstrakcija•Dažnai naudojant DI įvedamos abstrakcijos•Ar jos tikrai reikalingos?•Abstrakcijos prideda sudėtingumo•Automatiniam testavimui nebūtinos
DI != DIP
•Dependency Inversion Principas:
•High level modules should not depend on low level modules – both should depend upon abstractions• Abstractions should not depend on the details. Details should depend upon abstractions.
Reused Abstraction Principle
•Neįvedinėkite abstrakcijos, jeigu yra tik viena jos realizacija•Negalioja skirstant į sluoksnius
#8: Kartais prireikia bendros registracijos
•Ką daryti, jeigu turim bendrą priklausomybių registraciją kelioms aplikacijoms?
Bendra registracija
•Negalima talpinti registracijos kartu su priklausomybėmis tame pačiame projekte•Trys būdai:•Kopijuoti kiekvienojeaplikacijoje•Add as link•Saugoti bendrame aplikacijų lygio projekte
Composition Root
•Composition Root (CR) – centrinė vieta, kurioje sukuriamas objektų medis•Gali būti tik aplikacijose, neturi būti bibliotekose•Tipinės vietos .NET programose:•Console app – Main metodas•ASP.NET MVC – IControllerFactory•WCF – IInstanceProvider, ServiceHostFactory
•Kiek CR gali būti aplikacijoje?
#9: Composition Root gali būti keli
•Vienoje aplikacijoje yra keli įėjimo taškai (pvz.: ASP.NET + WCF)•Tai tarsi kelios aplikacijos vienoje•Skirtingos priklausomybės skirtinguose kontekstuose•Skirtingos gyvavimo trukmės skirtinguose kontekstuose
#10: Konteineris reikalingas ne visada•DI nėra priklausomas nuo įrankių•Nereikalingas, jei:•Priklausomybių medis nedidelis•Rašoma biblioteka ar framework
Kada naudoti konteinerį?
• © Mark Seeman: http://blog.ploeh.dk/2012/11/06/WhentouseaDIContainer/
Varguolio DI
•Rankomis konstruojamas priklausomybių medis turi privalumų:• Paprasta ir aišku• Strong typing• Papildomas tipų tikrinimas kompiliavimo metu• Circular dependency aptikimas
#11: IoC konteineris reikalingas, kai..•Dideli priklausomybių medžiai•Aspect Oriented Programming•Late binding•Lankstus gyvavimo trukmės konfigūravimas
IoC konteinerio panaudojimas•Turėtų būti naudojamas tik CR:• IoC konteinerį lengva pakeisti kitu• IoC konteinerio nereikia abstrahuoti
•Nenaudokite atributų DI atlikti•Nuorodos į konteinerį turėti būti tik aukščiausiame lygmenyje (aplikacijoje)
DI vs Service Location
• Jei naudoji IoC konteinerį, nereiškia, kad naudoji DI•Service Locator•CommonServiceLocator•Anti-pattern•Grąžina paslėptų priklausomybių problemą
#12: Release yra LABAI svarbu•Register Resolve Release šablonas•LABAI svarbi dalis:•Tvarkingai uždaromi WCF proxy•Atlaisvinami IDisposable objektų resursai
•Pasirinkite IoC konteinerį, kuris palaiko automatinį objektų medžio naikinimą (Unity to nesugeba)
Ne visi objektai yra sekami•Ką daryti su IoC konteinerio nesekamais IDisposable ir pnš. objektais?•Konteineris neseka objektų, kurių jis nesukūrė•Objektai turi būti naikinamitame kontekste, kuriamebuvo sukurti
Rekomenduojama medžiaga
•Dependency Injection in .NET, Mark Seeman•http://blog.ploeh.dk/ - Mark Seeman blog‘as•http://misko.hevery.com/ - straipsniai apie testuojamą dizainą ir DI•Agile Principles, Patterns, and Practices [in C#], Robert Martin
Klausimai?