Selamat tinggal, Clean Code (2020)
(overreacted.io)- Melalui pengalaman menulis ulang kode resize editor grafis dengan fokus menghapus duplikasi lalu akhirnya mengembalikannya, tulisan ini menunjukkan bahwa obsesi pada clean code bisa justru merusak kemudahan melakukan perubahan nyata
- Implementasi lama mengulang rumus untuk tiap handle pada Rectangle, Oval, Header, dan TextBlock, sedangkan implementasi baru berusaha menghapus duplikasi dengan memisahkan arah dan bentuk lalu menggabungkannya
- Tepat setelah refactoring, ukuran kode berkurang setengah dan titik perubahan terkumpul di satu tempat, tetapi ketika kemudian dibutuhkan perilaku khusus per bentuk dan per handle, abstraksi justru bisa menjadi penghambat
- Masalah yang lebih besar daripada penilaian teknis adalah langsung check-in ke master tanpa berdiskusi dengan rekan yang menulis kode aslinya, yang bisa merusak pembangunan kepercayaan dalam tim
- “Kebersihan” bukan tujuan, melainkan hanya alat untuk menangani sistem yang kompleks, dan yang lebih penting daripada bentuk kode adalah apakah tim dapat bersama-sama merespons perubahan
Pengulangan dalam kode resize editor grafis
- Pada kanvas editor grafis, ada kode untuk me-resize bentuk seperti persegi panjang dan oval menggunakan handle kecil di tepinya
- Implementasinya berjalan, tetapi rumus untuk menghitung posisi dan ukuran berulang untuk setiap bentuk dan arah handle
Rectanglememiliki metode sepertiresizeTopLeft,resizeTopRight,resizeBottomLeft,resizeBottomRightOvalmemiliki metode sepertiresizeLeft,resizeRight,resizeTop,resizeBottomHeaderdanTextBlockjuga masing-masing memiliki metode resize
- Jika pengguna menekan Shift, proses resize juga harus menangani menjaga rasio, sehingga rumusnya menjadi semakin banyak
Abstraksi untuk menghapus duplikasi
- Pengulangan terlihat pada dua sumbu
- Terjadi pengulangan di antara handle dengan arah yang sama:
Oval.resizeLeft()danHeader.resizeLeft()sama-sama menangani aksi drag handle kiri - Terjadi pengulangan di antara metode dalam bentuk yang sama: beberapa metode pada
Ovalsemuanya menangani oval
- Terjadi pengulangan di antara handle dengan arah yang sama:
- Struktur baru mencoba membagi kode menjadi
DirectionsdanShapesuntuk menggabungkan perilaku per arah dan perilaku per bentukDirectionsberisitop,left,bottom,rightShapesberisiOval,RectanglecreateHandle,createBoxdigunakan untuk menggabungkan handle dan bentuk
- Dalam pendekatan ini, dibuat konfigurasi handle seperti
fourCorners,fourSides,twoSides, lalu itu digunakan untuk membentukRectangle,Oval,Header,TextBlock
Ilusi tepat setelah refactoring
- Setelah refactoring, ukuran total kode berkurang setengah dan duplikasi tampak seolah hilang
- Saat ingin mengubah perilaku arah atau bentuk tertentu, terasa cukup mengubah satu tempat alih-alih banyak metode
- Larut malam ia melakukan check-in perubahan ke master, sambil merasa telah merapikan kode berantakan milik rekannya dengan elegan
Masalah yang terungkap keesokan harinya
- Keesokan harinya atasan meminta perubahan itu dibatalkan, dan saat itu sulit menerimanya karena ia yakin kode baru lebih bersih daripada kode lama
- Setelah waktu berlalu, keputusan itu ternyata benar karena dua alasan
- Ia menulis ulang dan melakukan check-in kode tanpa berbicara dengan orang yang menulis kode aslinya
- Demi mengurangi duplikasi, ia justru mengorbankan kemudahan menghadapi perubahan kebutuhan
- Tim engineering yang sehat harus terus membangun kepercayaan, dan penulisan ulang besar-besaran atas kode rekan kerja bisa menjadi pukulan besar bagi kolaborasi
Biaya abstraksi yang salah
- Setelah itu, muncul banyak kasus khusus dan perilaku khusus untuk berbagai handle pada berbagai bentuk
- Untuk mengakomodasi kebutuhan seperti itu dalam struktur abstraksi baru, kode bisa menjadi beberapa kali lebih rumit
- Sebaliknya, struktur asli yang “berantakan” justru cukup mudah diberi perubahan seperti ini karena tiap metode terpisah
- Menghapus duplikasi kode tidaklah gratis; saat mendapatkan satu kemampuan, kita bisa kehilangan kemampuan lain
Memikirkan kembali “kebersihan”
- Banyak developer bisa mengalami masa terobsesi pada “clean code” dan penghapusan duplikasi
- Saat tidak percaya diri pada kode yang ditulis sendiri, mudah untuk menggantungkan kebanggaan pada hal-hal yang bisa diukur seperti aturan lint yang ketat, aturan penamaan, struktur file, atau tidak adanya duplikasi
- Ketika sudah bisa membuat abstraksi, kita bisa mulai percaya bahwa abstraksi adalah kebajikan dan ingin menerapkannya setiap kali melihat kode berulang
- Kita perlu memikirkan secara mendalam hasil engineering nyata apa yang benar-benar terkait dengan rasa “bersih” atau “kotor” itu
- Bukan hanya bagaimana kode terlihat, tetapi juga bagaimana kode itu berubah dan diperbaiki bersama orang-orang dalam tim yang penting
Saat harus melepaskan clean code
- Clean code bukan tujuan, melainkan upaya untuk memahami sistem yang kompleks
- Saat kita belum yakin dampak perubahan dalam codebase akan seperti apa, clean code bisa menjadi mekanisme pertahanan yang membantu memberi arah
- Pada awalnya, pengalaman menyederhanakan kode kompleks lewat ekstraksi fungsi atau refactoring kelas bisa terasa menyenangkan
- Namun kita tidak boleh berhenti di sana lalu menjadi “fanatik clean code”
- Biarkan clean code menjadi penunjuk arah, tetapi pada titik tertentu kita harus melepaskannya
1 komentar
Pendapat Hacker News
Duplikasi kode kadang tidak apa-apa, tetapi itu bukan bukti bahwa Clean Code itu buruk
Rasanya refaktorisasi yang dilakukan agak berlebihan; kalau hanya mengekstrak “10 baris matematika yang berulang” menjadi sebuah fungsi, hasilnya mungkin akan lebih rapi
Rekan tim yang tidak menjadikan 10 baris itu sebagai fungsi juga tidak sepenuhnya benar, jadi kalau saya mungkin akan menolak PR-nya, tetapi saya tidak akan menulis ulang sendiri
Menulis ulang PR orang lain adalah penghinaan cepat yang menutup ruang diskusi, dan sering kali kita juga tidak tahu konteks mengapa kode itu ditulis seperti itu
Jika tidak ada standar coding, PR harus ditinjau dan ditolak; kalau dibiarkan di-commit dengan alasan “Clean Code tidak penting”, dalam beberapa bulan codebase itu akan menjadi tempat yang tidak ingin dikerjakan siapa pun
Yang bisa dipelajari di sini bukan Clean Code, melainkan komunikasi dan tenggang rasa
Penulis aslinya juga kehilangan kesempatan untuk belajar bagaimana kode berkualitas rendah benar-benar membuang waktu
Sekalipun pendekatan Clean Code lebih baik, inti masalah di sini bukan kodenya, melainkan ia membuang waktunya sendiri tanpa memberi umpan balik yang berguna
Yang terbaik adalah membuat penulis asli menaikkan standarnya, sementara dirinya mengerjakan hal lain yang memang perlu disentuh. Dengan kata lain, jawaban yang benar adalah code review
Orang-orang seperti ini sering kali menyelesaikan sesuatu yang bukan masalah, alih-alih menyelesaikan masalah nyata, sekaligus menciptakan masalah masa depan
Pada implementasi pertama, memang lebih tepat untuk tidak mengabstraksikan potongan kode sangat kecil seperti 10 baris itu. Kode yang melakukan tepat hal tersebut mudah diperbaiki nanti, dan mengabstraksikan 10 baris demi manfaat yang belum terbukti tidak banyak artinya
Clean Code sama sekali tidak penting, begitu pula sebagian besar aturan atau “prinsip” serupa. Justru hal-hal semacam itulah yang dipegang orang-orang untuk membenarkan struktur seperti sarang lebah yang mereka tumpuk di codebase seiring waktu
Akibatnya, kode cenderung menjadi terlalu diabstraksikan, sulit diubah, lambat, dan sulit dipahami
Jika membutuhkan prinsip, cukup lihat apakah hal yang sebenarnya dilakukan program, yaitu transformasi data, diekspresikan dengan jelas dan mudah diubah
Sebagian besar prinsip SOLID tidak membantu melihat apa itu transformasi data dan bagaimana terjadinya, atau malah menghalanginya, sehingga umumnya kurang berguna untuk memahami program nyata
Jika melihat refaktorisasi yang diusulkan, 10 baris itu sebenarnya tidak identik, hanya mirip
Rumus untuk mengubah ukuran sudut kiri atas persegi panjang dan rumus untuk mengubah kanan bawah elips itu berbeda. Dari luar tampak mirip, tetapi di beberapa tempat ada
-alih-alih+Dalam kasus ini, kompleksitasnya ada pada geometri itu sendiri, dan “mengabstraksikannya” hanya memindahkan kekusutan ke tempat lain, bukan menghilangkannya secara mendasar
Mungkin saja ada abstraksi matematis cerdas seperti sistem bilangan khusus, tetapi jika tidak bawaan bahasa, biaya mengimplementasikan operasi khusus dengan bilangan bulat dasar kemungkinan lebih besar daripada manfaatnya
“Clean Code” perlu rebranding
Selama lebih dari 25 tahun berkarier, saya terus melihat penolakan tanpa henti terhadap design pattern, abstraksi, penghapusan duplikasi, dan sebagainya
Alasannya selalu sama: abstraksi membuat kode lebih rumit, tidak ada waktu untuk menulis Clean Code, semuanya hanya selera dan opini
Namun tujuan Clean Code adalah membuat kode lebih sederhana dan lebih mudah dipelihara ketika kebutuhan berubah
Nilai perangkat lunak terletak pada kemampuannya untuk berubah seiring waktu. Kalau tidak, kita bisa saja memakai rangkaian tetap yang implementasi dan pemeliharaannya jauh lebih mudah dan murah
Jika refaktorisasi tidak mencapai tujuan ini, dan atasan bisa meyakinkan bahwa perubahan kebutuhan di masa depan justru menjadi lebih sulit dipelihara, maka kode itu memang tidak “clean”
Tidak berdiskusi dengan penulis asli adalah masalah prosedur dan etiket di luar ranah Clean Code. Bersikap kasar dan sepihak tidak menghapus nilai Clean Code
Buku terkenal Clean Code menyebut “tanpa duplikasi” sebagai syarat sistem yang dirancang dengan baik, dan menyebut duplikasi sebagai musuh utama pekerjaan tambahan, risiko tambahan, dan kompleksitas yang tidak perlu
Dengan definisi ini, penghapusan duplikasi menjadi sinonim dari penyederhanaan, dan itu salah
Menghapus duplikasi adalah memperkenalkan dependensi. Jika dependensi itu memodelkan masalah dengan baik, ia bisa menjadi abstraksi yang baik sekaligus penyederhanaan; jika tidak, ia hanya kompresi yang menyamar sebagai abstraksi
Sebagai catatan, kutipan ini adalah penyebutan Simple Design dari Kent Beck yang muncul di Clean Code
Yang satu adalah perasaan subjektif bahwa suatu kode bagus, dan yang lain adalah mengikuti buku Clean Code serta pedoman terkaitnya
Semakin banyak orang merasa bahwa keduanya cukup berbeda. Mengikuti sebagian pedoman buku itu kadang justru menghasilkan kode yang sama sekali tidak bersih
Di dunia ideal, semua orang ingin menulis clean code, tetapi makin sedikit orang yang merasa Clean Code adalah cara yang baik untuk mencapai tujuan itu
Terutama abstraksi berlebihan dan penghapusan duplikasi kini dianggap banyak orang sebagai sumber kode yang berantakan
Terkadang technical debt sudah tertanam dalam kebutuhan produk itu sendiri, sehingga tidak bisa diperbaiki dengan refaktorisasi atau praktik terbaik; yang bisa dilakukan hanya mengurangi rasa sakitnya
Tujuan Clean Code dan hasil praktiknya sangat berbeda. Sebab orang-orang umumnya tidak bisa memprediksi kondisi masa depan kode, bahkan ketika kebutuhan sudah ada di depan mata
Clean Code memancing pertanyaan mengerikan “bagaimana jika?”, dan ini mudah menjadi kotak Pandora yang menunda rilis tanpa akhir
Hampir selalu lebih baik menulis kode sesuai hal yang diketahui, dan membiarkan orang yang punya pengalaman domain memimpin arsitektur
Banyak abstraksi yang baik sudah ada di library. Tentu saja, sayangnya tidak selalu begitu
Abstraksi buruk memakan waktu, dan kode juga merupakan cara berkomunikasi dengan orang lain di tim, jadi bagaimana anggota tim menerima komunikasi itu jauh lebih penting daripada cara berpikir saya sendiri
Seorang rekan menulis banyak kode dengan copy-paste, lalu Anda melakukan refactoring setelah commit
Rekan itu mengeluh kepada atasan, atasan memarahi Anda, dan Anda akhirnya menyimpulkan bahwa lain kali Anda akan membiarkan kekacauan tetap ada di codebase
Ada pelajaran yang bisa diambil di sini, tetapi itu bukan berarti copy-paste lebih baik daripada menulis fungsi
Refactoring seharusnya diajukan sebagai perubahan terpisah dengan menandai penulis aslinya untuk direview
Namun fakta bahwa rekan itu tidak berbicara langsung dan malah membawanya ke atasan, lalu atasan menyuruh mengembalikannya, adalah sinyal yang cukup buruk
Jawaban yang mungkin adalah “Tidak, alasannya…” atau, lebih jarang, “Benar juga, besok saya kerjakan”
Tanpa keributan, semua orang terhindar dari masalah, dan mungkin ada yang belajar sesuatu
Namun penulis menambahkan konteks penting. Ia menukar kemungkinan perubahan kebutuhan dengan pengurangan duplikasi, dan kemudian setiap handle untuk bentuk membutuhkan banyak kasus khusus dan perilaku tersendiri
Ini menunjukkan perbedaan antara DRY insidental dan DRY esensial
Library A dan B sering terlihat konsisten satu sama lain sehingga kodenya menjadi sama, tetapi sebenarnya itu bisa saja kebetulan
Jika wrapper untuk lib A dan wrapper untuk lib B berisi kode yang sama tetapi membungkus hal yang benar-benar berbeda, mengabstraksikannya akan berakhir buruk
Hal yang sama berlaku untuk “15”. Jika “semua daftar harus selalu menampilkan 15 item”, maka mengabstraksikan angka 15 itu benar; tetapi jika itu masing-masing adalah “15 lagu teratas di homepage” dan “default 15 komentar di bawah lagu”, mengikat kedua angka 15 itu justru pilihan yang lebih buruk
Sinyal bahaya kedua adalah refactoring itu sendiri juga bukan refactoring yang bagus. Modularitasnya kurang, masih saling terikat, dan hanya sedikit mengurangi duplikasi
Itu bisa terdengar seperti, “Kode yang kamu tulis kurang bagus, jadi saya tulis ulang. Ada keberatan?”
Solusi terbaik mungkin adalah meminta penjelasan dalam bentuk “review terlambat”, mengusulkan solusi, dan berharap penulis asli tidak sekadar mengabaikannya
Intinya adalah menyadari bahwa kode akan berubah di masa depan. Kebutuhan berubah, dan kode terkait juga berubah
Jika kita membuat abstraksi yang membatasi kemampuan perubahan itu, kita merusak kemampuan diri kita di masa depan untuk menyesuaikan codebase
Terutama abstraksi yang sudah menghabiskan banyak waktu dan usaha sering membuat kita terikat secara emosional, sehingga kita membuang lebih banyak waktu untuk memaksakan perubahan agar cocok dengan solusi yang elegan
KISS memang tepat
Kasus ini terlihat seperti masalah “tidak ada yang suka orang sok pintar”
Ini sering terjadi terutama ketika developer junior belum belajar bahwa pekerjaan bukan hanya antara dirinya dan komputer, melainkan antara dirinya, komputer, dan orang lain
Versi yang lebih rapi kemungkinan besar akan diterima jika ia benar-benar berbicara dengan penulis asli dan menyepakati cara yang lebih baik
Judul tulisan ini tampaknya lebih cocok menjadi belajar cara bekerja dalam tim daripada “Selamat tinggal, Clean Code”
Kode yang lebih kompleks mungkin diterima sebagai ancaman, dan dianggap sebagai pesaing yang perlu ditekan lewat rantai manajemen
Jika Anda junior, Anda perlu tahu bahwa pernyataan ini bergantung pada konteks. Di banyak tempat kerja, kesederhanaan lebih penting daripada fleksibilitas, fitur bahasa yang membingungkan dihindari, dan cara kerja yang menghabiskan banyak waktu di depan keyboard serta bahasa semacam itu lebih disukai
Sebaliknya, filosofi yang menekankan pembelajaran seumur hidup, software craftsmanship, dan refleksi proses bertabrakan sepenuhnya dengan lingkungan seperti ini
Upaya untuk menjadi lebih baik tidak populer di kalangan orang yang tidak bertumbuh
Keduanya pilihan hidup yang valid. Software bisa menjadi tempat nyaman untuk bekerja 7 jam lalu pulang, sekaligus dunia eksplorasi yang hanya dibatasi imajinasi dan kecerdasan
Jika Anda ingin menemukan hal baru, berhati-hatilah menghabiskan puluhan tahun bersama orang-orang yang takut pada hal yang belum dikenal
Singkatnya, jika insentif Anda tidak selaras dengan rekan-rekan, pertimbangkan untuk pergi
Tulisan ini punya alasan untuk dicintai lama, dan telah membuka mata banyak developer yang jatuh ke perangkap yang sama
Bahkan saat bekerja sendiri, Anda bisa merancang abstraksi yang rapi secara berlebihan lalu kelak tersandung oleh abstraksi itu sendiri
Masalahnya adalah perubahan langsung di-commit ke branch main tanpa review
Setiap perubahan kode perlu review rekan, entah melalui pair programming atau PR tradisional, agar eskalasi seperti ini bisa dicegah
Atasan itu atasan yang buruk. Alih-alih memarahi, ia seharusnya menyadari bahwa proses yang baik sedang hilang
Jika tim memiliki budaya code review, ketika karyawan baru yang terlalu bersemangat mencoba hal seperti ini, rekan akan berkata “terima kasih, tapi bukan begini” atau “ide bagus, coba lakukan seperti ini”
Secara terpisah, saya pikir kode tidak boleh direfactor tanpa alasan yang baik. Kode buruk pun bisa saja merupakan kode yang hampir tidak pernah perlu diubah
Waktu terbaik untuk melakukan refactoring adalah ketika Anda perlu mengubah perilaku dan menyadari bahwa struktur yang ada membuatnya terlalu sulit
Sayangnya, dalam kasus ini tampaknya pelajaran yang dipetik keliru
Entah kenapa semua orang hanya membahas apa yang seharusnya ia lakukan sebagai gantinya. Ini pelajaran yang sepenuhnya sah
Di dunia keuangan, kita terus berurusan dengan produk yang sampai taraf tertentu mirip tetapi tidak sepenuhnya sama. Opsi saham dan opsi valas sama-sama opsi dan punya harga pelaksanaan, serta dihargai dengan suatu versi Black-Scholes, tetapi dalam praktiknya sangat berbeda
Orang yang baru bergabung sering sangat tergoda untuk menggeneralisasi banyak perilaku, dan kami sering berada di posisi atasan dalam tulisan asli: menyuruh developer muda untuk tenang dan membiarkannya tetap terpisah
Ini bukan berarti mengucapkan selamat tinggal pada clean code, melainkan bahwa kita harus menghindari abstraksi berlebihan agar benar-benar bisa mempertahankan clean code
Yang dilakukan handle umum adalah transformasi afin, yaitu translasi, rotasi, penskalaan, dan refleksi; jika penskalaannya seragam, itu transformasi similaritas. Ini dijamin bekerja pada bentuk apa pun
Masalah sebenarnya adalah jangan mengabstraksikan sesuatu yang belum cukup kita pahami. Terutama jika kita tidak tahu kemungkinan apa yang akan muncul di masa depan
Misalnya, jika kita mengira oval hanya mencakup lingkaran dan elips, kita akan cukup terkejut saat oval “sungguhan” pertama muncul
Karena penulis tidak secara aktif membedakan kode berantakan dan kode “tidak clean”, orang lain jadi mencoba membuat pembedaan itu
DRY itu bernilai, tetapi abstraksi punya biaya. Selalu ada trade-off
Salah satu alasan saya menyukai bahasa seperti Haskell adalah karena maksimalisme abstraksi berada di level bahasa, bukan di level coding
Semua orang sepakat tentang apa yang seharusnya dilakukan Applicative. Tantangannya bergeser lebih ke kanan dalam pipeline dari ide ke kode, yaitu menemukan Applicative yang cocok untuk masalahnya
Sebagian besar pola desain berorientasi objek punya padanan yang alami dan terdefinisi dengan baik di lingkungan seperti ini, dan membantu mengurangi abstraksi yang spesifik per proyek
Bagi pemula, biaya awal untuk mempelajari bahasanya besar, dan sering terjadi ketika membuka kode Haskell lain, ada sekitar 12 ekstensi compiler yang belum pernah dilihat sebelumnya dan harus dipahami
Meski begitu, ekstensi compiler itu bisa dibawa ke semua proyek setelahnya, jadi saya menganggapnya keuntungan bersih
Bagi ahli, kekurangannya adalah perlu gelar PhD untuk bisa memperkirakan berapa banyak RAM yang akan dimakan cats
Jika suatu kode memakai Applicative atau Monad, kita bisa mengetahui perilakunya berkat hukum-hukum itu
Pola desain berorientasi objek tidak punya hukum seperti itu. Itu konsep atau pola yang didefinisikan longgar sehingga terbuka untuk interpretasi dan kustomisasi pribadi, tetapi tidak punya hukum konkret yang memberi tahu persis apa itu dan perilaku atau output apa yang harus diharapkan
Namun untuk contoh di tulisan blog itu, saya harus mengatakan bahwa mengikuti jalur clean code sering sekali berakhir menyusahkan diri sendiri di masa depan
Jika nanti kita harus mempelajari abstraksi itu lagi untuk memahaminya, abstraksi tersebut tidak bermanfaat
Tempat yang paling alami cocok untuk OOP adalah widget GUI dan implementasi editor
Aturan yang menyatukan aturan-aturan OOP lainnya adalah jangan bertanya, perintahkan
Dalam contoh ini, handle akan dibagikan dengan cara yang diketahui, dan tiap bentuk akan memiliki titik kontrolnya sendiri. Jika handle kotak berubah, kita bisa memanggil
updateControlPoints(changedHandle), dan jika titik kontrol berubah, kita bisa memanggilupdateBoxHandles(changedControlPoint)Pemisahan lain yang rapi juga mungkin, tetapi saya akan melakukannya seperti itu
Namun soal library parsing mana yang dipakai, memilih
Data.Text.StrictatauData.Text.Lazy, seberapa banyak memakai gaya point-free, memilih.dan>>>atau kombinator lain, serta ekstensi bahasa apa yang digunakan, kesepakatan sulit dicapaiSaya suka Haskell, tetapi ia mengalami masalah yang mirip dengan bahasa lain. Orang-orang benar-benar tidak bisa sepakat tentang cara terbaik untuk mengerjakan sesuatu
Kita bisa mendapatkan sistem tipe Haskell dan performa yang dapat diprediksi
Bagian matematika yang berulang cukup dipindahkan ke fungsi terpisah, lalu dipanggil dari fungsi pengubahan ukuran
Fungsi pengubahan ukuran itu sendiri tampak berulang karena membentuk interface, jadi refactoring yang menghilangkannya adalah keliru
Namun matematika yang dilakukan fungsi-fungsi itu adalah target yang sepenuhnya valid untuk merapikan kode
Hasilnya memang banyak fungsi kecil yang murni, tetapi itu tidak menjadi masalah karena mudah diuji dan di-refactor
Ada banyak cara dan pola untuk memecahkan masalah yang sama, tetapi membongkar interface yang sudah dipakai orang lain bukan awal yang baik
Keunggulan abstraksi adalah kita bisa mengubah bagian dalam agar lebih fleksibel tanpa merusak bagian lain
Langkah pertama yang baik adalah, seperti yang dikatakan, membuat fungsi matematika yang lebih fleksibel di lapisan bawah dan membiarkan sisanya tetap seperti semula
Setelah itu, kita bisa berdiskusi lebih dalam dengan tim tentang cara berkomunikasi agar interface menyediakan facade yang jelas sementara implementasinya diabstraksikan
Yang digambarkan di sini terasa seperti abstraksi yang buruk
Masalah sebenarnya adalah orang-orang merancang hanya dengan melihat dua atau tiga contoh, tanpa memastikan apakah rancangan itu cukup umum untuk mengakomodasi penggunaan di masa depan
Abstraksi harus dilakukan dari bawah ke atas, bukan dari atas ke bawah
Tidak perlu membuat satu titik tunggal tempat semua hal terjadi dan yang menangani kombinasi
2^nMeski begitu, kita tetap bisa mengurangi pengulangan, mengubahnya di satu titik, dan mempertahankan kemampuan untuk melakukan perubahan khusus saat diperlukan
Jadi sekadar mengatakan “hindari abstraksi yang buruk” atau “buat agar bisa mengakomodasi penggunaan di masa depan” tidaklah cukup
Pada umumnya, tidak ada orang yang bisa memprediksi masa depan
Abstraksi harus digunakan dengan sangat hati-hati bahkan ketika terasa benar. Lebih baik menjadi skeptis ekstrem
Jika menyentuh satu hal di kode matematika, semuanya ikut terpengaruh
Pada suatu titik, lebih mudah membiarkan sebagian kode duplikat tetap ada, menandai kemiripannya dengan petunjuk struktur kode atau komentar, dan seiring waktu menekankan perbedaan utamanya lewat komentar
Pendekatan clean code untuk jenis kode seperti ini tidak menangani kebutuhan yang berubah dengan baik
Pada akhirnya, ini mudah berubah menjadi sekumpulan fungsi helper dengan beberapa jalur kode tergantung lokasi pemanggilan
Kadang ini bisa diabstraksikan, dan sebagian orang mungkin sudah menyadarinya, tetapi kalimat sebelumnya sebenarnya menjelaskan polimorfisme berorientasi objek
Namun bagaimana mungkin kita mengetahui kebutuhan yang tepat sejak awal? Mencoba “clean code” pada tahap sedini ini hanya akan berakhir sebagai abstraksi buruk atau overengineering
Pendekatan yang benar adalah tidak melakukan apa-apa, mencatat kemungkinan masalah, lalu menunggu sampai kita tahu lebih banyak tentang domain masalahnya
Kode yang agak duplikatif tetapi mudah dipahami seperti contoh awal tidak terlalu saya khawatirkan
Namun jika harus memperbaiki isu yang sama di tiga tempat, atau menambahkan kode fitur baru di tiga tempat, barulah saya khawatir
Saat itu saya mulai memikirkan apakah kode yang harus diubah atau ditambahkan bisa didorong ke suatu lokasi bersama dengan cara tertentu
Orang membaca design pattern atau DRY, lalu karena masih belajar, umumnya menerapkannya dengan keliru, kemudian menyalahkan teks aslinya
Rob Pike pernah mengatakan bahwa salah satu alasan Go menjadi seperti itu adalah “salinan kecil lebih baik daripada dependensi kecil”
Semakin lama saya memprogram, semakin saya memahami maksudnya
Pengulangan itu sendiri bukan masalah. Yang penting adalah memahami unit yang sedang dibaca dan mungkin akan diubah
DRY sering kali berarti menambahkan abstraksi lain, dan jika abstraksi itu tidak cukup ortogonal, sekarang kita harus mempertimbangkan dua unit, bukan satu, sehingga situasinya justru menjadi lebih buruk