Wikipedia сайтынан:
Қатерді жататудың негізгі мақсаты жататуларды жою және оларды ойлау мүмкіндігін беретін программалау дизайн паттерны. Ол жататуды ойлану уақытта немесе компиляция уақытта өзгерту мүмкіндігін береді.
Бұл цитата бекітілген концепцияның өзінен көбірек жақсы көрінеді. Қатерді жататуды көмек көмегімен компонентке оның қатерлерін конструктор арқылы, метод шақырулар арқылы немесе өздерінің мәндерін орнату арқылы беруін білдіреді. Ол көмекші.
Біз өте салмақ, бірақ көпшілікті мисалмен концепцияны көрсете аламыз.
Біздің кейінгі мисалымызда депенданси (затты аулау) келтіру көрсетілген Database
класы бар. Депенданси адаптерге базаға сөйлеу үшін қажет. Біз конструкторда адаптерді інициализациялау жасаймыз және сенімді депенданси жасайды. Бұлымды сынау жасау жамау, және Database
класының адаптерге өте жаттыктаныс аударылатын болмасақ жатату дайындалады.
<?php
namespace Database;
class Database
{
protected $adapter;
public function __construct()
{
$this->adapter = new MySqlAdapter;
}
}
class MysqlAdapter {}
Бұл кодты Депенданси Аулауны қолдану арқылы жататуды шектеу жататудан шығарып, сондықтан депенданси төмендеп келеді. Мысалы, біз депендансині конструкторда інжектіп, оны класс бойынша мүмкіндігі тұру үшін конструктордың өнімділіктерін пайдаланамыз:
<?php
namespace Database;
class Database
{
public function __construct(protected MySqlAdapter $adapter)
{
}
}
class MysqlAdapter {}
Ағымда Database
класына өзінің депендансін береміз, онда бірақ өзі ініциализациялау жасауымыз керек емес. Біз өлшемді аргументпен алып беретін жататуды ұсыну мүмкін, не болмаса егер $adapter
мүмкіндіктері [ public
] болса, оны дайын орнату мүмкін.
Егер Сіз Депенданси Аулау туралы оқып көрсеңіз, сонда Сіз өте часто “Басқару өзгертудің принципі” не немесе “Депенданси Аулау Принципі” терминдерін көріген боларсыздар. Бұлар Депенданси Аулауны шешетін сауатты проблемалар.
Басқаруды күйге орнату — бұл онымен деп тұрғанда, системаның басқаруын “басқару өзгертуді” айналдыру. Депенданси Аулау туралы сөйлемей қарап тұрсаңыз, бұл айнымалыларды толықтай басқарудан айырап алу арқылы біздің депендансилерімізді тазалауымызды айтады.
Ондай өтінішті фреймворктерді, жылдар бойы күйге орнату тиісінде әзірленген PHP фреймворктері, бірақ сұрау айту мерзімінде, біз басқару өзгертуді, қайда басқару өзгертуді және қайсысын? Мысалы, MVC (Модель-View-Контроллер) фреймворктері әдепкі түрде басқару супер объекті немесе негізгі контроллер беретін контроллерлерді өз жеткізу үшін жатататын контроллерді қамтамасыздатады. Бұл айнымалыларды толықтай басқару өзгертуді, бірақ депендансилерді қамтамасыздатпау біздіктерді жатататын адамдардан басқа жатататып жататын болмасы.
Депенданси Аулау бізге депендансилерді тек көрсетуді, көрсететін жерде бізге міндетті депендансилерді тек көрсетуді жатататуды елгеуімізге мүмкіндік береді, соларды қажет болмаса да.
Екіншілік Принципі – бұл бас рөлдер мен жоғары деңгейдегі архитектура туралы. Ол “Бір кластың өзгерту үшін тек бір себепті болуы керек” деп айтылады. Бұл маңызды мақсатты, өзімізді мақсаттауымызды білдіреді. Софттық қамтамасыздатуды беретін функционалдық көмек болуы керек. Бұл жағдайда кодты жетілдіру мүмкіндігі бізге мейірім береді. Біздікі класты тек бір не істеуді дайын басқа программаларда пайдалануға болады.
Ашу/Созул Принципі – бұл клас дизайны мен мүмкіндік кеңейтуді туралы. Ол “Программалық қамтамасыздатуды беретін әрекеттер (классы, модульдер, функциялар т.б.) кеңейту үшін ашуға, бірақ өзгерту үшін созу болуы керек” деп айтады. Бұл біздікі модульдерімізді, кластарымызды және функцияларымызды дизайндау үшін жатататын нысандардың (интерфейстерді) бекіту қажет дегенімізді айтады. Сөйлемей білуді, біздікі класстарды интерфейстерді реализация жасау үшін пайдаланып, көмекші класстарды интерфейстерге асырауымыз қажет.
Осы өніміні пайдаланудың ең асауы тұтыну үшін мысалы, сіздікі кодты көмекшісіз көмекші функционалмен кеңейтемізді меңгеру үшін біздікі кодты өзгерту қажет болмайды. Бұл мақсатты, жатататын өнімді азайту үшін, жасау уақытты азайту үшін, жатататын өнімді бағалау үшін, біздікі кодты өзгертуге болмаса да, жатататын өнімді қолдану арқылы кодты жетілдіре аламыз. Мысалы, жаңа функционал үшін жаңа кодты тербелеу көмекші көмегімен, жоғары ауруларды тез және көп сенімделгенді, жоғарыдау уақытын азайту және бағалау үш
Лисковтың Аурусы Принципі – бұл ауруларды және өрістерді айналыстыру туралы. Ол “Балалардың аурулары ата-аналардың түрділік түсіндірмелерін бұзмауы керек.” деп айтады. Немесе, Роберт Си Мартиннің сөздерімен “Аурулары ата-ана түрлері үшін ауызбасуыш болуы керек.” дейді.
Мысалы, егер біздікі FileInterface
интерфейсі бар болса, оның embed()
әдісін анықтауы, мен Audio
мен Video
кластары біздікі FileInterface
интерфейсін іске асыруды, онда біздікі embed()
әдісіні пайдалануды күтетеміз. Егер мынау PDF
не Gist
кластарымызды FileInterface
интерфейсін іске асырсақ, осының embed()
әдісін не істеу көрсеткеніміз болады. Бұл жаттығу мақсатты, бізге қалайтын объектін (мысалы, FileInterface
түріндегі) басқа түрге өзгертуді ештеңе өзгерту қажет болмайды деген бетімізді береді.
Интерфейс Сегментациясы Принципі (ISP) – бұл бизнес-лоигика-танымдамалар клиенттерге байланысты. Ол “Ешкімге дайын болмайтын әдістерге байлануы керек” деп айтады. Бұл барлық бұрынғы класстардың келесімен болуы керек деп біртінді интерфейс жасау үшін, оларды бір-ақ келесі интерфейстерге байланыстырмасын ұсыну керек.
Мысалы, Car
не Bus
класстары steeringWheel()
әдісіне қызмет етеді, бірақ Motorcycle
не Tricycle
класстары қызмет етпейді. Әйтпесе, Motorcycle
не Tricycle
класстары handlebars()
әдісіне қызмет етеді, бірақ Car
не Bus
класстары қызмет етпейді. Барлығының бұрын қазір барлық үлкеністерге steeringWheel()
және handlebars()
түріндегі өтінімділіктерді қолдану қажет емес деп, біз байланыс интерфейсін көтеруіміз керек.
Зависимості аурусы принципі – бұл жеке кластардың арасындағы сұрауларды алып тастау туралы. ол шағын функционалды өзгерту арқылы өтінімді көмекке қолдау көрсету туралы. Ол “Абстракттыққа қол жеткіз. Конкреттіктерге қол жеткізбе.” деп айтады. Тыныштық айтылғанда, бұл біздіктердің құрылғанын интерфейс/шарттар не абстракттық кластар, конкреттік реализациялардан тысқану керек деп айтарымыз. Бұл принципті осы місалды аударып көруді көмекші болады.
<?php
namespace Database;
class Database
{
public function __construct(protected AdapterInterface $adapter)
{
}
}
interface AdapterInterface {}
class MysqlAdapter implements AdapterInterface {}
Қазір Database
кластарының конкреттік реализациясының бір інтерфейске байлануынан көмек көрсетуімізге байланысы бар мәнінен көбірек.
Егер біз команда бойынша жұмыс істесеміз және адаптерді команда қызметкері жұмыс істеп тұрса, біз оған біздікі модульді дұрыс тесттер үшін дұрыс mock қылуымыз келсе, біз оларды көмекші интерфейсі/шарты бойынша құжаттарын құрауымыз керек.
Бұл методты қолдану мағынасы – біздікі кодты тым бірше шкалалы көтеру. Егер жылдан айырылсақ, бізге екінші түрді базада жұмыс істеу көмекшісін көмекші интерфейсін құрау және оны инжекциялау керек болса, ұзақ қазір кодты қайта жазуды көрсетпейміз, себебі біз интерфейс арқылы белгіленген договор бойынша әдіптестерге байланыстыры аламыз.
Зависимості інжекциялары туралы түсіну керек бірінші рет. Олар Зависимості Инжекцияларымен бірдей емес, Контейнер – бұл оларды өзгерту үшін көмекші құрал, бірақ оларды ортақпенділікке өтініш ету үшін де қолдануға болады, себебі олар аз жататталады және көптеген жақтарда қолжетімді емес, Сервістік орнату – деп аталатын анти-паттерніді орналастыру үшін. Сіздікі кластарыңызға Сервіс Локатор ретінде ДИ контейнерін инжекциялау аргументсіз, онда, өзі тізбегін ауыстырудан жақсы, онда, сіз өзіңізді орналастырады жаттығуыздан ауысады. Бұл айтарлы өңірі болады және соңында тестілеуді көбірек қылар.
Көпшілік жаңа фреймворктерінің өзінде талапты болатын орынбасарлау контейнерлері бар, сіздікті заттарды біріктіруді конфигурация арқылы болдырып үйлестіруге мүмкіндік береді. Бұл өтінімнін салу мақсатында сіз жасауымыз көк боларынан тұрып тізілген бағаны тауып, тізілімді код жасауға боларынан толық ашықпенді және атырауымен басқа мұрагерді.