Apa nilai menyembunyikan detail melalui abstraksi? Apakah tidak ada nilai dalam transparansi?

30

Latar Belakang

Saya bukan penggemar berat abstraksi. Saya akan mengakui bahwa seseorang dapat mengambil manfaat dari kemampuan beradaptasi, portabilitas dan penggunaan kembali antarmuka dll. Ada manfaat nyata di sana, dan saya tidak ingin mempertanyakan itu, jadi mari kita abaikan saja.

Ada "manfaat" abstraksi utama lainnya, yaitu menyembunyikan logika implementasi dan detail dari pengguna abstraksi ini. Argumennya adalah bahwa Anda tidak perlu mengetahui detailnya, dan bahwa seseorang harus berkonsentrasi pada logika mereka sendiri pada saat ini. Masuk akal dalam teori.

Namun, setiap kali saya memelihara aplikasi perusahaan besar, saya selalu perlu tahu lebih banyak detail. Ini menjadi kerumitan besar menggali lebih dalam dan lebih dalam ke abstraksi di setiap kesempatan hanya untuk mengetahui apa yang dilakukan sesuatu; yaitu harus melakukan "deklarasi terbuka" sekitar 12 kali sebelum menemukan prosedur tersimpan yang digunakan.

Mentalitas 'sembunyikan detail' ini sepertinya hanya menghalangi. Saya selalu berharap untuk antarmuka yang lebih transparan dan lebih sedikit abstraksi. Saya dapat membaca kode sumber tingkat tinggi dan tahu apa fungsinya, tetapi saya tidak akan pernah tahu bagaimana melakukannya, ketika bagaimana melakukannya, adalah apa yang benar-benar perlu saya ketahui.

Apa yang terjadi di sini? Apakah setiap sistem yang pernah saya kerjakan dirancang dengan buruk (dari perspektif ini setidaknya)?

Filosofi saya

Ketika saya mengembangkan perangkat lunak, saya merasa seperti saya mencoba untuk mengikuti filosofi yang saya rasa terkait erat dengan filosofi ArchLinux :

Arch Linux mempertahankan kompleksitas inheren dari sistem GNU / Linux, sekaligus menjaganya agar tetap teratur dan transparan. Pengembang dan pengguna Arch Linux percaya bahwa mencoba menyembunyikan kompleksitas sistem sebenarnya menghasilkan sistem yang lebih kompleks, dan karenanya harus dihindari.

Dan karena itu, saya tidak pernah mencoba menyembunyikan kerumitan perangkat lunak saya di balik lapisan abstraksi. Saya mencoba menyalahgunakan abstraksi, bukan menjadi budaknya.

Pertanyaan di hati

  1. Apakah ada nilai nyata dalam menyembunyikan detail?
  2. Bukankah kita mengorbankan transparansi?
  3. Bukankah transparansi ini berharga?
pengguna606723
sumber
7
Abstraksi dapat disalahgunakan dalam bentuk desain yang buruk. Namun bukan berarti abstraksi pada prinsipnya tidak bernilai.
Bernard
4
Saya pikir ada pertanyaan yang bagus di sana, namun, bunyinya banyak seperti kata-kata kasar terhadap abstraksi. Bisakah Anda tidak menekankan hal itu dan membawa lebih banyak pertanyaan aktual Anda.
PersonalNexus
4
Apakah Anda yakin menggunakan definisi yang tepat tentang "menyembunyikan detail"? Dalam konteks ini, ini tentang mengurangi sambungan , bukan tentang mencegah Anda mempelajari cara kerja sesuatu.
Andres F.
24
Kecuali Anda ingin memprogram dengan voltmeter dan osiloskop di meja Anda, Anda memprogram hanya abstraksi di atas abstraksi di atas abstraksi. Apakah ada nilai bagi Anda dalam menyembunyikan detail bahwa Anda sebenarnya memanipulasi bukan bit tetapi pada kenyataannya volt? Apakah dengan melakukan itu mengorbankan transparansi? Apakah transparansi itu berharga?
Eric Lippert
8
Saya pikir apa yang Anda hadapi bukanlah abstraksi, itu adalah lapisan tipuan kosong yang tidak benar-benar abstrak. Ya, itu sering ditemukan dalam sistem perusahaan besar dan tidak, itu tidak baik.
Michael Borgwardt

Jawaban:

47

Alasan menyembunyikan detail bukanlah untuk menyembunyikan detail; itu untuk memungkinkan untuk memodifikasi implementasi tanpa melanggar kode dependen.

Bayangkan Anda memiliki daftar objek, dan setiap objek memiliki Nameproperti dan data lainnya. Dan sering kali, Anda perlu menemukan item dalam daftar yang Namecocok dengan string tertentu.

Cara yang jelas adalah untuk mengulang setiap item satu per satu, dan memeriksa untuk melihat apakah Namecocok dengan string. Tetapi jika Anda menemukan bahwa itu memakan waktu terlalu banyak, (seperti jika Anda memiliki beberapa ribu item dalam daftar), Anda mungkin ingin menggantinya dengan pencarian kamus string-object.

Sekarang jika semua pencarian Anda dilakukan dengan mengambil daftar dan mengulanginya, Anda memiliki banyak pekerjaan yang harus dilakukan untuk memperbaikinya. Lebih sulit lagi jika Anda berada di perpustakaan dan pengguna pihak ketiga menggunakannya; Anda tidak bisa pergi keluar dan memperbaiki mereka kode!

Tetapi jika Anda memiliki FindByNamemetode untuk merangkum proses pencarian nama, Anda cukup mengubah cara penerapannya dan semua kode yang memanggilnya akan terus bekerja, dan mendapatkan jauh lebih cepat secara gratis. Itulah nilai sebenarnya dari abstraksi dan enkapsulasi.

Mason Wheeler
sumber
Saya setuju dengan ini, tetapi ini bukan inti dari pertanyaan. Saya sepenuhnya setuju bahwa metode untuk merangkum fungsionalitas tertentu berguna, tetapi saya merasa seperti ini tidak selalu motifnya. Apakah aku salah?
user606723
3
@ User606723: Seharusnya begitu. Itu tidak berarti selalu begitu . Beberapa orang tidak mengerti maksudnya dan mereka hanya menumpuk lebih banyak lapisan di atas lebih banyak lapisan dan mengubah segalanya menjadi berantakan. Inilah sebabnya mengapa programmer berpengalaman menyarankan pengembang baru untuk tidak pernah mengadopsi teknologi atau teknik baru sampai mereka memahaminya.
Mason Wheeler
3
@ user606723: Transparansi mendorong pemasangan yang ketat, jadi walaupun mungkin tidak selalu buruk, tetapi biasanya memang demikian.
Malfist
3
Masalah yang digambarkan Mason, tentang orang-orang yang menumpuk di atas lapisan dalam bentuk pemrograman pemujaan kargo, adalah mengapa saya curiga pada terlalu banyak warisan, dan mengapa komposisi lebih disukai daripada warisan. Tampaknya menjadi masalah bagi programmer Java.
jhocking
2
Tidak, kopling ketat tidak selalu buruk. Ini sering buruk, tetapi berusaha keras untuk menghindarinya dapat menghasilkan masalah yang lebih buruk, seperti soft-coding.
Mason Wheeler
16

Saya baru saja selesai membaca bagian dalam Kode Lengkap tentang abstraksi, jadi dari situlah sebagian besar sumber ini.

Inti dari abstraksi adalah untuk menghilangkan kebutuhan untuk bertanya "bagaimana ini diterapkan?". Ketika Anda menelepon user.get_id(), Anda tahu bahwa idapa yang akan Anda dapatkan kembali. Jika Anda harus bertanya "bagaimana cara mendapatkan id pengguna?" maka Anda mungkin tidak membutuhkan id, atau get_id()mengembalikan sesuatu yang tidak terduga dan dirancang dengan buruk.

Anda menggunakan abstraksi untuk memungkinkan Anda mendesain:

a house with doors and windows

bukan desain

a box with four walls,
    with 3 holes,
        two of which fit panes of glass surrounded by wood frames,
        one that fits a large plank of wood with hinges and a metal knob,
etc.
TorelTwiddler
sumber
Saya tidak berbicara tentang antarmuka ini. Antarmuka ini baik-baik saja. Saya berbicara tentang sistem rumit besar yang tersegmentasi di belakang banyak abstraksi yang berbeda.
user606723
9
@ user606723 Maka pertanyaan Anda adalah tentang desain overcomplex, bukan abstraksi
Andres F.
3
+1 untuk kode selesai. Ini mencakup mengapa abstraksi diperlukan untuk desain, dan mengapa level abstraksi yang salah menghalangi desain. Untuk membawa contoh Anda lebih lanjut, jika saya bekerja di kantor zonasi, saya ingin memikirkan rumah Anda, tanpa menguraikan detailnya. Tetapi jika Anda berpikir tentang rumah seperti saya, maka Anda tidak dapat membangunnya.
Spencer Rathbun
pertanyaan ini harus ditutup atau judulnya diubah
Jake Berger
8

Apakah ada nilai nyata dalam menyembunyikan detail?

Iya nih. Dengan menyajikan abstraksi, kita dapat berpikir dan memprogram di tingkat yang lebih tinggi.

Bayangkan memodelkan sistem fisik tanpa aljabar kalkulus atau matriks. Ini sama sekali tidak praktis. Demikian pula, jika kita hanya dapat memprogram pada tingkat skalar, kita tidak akan dapat memecahkan masalah yang menarik. Bahkan aplikasi web yang relatif sederhana dapat mengambil manfaat besar dari abstraksi seperti tag libs. Jauh lebih mudah untuk menyisipkan tag yang berarti "bidang entri alamat" daripada berulang kali membuat empat bidang teks dan kotak pilih. Dan jika Anda memutuskan untuk memperluas ke luar negeri, Anda bisa memodifikasi definisi tag, daripada memperbaiki setiap formulir untuk menangani alamat internasional. Penggunaan abstraksi yang efektif adalah yang membuat beberapa programmer sepuluh kali lebih efektif daripada yang lain.

Manusia memiliki memori kerja yang terbatas. Abstraksi memungkinkan kita untuk berpikir tentang sistem besar.

Aren't we sacrificing transparency?

Tidak. Jika abstraksi tidak digunakan, maka tujuan dari komponen perangkat lunak dikubur dalam rincian berulang. Pengembang menghabiskan hari-hari mereka mengarungi kode seperti ini:

for (i = 0; i < pilgrim.wives.size(); ++i) {
  wife = pilgrim.wives[i];
  for (j = 0; j < wife.sacks.size(); ++j) {
     sack = wife.sacks[i];
     for (k = 0; j < sack.cats.size(); ++j) {
        cat = sack.cats[k];
        for (m = 0; m < cat.kits.size(); ++m) {
           ++count;
        }
     }
  }
}

dan berpikir "oh ya loop empat tingkat atas kit", bukannya melihat

pilgrim.kits.each { ++count; }

Bukankah transparansi ini berharga?

Seperti yang Anda tunjukkan, ada biaya untuk tipuan. Tidak ada gunanya membuat layer "berjaga-jaga". Gunakan abstraksi untuk mengurangi duplikasi dan memperjelas kode.

kevin cline
sumber
7

Ketika orang mengatakan bahwa abstraksi menyembunyikan detail implementasi, mereka sebenarnya tidak berarti "sembunyikan" dalam arti membuatnya sulit ditemukan. Apa yang mereka maksudkan adalah memisahkan detail implementasi dari antarmuka publik, untuk menjaga antarmuka tetap sederhana, ringkas, dan dapat dikelola. Sama seperti mobil "menyembunyikan" sebagian besar bagian vitalnya, dan hanya menawarkan serangkaian kontrol yang cukup sederhana untuk mengoperasikannya, modul perangkat lunak "menyembunyikan" sebagian besar fungsinya jauh di dalam perutnya dan hanya memperlihatkan sejumlah metode akses terbatas untuk kemudikan. Bayangkan sebuah mobil di mana Anda harus secara manual mengoperasikan semua internal mesin (dan ada banyak sekali yang menakutkan), Anda akan memiliki waktu yang sangat sulit mengawasi lalu lintas dan menemukan jalan.

Tetapi menjaga antarmuka tetap sederhana bukan hanya hal estetika; itu dapat membuat perbedaan antara proyek yang sukses dan Death March. Mari kita berperan sebagai penasihat iblis selama satu menit; bayangkan proyek perangkat lunak tanpa abstraksi sama sekali. Jika Anda perlu mempertahankan nilai, Anda menggunakan variabel global. Jika Anda perlu menggunakan fungsionalitas lebih dari sekali, Anda salin dan tempel. Jika Anda memerlukan dua versi berbeda dari bagian kode tertentu, Anda salin-tempel, bungkus dalam ifpernyataan, dan modifikasi kedua cabang. Secara teknis, ini bekerja, tetapi beberapa bulan kemudian, Anda akan menghadapi beberapa masalah yang benar-benar buruk:

  • Ketika Anda menemukan dan memperbaiki bug, kemungkinan juga ada dalam contoh kode serupa yang disalin-salin, jadi selain mencari dan memperbaiki bug, Anda juga harus mencari kejadian lain dan memperbaikinya juga.
  • Untuk menemukan bug atau mengimplementasikan perubahan, programmer pemeliharaan harus dapat memahami kode yang relevan. Kesulitan dalam melakukan ini meningkat dengan ukuran bagian kode yang relevan, tetapi lebih banyak lagi dengan cakupannya. Menyimpan setengah lusin variabel di kepala Anda sambil secara mental melangkah melalui beberapa kode bisa dilakukan; tetapi jika Anda memiliki beberapa ratus di antaranya, produktivitas Anda sangat terpengaruh (saya suka membandingkan proses berpikir dengan program yang kehabisan RAM fisik dan harus masuk ke swapfile: alih-alih membaca kode dengan lancar dalam sekali jalan , programmer harus melompat bolak-balik untuk melihat semuanya).
  • Cakupan sepotong kode juga berdampak pada ukuran basis kode yang harus digali untuk menemukan bug. Jika Anda memiliki fungsi sepuluh baris dengan dua parameter, dan tidak ada global, dan Anda tahu nilai input dan garis tempat crash, menemukan bug biasanya sepele dan sering membutuhkan tidak lebih dari melihat kode. Jika itu beberapa ratus garis, dua puluh parameter, lima belas bola dunia, dan menyebut beberapa fungsi lain yang serupa, Anda akan merasakan kesakitan yang serius.
  • Tanpa abstraksi yang tepat, perubahan apa pun berpotensi memengaruhi sebagian besar basis kode, karena secara praktis apa pun mungkin bergantung pada kode yang akan diubah. Gejala khas dengan basis kode seperti itu adalah Anda membuat perubahan kecil yang tampaknya tidak bersalah, dan fitur yang sama sekali tidak terkait tiba-tiba rusak. Dengan abstraksi, Anda dapat membatasi jumlah kerusakan yang dapat dilakukan perubahan, dan Anda membuat dampaknya lebih mudah diprediksi. Jika Anda mengubah nama bidang pribadi, Anda hanya memiliki satu file sumber untuk diperiksa; jika Anda mengubah nama variabel global, Anda harus menjalankan seluruh basis kode.

Dalam basis kode yang tidak diabstraksi secara buruk, dampak biasanya tumbuh secara eksponensial dengan ukuran basis kode, yaitu, menambahkan jumlah kode yang konstan meningkatkan upaya pemeliharaan dengan faktor konstan. Untuk membuat keadaan menjadi lebih buruk, menambahkan lebih banyak programmer ke proyek tidak meningkatkan produktivitas secara linear, tetapi secara logaritma terbaik (karena semakin besar tim Anda, semakin banyak overhead yang diperlukan untuk komunikasi).

tammmer
sumber
2

Saya pikir Anda harus memahami cara kerjanya jika diperlukan. Setelah Anda memutuskan untuk melakukan apa yang Anda pikir akan dilakukan, maka Anda memiliki ketenangan pikiran. Saya tidak pernah berpikir tujuannya adalah untuk menyembunyikannya selamanya.

Setelah Anda mengatur alarm pada jam yang Anda yakin akan bekerja, Anda bisa tidur karena tahu itu akan berbunyi pada waktu corret. Bangun satu jam lebih awal hanya agar Anda bisa menyaksikan detik-detik berlalu begitu saja adalah sia-sia.

JeffO
sumber
1
Tentu, tetapi saya tidak sering diminta untuk mengubah cara jam alarm saya bekerja, atau meminta orang lain mengubah cara jam alarm saya bekerja tanpa sepenuhnya mengetahui perubahannya.
user606723
1
Apakah Anda melihat perubahan kode untuk setiap kerangka kerja yang pernah Anda gunakan?
JeffO
1
tidak, tapi saya tidak mempertahankan perubahan kode untuk setiap framework yang pernah saya gunakan.
user606723
3
Anda sudah cukup membuktikan poin JeffO: Anda juga tidak dalam bisnis mempertahankan jam alarm. Jika Anda membeli dan mulai menggunakannya tanpa melakukan penghancuran total dan analisis tentang cara kerjanya, Anda telah menerima bahwa bagian dalamnya akan abstrak bagi Anda. Tidak ada yang mengatakan Anda tidak dapat memisahkannya untuk mengetahui cara kerjanya, tetapi seberapa sering Anda merasa perlu?
Blrfl
2

Untuk menjawab pertanyaan Anda secara khusus:

Apakah ada nilai nyata dalam menyembunyikan detail?

Iya nih. Seperti yang Anda akui di baris pertama pertanyaan Anda.

Bukankah kita mengorbankan transparansi?

Tidak juga. Abstraksi yang ditulis dengan baik akan membuatnya mudah untuk memahami detail jika diperlukan.

Bukankah transparansi ini berharga?

Iya nih. Abstraksi harus dirancang dan diimplementasikan untuk membuat memahami detail dengan mudah saat dibutuhkan / diinginkan.

Craig
sumber
Akhirnya jawaban yang saya suka.
user606723
1

Saya akan mengatakan bahwa menyembunyikan detail sangat bagus ketika hal-hal yang disembunyikan bekerja.

Misalnya, kita mengembangkan antarmuka yang mendefinisikan perilaku (yaitu GetListItems, SendListItem), yang merupakan dua fitur yang diprakarsai oleh pengguna melalui beberapa klik tombol atau sesuatu .. SEKARANG, setiap pengguna dapat memiliki "ListItemStore" mereka sendiri .. katakan satu di facebook, yang di myspace .. (misalnya) .. dan mengatakan itu disimpan sebagai properti pengguna / pengaturan di suatu tempat di aplikasi melalui preferensi pengguna .. dan mengatakan itu mungkin bagi pengembang aplikasi untuk menambahkan ListItemStore tambahan selama waktu (mybook, facespace, dll.)

sekarang ada banyak detail dalam menghubungkan ke facebook dan mendapatkan barang-barang mereka .. dan ada banyak rincian yang sama ketika terhubung ke myspace .. dan seterusnya ...

sekarang, setelah kode "akses toko" awal ditulis, mungkin tidak perlu dimodifikasi (baik dalam kasus facebooks kita mungkin membutuhkan pengembang penuh waktu untuk mengikuti perubahan, tenaga ..),

jadi ketika Anda menggunakan kode itu sesuatu seperti:

    new ItemManager(user) //passes in user, allowing class to get all user properties
    ItemManager.GetListItems()

dan sekarang Anda sudah mendapatkan data Pengguna dari mana pun mereka menyimpannya, dan karena yang saya khawatirkan adalah mendapatkan daftar barang dan melakukan sesuatu dengannya, dan karena hanya butuh 2 baris yang akan berfungsi tidak peduli bagaimana banyak lagi toko yang ditambahkan, saya dapat kembali menjawab / memposting pertanyaan di tumpukan ... lol ..

Jadi, semua pipa ledeng untuk membuat itu terjadi adalah "tersembunyi" dan siapa yang benar-benar peduli bagaimana melakukannya selama saya mendapatkan daftar item yang benar .. jika Anda memiliki unit test, maka Anda bahkan dapat beristirahat lebih mudah karena hasilnya seharusnya ' sudah dikuantifikasi sudah ..

Hanzolo
sumber
Ya, tetapi bagian yang perlu dipertahankan tidak pernah dua baris itu. Itu tidak mungkin untuk gagal. Selalu level 2, 3, 4 turun yang perlu Anda ubah. Saya setuju bahwa ini hebat ketika Anda memiliki API yang dapat Anda percayai untuk menjadi stabil , tetapi bagaimana jika itu tidak dapat stabil hanya karena kompleksitas bisnis Anda?
user606723
1
@ user606723 jika API Anda tidak stabil, maka kemungkinan besar itu belum matang, atau lebih mungkin abstraksi yang salah
sdg
@ user606723 - Itu benar, dan dalam kasus itu konvensi penamaan sendiri harus mendefinisikan beberapa bentuk transparansi yang menyembunyikan logika / detail pemrograman aktual .. dan jika Anda harus memodifikasi sumber aktual, rincian & ide lebih lanjut harus diungkapkan melalui penamaan yang informatif jadi pada intinya, transparansi dapat dicapai dengan penamaan yang tepat sepanjang jalan, namun, kita tidak perlu benar-benar harus turun terlalu sering.
hanzolo
@ SDG, atau karena persyaratan sistem selalu berubah. Karena hukum berubah, karena perubahan API orang lain, itu di luar kendali kami.
user606723
1
@ user606723 - saya benar-benar bekerja pada sistem SaaS keuangan dan saya melihat perangkap tidak memiliki cukup abstraksi setiap siklus rilis. beberapa di antaranya adalah hasil dari desain yang buruk, tetapi biasanya itu adalah hasil dari mendorong kode di mana itu awalnya tidak dimaksudkan. Turun rantai bisa menyakitkan tanpa komentar, nama dan enkapsulasi . jika semua yang harus saya lakukan adalah Remeasurements.GetRemeasureType (grant), dan kemudian reMeasure.PerformCalc (), itu akan jauh lebih baik daripada menambahkan kelebihan dan membaca melalui cabang logis yang berbeda untuk sampai pada perhitungan yang tepat atau menambahkan yang baru
hanzolo
1

Apa yang Anda sebut sebagai "Menyembunyikan", banyak yang melihat sebagai pemisahan keprihatinan (misalnya Implementasi vs. Antarmuka).

Menurut pendapat saya, satu manfaat utama abstraksi adalah untuk mengurangi kekacauan detail yang tidak dibutuhkan dari ruang otak pengembang yang terbatas.

Jika kode implementasi dikaburkan, saya bisa melihat itu sebagai penghalang transparansi, tetapi abstraksi seperti yang saya lihat, adalah organisasi yang baik.

Somantra
sumber
1

Pertama, apa pun di luar instruksi kode mesin tunggal pada dasarnya adalah abstraksi - while...doloop adalah cara simbolis yang konsisten untuk mewakili perbandingan dan panggilan alamat yang diperlukan untuk mengulang satu set instruksi sampai suatu kondisi terpenuhi. Demikian juga tipe int adalah abstraksi untuk jumlah bit X (tergantung pada sistem Anda). Pemrograman adalah tentang abstraksi.

Anda mungkin setuju bahwa abstraksi primitif itu sangat berguna. Nah, jadi bisa membangun sendiri. Tentang OOAD dan OOP.

Misalkan Anda memiliki persyaratan di mana pengguna ingin dapat mengekspor data dari layar dalam berbagai format: teks terbatas, excel, dan pdf. Tidakkah berguna jika Anda dapat membuat antarmuka yang disebut "Eksportir" dengan metode ekspor (data), yang dengannya Anda dapat membuat DelimitedTextExporter, ExcelExporter, dan PDFExporter, yang masing-masing tahu cara membuat output khusus itu? Yang perlu diketahui oleh program panggilan adalah bahwa ia dapat memanggil metode ekspor (data), dan implementasi mana pun yang digunakan akan melakukan hal tersebut. Selain itu, jika aturan teks dibatasi berubah, Anda dapat mengubah DelimitedTextExporter tanpa harus mengacaukan ExcelExporter, mungkin melanggar itu.

Hampir semua pola desain terkenal yang digunakan dalam pemrograman OO bergantung pada abstraksi. Saya akan merekomendasikan membaca Pola Desain Kepala Pertama Freeman dan Freeman untuk mendapatkan perasaan yang lebih baik mengapa abstraksi adalah hal yang baik

Matthew Flynn
sumber
1
bahkan kode mesin adalah abstraksi, ada proses nyata, fisik, yang terjadi di bawah logika, bahkan elektronik digital adalah abstraksi atas apa yang sebenarnya terjadi karena siapa pun yang telah membuat hash overclocking sebuah chip dapat bersaksi kepada
jk.
Terlalu benar, meskipun tampaknya lebih konkret di tingkat instruksi mesin.
Matthew Flynn
1

Saya pikir saya mengerti perasaan Anda tentang ini, dan saya pikir saya memiliki pendapat yang sama.

Saya telah bekerja dengan pengembang Java yang mengubah 50 baris kode kelas menjadi 3 kelas dan 3 antarmuka karena mudah dimengerti. Dan saya tidak tahan.

Masalahnya sangat sulit untuk dipahami, hampir tidak mungkin untuk debug dan tidak pernah perlu untuk "mengalihkan implementasi".

Di sisi lain, saya juga melihat kode di mana beberapa objek berbagi perilaku yang sama dan digunakan di satu tempat, dan benar-benar bisa menggunakan pengurutan umum / pemrosesan loop jika metode akan diekspos melalui antarmuka umum.

Jadi, IMHO, objek inti yang cenderung digunakan dalam skenario serupa biasanya mendapat manfaat dari perilaku umum yang harus dapat diakses melalui antarmuka. Tapi itu cukup banyak, mengabstraksikan hal-hal sederhana karena itu benar, atau memungkinkan untuk beralih implementasi hanyalah cara untuk membuat kode berantakan.

Kemudian lagi, saya lebih suka kelas yang lebih cerdas daripada jumlah kelas kecil yang eksplosif dengan semua masalah manajemen seumur hidup, dan sulit untuk melihat hubungan, dan grafik panggilan spageti. Jadi beberapa orang akan tidak setuju dengan saya.

Coder
sumber
1

Tujuan pemandu persembunyian dan abstraksi harus memisahkan pengguna dari implementasi sehingga mereka dapat diubah secara mandiri. Jika konsumen digabungkan dengan detail implementasi, karena mengutak-atik internal mereka, keduanya dilemparkan menjadi batu dan menjadi lebih sulit untuk memperkenalkan fitur-fitur baru. atau algoritma yang lebih baik di masa depan.

Saat menulis modul, bagian tersembunyi dari implementasi memberi Anda sedikit pemikiran untuk dapat mengubahnya tanpa risiko melanggar kode lain yang tidak dapat Anda pikirkan.

Keuntungan lain untuk menyediakan antarmuka buram adalah bahwa mereka secara signifikan mengurangi luas permukaan antara subsistem. Dengan mengurangi jumlah cara mereka berinteraksi, mereka dapat menjadi lebih dapat diprediksi, lebih mudah untuk diuji dan memiliki lebih sedikit bug. Interaksi antar modul juga meningkat secara kuadratik dengan jumlah modul sehingga ada nilai dalam mencoba mengendalikan pertumbuhan kompleksitas ini.


Yang mengatakan, tentu saja mungkin untuk menyembunyikan terlalu banyak dan antarmuka sarang terlalu dalam. Ini adalah tugas programmer, sebagai manusia yang cerdas, untuk merancang sistem sehingga bermanfaat secara maksimal sambil juga meminimalkan kompleksitas dan memaksimalkan pemeliharaan.

hugomg
sumber
0

Dalam banyak kasus, Anda tidak perlu tahu bagaimana hal-hal diterapkan. Saya hampir dapat menjamin bahwa Anda akan menulis kode seperti ini people.Where(p => p.Surname == "Smith")berkali-kali dalam sehari namun Anda tidak akan pernah berpikir "bagaimana Where()cara kerja metode ini ?" Anda hanya tidak peduli - Anda tahu metode ini ada dan itu memberi Anda hasil yang Anda inginkan. Mengapa Anda peduli bagaimana cara kerjanya?

Ini persis sama untuk perangkat lunak in-house; hanya karena itu tidak ditulis oleh Oracle, Microsoft, dll tidak berarti Anda harus mencari cara penerapannya. Anda dapat dengan wajar mengharapkan suatu metode yang dipanggil GetAllPeopleWithSurname(string name)untuk mengembalikan Anda daftar orang-orang yang memiliki nama keluarga itu. Mungkin beralih ke daftar, mungkin menggunakan kamus, mungkin melakukan sesuatu yang benar-benar gila tetapi Anda tidak perlu peduli .

Tentu saja ada pengecualian untuk aturan ini (itu bukan aturan tanpa aturan!) Dan itu adalah jika ada bug dalam metode ini. Jadi, dalam contoh di atas, jika Anda memiliki daftar dengan 3 orang di dalamnya dan Anda tahu bahwa salah satu dari mereka memiliki nama keluarga Smith dan mereka tidak dikembalikan dalam daftar maka Anda peduli dengan penerapan metode itu karena jelas rusak .

Abstraksi, bila dilakukan dengan benar, luar biasa karena memungkinkan Anda untuk menyaring semua hal yang tidak berguna ketika Anda harus membacanya di kemudian hari. Jangan lupa bahwa lebih banyak waktu dihabiskan membaca kode daripada dihabiskan menulisnya, oleh karena itu penekanannya harus pada membuat tugas itu semudah mungkin. Anda mungkin juga berpikir bahwa abstraksi berarti hierarki objek selama lengan Anda tetapi bisa sesederhana refactoring metode 100 baris menjadi 10 metode, masing-masing 10 baris panjang. Jadi apa yang dulunya 10 langkah semua digabungkan bersama sekarang 10 langkah terpisah memungkinkan Anda untuk langsung pergi ke tempat di mana bug sial ini bersembunyi.

Stuart Leyland-Cole
sumber
Eh, tapi katakanlah kaulah yang memelihara implementasi. Maksud saya, seseorang peduli dengan implementasinya, dan orang itu adalah Anda. Anda juga merupakan pengguna implementasi ... Persyaratan bisnis berubah (dengan cara yang tidak dapat Anda prediksi) yang menyebabkan perubahan pada banyak lapisan. Saya kira maksud saya adalah bahwa bug bukan satu-satunya pengecualian untuk aturan itu.
user606723
Masalahnya adalahPeopleFactory.People.Strategy.MakePeople.(CoutryLaw.NameRegistry.NameMaker.Make()) as People.Female
Coder
@ user606723 Anda tidak perlu peduli dengan setiap baris kode di basis kode Anda sepanjang waktu. Jika ada bug dalam implementasi itu atau ditandai sebagai perlu ditulis ulang (karena lambat, ditulis dengan buruk atau apa pun) dan Anda menulis ulang, maka Anda peduli. Kalau tidak, itu harus dijauhkan. Mungkin masalah Anda adalah Anda mencoba memiliki semua kode setiap saat. Anda hanya harus berkonsentrasi pada kode yang sedang Anda kerjakan pada waktu tertentu menurut saya.
Stuart Leyland-Cole
@Coder Jelas itu bentuk ekstrim dari abstraksi! Pada awalnya saya pikir itu adalah hal yang OP lawan tetapi dari membaca sisa jawaban mereka, tampaknya mereka melihat semua abstraksi sebagai buruk buruk. Inilah sebabnya saya mencoba menjelaskan berbagai tingkat abstraksi dalam jawaban saya.
Stuart Leyland-Cole
0

Abstraksi mengakibatkan penyembunyian informasi. Ini harus berakhir di kopling lebih rendah. Ini harus mengarah pada risiko perubahan yang lebih sedikit. Ini harus mengarah pada programmer yang senang, tidak merasa gugup saat menyentuh kode.

Ide-ide tersebut diungkapkan melalui tiga undang-undang penting dalam arsitektur perangkat lunak:

Hukum Simon: "Hierarki mengurangi kompleksitas." (Hirarki memperkenalkan abstraksi)

Hukum Parna: "Hanya yang tersembunyi yang bisa diubah tanpa risiko."

Hukum Constantin: Program yang kuat membutuhkan sambungan rendah dan kohesi yang tinggi

ins0m
sumber
"Hierarki mengurangi kompleksitas." - belum tentu benar.
Coder
Tidak ada metodologi desain yang deterministik. Undang-undang ini tidak berasal dari IT / CS, tetapi dirumuskan dalam arti yang jauh lebih luas dan juga disebut oleh matematika, fisikawan, dll. Ini adalah prinsipal yang valid, tetapi tidak ada yang dapat mencegah Anda membuat Hierarki yang tidak masuk akal.
ins0m
0

Saya dalam bisnis aplikasi perusahaan juga, dan pertanyaan ini menarik perhatian saya karena saya memiliki pertanyaan yang sama. Saya memiliki beberapa wawasan tentang masalah abstraksi selama karir saya sejauh ini, tetapi wawasan saya bukanlah jawaban universal. Saya terus belajar / mendengarkan ide dan pemikiran baru, sehingga apa yang saya yakini sekarang dapat berubah.

Ketika saya merawat aplikasi perawatan kesehatan yang besar dan kompleks, hanya menyukai Anda, saya benci semua abstraksi di sana. Mengira-ngira ke mana arah semua kode itu adalah rasa sakit di leher. Melompati kelas yang berbeda membuat saya pusing. Jadi saya berkata pada diri sendiri "abstraksi menyebalkan, saya akan meminimalkan abstraksi ketika saya mendesain barang".

Kemudian, tiba saatnya saya harus merancang aplikasi (komponen layanan web relatif kecil) dari bawah ke atas. Mengingat semua rasa sakit, saya memiliki desain komponen yang cukup datar. Masalahnya adalah, ketika persyaratan berubah saya harus membuat perubahan ke banyak tempat yang berbeda (persyaratan cukup lancar, dan saya tidak bisa berbuat apa-apa). Itu sangat buruk, pada dasarnya saya membuang desain awal dan mendesain ulang dengan abstraksi, dan segalanya menjadi lebih baik - saya tidak perlu melakukan perubahan ke banyak tempat ketika persyaratan berubah lagi.

Saya mengirimkan aplikasi, duduk selama beberapa minggu kemudian diberitahu untuk mulai memelihara aplikasi. Saya sudah lama, saya tidak ingat semuanya jadi saya sedikit berjuang untuk memahami kode saya sendiri, dan abstraksi tidak membantu.

Saya ditempatkan di banyak proyek yang berbeda setelah itu dan memiliki kesempatan untuk bermain-main dengan level abstraksi sedikit lebih. Apa yang sebenarnya saya temukan adalah, dan ini hanya pendapat pribadi saya, abstraksi banyak membantu dalam pengembangan tetapi memiliki dampak negatif ketika Anda tidak menulis kode dan mencoba memahami semuanya sampai ke level terdalam suatu aplikasi; Anda akan menghabiskan lebih banyak waktu melompati kelas yang berbeda, dan mencoba membuat koneksi.

Perasaan saya adalah bahwa abstraksi sangat berharga selama waktu pengembangan sehingga masalah yang kita alami sebagai pengelola ketika mencoba memahami kode adalah bernilai sementara. Perangkat lunak ada untuk memecahkan masalah bisnis, masalah bisnis berkembang seiring waktu; karenanya, perangkat lunak harus berkembang seiring waktu. Tanpa abstraksi, mengembangkan perangkat lunak itu sangat sulit. Seseorang dapat mendesain abstraksi sedemikian rupa sehingga pengelola dapat menavigasi di sekitar basis kode dengan mudah begitu mereka melihat pola struktur kode, sehingga hanya kurva belajar awal yang membuat frustrasi.

Alvin
sumber
0

Seperti yang orang lain katakan, "menyembunyikan detail" di belakang abstraksi memungkinkan mereka untuk diubah tanpa mempengaruhi pengguna. Gagasan ini berasal dari Parnas ' On the Criteria to Be digunakan dalam Decomposing Systems Intoodules (1972) , dan berkaitan dengan gagasan tipe data abstrak (ADT) dan pemrograman berorientasi objek.

Pada sekitar waktu yang sama, Model Data Relasional Codd untuk Bank Data Bersama Besar (1970) termotivasi (lihat abstrak dan intro) dengan ingin mengubah representasi penyimpanan internal dari database, tanpa mempengaruhi pengguna database. Dia telah melihat programmer secara teratur mengambil hari, memodifikasi halaman kode, untuk mengatasi perubahan penyimpanan kecil.

Yang mengatakan, sebuah abstraksi tidak terlalu berguna jika Anda harus melihat apa yang ada di dalamnya untuk dapat menggunakannya. Sangat sulit untuk mendesainnya dengan baik. Contoh abstraksi yang baik adalah penambahan - kapan terakhir kali Anda harus berpikir tentang apa yang terjadi di dalam? (tetapi kadang-kadang Anda melakukannya, misalnya untuk melimpah).

Masalah mendasar (IMHO) adalah bahwa untuk merancang modul dengan baik (dalam pengertian Parnas), Anda perlu memprediksi apa yang akan berubah dan apa yang tidak. Memprediksi masa depan itu sulit - tetapi jika Anda memiliki banyak pengalaman dengan sesuatu, dan memahaminya dengan jelas, maka Anda dapat melakukan pekerjaan prediksi yang cukup baik. Dan karena itu, Anda dapat merancang modul (abstraksi) yang berfungsi dengan baik.

Namun, tampaknya memang nasib semua abstraksi - bahkan yang terbaik - yang pada akhirnya akan ada perubahan tak terduga (dan bisa dibantah, tidak terduga) yang membutuhkan pemutusan abstraksi. Untuk mengatasinya, beberapa abstraksi memiliki jalan keluar, di mana Anda bisa mendapatkan akses ke tingkat yang lebih dalam jika Anda benar-benar membutuhkannya.

Ini semua tampaknya sangat negatif. Tetapi saya pikir kebenarannya adalah kita dikelilingi oleh abstraksi yang bekerja dengan sangat baik sehingga kita tidak memperhatikannya, atau menyadari apa yang mereka sembunyikan. Kami hanya memperhatikan abstraksi yang buruk, jadi kami memiliki pandangan kuning tentang mereka.

13rn
sumber
0

Abstraksi sebagian besar untuk kepentingan konsumen mereka (misalnya, programmer aplikasi). Pemrogram sistem (perancang) memiliki lebih banyak pekerjaan yang harus dilakukan untuk membuatnya cantik dan berguna, itulah sebabnya desain yang baik biasanya tidak dilakukan oleh pemula.

Mungkin Anda tidak suka abstraksi karena selalu menambah kompleksitas? Mungkin sistem yang pernah Anda gunakan menderita abstractionitis (penggunaan abstraksi berlebihan)? Mereka bukan obat mujarab.

Kerja ekstra dan kerumitan abstraksi yang bermanfaat harus membuahkan hasil, tetapi sulit untuk memastikannya. Jika Anda menganggap abstraksi sebagai titik pivot, maka desain perangkat lunak dapat fleksibel di kedua sisi: implementasi abstraksi dapat dimodifikasi tanpa melanggar kode klien, dan / atau klien baru dapat dengan mudah menggunakan kembali abstraksi untuk membuat hal-hal baru.

Anda hampir bisa mengukur pengembalian investasi atas abstraksi dengan menunjukkan bahwa mereka telah "tertekuk" dari waktu ke waktu dalam satu atau kedua arah ini: perubahan implementasi yang relatif tidak menyakitkan dan tambahan klien baru.

Sebagai contoh: Menggunakan abstraksi kelas Socket di Java, saya yakin kode aplikasi saya dari Java 1.2 masih berfungsi dengan baik di bawah Java 7 (walaupun mungkin ada beberapa perubahan kinerja). Sejak Java 1.2, pasti ada banyak klien baru yang menggunakan abstraksi ini juga.

Adapun ketidakbahagiaan dengan abstraksi, jika saya berbicara dengan pengembang yang memelihara kode belakang kelas Socket, maka mungkin hidup mereka tidak sebagus dan semerah klien yang menggunakan Socket untuk menulis aplikasi yang menyenangkan. Bekerja pada implementasi abstraksi tentu lebih banyak pekerjaan daripada menggunakannya. Tapi itu tidak membuatnya buruk.

Adapun transparansi, dalam strategi desain top-down, transparansi total membuat desain yang buruk. Pemrogram yang cerdas cenderung memanfaatkan informasi yang mereka miliki secara maksimal, dan sistem kemudian menjadi sangat erat. Perubahan terkecil dari detail (misalnya, mengubah urutan byte dalam struktur data) dalam sebuah modul dapat memecahkan beberapa kode di tempat lain, karena seorang programmer pintar menggunakan informasi itu untuk melakukan sesuatu yang bermanfaat.David Parnas menunjukkan masalah ini dalam artikel-artikel setua tahun 1971 di mana ia mengusulkan menyembunyikan informasi dalam desain.

Referensi Anda ke ArchLinux masuk akal bagi saya jika Anda menganggap "bagian dalam" dari sistem operasi sebagai implementasi kompleks dari abstraksi yang merupakan OS untuk aplikasi yang berjalan di atasnya. Buat sederhana di nyali abstraksi.

Fuhrmanator
sumber
0

Saya akan menjawab pertanyaan Anda dengan pertanyaan; ketika Anda mengemudi untuk bekerja pagi ini (saya anggap Anda memang melakukannya), apakah Anda benar-benar peduli bagaimana mesin membuka katup untuk membiarkan campuran udara-bahan bakar, dan kemudian menyalakannya? Tidak. Anda tidak peduli bagaimana mesin mobil Anda bekerja saat Anda berkendara di jalan. Anda peduli itu terjadi bekerja.

Misalkan, suatu hari, mobil Anda gagal bekerja. Tidak memulai, melempar tongkat, mematahkan ikat pinggang, secara tidak masuk akal membajak ke penghalang beton itu bukan karena kesalahan Anda sendiri saat Anda sibuk mengirim SMS. Sekarang, Anda membutuhkan mobil baru (setidaknya sementara). Apakah Anda peduli persis bagaimana mobil baru ini bekerja? Tidak. Yang Anda pedulikan adalah yang pertama berhasil, dan kedua Anda dapat menggunakan pengetahuan dan keterampilan yang sama dengan yang Anda gunakan untuk mengendarai mobil lama Anda dengan mengendarai yang baru. Idealnya, Anda akan melihat bahwa tidak ada perubahan pada mobil yang Anda kendarai. Secara realistis, cara mobil baru ini bekerja harus memberi Anda "kejutan" sesedikit mungkin.

Prinsip dasar ini adalah prinsip inti di balik enkapsulasi dan abstraksi. Pengetahuan tentang bagaimana suatu objek melakukan apa yang seharusnya tidak menjadi syarat untuk menggunakannya untuk melakukan apa yang dilakukannya. Bahkan dalam pemrograman komputer, perincian jalur listrik dalam CPU yang menjalankan program Anda diabstraksikan di belakang setidaknya setengah lusin lapisan instruksi I / O, driver, perangkat lunak OS, dan runtime. Banyak insinyur perangkat lunak yang sangat sukses menulis kode yang sangat baik tanpa perlu khawatir tentang arsitektur perangkat keras yang tepat, atau bahkan OS build, yang akan menjalankannya. Termasuk saya.

Enkapsulasi / penyembunyian informasi memungkinkan mentalitas "tidak peduli bagaimana caranya, hanya peduli saja apa adanya". Objek Anda harus mengekspos apa yang bermanfaat bagi konsumen, dengan cara yang mudah dikonsumsi konsumen. Sekarang, kembali ke dunia nyata, ini tidak berarti bahwa mobil tidak boleh memberikan informasi apa pun kepada pengguna tentang pekerjaan dalam, atau bahwa mobil seharusnya hanya memberi pengguna fungsi yang paling dasar seperti kunci kontak, roda kemudi, dan pedal. Semua mobil memiliki spedometer dan pengukur bahan bakar, takometer, lampu idiot, dan umpan balik lainnya. Hampir semua mobil juga memiliki sakelar untuk berbagai subsistem independen, seperti lampu depan, sinyal belok, radio, penyesuaian tempat duduk, dll. Beberapa mobil memungkinkan input pengguna yang cukup esoteris, seperti sensitivitas diferensial pusat selip terbatas. Dalam semua kasus, jika Anda cukup tahu, Anda dapat membukanya dan mengubah hal-hal untuk membuatnya bekerja dengan cara yang sedikit berbeda. Tetapi, dalam banyak kasus, mungkin, mungkin saja, pengguna tidak dapat secara langsung dan independen mengendalikan pompa bahan bakar dari dalam kabin? Mungkin, mungkin saja, pengguna seharusnya tidak dapat mengaktifkan lampu rem mereka tanpa benar-benar menekan pedal rem?

Abstraksi memungkinkan "ini tidak sama dengan itu, tetapi karena mereka berdua XI dapat menggunakannya seperti yang saya lakukan pada setiap X" mentalitas. Jika objek Anda mewarisi atau mengimplementasikan abstraksi, konsumen Anda harus mengharapkan implementasi Anda untuk menghasilkan hasil yang sama atau serupa dengan implementasi abstraksi lainnya yang diketahui. Toyota Camry dan Ford Fusion keduanya adalah "mobil". Dengan demikian, mereka memiliki seperangkat fungsi yang diharapkan, seperti setir. Putar berlawanan arah jarum jam, mobil belok kiri. Putar searah jarum jam, mobil ke kanan. Anda dapat masuk ke mobil mana pun di Amerika Serikat dan mengharapkan mobil memiliki setir dan setidaknya dua pedal, yang di sebelah kanan adalah pedal "car goes" dan yang di tengah menjadi pedal "car stops" .

Sebuah akibat wajar dari abstraksi adalah "teori paling takjub". Jika Anda berada di belakang kemudi mobil baru untuk test drive, memutar setir searah jarum jam dan mobil berbelok ke kiri, Anda akan sangat terkejut untuk sedikitnya. Anda akan menuduh penjual menjajakan POS, dan tidak mungkin mendengarkan alasannya mengapa perilaku baru itu "lebih baik" daripada yang biasa Anda lakukan, atau seberapa baik perilaku ini "didokumentasikan" atau bagaimana " transparan "sistem kontrolnya. Meskipun ini mobil baru dan semua yang Anda kendarai masih menjadi "mobil", ketika mengendarai mobil ini Anda harus mengubah beberapa konsep mendasar tentang bagaimana mobil seharusnya dikendarai agar dapat menggerakkan mobil baru dengan sukses. Itu biasanya hal yang buruk, dan itu hanya terjadi ketika ada keuntungan intuitif pada paradigma baru. Mungkin penambahan sabuk pengaman adalah contoh yang bagus; 50 tahun yang lalu Anda baru saja masuk dan pergi, tetapi sekarang Anda harus mengencangkan, keuntungan intuitifnya adalah Anda tidak pergi melalui kaca depan atau ke kursi penumpang jika Anda mengalami kecelakaan. Bahkan kemudian, pengemudi menolak; banyak pemilik mobil memotong sabuk pengaman dari mobil sampai hukum disahkan mengamanatkan penggunaannya.

KeithS
sumber