Bisakah terlalu banyak abstraksi menjadi buruk?

46

Sebagai programmer saya merasa bahwa tujuan kami adalah untuk memberikan abstraksi yang baik pada model domain dan logika bisnis yang diberikan. Tapi di mana abstraksi ini harus berhenti? Bagaimana membuat trade-off antara abstraksi dan semua manfaatnya (fleksibilitas, kemudahan mengubah dll.) Dan kemudahan memahami kode dan semua manfaatnya.

Saya percaya saya cenderung menulis kode yang terlalu abstrak dan saya tidak tahu seberapa bagusnya; Saya sering cenderung menulis seperti itu semacam kerangka kerja mikro, yang terdiri dari dua bagian:

  1. Modul Mikro yang terhubung dalam kerangka mikro: modul ini mudah dipahami, dikembangkan, dan dipelihara sebagai satu kesatuan. Kode ini pada dasarnya mewakili kode yang benar-benar melakukan hal-hal fungsional, dijelaskan dalam persyaratan.
  2. Menghubungkan kode; sekarang di sini saya percaya berdiri masalahnya. Kode ini cenderung rumit karena terkadang sangat abstrak dan sulit dipahami pada awalnya; ini muncul karena fakta bahwa itu hanya abstraksi murni, dasar dalam realitas dan logika bisnis yang dilakukan dalam kode yang disajikan 1; dari alasan ini kode ini tidak diharapkan untuk diubah setelah diuji.

Apakah ini pendekatan yang baik dalam pemrograman? Itu saja, memiliki kode perubahan yang sangat terfragmentasi dalam banyak modul dan sangat mudah dipahami dan kode yang tidak berubah sangat kompleks dari abstraksi POV? Haruskah semua kode menjadi seragam seragam (yaitu kode 1 lebih kompleks dan saling terkait dan kode 2 lebih sederhana) sehingga siapa pun yang melihatnya dapat memahaminya dalam jumlah waktu yang wajar tetapi perubahan itu mahal atau solusi yang disajikan di atas baik, di mana "Mengubah kode" sangat mudah dipahami, disadap, diubah dan "menghubungkan kode" agak sulit.

Catatan: ini bukan tentang keterbacaan kode! Kedua kode pada 1 dan 2 dapat dibaca, tetapi kode pada 2 dilengkapi dengan abstraksi yang lebih kompleks sedangkan kode 1 dilengkapi dengan abstraksi sederhana.

m3th0dman
sumber
3
Komentar dan nama yang jelas diciptakan untuk mempercepat waktu yang dibutuhkan untuk memahami kode yang kompleks. Baik-baik saja untuk kode level bawah Anda menjadi lebih kompleks; pada tingkat tertentu, Anda hampir pasti memanggil tingkat yang jauh lebih kompleks dan jauh lebih rendah pula.
DougM
25
"Terlalu banyak" itu buruk menurut definisi.
Jon Purdy
@JimmyHoffa: Harus menyimpan tipe-tipe itu di tempatnya. Dan jangan cemburu — aku tidak bisa menulis Haskell sepanjang hari. Sebenarnya sebagian besar PHP, JavaScript, dan OCaml.
Jon Purdy

Jawaban:

78

Kata-kata pertama dari TC ++ PL4:

Semua masalah dalam ilmu komputer dapat diselesaikan dengan tingkat tipuan lain, kecuali untuk masalah terlalu banyak lapisan tipuan. - David J. Wheeler

(David Wheeler adalah penasihat tesis saya. Kutipan tanpa baris terakhir yang penting kadang-kadang disebut "Hukum pertama Ilmu Komputer.")

Bjarne
sumber
6
Dan bagaimana Anda tahu ketika Anda memiliki terlalu banyak tingkat tipuan? Saya cenderung mengatakan itu datang dengan pengalaman, tetapi seorang programmer yang lebih berpengalaman dengan mudah memahami lebih banyak tipuan sehingga tidak melihat masalah dengan level terlalu banyak.
m3th0dman
2
@ m3th0dman - Anda memiliki level abstraksi yang tepat saat membuat perubahan di masa depan menjadi mudah. Tentu saja, Anda juga dapat bertanya bagaimana Anda tahu kapan itu akan terjadi yang hanya mengulangi siklus pertanyaan dengan cara yang berbeda.
1
pertanyaan ini seperti tergantung pada tingkat programmer .. Anda akan memiliki programmer yang kompleks yang akan memahami arsitektur 8-tier layer Anda yang gila & menemukannya brilian, sementara coders sederhana namun halus lainnya akan merasa konyol & berdebat tentang level 8-gila Anda layered project .. disinilah dokumentasi terbayar, tidak hanya memungkinkan Anda untuk mendokumentasikan kode Anda, tetapi juga memungkinkan Anda untuk mempertahankannya
Ryan
1
maafkan ketidaktahuan saya, tapi saya tidak mengerti "TC ++ PL4"
LastTribunal
30

Iya tentu saja. Masalahnya, tidak ada abstraksi yang sempurna. Semua detail dari lapisan yang diletakkan di atas abstraksi ada karena suatu alasan, dan itu dapat menyederhanakan banyak hal, tetapi jika kompleksitas itu tidak diperlukan pada beberapa titik, itu mungkin tidak akan ada di tempat pertama. Dan itu berarti bahwa pada titik tertentu, setiap abstraksi akan bocor dengan cara tertentu.

Dan di situlah letak masalahnya. Ketika abstraksi gagal, semakin banyak Anda berada di antara kode yang Anda tulis dan apa yang sebenarnya terjadi, semakin sulit untuk mencari tahu masalahnya dan memperbaikinya, karena ada lebih banyak tempat di mana masalahnya mungkin. Dan semakin banyak lapisan, semakin banyak yang harus Anda ketahui untuk melacaknya.

Mason Wheeler
sumber
1
"Dan itu berarti bahwa pada titik tertentu, setiap abstraksi akan bocor dalam beberapa cara.": Benar. Abstraksi yang lebih baik adalah yang lebih jarang bocor.
Giorgio
11
Mengingat jawaban Bjarne (dan referensi halaman wiki David Wheeler ), mungkin Anda dapat mengubah atribusi kutipan Anda? :)
congusbongus
2
@CongXu: Btw Saya telah melakukannya dari ujung yang lain: googling untuk "Bjarne Stroustrup quotes" dan belum menemukan referensi tunggal dari Bjarne setelah mengucapkan kalimat "menambahkan lapisan lain dari tipuan" ... Tidak konklusif tentu saja tetapi apakah membuatnya sangat tidak mungkin dia adalah orang pertama yang mengucapkannya.
Marjan Venema
1
Semakin banyak lapisan abstraksi berarti abstraksi sederhana dan dengan demikian lebih sedikit kebocoran per abstraksi. Jadi dalam formulasi matematis (tentu saja, tanpa bukti) jumlah kebocoran abstraksi mungkin konstan karena jumlah level abstraksi berubah.
m3th0dman
2
Saya pernah dengan naif mengambil saran dari seorang senior untuk menambahkan abstraksi di mana itu tidak diperlukan. Itu tidak pernah digunakan melebihi apa yang ingin saya lakukan di tempat pertama.
Cees Timmerman
15

Ya, tentu saja.

Analogi yang saya suka gunakan untuk menjelaskan pemrograman adalah penjahit. Saat membuat setelan, Penjahit yang baik akan selalu meninggalkan sejumlah kecil kain di lokasi strategis di dalam garmen untuk memungkinkan garmen itu diambil atau dikeluarkan, tanpa mengubah bentuk atau struktur keseluruhannya.

Good Tailor's tidak meninggalkan rim kain di setiap jahitan hanya jika Anda tumbuh lengan ketiga, atau menjadi hamil. Terlalu banyak bahan di tempat yang salah akan membuat pakaian tidak pas, dan tidak nyaman, kain tambahan hanya menghalangi penggunaan normal. Untuk sedikit kain dan pakaian mudah robek dan tidak akan dapat diubah untuk mengatasi perubahan kecil pada fisik pemakainya, yang mempengaruhi cara duduk.

Mungkin suatu hari, Penjahit Baik kita akan ditugaskan untuk membuat gaun yang begitu ketat sehingga dia harus menjahit pakaiannya. Dan mungkin Penjahit Baik kita diminta untuk membuat pakaian hamil, di mana gaya dan kecocokan adalah yang kedua untuk kenyamanan dan kemampuan yang berkembang. Tetapi sebelum melakukan salah satu dari pekerjaan khusus tersebut, Penjahit yang baik akan cukup bijaksana untuk membuat semua orang menyadari kompromi yang sedang dilakukan untuk mencapai tujuan-tujuan tersebut.

Terkadang kompromi ini adalah rute yang tepat untuk diambil, dan orang-orang bersedia menerima konsekuensinya. Tetapi dalam kebanyakan kasus, pendekatan cuti sedikit di mana itu dianggap paling akan melebihi manfaat yang dirasakan.

Jadi, hubungkan ini kembali ke abstraksi. Sangat mungkin untuk memiliki terlalu banyak lapisan abstraksi, sama seperti mungkin untuk memiliki cara untuk sedikit. Seni sejati programmer, seperti teman penjahit kami, adalah meninggalkan sedikit tempat yang paling diperhitungkan.

Kembali ke topik.

Masalah dengan kode biasanya bukan abstraksi, tetapi dependensi. Seperti yang telah Anda tunjukkan, ini adalah kode yang menghubungkan objek diskrit yang menjadi masalah, karena ada ketergantungan implisit di antara mereka. Pada titik tertentu komunikasi antara hal - hal hanya perlu konkret, tetapi menilai di mana titik itu biasanya membutuhkan beberapa dugaan.

Yang dikatakan "Mikro" apa pun biasanya merupakan indikasi bahwa Anda telah terlalu besar mengatur tata letak objek Anda, dan mungkin menggunakan Type sebagai sinonim untuk apa yang seharusnya menjadi Data . Memiliki lebih sedikit barang juga berarti lebih sedikit ketergantungan yang dibutuhkan untuk berkomunikasi di antara mereka.

Saya penggemar berat pesan tidak sinkron antar sistem karena alasan ini. Anda berakhir dengan dua sistem yang tergantung pada pesan , bukan satu sama lain. Memberi Anda hubungan yang lebih erat antara sistem komunikasi. Pada titik itu, jika Anda perlu memiliki ketergantungan antara sistem, Anda perlu mempertimbangkan apakah Anda memiliki bit yang bergantung pada tempat yang tepat. Dan sering kali hal itu tidak Anda lakukan.

Akhirnya, kode yang rumit akan menjadi rumit. Sering kali tidak ada jalan lain untuk itu. Tetapi kode yang memiliki lebih sedikit ketergantungan jauh lebih mudah dipahami daripada kode yang bergantung pada berbagai kondisi eksternal.

Matt D
sumber
2
+1 untuk "Penjahit Yang Baik jangan meninggalkan rim kain di setiap jahitan hanya jika Anda kebetulan menumbuhkan lengan ketiga, atau menjadi hamil". Sayangnya, kita sering merancang perangkat lunak dengan cara ini.
Kemoda
Seiring dengan pemahaman, orang juga dapat menemukan abstraksi yang berguna ketika menekuk garis melengkung menjadi garis lurus. Berarti Anda mengurangi kompleksitas dan / atau entropi dengan abstraksi. Mungkin sesuatu seperti handler tipe data Curry di mana lemak yang Anda cukur masih berguna nantinya.
Cody
13

Saya merasa bahwa tujuan kami adalah memberikan abstraksi yang baik pada model domain dan logika bisnis yang diberikan.

Saya memiliki pandangan yang berbeda: tujuan kami adalah menyelesaikan masalah bisnis. Abstraksi hanyalah teknik untuk mengatur solusi. Jawaban lain menggunakan analogi pakaian yang dibuat khusus. Saya memiliki analogi lain yang saya suka pikirkan: kerangka. Kode itu seperti kerangka, dan abstraksi adalah sambungan antar tulang. Jika Anda tidak memiliki sendi, maka Anda hanya berakhir dengan satu tulang yang tidak bisa bergerak sama sekali dan tidak berguna. Tetapi jika Anda memiliki terlalu banyak sendi, Anda berakhir dengan tumpukan ceroboh yang tidak dapat berdiri sendiri. Triknya adalah menemukan keseimbangan yang tepat - sambungan yang cukup untuk memungkinkan gerakan, tetapi tidak terlalu banyak sehingga tidak ada bentuk atau struktur yang sebenarnya ditentukan.

Jordan Lev
sumber