Чи зміни в роботі порушують принцип заміни Ліскова?


14

Скажіть, у мене є:

interface Thing
{
    GetThing();
}

class FastThing : Thing 
{
    public int GetThing()
    {
        return 1;
    }
}

class SlowThing : Thing
{
    public int GetThing()
    {
        return GetThingFromDatabase();
    }
}

Це порушення принципу заміни Ліскова?


GetThingFromDatabase()недостатньо повільно, щоб зробити це суперечливим. Factor4096BitPublicKey();return 1;зробив би речі трохи цікавішими.
Патрік


1
Якщо ви заміните FastThingна SlowThing, LSP не застосовується. Якщо ви додасте коментар, до Thing::GetThingякого сказано "Дуже швидко", питання можна обговорити.
Головопад

Відповіді:


14

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

Але багато інтерфейсів передбачають або прямо заявляють гарантії продуктивності, як за складністю, так і за рівний час. Наприклад, у стандарті C ++ незаконно реалізовувати бібліотеку за допомогою виклику, що блокує, за винятком випадків, коли Стандарт це прямо дозволяє.


3
Продуктивність не є чимось придатним для перевірки типу. Це обіцянка виконавця / технічного обслуговування бібліотеки.
дієтабудда

3
Я це прямо заявив у своїй відповіді?
DeadMG

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

7
Лісков заявляє, що для Похідних він повинен бути використаний у будь-якому місці бази. Це може бути неправдою, якщо База гарантує певні характеристики чи характеристики. Наприклад, якщо Блоковані блоки можуть бути потенційними для тупикових ситуацій.
DeadMG

8

TL; DR: Ні

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


3
Я лише коротко ознайомився з цим документом, але ви впевнені, що обмеження в часі не можна зробити формально доказовими? І навіть якщо Лісков не мав на увазі, що на словах, включаючи обмеження в часі, можна розглядати як хороше розширення класичного LSP, яке може бути доречним для програмування в реальному світі.
Док Браун

@Doc Brown: чи тимчасова передача корисна для розгляду заміни об'єкта, чи ні, це ортогональна для Ліскова. Можна додати це як заповіт, але це не може і ніколи не буде частиною Лискова. Це як би мати логічне рівняння Булевого і сказати! Неправдиве може бути замінене істинним, лише якщо воно досить швидко. Швидкість не має нічого спільного з математикою чи логікою.
дієтабудда

Контрприклад: цей код викликається в EDT Java або в циклі подій Node. Докорінно повільніша робота повільної версії призведе до напівзлому програмного забезпечення. Я думаю, що відповідна відповідь на це питання "напевно, немає, але є винятки".
user949300

6

Які гарантії дає інтерфейс? Оскільки GetThingне дає гарантій, то підтипи не повинні його дотримуватися.

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


4

Продуктивність програмного забезпечення не має нічого спільного з Принципом заміни Ліскова.

Цей принцип пов'язаний із заміною підтипів та поведінковим впливом заміни цього об'єкта лише в термінах OOP.

Вхід і вихід getThing()залишаються однаковими для обох випадків, і повільний і швидкий, ймовірно, приводять об'єкти до одного стану.


1

Чи має значення те, що конкретно говорить сам Принцип заміщення Ліскова? Якщо підтип порушує сподівання споживача супертипу, це здається поганим, незалежно від того, чи є ЛСП більш обмежувальним.

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

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


2
наскільки я можу сказати, приклад розміщений не Java
gnat

0

Дядько Боб відповів на дуже подібне запитання, де він стверджує, що порушення ЛСП вимагає 3 сторін:

Тип T, підтип S і програма P, яка використовує T, але отримує екземпляр S.

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

Ви можете знайти його відповідь тут . (Вам потрібно буде прокрутити униз і шукати відповідь у користувача на ім’я Роберт Мартін)


1
як це відповідає на поставлене запитання?
гнат

@gnat Тому що запитання, як його задано, є неповним. Щоб визначити порушення ЛСП, потрібно 3 сторони. З яких він постачав лише 2 сторони.
TMc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.