Чому підкласифікація є занадто поганою (і, отже, чому ми повинні використовувати прототипи, щоб усувати її)?


10

Я читав схеми дизайну, і читав, що модель дизайну прототипу не усуває зайву підкласифікацію.

Чому підкласифікація погана? Яку перевагу може мати використання прототипу над підкласифікацією?


каже хто? у вас є посилання?
Камю

Я читав с.118 цієї книги. goo.gl/6JGw1
David Faux

Відповіді:


19

Чому підкласифікація занадто погана

"Занадто багато" - це заклик судження; але візьми від мене це погано. Код, з яким я працюю, має спадщину DEEP, і код просто чортовий важко читати, розуміти, слідкувати, відстежувати, налагоджувати тощо. Написати тестовий код для цього матеріалу фактично неможливо.

Зразк прототипу не відповідає субкласифікації

Або питання означає "чи не забирає занадто багато підкласів?". Ця закономірність вимагає клонування об’єкта "шаблон", щоб уникнути підкласифікації, принаймні в цьому пункті. Не існує жодного правила, яке говорить про те, що "шаблон" не може бути підкласом.

Улюблений склад над спадщиною

Ця ідея тут також включає делегування та об'єднання. Дотримуючись цього евристичного засобу, програмне забезпечення має бути більш гнучким, легшим у обслуговуванні, розширенні та повторному використанні.

Коли клас складається з частин, ви можете замінити їх під час виконання . Це має глибокий вплив на доказовість.

Тестування простіше . Ви можете використовувати підроблені деталі (тобто "макети", "подвійні" та інші тестування-бесіди). Глибоке наслідування нашого коду означає, що ми повинні створити всю ієрархію, щоб перевірити будь-який біт цього. У нашому випадку це неможливо без запуску коду в реальному середовищі. Наприклад, нам потрібна база даних для створення об'єктів бізнесу.

Зміни пов'язані з побічними ефектами та невпевненістю - чим більше "основи" класу, тим більш поширені ефекти, добрі чи погані. Можуть бути бажані зміни, які ви не наважуєтеся внести через невизначеність побічних ефектів. Або зміна, яка є хорошою для якогось місця в нашому ланцюжку спадкування, є поганою для іншого. Це, безумовно, мій досвід.


Мені б дуже цікаво побачити кілька прикладів того, коли успадкування ускладнює тестування (особливо насмішкувато) і як композиція допомагає в цьому.
Арман

@alison: метод у похідному класі, який використовує інший метод із базового класу, де реалізація в базовому класі практично не дає змоги перевірити сценарії помилок. Якби це була композиція, було б простіше ввести предмет, який спричиняє виникнення помилки
Rune FS

@allison: Приклади? Коли база коду дуже велика, коли базові класи використовуються десятками класів безпосередньо та сотнями по спадку. Оскільки точка глибокого успадкування повторно використовується, і тому базовий клас генерізується до того, що трасування стека налагодження не може показати, які методи насправді викликаються. Нарешті, коли немає ін'єкції залежності, вже вбудований у такий Франкенштейн. Клас вищого рівня може бути "півдесятка або більше інших речей, які спільно" мають "десятки внутрішніх предметів - кожен з яких має власний будинок веселої спадщини.
radarbob

8

Я думаю, що одна з причин, яку це сприймає як погану практику, полягає в тому, що з часом кожен підклас може містити атрибути та методи, які не мають сенсу для цього об’єкта, чим далі ви спускаєтесь по ланцюгу (у погано розвиненій ієрархії). Ви можете закінчити роздутий клас, який містить елементи, які не мають сенсу для цього класу.

Я сам агностик щодо цього. Наче догматично сказати, що це погано. Будь-що погано при неправильному використанні.


2

Дві причини.

  1. Це виконання. Щоразу, коли ви викликаєте підклас з надкласового класу, ви здійснюєте виклик методу, тому якщо ви вклали п'ять класів і викликаєте метод у базовому класі, ви будете робити п'ять викликів методу. Більшість компіляторів / програм виконання намагаються розпізнати це та оптимізувати додаткові виклики, але це безпечно лише для дуже простих випадків.

  2. Це розум ваших колег-програмістів. Якщо ви вкладаєте п'ять класів, я повинен вивчити всі чотири батьківські класи, щоб встановити, що ви дійсно викликаєте метод у базовому класі, він стає втомливим. Можливо, мені також доведеться переглядати п'ять викликів методів під час налагодження програми.


6
-1: Ти маєш рацію про №2; але не про №1. Кілька шарів успадкування не обов'язково впливатимуть на час виконання.
Джим Г.

Турбуєшся про кілька додаткових процедурних дзвінків на рівні машинного коду та використання ОП та успадкування, і ти турбуєшся про
розумність

@JimG. Це не може, але може. :) Також можна потурбуватися про використання пам'яті: якщо ви не повторно використовуєте всі базові змінні, вони все одно можуть бути виділені як частина побудови об'єкта.
Адам Лір

2

"Занадто багато" - це заклик судження.

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

Однак, користь композиції над спадщиною є гарним правилом.

Коли ви підкласуєте, тестування може бути складніше (як зазначав radarbob ). У глибокій ієрархії виділення проблемного коду складніше, оскільки інстанціювання підкласу вимагає залучення всієї ієрархії надкласового класу та купки додаткового коду. При композиційному підході ви можете виділити та протестувати кожен компонент свого об'єднаного об'єкта за допомогою одиничних тестів, макетних об'єктів тощо.

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

Один із прикладів, про які я можу придумати, - це java.util.Properties, який успадковується від Hashtable. Клас "Властивості" призначений лише для зберігання пар String-String (це відмічено в Javadocs). Через наслідування методи put and putAll від Hashtable потрапили до користувачів властивостей. У той час як "правильний" спосіб зберігання властивості є за допомогою setProperty (), абсолютно нічого не заважає користувачеві викликати put () та передавати його в String and Object.

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


2

Спадщина може порушити інкапсуляцію в деяких випадках, і якщо це трапиться, це погано. Читайте докладніше.


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

У міру розвитку потреб бібліотека може розвиватися і може мати більше клієнтів; або він може забезпечити розширену функціональність, успадкувавши від власного класу інші смаки. Все йде нормально.

Однак принциповим є те, що якщо програма переймає клас і починає його підклас, то тепер підклас - це клієнт, а не внутрішній партнер. Однак, на відміну від чіткого однозначного способу визначення загальнодоступного API, підклас тепер значно глибше всередині бібліотеки (доступ до всіх приватних змінних тощо). Це ще не погано, але бридкий персонаж може передати API, який занадто багато всередині APP, а також у бібліотеці,

По суті, хоча це не завжди так, але,

Легко використати спадщину, щоб порушити інкапсуляцію

Дозволити підкласифікацію може бути помилковим, якщо це зробити.


1

Короткий швидкий відповідь:

Це залежить від того, що ти робиш.

Розширений нудний відповідь:

Розробник може зробити додаток. використовуючи або шаблони підкласифікації, або (прототипи). Іноді одна техніка працює краще. Іноді інша техніка працює краще.

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

Додаткова примітка:

Деякі відповіді стосуються "багаторазового успадкування". Незважаючи на це, не головне питання, це пов'язано з темою. Існує кілька подібних публікацій про "множинне спадкування проти складу". У мене був випадок, коли я змішую обоє.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.