Saya sedang membaca wiki ini tentang Prinsip Abstraksi Stabil (SAP) .
SAP menyatakan bahwa semakin stabil suatu paket, semakin abstrak seharusnya. Ini menyiratkan bahwa jika suatu paket kurang stabil (lebih cenderung berubah) maka itu harus lebih konkret. Apa yang saya tidak benar-benar mengerti adalah mengapa ini harus terjadi. Tentunya dalam semua kasus terlepas dari stabilitas kita harus bergantung pada abstraksi dan menyembunyikan implementasi konkret?
design
design-patterns
architecture
object-oriented-design
design-principles
SteveCallender
sumber
sumber
Jawaban:
Pikirkan paket Anda sebagai API, untuk mengambil contoh dari kertas, mengambil definisi untuk
Reader
denganstring Reader.Read()
danWriter
denganvoid Writer.Write(string)
sebagai API abstrak Anda.Anda kemudian dapat membuat kelas
Copy
dengan metodeCopier.Copy(Reader, Writer)
dan implementasiWriter.Write(Reader.Read())
dan mungkin beberapa pemeriksaan kewarasan.Sekarang, Anda membuat implementasi konkret, misalnya
FileReader
,FileWriter
,KeyboardReader
danDownloadThingsFromTheInternetReader
.Bagaimana jika Anda ingin mengubah implementasi Anda
FileReader
? Tidak masalah, cukup ganti kelas dan kompilasi ulang.Bagaimana jika Anda ingin mengubah definisi abstraksi Anda
Reader
? Ups, Anda tidak bisa hanya mengubah itu, tetapi Anda juga harus mengubahCopier
,FileReader
,KeyboardReader
danDownloadThingsFromTheInternetReader
.Ini adalah alasan di balik Prinsip Abstraksi Stabil: Jadikan konkretisasi Anda lebih stabil daripada abstraksi.
sumber
Karena YAGNI .
Jika saat ini Anda hanya memiliki satu implementasi dari satu hal , mengapa repot dengan lapisan tambahan dan tidak berguna? Ini hanya akan menyebabkan kompleksitas yang tidak perlu. Lebih buruk lagi, kadang-kadang Anda memberikan pemikiran abstrak pada hari implementasi kedua akan datang ... dan hari ini tidak pernah terjadi. Buang-buang pekerjaan!
Saya juga berpikir pertanyaan sebenarnya untuk ditanyakan sendiri bukanlah "Apakah saya harus bergantung pada abstraksi?" melainkan "Apakah saya memerlukan modularitas?". Dan modularitas tidak selalu dibutuhkan, lihat di bawah.
Di perusahaan tempat saya bekerja, beberapa peranti lunak yang saya kembangkan sangat terkait dengan beberapa peranti keras yang dengannya ia harus berkomunikasi. Perangkat ini dikembangkan untuk memenuhi tujuan yang sangat spesifik dan semuanya modular. :-) Setelah perangkat pertama yang diproduksi keluar dari pabrik dan diinstal di suatu tempat, baik firmware dan hardware tidak pernah bisa berubah, pernah .
Jadi, saya dapat memastikan bahwa beberapa bagian dari perangkat lunak tidak akan pernah berevolusi. Bagian-bagian ini tidak perlu bergantung pada abstraksi karena hanya ada satu implementasi dan yang ini tidak akan pernah berubah. Mengumumkan abstraksi pada bagian kode ini hanya akan membingungkan semua orang dan membutuhkan waktu lebih lama (tanpa menghasilkan nilai apa pun).
sumber
Saya pikir Anda mungkin bingung dengan kata stabil yang dipilih oleh Robert Martin. Di sinilah saya pikir kebingungan dimulai:
Jika Anda membaca hingga artikel asli , Anda akan melihat (beri penekanan pada saya):
Saya selalu bergumul dengan pilihan penulis kata stabil , karena saya (seperti Anda) cenderung memikirkan aspek "kemungkinan" stabilitas, yaitu, tidak mungkin berubah . Kesulitan menyiratkan bahwa mengubah modul itu akan merusak banyak modul lain, dan itu akan menjadi banyak pekerjaan untuk memperbaiki kode.
Martin juga menggunakan kata-kata independen dan bertanggung jawab , yang bagi saya menyampaikan lebih banyak makna. Dalam seminar pelatihannya, ia menggunakan metafora tentang orang tua dari anak-anak yang tumbuh dewasa, dan bagaimana mereka harus "bertanggung jawab," karena anak-anak mereka bergantung pada mereka. Perceraian, pengangguran, penahanan, dll. Adalah contoh nyata dari dampak negatif perubahan orangtua terhadap anak-anak. Karena itu, orang tua harus "stabil" untuk kepentingan anak-anak mereka. Omong-omong, metafora anak-anak / orang tua ini tidak harus terkait dengan warisan di OOP!
Jadi, mengikuti semangat "bertanggung jawab", saya muncul dengan makna alternatif untuk sulit diubah (atau tidak boleh berubah ):
Jadi, memasukkan definisi-definisi ini ke dalam pernyataan
Mari kita mengutip Prinsip Abstraksi Stabil (SAP), menekankan kata-kata membingungkan stabil / tidak stabil:
Klarifikasi tanpa kata-kata yang membingungkan ini:
TL; DR
Judul pertanyaan Anda menanyakan:
Saya pikir jika Anda membuat abstraksi dengan benar (misalnya, mereka ada karena banyak kode tergantung pada mereka), maka tidak ada kerugian yang signifikan.
sumber
Abstraksi adalah hal-hal yang sulit diubah dalam perangkat lunak karena semuanya bergantung padanya. Jika paket Anda akan sering berubah dan memberikan abstraksi, orang-orang yang bergantung padanya akan dipaksa untuk menulis ulang banyak kode mereka ketika Anda mengubah sesuatu. Tetapi jika paket Anda yang tidak stabil menyediakan beberapa implementasi konkret, kode yang jauh lebih kecil harus ditulis ulang setelah perubahan.
Jadi, jika paket Anda akan sering berubah, itu harus lebih baik memberikan beton, bukan abstraksi. Kalau tidak ... siapa yang akan menggunakannya? ;)
sumber
Perlu diingat metrik stabilitas Martin dan apa yang ia maksud dengan "stabilitas":
Atau:
Yaitu, sebuah paket dianggap sepenuhnya tidak stabil jika semua dependensinya keluar: ia menggunakan hal-hal lain, tetapi tidak ada yang menggunakannya. Dalam hal itu, masuk akal untuk hal itu menjadi konkret. Ini juga akan menjadi jenis kode yang paling mudah untuk diubah karena tidak ada yang menggunakannya, dan karena itu tidak ada lagi yang bisa rusak jika kode itu dimodifikasi.
Sementara itu ketika Anda memiliki skenario yang berlawanan dari "stabilitas" lengkap dengan paket yang digunakan oleh satu atau lebih hal tetapi tidak menggunakan apa pun sendiri, seperti paket pusat yang digunakan oleh perangkat lunak, saat itulah Martin mengatakan hal ini harus abstrak. Itu juga diperkuat oleh bagian DIP dari SOLI (D), Dependency Inversion Principle, yang pada dasarnya menyatakan bahwa dependensi harus mengalir secara seragam menuju abstraksi untuk kode level rendah dan level tinggi.
Artinya, dependensi harus mengalir secara seragam ke arah "stabilitas", dan lebih tepatnya, dependensi harus mengalir ke paket dengan dependensi yang lebih masuk daripada dependensi keluar dan, selanjutnya, dependensi harus mengalir ke arah abstraksi. Inti dari alasan di balik itu adalah bahwa abstraksi menyediakan ruang bernapas untuk menggantikan satu subtipe dengan subtipe lainnya, menawarkan tingkat fleksibilitas untuk bagian beton yang mengimplementasikan antarmuka untuk berubah tanpa memutus ketergantungan yang masuk ke antarmuka abstrak tersebut.
Yah, saya sebenarnya tidak setuju dengan Martin di sini untuk domain saya setidaknya, dan di sini saya perlu memperkenalkan definisi baru "stabilitas" seperti dalam, "kurang alasan untuk berubah". Dalam hal ini saya akan mengatakan dependensi harus mengalir ke stabilitas, tetapi antarmuka abstrak tidak membantu jika antarmuka abstrak tidak stabil (menurut definisi saya "tidak stabil", seperti cenderung berulang kali diubah, bukan Martin). Jika pengembang tidak bisa mendapatkan abstraksi yang benar dan klien berulang kali mengubah pikiran mereka dengan cara yang membuat abstrak mencoba memodelkan perangkat lunak tidak lengkap atau tidak efektif, maka kami tidak lagi mendapat manfaat dari peningkatan fleksibilitas antarmuka abstrak untuk melindungi sistem terhadap perubahan pemutusan ketergantungan yang bertingkat. . Dalam kasus pribadi saya, saya telah menemukan mesin ECS, seperti yang ditemukan di game AAA,paling konkret : menuju data mentah, tetapi data tersebut sangat stabil (seperti, "tidak mungkin perlu diubah"). Saya sering menemukan kemungkinan sesuatu yang membutuhkan perubahan di masa depan menjadi metrik yang lebih berguna daripada rasio eferen dengan total kopling dalam memandu keputusan SE.
Jadi saya akan mengubah DIP sedikit dan hanya mengatakan, "dependensi harus mengalir ke komponen yang memiliki probabilitas terendah memerlukan perubahan lebih lanjut", terlepas dari apakah komponen-komponen itu adalah antarmuka abstrak atau data mentah. Yang penting bagi saya adalah probabilitas bahwa mereka mungkin memerlukan perubahan desain langsung. Abstraksi hanya berguna dalam konteks stabilitas ini jika sesuatu, dengan menjadi abstrak, mengurangi kemungkinan itu.
Untuk banyak konteks yang mungkin terjadi dengan insinyur dan klien yang layak yang mengantisipasi kebutuhan perangkat lunak dimuka dan desain stabil (seperti dalam, tidak berubah) abstraksi, sementara abstraksi itu menawarkan semua ruang bernapas yang mereka butuhkan untuk menukar implementasi konkret. Tetapi dalam beberapa domain, abstraksi mungkin tidak stabil dan cenderung tidak memadai, sedangkan data yang dibutuhkan mesin mungkin jauh lebih mudah untuk diantisipasi dan dibuat stabil terlebih dahulu. Jadi dalam kasus-kasus itu, sebenarnya bisa lebih menguntungkan dari sudut pandang rawatan (kemudahan mengubah dan memperluas sistem) agar ketergantungan mengalir ke data daripada abstraksi. Dalam ECS, bagian yang paling tidak stabil (seperti bagian yang paling sering diubah) biasanya adalah fungsi yang berada di sistem (
PhysicsSystem
, misalnya), sedangkan bagian yang paling stabil (seperti yang paling tidak mungkin diubah) adalah komponen yang hanya terdiri dari data mentah (MotionComponent
, misalnya) yang digunakan semua sistem.sumber