Що таке "передчасна абстракція"?


10

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

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

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

(2) Опускати важливі речі - це одне, цілком можливо, що щось пропущено із специфікації, яка згодом виявляється важливою, рішення цього - не придумати власну конкрецію та витрачати ресурси, коли дізнаєшся здогадалися неправильно, це отримати більше інформації від клієнта.

Ми завжди повинні працювати від абстракцій до конкрементів, оскільки це найбільш прагматичний спосіб робити, а не навпаки.

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

Наведемо приклад, скажімо, що клієнт бажає створити робот для упаковки предметів:

public abstract class BaggingRobot() {
    private Collection<Item> items;

    public abstract void bag(Item item);
}

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

Немає такого поняття, як передчасна абстракція, лише передчасна конкреція. Що не так у цьому твердженні? Де вади моїх міркувань? Дякую.


1
Протилежністю передчасного абстрагування є YAGNI - You Ain't Gonna Need It, що, на мою думку, майже завжди неправильне. Майже. Я бачив, як це відбувається, але це рідко. Я здебільшого згоден з тим, що ви тут говорите.
користувач1118321

Відповіді:


19

Принаймні, на мою думку, передчасна абстракція є досить поширеною, і особливо це було на початку історії ООП.

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

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


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

1
@James: це також може означати абстрагування "занадто багато", ніж специфікації версії 1.0, оскільки ви вважаєте, що знаєте про нову вимогу в специфікації пізнішої версії, тому вже реалізуйте v1.0 більш загальним способом, ніж необхідні. Щось, добре передбачити, що може статися в більш пізній версії, але також існує певний ризик переобладнання.
Док Браун

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

6

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

Ви не додавали б абстракцію просто тому, що вона вам може знадобитися (без реальної основи для думки, вам потрібно буде додавати нові класи в майбутньому). Правильною метафорою тут може бути сантехніка. Будемо сподіватися, що 6-ти напрямна труба, яка дозволяє текти води вгору / вниз, схід / захід, північ / південь, буде найбільш гнучким типом труби, яку ви могли мати. Ви теоретично можете використовувати 6-спрямовану трубу в будь-якому місці, де потрібна труба, і перекрити непотрібні напрямки, правда?

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

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

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


Ви здаєтеся трохи classзосередженим ... Навіть якщо класів багато, абстракція не обмежується їх використанням / користю для них.
Deduplicator

1
@Deduplicator Справедливо, але це не міняє моєї точки зору. Якщо використовується абстракція, вона повинна бути негайно вигідною, або це має бути запланована зміна найближчим часом. Має значення не те, що ми маємо на увазі класи або функціональне програмування.
Ніл

3

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

Переглядаючи це, будь-який іменник (або іменникова фраза) буде розглядатися як можливий клас. Будь-які дієслова (або дієслівні фрази) були б потенційними методами на заняттях. Тож «мішковий робот» міг бути класом BaggingRobot. "Відкрити сумку" може стати методом OpenBag.

Після кількох ітерацій це перетвориться на діаграму класів.

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

Абстрактні класи вводяться лише тоді, коли стане зрозуміло, що:

  • Є кілька подібних класів, які могли б формувати ієрархію.
  • Вони насправді мають щось спільне, так що базовий клас виконує корисну мету.

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


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

Об'єкт BaggingRobot, який ставить об'єкти Item у об'єкти Bag, - це вже абстракція реального робота, який кладе речі в мішки.
користувач253751

1

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

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

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

Редагування Щоб відповісти на деякі моменти від коментарів у коментарях, я доповнюю це, щоб уточнити та відповісти таким чином, що не потребує тривалого ланцюга коментарів, а конкретніше стосується пунктів (1) та (2).

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

(Наголос мій). Якщо припустити, що в кінцевій програмі речі існуватимуть, це не саме те, що я бачу у вашому прикладі. Клієнт попросив робота-мішечка. Це дуже специфічний запит, якщо дещо розпливчастий у своїй мові. Замовник хоче, щоб робот, який мішкує предмети, тому ви виробляєте пару предметів

public class Item {
/* Relevant item attributes as specified by customer */
}
public class BaggingRobot {
  private Collection<Item> items;

  public void bag(Item item);
}

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

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

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

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


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

"Я б рекомендував більше спілкування щодо впровадження рішення про здогадки" - Ви маєте на увазі, як я запропонував? Цитуючи те, що я сказав в ОП, "рішення цього не полягає у створенні власної конкреції та відходів, коли ви зрозуміли, що неправільно здогадалися, це отримати більше інформації від клієнта".
Джеймс

"Хоча це може здатися нешкідливим просто ляпати" абстрактне "за визначенням класу і відчувати себе безпечним, знаючи, що ви можете продовжити його пізніше" - Коли я кажу "абстракція", я маю на увазі "абстракцію", я не маю на увазі "абстрактне ключове слово". Інтерфейси можуть бути абстракціями, абстракції - нечітка логіка, саме про це йдеться у всій публікації. Клієнт спілкується з точки зору абстракцій, тому ми повинні програмувати абстрактно, доки ми не дізнаємось більше про домен.
Джеймс

1
"Ви можете виявити, що вам ніколи не потрібно" - Це не має жодного сенсу. Клієнт каже: "Я хочу робота, який мішує речі", ви створюєте абстракцію, яка відповідає цим критеріям. Будь-яка додаткова інформація, яку ви отримаєте від клієнта, буде детальною інформацією про те, як вони хочуть зробити випуск. Це не скасовує вашу абстракцію. Клієнт не раптом передумує про основну ідею того, що купує. Робот все ще збирається до мішків. Створена вами абстракція все ще застосовуватиметься.
Джеймс

"або ви можете розширити його таким чином, що надто ускладнює дизайн вниз, абстрагуючи неправильні речі". ... Чи чесно ви прочитали те, що я сказав, або просто заголовок? Серйозно? Пункт читання (1) та (2)
Джеймс,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.