-
Notifications
You must be signed in to change notification settings - Fork 0
/
dependency_injection.html
123 lines (106 loc) · 20.7 KB
/
dependency_injection.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome file</title>
<link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>
<body class="stackedit">
<div class="stackedit__left">
<div class="stackedit__toc">
<ul>
<li><a href="#қатерді-жатату-dependency-injection">Қатерді жатату (Dependency Injection)</a>
<ul>
<li><a href="#негізгі-концепция">Негізгі Концепция</a></li>
<li><a href="#сауатты-проблема">Сауатты Проблема</a></li>
<li><a href="#контейнерлер">Контейнерлер</a></li>
<li><a href="#көбірек-оқу">Көбірек оқу</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="stackedit__right">
<div class="stackedit__html">
<h1 id="қатерді-жатату-dependency-injection">Қатерді жатату (Dependency Injection)</h1>
<p><a href="https://wikipedia.org/wiki/Dependency_injection">Wikipedia</a> сайтынан:</p>
<blockquote>
<p>Қатерді жататудың негізгі мақсаты жататуларды жою және оларды ойлау мүмкіндігін беретін программалау дизайн паттерны. Ол жататуды ойлану уақытта немесе компиляция уақытта өзгерту мүмкіндігін береді.</p>
</blockquote>
<p>Бұл цитата бекітілген концепцияның өзінен көбірек жақсы көрінеді. Қатерді жататуды көмек көмегімен компонентке оның қатерлерін конструктор арқылы, метод шақырулар арқылы немесе өздерінің мәндерін орнату арқылы беруін білдіреді. Ол көмекші.</p>
<h2 id="негізгі-концепция">Негізгі Концепция</h2>
<p>Біз өте салмақ, бірақ көпшілікті мисалмен концепцияны көрсете аламыз.</p>
<p>Біздің кейінгі мисалымызда депенданси (затты аулау) келтіру көрсетілген <code>Database</code> класы бар. Депенданси адаптерге базаға сөйлеу үшін қажет. Біз конструкторда адаптерді інициализациялау жасаймыз және сенімді депенданси жасайды. Бұлымды сынау жасау жамау, және <code>Database</code> класының адаптерге өте жаттыктаныс аударылатын болмасақ жатату дайындалады.</p>
<pre class=" language-php"><code class="prism language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">Database</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Database</span>
<span class="token punctuation">{</span>
<span class="token keyword">protected</span> <span class="token variable">$adapter</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">adapter</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MySqlAdapter</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">MysqlAdapter</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span></code></pre>
<p>Бұл кодты Депенданси Аулауны қолдану арқылы жататуды шектеу жататудан шығарып, сондықтан депенданси төмендеп келеді. Мысалы, біз депендансині конструкторда інжектіп, оны класс бойынша мүмкіндігі тұру үшін <a href="https://www.php.net/manual/en/language.oop5.decon.php#language.oop5.decon.constructor.promotion">конструктордың өнімділіктерін пайдаланамыз</a>:</p>
<pre class=" language-php"><code class="prism language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">Database</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Database</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span><span class="token keyword">protected</span> MySqlAdapter <span class="token variable">$adapter</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">MysqlAdapter</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span></code></pre>
<p>Ағымда <code>Database</code> класына өзінің депендансін береміз, онда бірақ өзі ініциализациялау жасауымыз керек емес. Біз өлшемді аргументпен алып беретін жататуды ұсыну мүмкін, не болмаса егер <code>$adapter</code> мүмкіндіктері [ <code>public</code> ] болса, оны дайын орнату мүмкін.</p>
<h2 id="сауатты-проблема">Сауатты Проблема</h2>
<p>Егер Сіз Депенданси Аулау туралы оқып көрсеңіз, сонда Сіз өте часто <em>“Басқару өзгертудің принципі”</em> не немесе <em>“Депенданси Аулау Принципі”</em> терминдерін көріген боларсыздар. Бұлар Депенданси Аулауны шешетін сауатты проблемалар.</p>
<h3 id="басқаруды-күйге-орнату-inversion-of-control">Басқаруды Күйге Орнату (Inversion of Control)</h3>
<p>Басқаруды күйге орнату — бұл онымен деп тұрғанда, системаның басқаруын “басқару өзгертуді” айналдыру. Депенданси Аулау туралы сөйлемей қарап тұрсаңыз, бұл айнымалыларды толықтай басқарудан айырап алу арқылы біздің депендансилерімізді тазалауымызды айтады.</p>
<p>Ондай өтінішті фреймворктерді, жылдар бойы күйге орнату тиісінде әзірленген PHP фреймворктері, бірақ сұрау айту мерзімінде, біз басқару өзгертуді, қайда басқару өзгертуді және қайсысын? Мысалы, MVC (Модель-View-Контроллер) фреймворктері әдепкі түрде басқару супер объекті немесе негізгі контроллер беретін контроллерлерді өз жеткізу үшін жатататын контроллерді қамтамасыздатады. Бұл айнымалыларды толықтай басқару өзгертуді, бірақ депендансилерді қамтамасыздатпау біздіктерді жатататын адамдардан басқа жатататып жататын болмасы.</p>
<p>Депенданси Аулау бізге депендансилерді тек көрсетуді, көрсететін жерде бізге міндетті депендансилерді тек көрсетуді жатататуды елгеуімізге мүмкіндік береді, соларды қажет болмаса да.</p>
<h3 id="s.o.l.i.d.">S.O.L.I.D.</h3>
<h4 id="екіншілік-принципі-s">Екіншілік Принципі: S</h4>
<p>Екіншілік Принципі – бұл бас рөлдер мен жоғары деңгейдегі архитектура туралы. Ол “Бір кластың өзгерту үшін тек бір себепті болуы керек” деп айтылады. Бұл маңызды мақсатты, өзімізді мақсаттауымызды білдіреді. Софттық қамтамасыздатуды беретін функционалдық көмек болуы керек. Бұл жағдайда кодты жетілдіру мүмкіндігі бізге мейірім береді. Біздікі класты тек бір не істеуді дайын басқа программаларда пайдалануға болады.</p>
<h4 id="ашусозул-принципі-o">Ашу/Созул Принципі: O</h4>
<p>Ашу/Созул Принципі – бұл клас дизайны мен мүмкіндік кеңейтуді туралы. Ол “Программалық қамтамасыздатуды беретін әрекеттер (классы, модульдер, функциялар т.б.) кеңейту үшін ашуға, бірақ өзгерту үшін созу болуы керек” деп айтады. Бұл біздікі модульдерімізді, кластарымызды және функцияларымызды дизайндау үшін жатататын нысандардың (интерфейстерді) бекіту қажет дегенімізді айтады. Сөйлемей білуді, біздікі класстарды интерфейстерді реализация жасау үшін пайдаланып, көмекші класстарды интерфейстерге асырауымыз қажет.</p>
<p>Осы өніміні пайдаланудың ең асауы тұтыну үшін мысалы, сіздікі кодты көмекшісіз көмекші функционалмен кеңейтемізді меңгеру үшін біздікі кодты өзгерту қажет болмайды. Бұл мақсатты, жатататын өнімді азайту үшін, жасау уақытты азайту үшін, жатататын өнімді бағалау үшін, біздікі кодты өзгертуге болмаса да, жатататын өнімді қолдану арқылы кодты жетілдіре аламыз. Мысалы, жаңа функционал үшін жаңа кодты тербелеу көмекші көмегімен, жоғары ауруларды тез және көп сенімделгенді, жоғарыдау уақытын азайту және бағалау үш</p>
<h4 id="лисковтың-аурусы-принципі-l">Лисковтың Аурусы Принципі: L</h4>
<p>Лисковтың Аурусы Принципі – бұл ауруларды және өрістерді айналыстыру туралы. Ол “Балалардың аурулары ата-аналардың түрділік түсіндірмелерін бұзмауы керек.” деп айтады. Немесе, Роберт Си Мартиннің сөздерімен “Аурулары ата-ана түрлері үшін ауызбасуыш болуы керек.” дейді.</p>
<p>Мысалы, егер біздікі <code>FileInterface</code> интерфейсі бар болса, оның <code>embed()</code> әдісін анықтауы, мен <code>Audio</code> мен <code>Video</code> кластары біздікі <code>FileInterface</code> интерфейсін іске асыруды, онда біздікі <code>embed()</code> әдісіні пайдалануды күтетеміз. Егер мынау <code>PDF</code> не <code>Gist</code> кластарымызды <code>FileInterface</code> интерфейсін іске асырсақ, осының <code>embed()</code> әдісін не істеу көрсеткеніміз болады. Бұл жаттығу мақсатты, бізге қалайтын объектін (мысалы, <code>FileInterface</code> түріндегі) басқа түрге өзгертуді ештеңе өзгерту қажет болмайды деген бетімізді береді.</p>
<h4 id="интерфейс-сегментациясы-принципі-i">Интерфейс Сегментациясы Принципі: I</h4>
<p>Интерфейс Сегментациясы Принципі (ISP) – бұл <em>бизнес-лоигика-танымдамалар</em> клиенттерге байланысты. Ол “Ешкімге дайын болмайтын әдістерге байлануы керек” деп айтады. Бұл барлық бұрынғы класстардың келесімен болуы керек деп біртінді интерфейс жасау үшін, оларды бір-ақ келесі интерфейстерге байланыстырмасын ұсыну керек.</p>
<p>Мысалы, <code>Car</code> не <code>Bus</code> класстары <code>steeringWheel()</code> әдісіне қызмет етеді, бірақ <code>Motorcycle</code> не <code>Tricycle</code> класстары қызмет етпейді. Әйтпесе, <code>Motorcycle</code> не <code>Tricycle</code> класстары <code>handlebars()</code> әдісіне қызмет етеді, бірақ <code>Car</code> не <code>Bus</code> класстары қызмет етпейді. Барлығының бұрын қазір барлық үлкеністерге <code>steeringWheel()</code> және <code>handlebars()</code> түріндегі өтінімділіктерді қолдану қажет емес деп, біз байланыс интерфейсін көтеруіміз керек.</p>
<h4 id="зависимості-аурусы-принципі-d">Зависимості аурусы принципі: D</h4>
<p>Зависимості аурусы принципі – бұл жеке кластардың арасындағы сұрауларды алып тастау туралы. ол шағын функционалды өзгерту арқылы өтінімді көмекке қолдау көрсету туралы. Ол “Абстракттыққа қол жеткіз. Конкреттіктерге қол жеткізбе.” деп айтады. Тыныштық айтылғанда, бұл біздіктердің құрылғанын интерфейс/шарттар не абстракттық кластар, конкреттік реализациялардан тысқану керек деп айтарымыз. Бұл принципті осы місалды аударып көруді көмекші болады.</p>
<pre class=" language-php"><code class="prism language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">Database</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Database</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span><span class="token keyword">protected</span> AdapterInterface <span class="token variable">$adapter</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">AdapterInterface</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">MysqlAdapter</span> <span class="token keyword">implements</span> <span class="token class-name">AdapterInterface</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span></code></pre>
<p>Қазір <code>Database</code> кластарының конкреттік реализациясының бір інтерфейске байлануынан көмек көрсетуімізге байланысы бар мәнінен көбірек.</p>
<p>Егер біз команда бойынша жұмыс істесеміз және адаптерді команда қызметкері жұмыс істеп тұрса, біз оған біздікі модульді дұрыс тесттер үшін дұрыс mock қылуымыз келсе, біз оларды көмекші интерфейсі/шарты бойынша құжаттарын құрауымыз керек.</p>
<p>Бұл методты қолдану мағынасы – біздікі кодты тым бірше шкалалы көтеру. Егер жылдан айырылсақ, бізге екінші түрді базада жұмыс істеу көмекшісін көмекші интерфейсін құрау және оны инжекциялау керек болса, ұзақ қазір кодты қайта жазуды көрсетпейміз, себебі біз интерфейс арқылы белгіленген договор бойынша әдіптестерге байланыстыры аламыз.</p>
<h2 id="контейнерлер">Контейнерлер</h2>
<p>Зависимості інжекциялары туралы түсіну керек бірінші рет. Олар Зависимості Инжекцияларымен бірдей емес, Контейнер – бұл оларды өзгерту үшін көмекші құрал, бірақ оларды ортақпенділікке өтініш ету үшін де қолдануға болады, себебі олар аз жататталады және көптеген жақтарда қолжетімді емес, Сервістік орнату – деп аталатын анти-паттерніді орналастыру үшін. Сіздікі кластарыңызға Сервіс Локатор ретінде ДИ контейнерін инжекциялау аргументсіз, онда, өзі тізбегін ауыстырудан жақсы, онда, сіз өзіңізді орналастырады жаттығуыздан ауысады. Бұл айтарлы өңірі болады және соңында тестілеуді көбірек қылар.</p>
<p>Көпшілік жаңа фреймворктерінің өзінде талапты болатын орынбасарлау контейнерлері бар, сіздікті заттарды біріктіруді конфигурация арқылы болдырып үйлестіруге мүмкіндік береді. Бұл өтінімнін салу мақсатында сіз жасауымыз көк боларынан тұрып тізілген бағаны тауып, тізілімді код жасауға боларынан толық ашықпенді және атырауымен басқа мұрагерді.</p>
<h2 id="көбірек-оқу">Көбірек оқу</h2>
<ul>
<li><a href="http://fabien.potencier.org/what-is-dependency-injection.html">Dependency Injection не?</a></li>
<li><a href="https://mwop.net/blog/260-Dependency-Injection-An-analogy.html">Dependency Injection: Түсіндіру</a></li>
<li><a href="https://code.tutsplus.com/tutorials/dependency-injection-huh--net-26903">Dependency Injection: Қалай?</a></li>
<li><a href="https://medium.com/philipobenito/dependency-injection-as-a-tool-for-testing-902c21c147f1">Тест жасау үшін Dependency Injection ретінде қолдану</a></li>
</ul>
</div>
</div>
</body>
</html>