Mengapa (/ apakah) Bertrand Meyer menganggap subklasifikasi adalah satu-satunya cara untuk memperpanjang modul "tertutup"?

19

Dalam Konstruksi Perangkat Lunak Berorientasi Objek Meyer (1988) ia mendefinisikan prinsip terbuka / tertutup sebagai berikut:

  • Modul akan dikatakan terbuka jika masih tersedia untuk perpanjangan. Misalnya, harus dimungkinkan untuk menambahkan bidang ke struktur data yang dikandungnya, atau elemen baru ke set fungsi yang dijalankannya.
  • Modul akan dikatakan tertutup jika tersedia untuk digunakan oleh modul lain. Ini mengasumsikan bahwa modul telah diberikan deskripsi yang stabil dan terdefinisi dengan baik (antarmuka dalam arti menyembunyikan informasi).

Dia melanjutkan dengan mengatakan:

Jika Anda membuka kembali modul, Anda juga harus membuka kembali semua kliennya untuk memperbaruinya, karena mereka bergantung pada versi yang lama. ... [Masalah ini] muncul setiap kali sebuah modul harus diperluas oleh fungsi atau elemen data baru, memicu perubahan pada klien langsung dan tidak langsung. ... Dengan pendekatan klasik untuk desain dan pemrograman, tidak ada cara untuk menulis modul yang terbuka dan tertutup.

Solusi Meyer untuk dilema ini adalah: jangan pernah memperluas modul perpustakaan dengan memodifikasi kelas yang ada; sebagai gantinya, tulis modul baru yang mensubkelaskan kelas yang ada, dan minta klien baru bergantung pada modul baru itu.

Sekarang, pada tahun 1988, saya menulis program mainan (prosedural) di Turbo Pascal dan Blankenship Basic, dan pengalaman profesional abad ke-21 saya adalah pada JVM, CLR, dan dalam bahasa yang dinamis, jadi saya tidak tahu apa yang dimaksud Meyer oleh "pendekatan klasik untuk desain dan pemrograman".

Salah satu contoh konkret Meyer tentang mengapa modul klien harus dibuka kembali (pernyataan beralih pada enumerasi yang sekarang memiliki lebih banyak anggota, membutuhkan lebih banyak kasus) tampaknya cukup masuk akal, tetapi ia hampir tidak membenarkan pernyataan bahwa setiap kali Anda menambahkan fungsionalitas ke perpustakaan modul, Anda perlu memperbarui semua kliennya .

Apakah ada alasan historis bahwa pernyataan ini tampak jelas pada tahun 1988? Apakah, katakanlah, menambahkan fungsi atau struktur data ke pustaka C statis mengubah tata letak sedemikian rupa sehingga bahkan dengan API yang kompatibel mundur, klien harus dikompilasi ulang? Atau apakah Meyer benar-benar hanya berbicara tentang mekanisme untuk menegakkan kompatibilitas API?

David Moles
sumber
3
Pertanyaan menarik! Saya merasa bahwa jawabannya akan entah bagaimana terkait dengan perbedaan mendasar antara Jenis Data Abstrak dan Abstraksi Data Berorientasi Objek , yang merupakan dua mekanisme abstraksi data yang dominan dalam Pemrograman Modular (apa yang disebut Betrand Meyer sebagai "pendekatan klasik" ") dan Pemrograman Berorientasi Objek (baca komentar!), masing-masing.
Jörg W Mittag
Itu aneh. Tampaknya sangat bertentangan dengan kenyataan (bahkan pada tahun 1988). Juga, pendekatannya yang dianjurkan akan menghasilkan pengembangan modul yang tidak membantu.
@ dan1111: Pendekatan Eiffel terhadap pewarisan, termasuk, tetapi tidak terbatas pada pendekatannya terhadap pewarisan berganda berbeda dari C ++, Java, C #, dll., sehingga tidak mengherankan bahwa pendekatannya berbeda. Dia mengembangkan Eiffel secara khusus untuk mendukung pandangannya tentang OO.
Jörg W Mittag

Jawaban:

18

Sejauh yang saya tahu, pertanyaan ini telah dijawab oleh Bertrand Meyer sendiri, dan jawabannya adalah, pernyataan ini tidak akurat. Dengan pendekatan klasik untuk merancang dan pemrograman, ada memang bisa menjadi cara untuk menulis modul yang baik terbuka dan tertutup.

Untuk mengetahuinya, Anda perlu mempelajari edisi kedua buku ini (diterbitkan sembilan tahun kemudian, pada tahun 1997). Menurut Kata Pengantar untuk edisi kedua , itu

bukan pembaruan tetapi hasil pengerjaan ulang menyeluruh. Tidak satu paragraf dari versi asli tidak tersentuh. (Sebenarnya, tidak satu baris.)

Secara khusus, pernyataan yang membingungkan Anda telah hilang. Masih ada bab prinsip Tertutup Terbuka di "§3.3 Lima Prinsip", dan ada diskusi lebih lanjut menyeluruh dari topik ini di "§14.7 Pengantar Warisan" tetapi pernyataan dari edisi pertama tidak ada lagi.

Apa yang ada di sana sebagai gantinya berfokus pada bagaimana lebih mudah dan idiomatis dalam pendekatan OO yang bertentangan dengan cara-cara sebelumnya,

Berkat warisan, pengembang OO dapat mengadopsi pendekatan pengembangan perangkat lunak yang jauh lebih banyak daripada yang mungkin dilakukan dengan metode sebelumnya ... (§3.3)

Persyaratan ganda ini (terbuka dan tertutup) terlihat seperti dilema, dan struktur modul klasik tidak memberikan petunjuk. Tapi warisan menyelesaikannya. Kelas ditutup, karena itu dapat dikompilasi, disimpan di perpustakaan, baselined, dan digunakan oleh kelas klien. Tapi itu juga terbuka, karena setiap kelas baru dapat menggunakannya sebagai orangtua, menambahkan fitur baru dan mendeklarasikan ulang fitur bawaan; dalam proses ini tidak perlu mengubah aslinya atau mengganggu kliennya ... (§14.7)

Karena Anda juga tampaknya bertanya-tanya tentang apa yang dimaksud "pendekatan klasik" Meyer di sini, Anda dapat menemukan penjelasannya di §4.7 Struktur Modular Tradisional . Bagian ini menjelaskan bahwa ini berarti "perpustakaan rutin" dan "paket" (untuk yang terakhir, penulis mengatakan istilah ini diambil dari Ada dan menyebutkan bahasa lain yang memiliki fitur ini - cluster di CLU dan modul di Modula).

Jika Anda memikirkannya, tidak satu pun dari pendekatan ini pada awalnya dimaksudkan untuk membantu dalam penulisan kode yang menganut prinsip terbuka-tertutup. Hal ini dapat mengarahkan penulis ke penilaian yang agak prematur yang kemudian diperbaiki di edisi kedua.


Adapun apa yang secara khusus membuat penulis berubah pikiran tentang pernyataan itu di antara edisi pertama dan kedua, saya pikir orang dapat menemukan jawaban, lagi, dalam buku itu sendiri, yaitu di Bagian F: Menerapkan metode dalam berbagai bahasa dan lingkungan " . bab ini, penulis membahas bagaimana metode berorientasi objek dapat digunakan dalam bahasa yang lebih lama:

Bahasa klasik seperti Fortran sama sekali bukan OO, tetapi orang yang masih harus menggunakannya ... mungkin ingin menerapkan ide OO sebanyak mungkin dalam batasan pendekatan lama ini.

Secara khusus, pada bagian ini Meyer menjelaskan secara terperinci bagaimana mungkin untuk menerapkan warisan (dengan beberapa peringatan dan batasan, tetapi masih) di C dan bahkan di Fortran.

Anda lihat, ini benar-benar panggilan untuk merevisi pernyataan itu dari edisi pertama. Tampaknya mustahil untuk menjelaskan bagaimana mendamaikan "dengan pendekatan klasik ... tidak ada cara" dengan contoh-contoh realistis tentang bagaimana tepatnya hal itu dapat dilakukan.

agas
sumber
Menarik, dan saya pasti harus mencoba untuk mendapatkan edisi kedua, tetapi masih belum jelas bagi saya mengapa bahkan perpustakaan "klasik" non-OO tidak dapat menambahkan (setidaknya jenis tertentu) fitur tanpa mengganggu nya klien.
David Moles
Hal @DavidMoles adalah, itu bisa , dan bagian terakhir dari jawaban saya menjelaskan hal itu, dan bahwa Meyer sendiri menyadari bahwa (ketika ia mengerjakan ulang untuk Edisi ke-2) dan bahkan memberikan contoh bagaimana hal itu dapat dilakukan. "Adapun apa yang secara khusus membuat penulis berubah pikiran ..." etc
agustus
Hmm. Saya tidak melihat "versi 2 perpustakaan ini, yang menggantikan versi 1 dan kompatibel dengan itu, menambahkan fungsi berikut ..." sebagai "warisan" kecuali dalam cara konseptual seluas mungkin.
David Moles
(Warisan, bagi saya, menyiratkan bahwa versi 1 masih ada dan dipanggil oleh versi 2.)
David Moles
@DavidMoles menggantikan dengan versi 2 (seperti dalam, mengubah kode sumber dan kompilasi ulang ) tidak akan memenuhi syarat sebagai "ditutup untuk modifikasi", Anda cukup memeriksa ini di artikel Wikipedia : "entitas dapat memungkinkan perilakunya diperluas tanpa mengubah kode sumbernya ... "
agas