Книги Українською Мовою » 💛 Інше » Занурення в патерни проектування, Олександр Швець 📚 - Українською

Читати книгу - "Занурення в патерни проектування, Олександр Швець"

В нашій бібліотеці можна безкоштовно в повній версії читати книгу онлайн українською мовою "Занурення в патерни проектування" автора Олександр Швець. Жанр книги: 💛 Інше. Наш веб сайт ReadUkrainianBooks.com дає можливість читати повні версії улюблених книг на Вашому гаджеті (IPhone, Android) або комп’ютері абсолютно безкоштовно, без реєстрації та СМС. Також маєте можливість завантажити книги на свій гаджет у форматі PDF, EPUB, FB2. Файли електронних книг - це цифрові файли, які призначені для перегляду на спеціальних пристроях, що відомі як читальні пристрої для електронних книг.

Шрифт:

-
+

Інтервал:

-
+

Добавити в закладку:

Добавити
1 ... 8 9 10 ... 58
Перейти на сторінку:
вміє году­ва­ти виклю­чно бен­га­льську поро­ду котів (під­клас котів): feed(BengalCat c). Що буде з кліє­нтським кодом? Він так само пода­сть до мето­ду зви­чайно­го кота, проте метод вміє году­ва­ти тільки бен­га­лів, тому не зможе від­пра­цю­ва­ти, "зла­ма­вши" кліє­нтський код.

Тип зна­че­ння мето­ду під­кла­су, що пове­ртає­ться, пови­нен збі­га­ти­ся або бути під­ти­пом зна­че­ння базо­во­го мето­ду, що пове­ртає­ться. Тут все те саме, що і в попе­ре­дньо­му пункті, але навпаки.

Базо­вий метод: buyCat(): Cat. Кліє­нтський код очі­кує на вихо­ді будь-якого хатньо­го кота. Добре: Метод під­кла­су: buyCat(): BengalCat. Кліє­нтський код отри­має бен­га­льсько­го кота, який є хатнім котом, тому все буде добре. Пога­но: Метод під­кла­су: buyCat(): Animal. Кліє­нтський код "зла­має­ться", оскі­льки незро­зумі­ла тва­ри­на (можли­во, кро­ко­дил) не помі­сти­ться у ящику для пере­не­се­ння котів.

Ще один анти-при­клад зі світу мов з дина­мі­чною типі­за­цією: базо­вий метод пове­ртає рядок, а пере­ви­зна­че­ний метод — число.

Метод не пови­нен вики­да­ти виклю­че­ння, які не вла­сти­ві базо­во­му мето­ду. Типи виклю­че­нь у пере­ви­зна­че­но­му мето­ді пови­нні збі­га­ти­ся або бути під­ти­па­ми виклю­че­нь, які вики­даю­ть базо­вий метод. Блоки try-catch у кліє­нтсько­му коді спря­мо­ва­ні на конкре­тні типи виклю­че­нь, що вики­даю­ться базо­вим мето­дом. Тому неспо­ді­ва­не виклю­че­ння, вики­ну­те під­кла­сом, може про­ско­чи­ти скрі­зь обро­бни­ка кліє­нтсько­го коду та при­зве­сти до збою в програмі.

У більшо­сті суча­сних мов про­гра­му­ва­ння, осо­бли­во стро­го типі­зо­ва­них (Java, C# та інші), пере­ра­хо­ва­ні обме­же­ння вбу­до­ва­но без­по­се­ре­дньо у компі­ля­тор. Тому при їхньо­му пору­ше­нні ви не змо­же­те зібра­ти програму.

Метод не пови­нен поси­лю­ва­ти перед-умови. Напри­клад, базо­вий метод пра­цює з пара­ме­тром типу int. Якщо під­клас вима­гає, щоб зна­че­ння цього пара­ме­тра було більшим за нуль, то це поси­лює вимо­ги перед­умо­ви. Кліє­нтський код, який до цього від­мі­нно пра­цю­вав, подаю­чи до мето­ду нега­ти­вні числа, тепер зла­має­ться при робо­ті з об’єктом підкласу.

Метод не пови­нен посла­блю­ва­ти пост-умови. Напри­клад, базо­вий метод вима­гає, щоб після заве­рше­ння мето­ду всі під­клю­че­ння до бази даних було закри­то, а під­клас зали­шає ці під­клю­че­ння від­кри­ти­ми, щоб потім вико­ри­сто­ву­ва­ти повто­рно. Проте кліє­нтський код базо­во­го класу нічо­го про це не знає. Він може заве­рши­ти про­гра­му від­ра­зу після викли­ку мето­ду, зали­ши­вши в систе­мі запу­ще­ні про­це­си-при­ви­ди.

Інва­ріа­нти класу пови­нні зали­ши­ти­ся без змін. Інва­ріа­нт — це набір умов, за яких об’єкт має сенс. Напри­клад, інва­ріа­нт кота — це наявні­сть чоти­рьох лап, хво­ста, зда­тні­сть мурко­ті­ти та інше. Інва­ріа­нт може бути опи­са­но не тільки явно, контра­ктом або пере­ві­рка­ми в мето­дах класу, але й побі­чно, напри­клад, юніт-теста­ми або кліє­нтським кодом.

Цей пункт легше за все пору­ши­ти при спа­дку­ва­нні, оскі­льки ви може­те про­сто не підо­зрю­ва­ти про існу­ва­ння якої­сь з умов інва­ріа­нта скла­дно­го класу. Ідеа­льним був би під­клас, який тільки вво­ди­ть нові мето­ди й поля, не торкаю­чи­сь полів базо­во­го класу.

Під­клас не пови­нен змі­ню­ва­ти зна­че­ння при­ва­тних полів базо­во­го класу. Цей пункт може зву­ча­ти дивно, але в деяких мовах про­гра­му­ва­ння доступ до при­ва­тних полів можна отри­ма­ти через меха­ні­зм рефле­ксії. В інших мовах, на кшта­лт Python та JavaScript, зовсім немає жорстко­го захи­сту при­ва­тних полів.

При­клад

Щоб закри­ти тему принци­пу під­ста­но­вки, давайте роз­гля­не­мо при­клад невда­лої ієра­рхії кла­сів документів.

ДО: під­клас «обну­ляє» робо­ту базо­во­го методу.

Метод збе­ре­же­ння в під­кла­сі ReadOnlyDocuments вики­не виня­ток, якщо хтось нама­га­ти­ме­ться викли­ка­ти його метод збе­ре­же­ння. Базо­вий метод не має тако­го обме­же­ння. Тому кліє­нтський код зму­ше­ний пере­ві­ря­ти тип доку­ме­нта під час збе­ре­же­ння всіх документів.

При цьому пору­шує­ться ще й принцип від­кри­то­сті/закри­то­сті, оскі­льки кліє­нтський код почи­нає зале­жа­ти від конкре­тно­го класу, який не можна замі­ни­ти на інший, не вно­ся­чи змін до кліє­нтсько­го коду.

ПІСЛЯ: під­клас роз­ши­рює базо­вий клас новою поведінкою.

Про­бле­му можна вирі­ши­ти, якщо пере­прое­кту­ва­ти ієра­рхію кла­сів. Базо­вий клас зможе тільки від­кри­ва­ти доку­ме­нти, але не мати­ме змоги збе­рі­га­ти їх. Під­клас, який тепер нази­ва­ти­ме­ться WritableDocument, роз­ши­ри­ть пове­ді­нку батькі­всько­го класу, дозво­ли­вши збе­ре­гти документ.

I Принцип поді­лу інте­рфе­йсу Interface Segregation Principle

Кліє­нти не пови­нні зале­жа­ти від мето­дів, які вони не вико­ри­сто­вую­ть.

Пра­гні­ть дося­гти того, щоб інте­рфе­йси були доси­ть вузьки­ми, а кла­сам не дово­ди­ло­ся б реа­лі­зо­ву­ва­ти надмі­рну поведінку.

Принцип поді­лу інте­рфе­йсів каже про те, що зана­дто «товсті» інте­рфе­йси нео­бхі­дно роз­ді­ля­ти на більш мале­нькі й спе­ци­фі­чні, щоб кліє­нти мале­ньких інте­рфе­йсів знали тільки про мето­ди, нео­бхі­дні їм для робо­ти. В резуль­та­ті при зміні мето­ду інте­рфе­йсу не пови­нні змі­ню­ва­ти­ся кліє­нти, які цей метод не вико­ри­сто­вую­ть.

Успа­дку­ва­ння дозво­ляє класу мати тільки один супе­рклас, але не обме­жує кількі­сть інте­рфе­йсів, які він може реа­лі­зу­ва­ти. Більші­сть об’єктних мов про­гра­му­ва­ння дозво­ляю­ть кла­сам реа­лі­зо­ву­ва­ти від­ра­зу кілька інте­рфе­йсів, тому немає потре­би заштов­ху­ва­ти у ваш інте­рфе­йс більше пове­ді­нок, ніж він того потре­бує. Ви завжди може­те при­свої­ти класу від­ра­зу кілька менших інтерфейсів.

При­клад

Уяві­ть бібліо­те­ку для робо­ти з хма­рним про­вайде­ра­ми. У першій версії вона під­три­му­ва­ла тільки Amazon, який має повний набір хма­рних послуг. На під­ста­ві цього й прое­кту­ва­вся інте­рфе­йс майбу­тніх класів.

Але пізні­ше стало зро­зумі­ло, що такий інте­рфе­йс хма­рно­го про­вайде­ра зана­дто широ­кий, оскі­льки є інші про­вайде­ри, які реа­лі­зую­ть тільки части­ну з усіх досту­пних сервісів.

ДО: не всі кліє­нти можу­ть реа­лі­зу­ва­ти опе­ра­ції інтерфейсу.

Щоб не пло­ди­ти класи з поро­жньою реа­лі­за­цією, роз­ду­тий інте­рфе­йс можна роз­би­ти на части­ни. Класи, які були зда­тні реа­лі­зу­ва­ти всі опе­ра­ції ста­ро­го інте­рфе­йсу, можу­ть реа­лі­зу­ва­ти від­ра­зу кілька нових частко­вих інтерфейсів.

ПІСЛЯ: роз­ду­тий інте­рфе­йс роз­би­тий на частини.

D Принцип інве­рсії зале­жно­стей Dependency Inversion Principle

Класи верх­ніх рівнів не пови­нні зале­жа­ти від кла­сів нижніх рівнів. Оби­два пови­нні зале­жа­ти від абстра­кцій. Абстра­кції не пови­нні зале­жа­ти від дета­лей. Дета­лі пови­нні зале­жа­ти від абстракцій.

Зазви­чай під час прое­кту­ва­ння про­грам можна виді­ли­ти два

1 ... 8 9 10 ... 58
Перейти на сторінку:

 Увага!

Сайт зберігає кукі вашого браузера. Ви зможете в будь-який момент зробити закладку та продовжити читання книги «Занурення в патерни проектування, Олександр Швець», після закриття браузера.

Коментарі та відгуки (0) до книги "Занурення в патерни проектування, Олександр Швець"