Mengapa banyak pengembang perangkat lunak melanggar prinsip terbuka / tertutup?

74

Mengapa banyak pengembang perangkat lunak melanggar prinsip terbuka / tertutup dengan memodifikasi banyak hal seperti mengganti nama fungsi yang akan merusak aplikasi setelah memutakhirkan?

Pertanyaan ini melompat ke kepala saya setelah versi cepat dan berkelanjutan di perpustakaan Bereaksi .

Setiap periode singkat saya melihat banyak perubahan dalam sintaks, nama komponen, ... dll

Contoh dalam versi React yang akan datang :

Peringatan Penghentian Baru

Perubahan terbesar adalah kami telah mengekstrak React.PropTypes dan React.createClass ke dalam paket mereka sendiri. Keduanya masih dapat diakses melalui objek Bereaksi utama, tetapi menggunakan salah satu akan mencatat peringatan penghentian satu kali ke konsol ketika dalam mode pengembangan. Ini akan memungkinkan optimasi ukuran kode di masa depan.

Peringatan ini tidak akan memengaruhi perilaku aplikasi Anda. Namun, kami menyadari bahwa mereka dapat menyebabkan beberapa frustrasi, terutama jika Anda menggunakan kerangka kerja pengujian yang memperlakukan console.error sebagai kegagalan.


  • Apakah perubahan ini dianggap sebagai pelanggaran terhadap prinsip itu?
  • Sebagai seorang pemula untuk sesuatu seperti Bereaksi , bagaimana saya mempelajarinya dengan perubahan cepat di perpustakaan (ini sangat membuat frustrasi)?
Anyname Donotcare
sumber
6
Ini jelas merupakan contoh mengamatinya , dan klaim Anda 'begitu banyak' tidak berdasar. Proyek Lucene dan RichFaces adalah contoh terkenal, dan API Windows COMM port, tapi saya tidak bisa memikirkan yang lain begitu saja. Dan apakah React benar-benar 'pengembang perangkat lunak besar'?
user207421
62
Seperti prinsip apa pun, OCP memiliki nilainya. Tapi itu mengharuskan pengembang memiliki pandangan jauh ke depan yang tak terbatas. Di dunia nyata, orang sering salah desain pertama mereka. Seiring berjalannya waktu, beberapa orang memilih untuk memperbaiki kesalahan lama mereka demi kompatibilitas, yang lain lebih memilih untuk akhirnya membersihkannya demi memiliki basis kode yang kompak dan tidak berbeban.
Theodoros Chatzigiannakis
1
Kapan terakhir kali Anda melihat bahasa berorientasi objek "seperti yang dimaksudkan"? Prinsip inti adalah sistem pengiriman pesan yang berarti setiap bagian dari sistem dapat diperpanjang oleh siapa pun. Sekarang bandingkan dengan bahasa khas OOP Anda - berapa banyak yang memungkinkan Anda memperluas metode yang ada dari luar? Berapa banyak yang membuatnya cukup mudah untuk berguna?
Luaan
Warisan menyebalkan. Pengalaman selama 30 tahun telah menunjukkan bahwa Anda harus sepenuhnya membuang warisan dan mulai segar, setiap saat. Hari ini setiap orang memiliki koneksi di mana-mana setiap saat, jadi warisan sama sekali tidak relevan hari ini. contoh terakhir adalah "Windows versus Mac". Microsoft secara tradisional mencoba "mendukung warisan", Anda melihat ini dalam banyak cara. Apple selalu mengatakan "F- - - You" kepada pengguna lawas. (Ini berlaku untuk semuanya, mulai dari bahasa hingga perangkat hingga OS). Faktanya, Apple benar-benar benar dan MSFT benar-benar salah, sederhana dan sederhana.
Fattie
4
Karena sebenarnya tidak ada "prinsip" dan "pola desain" yang bekerja 100% dari waktu dalam kehidupan nyata.
Matti Virkkunen

Jawaban:

148

Jawaban IMHO JacquesB, meskipun mengandung banyak kebenaran, menunjukkan kesalahpahaman mendasar dari OCP. Agar adil, pertanyaan Anda sudah mengungkapkan kesalahpahaman ini, juga - fungsi penamaan ulang merusak kompatibilitas , tetapi bukan OCP. Jika melanggar kompatibilitas tampaknya perlu (atau mempertahankan dua versi komponen yang sama agar tidak merusak kompatibilitas), OCP sudah rusak sebelumnya!

Seperti yang Jorg W Mittag katakan dalam komentarnya, prinsipnya tidak mengatakan "Anda tidak dapat mengubah perilaku komponen" - katanya, orang harus mencoba mendesain komponen dengan cara yang terbuka untuk digunakan kembali (atau diperluas) dalam beberapa hal, tanpa perlu modifikasi. Ini dapat dilakukan dengan memberikan "titik ekstensi" yang tepat, atau, sebagaimana disebutkan oleh @AntP, "dengan mendekomposisi struktur kelas / fungsi ke titik di mana setiap titik ekstensi alami ada di sana secara default." IMHO mengikuti OCP tidak memiliki kesamaan dengan "menjaga versi lama di sekitar tidak berubah untuk kompatibilitas mundur" ! Atau, mengutip komentar @ DerekElkin di bawah ini:

OCP adalah saran tentang cara menulis modul [...], bukan tentang menerapkan proses manajemen perubahan yang tidak pernah memungkinkan modul untuk berubah.

Pemrogram yang baik menggunakan pengalaman mereka untuk merancang komponen dengan mempertimbangkan titik ekstensi "benar" (atau - bahkan lebih baik - dengan cara tidak diperlukan titik ekstensi buatan). Namun, untuk melakukan ini dengan benar dan tanpa rekayasa ulang yang tidak perlu, Anda harus tahu sebelumnya bagaimana bentuk kasus penggunaan komponen Anda di masa depan. Bahkan programmer berpengalaman tidak dapat melihat masa depan dan mengetahui semua persyaratan yang akan datang sebelumnya. Dan itulah mengapa terkadang kompatibilitas ke belakang perlu dilanggar - tidak peduli berapa banyak titik ekstensi yang dimiliki komponen Anda, atau seberapa baik mengikuti OCP sehubungan dengan jenis persyaratan tertentu, akan selalu ada persyaratan yang tidak dapat diimplementasikan dengan mudah tanpa memodifikasi komponen.

Doc Brown
sumber
14
IMO alasan terbesar untuk "melanggar" OCP adalah karena dibutuhkan banyak upaya untuk menyesuaikannya dengan benar. Eric Lippert memiliki posting blog yang bagus tentang mengapa banyak kelas .NET framework tampaknya melanggar OCP.
BJ Myers
2
@ BJMyers: terima kasih atas tautannya. Jon Skeet memiliki postingan yang bagus tentang OCP karena beeing sangat mirip dengan ide variasi yang dilindungi.
Doc Brown
8
INI! OCP mengatakan bahwa Anda harus menulis kode yang dapat diubah tanpa disentuh! Mengapa? Jadi, Anda hanya perlu menguji, meninjau, dan mengompilasinya sekali. Perilaku baru harus berasal dari kode baru. Bukan dengan mengacaukan kode lama yang sudah terbukti. Bagaimana dengan refactoring? Refactoring yang baik jelas merupakan pelanggaran terhadap OCP! Itulah sebabnya menulis kode berpikir dosa Anda hanya akan menolaknya jika asumsi Anda berubah. Tidak! Masukkan setiap asumsi ke dalam kotak kecilnya sendiri. Jika salah, jangan perbaiki kotaknya. Tulis yang baru. Mengapa? Karena Anda mungkin perlu kembali ke yang lama. Ketika Anda melakukannya, alangkah baiknya jika masih berfungsi.
candied_orange
7
@CandiedOrange: terima kasih atas komentar Anda. Saya tidak melihat refactoring dan OCP sangat bertentangan saat Anda menggambarkannya. Untuk menulis komponen yang mengikuti OCP sering membutuhkan beberapa siklus refactoring. Tujuannya harus menjadi komponen yang tidak perlu modifikasi untuk menyelesaikan seluruh "keluarga" persyaratan. Namun demikian, seseorang tidak boleh menambahkan titik ekstensi sewenang-wenang ke komponen "berjaga-jaga", yang menyebabkan terlalu mudah untuk melakukan rekayasa ulang. Mengandalkan kemungkinan refactoring dapat menjadi alternatif yang lebih baik untuk ini dalam banyak kasus.
Doc Brown
4
Jawaban ini melakukan pekerjaan yang baik untuk memanggil kesalahan dalam jawaban teratas (saat ini) - Saya pikir hal utama tentang menjadi sukses dengan buka / tutup adalah berhenti berpikir dalam hal "titik ekstensi" dan untuk mulai berpikir tentang membusuk Anda struktur kelas / fungsi ke titik di mana setiap titik ekstensi alami ada secara default. Memprogram "luar dalam" adalah cara yang sangat baik untuk mencapai hal ini, di mana setiap skenario metode / fungsi Anda saat ini dijalankan didorong ke antarmuka eksternal, yang membentuk titik ekstensi alami untuk dekorator, adaptor, dll.
Semut
67

Prinsip terbuka / tertutup memiliki manfaat, tetapi juga memiliki beberapa kelemahan serius.

Secara teori prinsip ini memecahkan masalah kompatibilitas ke belakang dengan membuat kode yang "terbuka untuk ekstensi tetapi ditutup untuk modifikasi". Jika suatu kelas memiliki beberapa persyaratan baru, Anda tidak pernah memodifikasi kode sumber dari kelas itu sendiri tetapi malah membuat subkelas yang hanya menimpa anggota yang tepat yang diperlukan untuk mengubah perilaku. Karenanya, semua kode yang ditulis terhadap versi asli kelas tidak terpengaruh, sehingga Anda dapat yakin bahwa perubahan Anda tidak merusak kode yang ada.

Pada kenyataannya, Anda dengan mudah berakhir dengan kode mengasapi dan kelas-kelas usang yang membingungkan. Jika tidak mungkin untuk mengubah beberapa perilaku komponen melalui ekstensi, maka Anda harus memberikan varian baru komponen dengan perilaku yang diinginkan, dan menjaga versi lama tidak berubah untuk kompatibilitas ke belakang.

Katakanlah Anda menemukan cacat desain mendasar di kelas dasar yang banyak mewarisi dari kelas. Katakanlah kesalahan adalah karena bidang pribadi dari jenis yang salah. Anda tidak dapat memperbaikinya dengan mengabaikan anggota. Pada dasarnya Anda harus mengganti seluruh kelas, yang berarti Anda akhirnya memperluas Objectuntuk memberikan kelas dasar alternatif - dan sekarang Anda juga harus memberikan alternatif untuk semua subclass, sehingga berakhir dengan hierarki objek yang digandakan, satu hierarki cacat, satu ditingkatkan . Tetapi Anda tidak dapat menghapus hierarki yang cacat (karena penghapusan kode adalah modifikasi), semua klien di masa depan akan terkena kedua hierarki tersebut.

Sekarang jawaban teoretis untuk masalah ini adalah "desain saja dengan benar pertama kali". Jika kode diuraikan dengan sempurna, tanpa cacat atau kesalahan, dan dirancang dengan titik ekstensi yang disiapkan untuk semua kemungkinan perubahan persyaratan di masa depan, maka Anda menghindari kekacauan. Namun pada kenyataannya semua orang membuat kesalahan, dan tidak ada yang bisa memprediksi masa depan dengan sempurna.

Ambil sesuatu seperti .NET framework - masih membawa sekitar sekumpulan kelas koleksi yang dirancang sebelum obat generik diperkenalkan lebih dari satu dekade lalu. Ini tentu merupakan keuntungan bagi kompatibilitas ke belakang (Anda dapat meningkatkan kerangka kerja tanpa harus menulis ulang apa pun), tetapi juga membengkak kerangka kerja dan memberi pengembang sejumlah pilihan di mana banyak yang sudah usang.

Rupanya para pengembang React merasa tidak sepadan dengan biaya dalam kerumitan dan kode-gembung untuk secara ketat mengikuti prinsip terbuka / tertutup.

Alternatif pragmatis untuk membuka / menutup dikontrol depresiasi. Daripada melanggar kompatibilitas ke belakang dalam satu rilis, komponen lama disimpan untuk siklus rilis, tetapi klien diberitahu melalui peringatan kompiler bahwa pendekatan lama akan dihapus dalam rilis berikutnya. Ini memberi klien waktu untuk memodifikasi kode. Ini tampaknya menjadi pendekatan Bereaksi dalam kasus ini.

(Penafsiran saya tentang prinsip ini didasarkan pada Prinsip Terbuka-Terbuka oleh Robert C. Martin)

JacquesB
sumber
37
"Prinsipnya pada dasarnya mengatakan kamu tidak bisa memodifikasi perilaku komponen. Sebaliknya kamu harus memberikan varian komponen yang baru dengan perilaku yang diinginkan, dan menjaga versi lama tidak berubah untuk kompatibilitas ke belakang." - Saya tidak setuju dengan ini. Prinsip tersebut mengatakan bahwa Anda harus merancang komponen sedemikian rupa sehingga tidak perlu mengubah perilakunya karena Anda dapat memperluasnya untuk melakukan apa yang Anda inginkan. Masalahnya adalah bahwa kita belum menemukan cara melakukannya, terutama dengan bahasa yang saat ini digunakan secara luas. Masalah Ekspresi adalah salah satu bagian dari ...
Jörg W Mittag
8
... itu, misalnya. Baik Java maupun C♯ tidak memiliki solusi untuk Ekspresi. Haskell dan Scala melakukannya, tetapi basis pengguna mereka jauh lebih kecil.
Jörg W Mittag
1
@Iorgio: Di Haskell, solusinya adalah kelas tipe. Dalam Scala, solusinya adalah implisit dan objek. Maaf, saat ini saya tidak memiliki tautannya. Ya, multimethods (sebenarnya, mereka bahkan tidak perlu "multi", itu sifat "terbuka" dari metode Lisp yang diperlukan) juga merupakan solusi yang mungkin. Perhatikan bahwa ada beberapa frasa masalah ekspresi, karena biasanya makalah ditulis sedemikian rupa sehingga penulis menambahkan batasan pada masalah ekspresi yang menghasilkan fakta bahwa semua solusi yang ada saat ini menjadi tidak valid, kemudian menunjukkan bagaimana caranya sendiri ...
Jörg W Mittag
1
... bahasa bahkan dapat menyelesaikan versi "lebih keras" ini. Sebagai contoh, Wadler awalnya mengutarakan masalah ekspresi tidak hanya tentang ekstensi modular, tetapi ekstensi modular aman secara statis . Namun multimethod umum Lisp tidak aman secara statis, mereka hanya aman secara dinamis. Odersky kemudian memperkuat ini lebih jauh dengan mengatakan itu harus modular aman secara statis, yaitu keselamatan harus dapat diperiksa secara statis tanpa melihat keseluruhan program, hanya dengan melihat modul ekstensi. Ini sebenarnya tidak dapat dilakukan dengan kelas tipe Haskell, tetapi dapat dilakukan dengan Scala. Dan di ...
Jörg W Mittag
2
@Iorgio: Tepat. Hal yang membuat multimethods Common Lisp menyelesaikan EP sebenarnya bukan pengiriman ganda. Itu adalah fakta bahwa metodenya terbuka. Dalam FP biasa (atau pemrograman prosedural), jenis diskriminasi terkait dengan fungsi. Dalam OO khas, metode terikat pada jenis. Metode umum Lisp terbuka , mereka dapat ditambahkan ke kelas setelah fakta dan dalam modul yang berbeda. Itulah fitur yang membuat mereka dapat digunakan untuk menyelesaikan EP. Misalnya, protokol Clojure adalah pengiriman tunggal, tetapi juga menyelesaikan EP (selama Anda tidak bersikeras pada keamanan statis).
Jörg W Mittag
20

Saya akan menyebut prinsip buka / tutup sebagai ideal. Seperti semua cita-cita, itu memberikan sedikit pertimbangan untuk realitas pengembangan perangkat lunak. Seperti halnya semua cita-cita, mustahil untuk benar-benar mencapainya dalam praktik - seseorang hanya berusaha mendekati ideal itu sebaik mungkin.

Sisi lain dari cerita ini dikenal sebagai Golden Borgol. Borgol Emas adalah apa yang Anda dapatkan ketika Anda terlalu banyak mengandalkan prinsip terbuka / tertutup. Borgol Emas adalah apa yang terjadi ketika produk Anda yang tidak pernah rusak kompatibilitas tidak dapat tumbuh karena kesalahan masa lalu yang terlalu banyak telah dibuat.

Contoh terkenal ini ditemukan di manajer memori Windows 95. Sebagai bagian dari pemasaran untuk Windows 95, dinyatakan bahwa semua aplikasi Windows 3.1 akan berfungsi di Windows 95. Microsoft sebenarnya memperoleh lisensi untuk ribuan program untuk mengujinya di Windows 95. Salah satu kasus yang bermasalah adalah Sim City. Sim City sebenarnya memiliki bug yang menyebabkannya menulis ke memori yang tidak terisi. Di Windows 3.1, tanpa manajer memori "yang tepat", ini adalah kesalahan kecil. Namun, pada Windows 95, manajer memori akan menangkap ini dan menyebabkan kesalahan segmentasi. Solusinya? Di Windows 95, jika nama aplikasi Anda simcity.exe, OS akan benar-benar mengendurkan kendala manajer memori untuk mencegah kesalahan segmentasi!

Masalah sebenarnya di balik cita-cita ini adalah konsep produk dan layanan yang dikupas. Tidak ada yang benar-benar melakukan yang satu atau yang lain. Semuanya berbaris di suatu tempat di wilayah abu-abu di antara keduanya. Jika Anda berpikir dari pendekatan yang berorientasi produk, buka / tutup terdengar seperti ideal. Produk Anda dapat diandalkan. Namun, ketika datang ke layanan, ceritanya berubah. Sangat mudah untuk menunjukkan bahwa dengan prinsip terbuka / tertutup, jumlah fungsionalitas yang harus didukung oleh tim Anda harus secara asimptotik mendekati tak terhingga, karena Anda tidak pernah dapat membersihkan fungsionalitas lama. Ini berarti tim pengembangan Anda harus mendukung semakin banyak kode setiap tahun. Akhirnya Anda mencapai titik puncaknya.

Sebagian besar perangkat lunak saat ini, terutama open source, mengikuti versi santai umum dari prinsip buka / tutup. Sangat umum untuk melihat terbuka / tertutup diikuti secara kasar untuk rilis kecil, tetapi ditinggalkan untuk rilis besar. Sebagai contoh, Python 2.7 berisi banyak "pilihan buruk" dari Python 2.0 dan 2.1 hari, tetapi Python 3.0 menyapu semuanya. (Juga, pergeseran dari Windows 95 basis kode untuk basis kode Windows NT ketika mereka merilis Windows 2000 pecah segala macam hal, tetapi tidak berarti kita tidak pernah harus berurusan dengan manajer memori memeriksa nama aplikasi untuk memutuskan perilaku!)

Cort Ammon
sumber
Itu cerita yang sangat bagus tentang SimCity. Apakah anda memiliki sumbernya?
BJ Myers
5
@BJMyers Ini adalah cerita lama, Joel Spoleky menyebutkannya di akhir artikel ini . Saya awalnya membacanya sebagai bagian dari buku tentang mengembangkan video game bertahun-tahun yang lalu.
Cort Ammon
1
@ BJMyers: Saya cukup yakin mereka memiliki "peretasan" kompatibilitas serupa untuk puluhan aplikasi populer.
Doc Brown
3
@BJMyers ada banyak hal seperti ini, jika Anda ingin membaca yang baik pergi ke blog The Old New Thing oleh Raymond Chen , telusuri tag History atau cari "kompatibilitas". Ada banyak kenangan yang teringat, termasuk sesuatu yang sangat dekat dengan kasus SimCity tersebut - Addentum: Chen tidak suka menyebut nama untuk disalahkan.
Theraot
2
Sangat sedikit hal yang terjadi bahkan dalam transisi 95-> NT. SimCity asli untuk Windows masih berfungsi dengan baik pada Windows 10 (32-bit). Bahkan game DOS masih berfungsi dengan baik asalkan Anda menonaktifkan suara atau menggunakan sesuatu seperti VDMSound untuk memungkinkan subsistem konsol menangani audio dengan benar. Microsoft menanggapi kompatibilitas dengan sangat serius, dan mereka juga tidak mengambil pintasan "mari kita letakkan di mesin virtual". Terkadang butuh solusi, tapi itu masih cukup mengesankan, terutama dalam hal relatif.
Luaan
11

Jawaban Doc Brown paling dekat dengan akurat, jawaban lain menggambarkan kesalahpahaman dari Prinsip Tertutup Terbuka.

Secara eksplisit mengartikulasikan kesalahpahaman, tampaknya ada keyakinan bahwa OCP berarti bahwa Anda tidak harus membuat perubahan mundur kompatibel (atau bahkan setiap perubahan atau sesuatu sepanjang garis-garis ini.) The OCP adalah tentang merancang komponen sehingga Anda tidak perlu untuk buat perubahan pada mereka untuk memperluas fungsionalitasnya, terlepas dari apakah perubahan itu kompatibel atau tidak. Ada banyak alasan lain selain menambahkan fungsionalitas yang Anda dapat membuat perubahan pada komponen apakah mereka kompatibel ke belakang (mis. Refactoring atau optimasi) atau mundur tidak kompatibel (mis. Deprecating dan menghapus fungsionalitas). Anda dapat melakukan perubahan ini tidak berarti bahwa komponen Anda melanggar OCP (dan jelas bukan berarti Anda melanggar OCP).

Sungguh, ini bukan tentang kode sumber sama sekali. Pernyataan yang lebih abstrak dan relevan dari OCP adalah: "komponen harus memungkinkan untuk perpanjangan tanpa perlu melanggar batas abstraksi". Saya akan melangkah lebih jauh dan mengatakan rendisi yang lebih modern adalah: "komponen harus menegakkan batas abstraksinya tetapi memungkinkan untuk perpanjangan". Bahkan dalam artikel tentang OCP oleh Bob Martin ketika ia "menggambarkan" "tertutup untuk modifikasi" sebagai "kode sumber tidak dapat diganggu gugat", ia kemudian mulai berbicara tentang enkapsulasi yang tidak ada hubungannya dengan memodifikasi kode sumber dan segala sesuatu yang berkaitan dengan abstraksi batas-batas.

Jadi, premis yang salah dalam pertanyaan adalah bahwa OCP (dimaksudkan sebagai) pedoman tentang evolusi basis kode. OCP biasanya di-slogan sebagai "sebuah komponen harus terbuka untuk ekstensi dan tertutup untuk modifikasi oleh konsumen". Pada dasarnya, jika seorang konsumen komponen ingin menambahkan fungsionalitas ke komponen mereka harus dapat memperluas komponen lama ke yang baru dengan fungsi tambahan, tetapi mereka tidak dapat mengubah komponen yang lama.

OCP tidak mengatakan apa pun tentang pembuat komponen yang mengubah atau menghapus fungsionalitas. OCP tidak menganjurkan menjaga kompatibilitas bug selamanya. Anda, sebagai pembuat, tidak melanggar OCP dengan mengubah atau bahkan menghapus komponen. Anda, atau lebih tepatnya komponen yang Anda tulis, melanggar OCP jika satu-satunya cara konsumen dapat menambahkan fungsionalitas ke komponen Anda adalah dengan memutasikannya misalnya dengan menambal monyetatau memiliki akses ke kode sumber dan kompilasi ulang. Dalam banyak kasus, tak satu pun dari ini adalah pilihan bagi konsumen yang berarti jika komponen Anda tidak "terbuka untuk perpanjangan" mereka tidak beruntung. Mereka tidak bisa menggunakan komponen Anda untuk kebutuhan mereka. OCP berpendapat untuk tidak menempatkan konsumen perpustakaan Anda ke posisi ini, setidaknya sehubungan dengan beberapa kelas "ekstensi" yang dapat diidentifikasi. Bahkan ketika modifikasi dapat dilakukan pada kode sumber atau bahkan salinan utama dari kode sumber, yang terbaik adalah "berpura-pura" bahwa Anda tidak dapat memodifikasinya karena ada banyak konsekuensi negatif potensial untuk melakukannya.

Jadi untuk menjawab pertanyaan Anda: Tidak, ini bukan pelanggaran OCP. Tidak ada perubahan yang dibuat oleh penulis dapat menjadi pelanggaran terhadap OCP karena OCP tidak sebanding dengan perubahan. Perubahan, bagaimanapun, dapat membuat pelanggaran OCP, dan mereka dapat dimotivasi oleh kegagalan OCP di versi sebelumnya dari basis kode. OCP adalah properti dari sepotong kode tertentu, bukan sejarah evolusi basis kode.

Sebaliknya, kompatibilitas mundur adalah properti dari perubahan kode. Tidak masuk akal untuk mengatakan sebagian kode kompatibel atau tidak kompatibel. Masuk akal untuk berbicara tentang kompatibilitas mundur beberapa kode sehubungan dengan beberapa kode lama. Oleh karena itu, tidak pernah masuk akal untuk berbicara tentang potongan pertama dari beberapa kode yang kompatibel atau tidak. Potongan kode pertama dapat memuaskan atau gagal untuk memenuhi OCP, dan secara umum kita dapat menentukan apakah beberapa kode memenuhi OCP tanpa merujuk ke versi historis dari kode.

Adapun pertanyaan terakhir Anda, ini bisa dibilang off-topic untuk StackExchange secara umum sebagai terutama berdasarkan pendapat, tetapi singkatnya adalah selamat datang di teknologi dan khususnya JavaScript di mana dalam beberapa tahun terakhir fenomena yang Anda gambarkan telah disebut kelelahan JavaScript . (Jangan ragu-ragu ke google untuk menemukan berbagai artikel lain, beberapa menyindir, membicarakan hal ini dari berbagai perspektif.)

Derek Elkins
sumber
3
"Kamu, sebagai pembuat, tidak melanggar OCP dengan mengubah atau bahkan menghapus komponen." - dapatkah Anda memberikan referensi untuk ini? Tidak satu pun definisi prinsip yang saya lihat menyatakan bahwa "pencipta" (apa pun artinya) dikecualikan dari prinsip tersebut. Menghapus komponen yang diterbitkan jelas merupakan suatu perubahan besar.
JacquesB
1
@ JacquesB Orang dan bahkan perubahan kode tidak melanggar OCP, komponen (yaitu potongan kode aktual) lakukan. (Dan, untuk menjadi sangat jelas, itu berarti komponen gagal untuk menjalankan OCP itu sendiri, bukan karena melanggar OCP dari beberapa komponen lain.) Inti dari jawaban saya adalah bahwa OCP tidak berbicara tentang perubahan kode , melanggar atau sebaliknya. Sebuah komponen adalah baik terbuka untuk perluasan dan tertutup untuk modifikasi, atau tidak, seperti metode mungkin privateatau tidak. Jika seorang penulis membuat privatemetode publicnanti, itu tidak berarti mereka telah melanggar kontrol akses, (1/2)
Derek Elkins
2
... juga tidak berarti metode itu tidak benar-benar privatesebelumnya. "Menghapus komponen yang diterbitkan jelas merupakan perubahan besar," adalah non sequitur. Entah komponen versi baru memenuhi OCP atau tidak, Anda tidak perlu riwayat basis kode untuk menentukan ini. Dengan logika Anda, saya tidak pernah bisa menulis kode yang memenuhi OCP. Anda mengkonfigurasikan kompatibilitas ke belakang, properti kode berubah, dengan OCP, properti kode. Komentar Anda sama masuk akal dengan mengatakan quicksort tidak kompatibel. (2/2)
Derek Elkins
3
@ JacquesB Pertama, perhatikan lagi bahwa ini berbicara tentang modul yang sesuai dengan OCP. OCP adalah saran tentang cara menulis modul sehingga mengingat kendala bahwa kode sumber tidak dapat diubah, modul tetap dapat diperpanjang. Sebelumnya di makalah ia berbicara tentang merancang modul yang tidak pernah berubah, bukan tentang menerapkan proses manajemen perubahan yang tidak pernah memungkinkan modul untuk berubah. Mengacu pada hasil edit untuk jawaban Anda, Anda tidak "mematahkan OCP" dengan memodifikasi kode modul. Sebaliknya, jika "memperluas" modul mengharuskan Anda untuk mengubah kode sumber, (1/3)
Derek Elkins
2
"OCP adalah properti dari sepotong kode tertentu, bukan sejarah evolusi basis kode." - luar biasa!
Doc Brown