Apakah ada kerugian signifikan tergantung pada abstraksi?

9

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?

SteveCallender
sumber
Coba gunakan komponen yang membuat Anda nyaman, dengan tidak menggunakan abstraksi yang disediakannya, tetapi lakukan semuanya dengan detail penuh pada satu tingkat lebih rendah dari yang biasa Anda lakukan. Itu akan memberi Anda kesan yang cukup baik tentang kelebihan dan kekurangan dari abstraksi.
Kilian Foth
2
Apakah Anda membaca artikel yang ditautkan dan / atau buku yang menjadi dasar artikel tersebut?
Jörg W Mittag
1
+1 Pertanyaan yang bagus, terutama karena saya tidak berpikir hubungan antara stabilitas dan abstraksi langsung intuitif. Halaman 11 dari artikel ini membantu, contoh kasus abstraknya masuk akal, tetapi mungkin seseorang dapat menulis contoh kasus nyata yang lebih jelas. Permintaan ditangguhkan.
Mike
Apa masalah domain yang Anda hadapi untuk abstraksi ini? Sebagaimana dicatat pada C2: "Dalam memodelkan domain dunia nyata - dunia pelanggan, karyawan, faktur, tagihan bahan baku, produk, SKU, pembayaran, dll. - abstraksi yang stabil mungkin sulit ditemukan. Domain komputasi - the dunia tumpukan, antrian, fungsi, pohon, proses, utas, widget grafis, laporan, formulir, dll. - jauh lebih mungkin stabil. " dan "Di beberapa domain, abstraksi stabil sulit didapat." Tanpa mengetahui masalah apa yang Anda coba selesaikan dengan SAP, sulit untuk memberikan jawaban yang baik.
@ JörgWMittag dan Mike - Ya saya membaca artikel. Saya hanya merasa bahwa tidak ada penjelasan mengapa "paket instable harus konkret". Pada halaman 13 dari artikel tersebut ia menunjukkan grafik tetapi tidak benar-benar menjelaskan terlalu detail mengapa (1,1) pada grafik harus dihindari? Apakah ide yang pada dasarnya tidak stabil berarti ketergantungan yang kurang aferen dan tidak perlu menggunakan abstraksi? Jika demikian ... apakah itu bukan praktik yang baik untuk menggunakan abstraksi, kalau-kalau stabilitas berubah dengan perubahan persyaratan ..
SteveCallender

Jawaban:

7

Pikirkan paket Anda sebagai API, untuk mengambil contoh dari kertas, mengambil definisi untuk Readerdengan string Reader.Read()dan Writerdengan void Writer.Write(string)sebagai API abstrak Anda.

Anda kemudian dapat membuat kelas Copydengan metode Copier.Copy(Reader, Writer)dan implementasi Writer.Write(Reader.Read())dan mungkin beberapa pemeriksaan kewarasan.

Sekarang, Anda membuat implementasi konkret, misalnya FileReader, FileWriter, KeyboardReaderdan DownloadThingsFromTheInternetReader.

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 mengubah Copier, FileReader, KeyboardReaderdan DownloadThingsFromTheInternetReader.

Ini adalah alasan di balik Prinsip Abstraksi Stabil: Jadikan konkretisasi Anda lebih stabil daripada abstraksi.

Residuum
sumber
1
Saya setuju dengan semua yang Anda katakan, tetapi saya percaya definisi stabilitas dan definisi penulis berbeda. Anda memperlakukan stabilitas sebagai kebutuhan untuk berubah, kata penulis, "stabilitas bukanlah ukuran kemungkinan modul akan berubah; melainkan ukuran kesulitan dalam mengubah modul." Jadi pertanyaan saya lebih mengapa itu bermanfaat untuk paket yang mudah diubah menjadi lebih konkret daripada abstrak?
SteveCallender
1
@SteveCallender Perbedaannya sangat tipis: Definisi penulis tentang "stabilitas" adalah apa yang oleh sebagian besar orang disebut "kebutuhan akan stabilitas",. Yakni semakin banyak modul bergantung pada suatu modul, semakin banyak "stabil" suatu modul yang dibutuhkan.
Residuum
6

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).

Tutul
sumber
1
Saya cenderung setuju dengan YAGNI, tetapi saya ingin tahu tentang contoh Anda. Apakah Anda tidak pernah mengulangi kode apa pun di perangkat yang berbeda? Saya merasa sulit untuk percaya bahwa tidak ada kode umum di seluruh perangkat dari perusahaan yang sama. Juga, bagaimana klien suka ketika Anda tidak memperbaiki bug di firmware mereka? Apakah Anda mengatakan tidak pernah ada bug, pernah ? Jika Anda memiliki kode yang sama yang bermasalah dalam 4 implementasi yang berbeda, Anda harus memperbaiki bug 4 kali jika tidak ada dalam modul umum.
Fuhrmanator
1
@Fuhrmanator kode umum berbeda dari abstraksi. Kode umum bisa berarti metode pembantu atau pustaka - tidak ada abstraksi yang diperlukan.
Eilon
@Fuhrmanator Tentu saja kita memiliki kode umum di perpustakaan, tetapi seperti yang dikatakan Eilon, tidak semuanya tergantung pada abstraksi (beberapa bagian melakukannya, namun). Saya tidak pernah mengatakan tidak pernah ada bug, saya mengatakan mereka tidak dapat ditambal (untuk alasan yang berada di luar ruang lingkup pertanyaan OP).
Melihat
@ Eilon komentar saya tentang modularitas tidak selalu diperlukan (bukan abstraksi).
Fuhrmanator
@Spotted Tidak masalah tentang tidak bisa menambal. Ini hanya contoh yang cukup spesifik dan tidak khas pada kebanyakan perangkat lunak.
Fuhrmanator
6

Saya pikir Anda mungkin bingung dengan kata stabil yang dipilih oleh Robert Martin. Di sinilah saya pikir kebingungan dimulai:

Ini menyiratkan bahwa jika suatu paket kurang stabil (lebih cenderung berubah) maka itu harus lebih konkret.

Jika Anda membaca hingga artikel asli , Anda akan melihat (beri penekanan pada saya):

Definisi klasik dari stabilitas kata adalah: "Tidak mudah dipindahkan." Ini adalah definisi yang akan kita gunakan dalam artikel ini. Artinya, stabilitas bukanlah ukuran kemungkinan bahwa modul akan berubah; melainkan merupakan ukuran dari kesulitan dalam mengubah modul .

Jelas, modul yang lebih sulit untuk diubah, akan menjadi kurang stabil. Semakin sulit modul diubah, yaitu semakin stabil, semakin tidak stabil.

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 ):

  • Wajib - artinya kelas lain bergantung pada kelas ini sehingga tidak boleh berubah.
  • Beholden - ibid.
  • Dibatasi - kewajiban kelas ini membatasi fasilitasnya untuk berubah.

Jadi, memasukkan definisi-definisi ini ke dalam pernyataan

semakin stabil suatu paket, semakin abstrak seharusnya

  • semakin banyak paket wajib , semakin abstrak seharusnya
  • semakin terikat paket semakin abstrak seharusnya
  • semakin terbatas paket, semakin abstrak seharusnya

Mari kita mengutip Prinsip Abstraksi Stabil (SAP), menekankan kata-kata membingungkan stabil / tidak stabil:

Paket yang stabil maksimal harus abstrak maksimal. Paket yang tidak stabil harus konkret. Keabstrakan suatu paket harus sebanding dengan stabilitasnya .

Klarifikasi tanpa kata-kata yang membingungkan ini:

Paket-paket yang secara maksimal terikat pada bagian lain dari sistem harus abstrak maksimal. Paket yang dapat berubah tanpa kesulitan harus konkret. Abstraksi suatu paket harus proporsional dengan seberapa sulitnya untuk memodifikasi .

TL; DR

Judul pertanyaan Anda menanyakan:

Apakah ada kerugian signifikan tergantung pada abstraksi?

Saya pikir jika Anda membuat abstraksi dengan benar (misalnya, mereka ada karena banyak kode tergantung pada mereka), maka tidak ada kerugian yang signifikan.

Fuhrmanator
sumber
0

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.

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? ;)

Vladislav Rastrusny
sumber
0

Perlu diingat metrik stabilitas Martin dan apa yang ia maksud dengan "stabilitas":

Instability = Ce / (Ca+Ce)

Atau:

Instability = Outgoing / (Incoming+Outgoing)

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.

Apakah ada kerugian signifikan tergantung pada abstraksi?

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