Тәуелділік инъекциясы (DI) түсіну оңай ұғым емес және оны жаңа немесе бар қолданбаларға қолдану одан да шатастырады. Джесс Смит C# және Java бағдарламалау тілдерінде инъекциялық контейнерсіз тәуелділік инъекциясын қалай жасау керектігін көрсетеді. Бұл мақалада мен .NET және Java қолданбаларында тәуелділік инъекциясын (DI) қалай енгізу керектігін көрсетемін.
Тәуелділік инъекциясының тұжырымдамасы алғаш рет әзірлеушілердің назарына 2000 жылы Роберт Мартин «Дизайн принциптері мен үлгілері» (кейінірек SOLID аббревиатурасымен белгілі ) мақаласын жазған кезде келді. SOLID ішіндегі D кейінірек тәуелділік инъекциясы ретінде белгілі болған инversionға тәуелділікке (DOI) қатысты. Түпнұсқа және ең кең тараған анықтама: тәуелділік инversionсы - негізгі класс тәуелділіктерді басқару тәсілінің инversionсы.
Copy
Мартиннің бастапқы мақаласы төменгі деңгейдегі сыныпқа сыныптың тәуелділігін көрсету үшін келесі codeты пайдаланды
WritePrinter
:
void Copy()
{
int c;
while ((c = ReadKeyboard()) != EOF)
WritePrinter(c);
}
Бірінші айқын мәселе, егер сіз әдістің параметрлер тізімін немесе түрлерін өзгертсеңіз
WritePrinter
, сол әдіске тәуелділік бар жерде жаңартуларды енгізу қажет. Бұл процесс техникалық қызмет көрсету шығындарын арттырады және жаңа қателердің ықтимал көзі болып табылады.
Тағы бір мәселе: Көшіру сыныбы енді қайта пайдалануға ықтимал үміткер емес. Мысалы, пернетақтадан енгізілген таңбаларды принтерге емес, файлға шығару қажет болса ше? Ол үшін сыныпты
Copy
келесідей өзгертуге болады (C++ тілінің синтаксисі):
void Copy(outputDevice dev)
{
int c;
while ((c = ReadKeyboard()) != EOF)
if (dev == printer)
WritePrinter(c);
else
WriteDisk(c);
}
Жаңа тәуелділіктің енгізілгеніне қарамастан
WriteDisk
, жағдай жақсармады (керісінше нашарлады), себебі басқа принцип бұзылды: «бағдарламалық қамтамасыз ету нысандары, яғни сыныптар, модульдер, функциялар және т.б. кеңейту үшін ашық, бірақ жабық болуы керек. өзгерту». Мартин бұл жаңа шартты if/else мәлімдемелері codeтың тұрақтылығы мен икемділігін төмендететінін түсіндіреді. Шешім - жазу және оқу әдістері тәуелді болу үшін тәуелділіктерді инversionлау
Copy
. «Тәуелділіктердің» орнына олар конструктор арқылы өтеді. Өзгертілген code келесідей көрінеді:
class Reader
{
public:
virtual int Read() = 0;
};
class Writer
{
public:
virtual void Write(char) = 0;
};
void Copy(Reader& r, Writer& w)
{
int c;
while((c=r.Read()) != EOF)
w.Write(c);
}
Енді сыныпты
Copy
класс әдістерінің әртүрлі іске асыруларымен оңай қайта пайдалануға болады
Reader
және
Writer
. Класта
Copy
түрлердің ішкі құрылымы туралы ақпарат жоқ
Reader
,
Writer
бұл оларды әртүрлі іске асырулармен қайта пайдалануға мүмкіндік береді. Бірақ егер мұның бәрі сізге қандай да бір құмарлық сияқты көрінсе, Java және C# тіліндегі келесі мысалдар жағдайды түсіндіреді.
Java және C# тіліндегі мысал
DI
Тәуелділік контейнерінсіз тәуелділік инъекциясының қарапайымдылығын көрсету үшін бірнеше қадамда пайдалану үшін теңшеуге болатын қарапайым мысалдан бастайық . Бізде
HtmlUserPresentation
оның әдістері шақырылған кезде HTML пайдаланушы интерфейсін жасайтын класс бар делік. Міне, қарапайым мысал:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Осы сынып codeын пайдаланатын кез келген жобаның классқа тәуелділігі болады
HtmlUserPresentation
, нәтижесінде жоғарыда сипатталған қолайлылық және техникалық қызмет көрсету мәселелері туындайды. Жақсарту бірден өзін ұсынады: қазіргі уақытта сыныпта қол жетімді барлық әдістердің қолтаңбалары бар интерфейс жасау
HtmlUserPresentation
. Міне, осы интерфейстің мысалы:
public interface IHtmlUserPresentation {
String createTable(ArrayList rowVals, String caption);
String createTableRow(String tableCol);
}
Интерфейсті жасағаннан кейін
HtmlUserPresentation
оны пайдалану үшін классты өзгертеміз. Түрді құруға оралсақ
HtmlUserPresentation
, енді біз негізгі түрдің орнына интерфейс түрін пайдалана аламыз:
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Интерфейс құру бізге басқа іске асыруларды оңай пайдалануға мүмкіндік береді
IHtmlUserPresentation
. Мысалы, егер біз осы түрді сынағымыз келсе, біз негізгі түрді
HtmlUserPresentation
деп аталатын басқа түрмен оңай ауыстыра аламыз
HtmlUserPresentationTest
. Осы уақытқа дейін енгізілген өзгертулер codeты тексеруді, қолдауды және масштабтауды жеңілдетеді, бірақ қайта пайдалану үшін ештеңе жасамайды, өйткені
HtmlUserPresentation
түрін пайдаланатын барлық сыныптар әлі де оның бар екенін біледі.
IHtmlUserPresentation
Бұл тікелей тәуелділікті жою үшін интерфейс түрін оны пайдаланатын сыныптың немесе әдістің конструкторына (немесе әдіс параметрлерінің тізіміне) беруге болады :
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
Конструктор
UploadFile
енді түрдегі барлық функцияларға қол жеткізе алады
IHtmlUserPresentation
, бірақ осы интерфейсті жүзеге асыратын класстың ішкі құрылымы туралы ештеңе білмейді. Бұл контексте типті енгізу сынып данасы жасалған кезде орын алады
UploadFile
. Интерфейс түрі
IHtmlUserPresentation
әртүрлі енгізулерді әртүрлі сыныптарға немесе әртүрлі функционалдылықты қажет ететін әдістерге беру арқылы қайта пайдалануға болады.
Қорытынды және материалды бекіту бойынша ұсыныстар
Тәуелділік инъекциясы туралы білдіңіз және олардың біреуі мақсатты түрдің функционалдығына қол жеткізу үшін екіншісін іске қосқанда, сыныптар бір-біріне тікелей тәуелді деп айтылады. Екі түр арасындағы тікелей тәуелділікті ажырату үшін интерфейсті жасау керек. Интерфейс түрге қажетті функционалдылықтың контекстіне байланысты әртүрлі іске асыруларды қосу мүмкіндігін береді. Интерфейс түрін сынып конструкторына немесе әдіске беру арқылы функционалдылықты қажет ететін сынып/әдіс интерфейсті жүзеге асыратын түр туралы ешқандай мәліметтерді білмейді. Осыған байланысты интерфейс түрін ұқсас, бірақ бірдей емес әрекетті қажет ететін әртүрлі сыныптарда қайта пайдалануға болады.
- Тәуелділік инъекциясымен тәжірибе жасау үшін бір немесе бірнеше қолданбалардағы codeты қарап шығыңыз және көп пайдаланылатын негізгі түрді интерфейске түрлендіруге тырысыңыз.
- Осы жаңа интерфейс түрін пайдалану үшін осы негізгі түрді тікелей жасайтын сыныптарды өзгертіңіз және оны пайдаланатын сынып әдісінің конструкторы немесе параметрлер тізімі арқылы өткізіңіз.
- Осы интерфейс түрін тексеру үшін сынақты іске қосыңыз. Кодыңыз қайта өңделгеннен кейін
DI
оны іске асыру оңайырақ болады және қайта пайдалану және техникалық қызмет көрсету тұрғысынан қолданбаңыздың қаншалықты икемді болатынын байқайсыз.
GO TO FULL VERSION