Apakah perubahan kinerja melanggar Prinsip Substitusi Liskov?

14

Katakan saya punya:

interface Thing
{
    GetThing();
}

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

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

Apakah ini merupakan pelanggaran terhadap Prinsip Pergantian Liskov?

ConditionRacer
sumber
GetThingFromDatabase()tidak cukup lambat untuk membuat ini kontroversial. Factor4096BitPublicKey();return 1;akan membuat hal-hal sedikit lebih menarik.
Patrick
1
Jika Anda mengganti FastThingdengan SlowThing, LSP tidak berlaku. Jika Anda menambahkan komentar Thing::GetThingyang mengatakan "Sangat cepat", pertanyaannya dapat didiskusikan.
Cephalopod

Jawaban:

14

Itu sangat tergantung. Beberapa antarmuka memiliki, misalnya, kendala kompleksitas (ini jelas tidak dapat ditegakkan secara terprogram). Kasus paling mendasar adalah "GetThing () memberikan int- yaitu, ia berhenti", dalam hal ini, jawabannya adalah "Tidak" - kedua versi GetThing () berhenti dan kembalikan int.

Tetapi banyak antarmuka telah menyiratkan atau secara eksplisit menyatakan jaminan kinerja, baik dalam kompleksitas atau dalam waktu datar. Misalnya, dalam Standar C ++, ilegal untuk mengimplementasikan perpustakaan dengan panggilan pemblokiran kecuali jika Standar secara tegas mengizinkan.

DeadMG
sumber
3
Kinerja bukanlah sesuatu yang dapat ditegakkan melalui pemeriksaan tipe. Ini janji pelaksana / pengelola perpustakaan.
dietbuddha
3
Saya secara eksplisit menyatakan demikian dalam jawaban saya?
DeadMG
1
Maksud saya adalah bahwa begitu Anda memasukkan apa pun selain mengetik dalam kriteria Anda tidak lagi berbicara tentang Liskov karena khusus untuk mengetik. Meskipun "praktik" tidak menundukkan objek yang berkinerja berbeda mungkin baik, Liskov sendiri tidak mengatakan apa-apa tentang itu.
dietbuddha
7
Liskov menyatakan bahwa untuk Berasal, itu harus dapat digunakan di mana pun Basis berada. Itu mungkin tidak benar jika Pangkalan menjamin kinerja atau karakteristik tertentu. Misalnya, jika berasal blok, mungkin ada potensi kebuntuan.
DeadMG
8

TL; DR: Tidak

Menurut "Subtyping Perilaku Menggunakan Invarian dan Kendala" (formalisasi prinsip) itu terutama berkaitan dengan sifat "keamanan" dari jenis objek. Properti yang mengatur substitusi hanya dalam konteks tipe informasi. Jenis objek adalah orthogonal untuk kinerjanya. Oleh karena itu perbedaan dalam kinerja bukan merupakan pelanggaran terhadap Prinsip Pergantian Liskov.

dietbuddha
sumber
3
Saya hanya melihat sekilas ke kertas itu, tetapi apakah Anda yakin bahwa batasan waktu tidak dapat dibuat secara formal terbukti? Dan bahkan jika Liskov tidak berarti bahwa dalam kata-kata, termasuk batasan waktu dapat dilihat sebagai perpanjangan yang baik dari LSP klasik yang mungkin relevan dengan pemrograman dunia nyata.
Doc Brown
@ Doc Brown: apakah waktu berguna sebagai pertimbangan untuk mengganti suatu objek atau tidak adalah ortogonal untuk Liskov. Untuk dapat menambahkannya sebagai aturan sperate, tetapi tidak dapat dan tidak akan pernah menjadi bagian dari Liskov. Ini seperti memiliki persamaan logika Boolean dan mengatakan! Salah hanya dapat diganti dengan Benar jika itu cukup cepat. Kecepatan tidak ada hubungannya dengan matematika atau logika.
dietbuddha
Contoh-balik: kode ini disebut dalam Java EDT, atau dalam loop acara Node. Kinerja yang lambat dari versi lambat akan membuat semi-break software. Saya pikir jawaban yang tepat untuk pertanyaan ini adalah "mungkin tidak tetapi ada pengecualian".
user949300
6

Apa jaminan yang dihasilkan antarmuka? Karena GetThingtidak ada jaminan maka subtipe tidak perlu menghormatinya.

Jika antarmuka adalah sesuatu seperti GetThingInLinearTimeatau jika tipe dasar adalah virtual dan implementasi standar adalah satu kompleksitas, maka membuat kompleksitas algoritme yang lebih buruk akan melanggar LSP.

Telastyn
sumber
4

Kinerja perangkat lunak tidak ada hubungannya dengan Prinsip Substitusi Liskov.

Prinsipnya ada hubungannya dengan subtipe, dan dampak perilaku dari mengganti objek itu hanya dalam istilah OOP.

Input dan output getThing()tetap sama untuk kedua kasus, dan keduanya lambat dan cepat cenderung menempatkan objek dalam keadaan yang sama.

Reactgular
sumber
1

Apakah penting apa yang dikatakan Prinsip Substitusi Liskov itu sendiri? Jika subtipe melanggar harapan konsumen dari supertipe, itu sepertinya hal yang buruk terlepas dari apakah LSP lebih ketat.

Jadi dalam pandangan saya, apakah semua harapan yang masuk akal dari pengguna sebuah abstraksi dipenuhi oleh subtipe tampaknya menjadi generalisasi yang baik dari LSP.

Namun, dalam contoh Anda telah memposting dan dengan antarmuka Java secara umum, tidak jelas bahwa pengguna Thingantarmuka memiliki harapan yang masuk akal apakah harus cepat atau lambat. Jika javadocs antarmuka menyertakan bahasa tentang operasi apa yang dijanjikan akan cepat, maka mungkin ada argumen untuk masalah dengan alasan kinerja. Tetapi konvensi Java tentu untuk berbagai implementasi memiliki karakteristik kinerja yang berbeda.

trptkolin
sumber
2
sejauh yang saya tahu, contoh yang diposting bukan Java
nyamuk
0

Paman Bob menjawab pertanyaan yang sangat mirip di mana ia menyatakan bahwa pelanggaran LSP membutuhkan 3 pihak:

Tipe T, Subtipe S, dan program P yang menggunakan T tetapi diberi instance S.

Saya berani menebak bahwa pertanyaan ini memiliki struktur yang sama dengan yang dia jawab, dalam hal itu tidak menyebutkan P yang menggunakan T dan perilaku apa yang diharapkan P.

Anda dapat menemukan jawabannya di sini . (Anda harus menggulir ke bawah dan mencari jawaban dari pengguna bernama Robert Martin)

TMc
sumber
1
bagaimana ini menjawab pertanyaan yang diajukan?
nyamuk
@gnat Karena pertanyaannya, seperti yang ditanyakan, tidak lengkap. Dibutuhkan 3 pihak untuk menentukan pelanggaran LSP. Dari jumlah tersebut, ia hanya memasok 2 pihak.
TMc