- Berdasarkan kutipan Linus Torvalds, desain yang baik dimulai dengan menetapkan struktur data dan relasinya secara stabil sebelum menulis kode
- Model data yang dirancang dengan baik secara alami menyederhanakan logika aplikasi, serta membuat perangkat lunak lebih andal dan mudah dipahami
- Jika pemodelan data ditunda, beban kerja berikutnya akan membesar; tetapi jika struktur ditata dengan baik sejak awal, migrasi dan perluasan sistem yang kompleks menjadi lebih mudah
- Dalam satu proyek, alih-alih mengoptimalkan algoritme yang kompleks, restrukturisasi data menghilangkan seluruh kategori masalah itu sendiri, dan mengganti fungsi 500 baris dengan fungsi 50 baris plus struktur data
- Dalam praktik, perlu menerapkan tipe yang lebih ketat pada antarmuka dan basis data, serta merancang alur data dan interaksi komponen terlebih dahulu sebelum detail kode
Struktur Data Menentukan Desain Kode
- Linus Torvalds memandang Git sebagai desain sederhana dengan struktur data yang stabil dan terdokumentasi, dan menekankan cara menempatkan kode di sekitar data
- Kutipan “Programmer yang buruk mengkhawatirkan kode; programmer yang baik mengkhawatirkan struktur data dan relasinya” adalah kalimat utamanya
- Salah satu alasan keberhasilan Git adalah desain kodenya yang berpusat pada data
- Struktur data yang baik memudahkan desain dan pemeliharaan kode, serta meningkatkan keandalan perangkat lunak, keterpahaman sistem, dan keterbacaan kode
- Logika aplikasi sering kali mengikuti model data
- Jika model data baru dipikirkan belakangan, beban kerja berikutnya akan bertambah
- Model data yang dirancang dengan baik memudahkan migrasi dan perluasan sistem kompleks di kemudian hari
- Dalam contoh proyek nyata, restrukturisasi data memberi dampak lebih besar daripada sekadar menyempurnakan algoritme kompleks
- Dengan mengubah struktur data, seluruh kategori masalah dihilangkan
- Fungsi 500 baris digantikan oleh fungsi 50 baris dan struktur data yang dirancang dengan baik
- Kode baru menjadi lebih cepat, sekaligus lebih mudah dipahami dan dipelihara
- Namun karena data lama harus direstrukturisasi, bebannya berpindah ke lapisan yang lebih bawah
Lebih Baik Memindahkan Kompleksitas ke Sisi Data
- “Rule of Representation” dalam The Art of Unix Programming menjelaskan bahwa pengetahuan sebaiknya ditempatkan dalam data agar logika program menjadi sederhana dan tangguh
- Logika prosedural sulit diverifikasi oleh manusia, sementara struktur data yang kompleks lebih mudah dimodelkan dan dinalar
- Diagram pohon pointer dengan 50 node bisa memiliki daya ungkap dan penjelasan yang lebih tinggi daripada diagram alur program 50 baris
- Mengekspresikan tabel transformasi sebagai inisialisasi array lebih transparan dan jelas daripada menulis konten yang sama dengan pernyataan
switch - Jika harus memilih di mana kompleksitas ditempatkan—di kode atau struktur data—lebih baik memindahkan kompleksitas ke struktur data
Dalam Praktik, Rancang Alur Data Terlebih Dahulu
- Cara paling langsung untuk mempraktikkannya adalah memulai dari data
- Menerapkan tipe yang lebih ketat pada antarmuka atau basis data dapat mengurangi kompleksitas kode
- Perlu meluangkan lebih banyak waktu sejak awal untuk memikirkan struktur data
- Ini bukan berarti kode tidak penting; semua elemen tetap penting bersama-sama
- Sebelum masuk ke detail kode, pendekatan tingkat tinggi yang terlebih dahulu melihat bagaimana data mengalir dan bagaimana komponen saling berinteraksi sangat berguna
- Sebagai contoh persyaratan Senior Engineer (L5), di FAANG penulisan dokumen desain tingkat tinggi untuk sistem yang lebih kompleks umumnya termasuk di dalamnya
- Memimpin perencanaan tim dan membangun roadmap yang baik untuk fitur menengah hingga besar juga termasuk di sini
- Kemampuan merancang alur data dan interaksi komponen terlebih dahulu berkaitan dengan dampak engineering pada level yang lebih tinggi
1 komentar
Pendapat di Hacker News
Tulisan Substack itu tampaknya sekadar menyalin beberapa kutipan dari tulisan Stack Exchange ini: https://softwareengineering.stackexchange.com/questions/1631...
“Tunjukkan kepadaku flowchart [kode] dan sembunyikan tabel [skema]-nya, maka aku akan terus kebingungan. Tunjukkan kepadaku tabel [skema]-nya, dan biasanya aku tidak perlu flowchart [kode]-nya. Karena semuanya akan jelas.” — Fred Brooks, “The Mythical Man Month”, bab 9
“Bacalah The Mythical Man Month. Aku ingat dulu berpikir bahwa buku setua itu tidak mungkin mengatakan hal yang relevan dengan pengembangan perangkat lunak masa kini, tetapi aku keliru.”
Pada titik itu, developer aplikasi mulai menyalahgunakan database dengan alasan mereka lebih cepat dan punya lebih banyak hal untuk dikerjakan
Struktur data dan tipe bukanlah hal yang sama. Struktur data adalah pola bit dan referensi ke pola bit lain, yaitu pointer atau relasi.
Tipe, sebagaimana digunakan dalam bahasa pemrograman, memang memberi batasan pada pola bit semacam itu, tetapi juga dapat mengekspresikan banyak fitur bahasa lainnya. Membuat hierarki tipe yang rumit dengan abstraksi yang tidak perlu bukan berarti “memedulikan struktur data”, dan ini adalah pola kegagalan yang sering juga menjebak engineer cerdas
Tipe adalah bit di atas disk
Maksud aslinya di sini lebih dekat pada: pikirkan masalahnya lebih dalam dan jangan memilih struktur yang akan menyandungmu nanti. Misalnya, lihat seberapa jauh Unix pipe menyebar, dan ke berapa banyak ranah serta kasus penggunaan ia meluas. Itu adalah cara yang sangat baik untuk memvisualisasikan cara membangun sistem sambil menghormati batasan manusia dan mesin.
Ken Thompson dan yang lain pun butuh waktu cukup lama untuk menyadari bahwa sesuatu seperti pipe masuk akal di Unix. Itu bukan wawasan yang didapat dengan mudah; dibutuhkan kegigihan dan kerja lanjutan untuk menemukan blok penyusun yang tepat bagi sistem
Linus selalu pandai merangkum hal-hal yang dipikirkan orang lain secara samar. Apa yang dibicarakan dalam tulisan itu juga mirip dengan DDD yang telah menjadi keterampilan yang hilang.
Yang dimaksud “hilang” di sini adalah bahwa kebanyakan developer yang ditemui sekarang lebih tertarik memindah-mindahkan algoritme dan JSON ke sana kemari daripada memahami domain yang mereka tangani serta memodelkan entitas dan interaksinya. Dalam desain modern berbasis AWS, ini muncul sebagai kumpulan GSI DynamoDB yang landasannya lemah, objek-objek yang miskin, dan lapisan “service” seperti skrip yang menumpuk hack di atas hack. Mungkin ada asumsi implisit bahwa di dalam batas layanan, konteks domain akan terdefinisi cukup baik, tetapi menurut saya itu bukan asumsi yang bagus.
Saya tidak tahu di mana industri kita kehilangan ketelitian dalam desain. Apakah di sekolah, di pipeline wawancara, karena standar diturunkan, atau semuanya sekaligus.
Lebih buruk lagi, desain melakukan dosa besar: tidak mudah diotomatisasi. Karena itu orang-orang mengikuti desain yang dipaksakan alat tanpa sikap kritis, dan merasa tidak nyaman dengan gagasan bahwa mereka harus memikirkan lebih dalam apa yang mereka kerjakan. Semua orang ingin mengalihdayakan pemikiran ini kepada “pakar”.
Masalah lainnya, hal ini juga tidak diajarkan dengan benar, harus dipelajari sendiri selama bertahun-tahun, dan karena dianggap kurang nyata dibanding kode, ia diperlakukan sebagai kurang penting. Namun keyakinan seperti ini pada akhirnya membatasi tingkat hal yang bisa dibuat pada level pemula tingkat lanjut. Para programmer secara kolektif memilih menjaga standar serendah mungkin, dan dalam topik ini tampaknya ada psikologi seperti kepiting yang saling menarik turun.
Karena secara sintaksis tidak identik, kodenya tidak terlihat seperti duplikasi, tetapi secara fungsional ada banyak duplikasi kode yang melakukan hal yang sama.
1 https://martinfowler.com/bliki/AnemicDomainModel.html
2 https://wiki.c2.com/?PrimitiveObsession
Menurut saya itu karena konsekuensi dari kode buruk tidak terlalu terlihat. Jembatan yang buruk akan runtuh, tetapi kode yang buruk hanya akan direfaktor atau diganti dengan lebih banyak kode. Satu berkas teks yang tidak dipahami manajemen hanya berubah menjadi berkas teks lain yang juga tidak dipahami manajemen.
Dan begitu sesuatu sudah berjalan, terjadilah pemadaman listrik. Tidak ada yang lebih permanen daripada hack sementara yang kebetulan bekerja sempurna. Namun 1000 hack sementara tidak akan menghasilkan sistem yang direkayasa dengan baik. Menurut saya, menjadi matang dalam pengembangan perangkat lunak berarti berfokus pada data dan relasi, bukan pada penulisan kode. Kita harus bisa mengubahnya menjadi kode, tetapi yang harus diubah menjadi kode adalah data dan relasinya, bukan mengubah kode yang berjalan menjadi model data.
Hanya karena entitas domain bisa memuat semua logika, bukan berarti ia harus melakukannya. Misalnya jika perlu memeriksa apakah nama pengguna sudah ada, bagaimana caranya melakukan itu di dalam entitas domain yang “tidak boleh bergantung” pada lapisan akses data? Sering kali yang disarankan adalah semacam “domain service”, tetapi itu membuat logika bisnis tersebar ke beberapa tempat, sehingga terasa berlawanan dengan tujuan DDD.
Saya cukup menyukai DDD sebagai filosofi, tetapi sangat tidak suka pola “DDD taktis”. Menurut saya terlalu banyak orang menyamakan Domain-Driven Design dengan Domain-Driven Implementation. Saya mencoba membuat domain yang kaya di tempat yang tepat, tetapi itu tidak cocok untuk semua proyek, dan saya berusaha tidak tenggelam dalam istilah. Saya tidak peduli apakah tipe “Name” adalah value object atau aggregate root. Yang paling penting adalah bounded context. Saya juga mengakui bahwa DDD kadang bisa meningkatkan kompleksitas aplikasi dengan manfaat yang nyaris tidak ada. Saya jelas tidak akan menyebutnya solusi serbaguna.
Saya akan tetap menggunakan DDD, tetapi sulit menghilangkan perasaan bahwa DDD adalah upaya untuk menyampaikan “lihat, pemrograman berorientasi objek juga tidak seburuk itu, kan?” Dan saya juga tidak yakin apakah tujuan itu tercapai.
Ini terasa menarik karena sebelum mulai menjadi engineer profesional, saya setiap hari mengerjakan data dan analisis statistik dengan sistem statistik seperti Matlab, R, dan Python awal.
Karena itu, sudut pandang engineering saya selalu didasarkan pada dua hal: mengelola state fungsional dan alur kerja data.
Setelah 10 tahun bekerja sebagai software engineer, kebanyakan engineer “ilmiah” seperti Minsky atau Shannon menjelaskan dunia komputasi sebagai pengelolaan state, transformasi data, dan pengelolaan overhead komputasi. Para tokoh besar dan pionir perangkat lunak semuanya menganggap data dan state sangat penting; komputasi awal pada dasarnya memang hanya itu, dan pola seperti itu diharapkan terus berlanjut.
Sebaliknya, dalam desain sistem engineering, asumsi dasar yang selalu benar dan diikuti semua orang sama sekali tidak konsisten; kalaupun ada, biasanya lebih mirip tren. Dalam sebagian besar perangkat lunak operasional, jadwal bisnis jauh lebih menentukan prioritas dan struktur engineering daripada ketangguhan, antifragilitas, dan pengelolaan state.
Organisasi profesional seperti gilda atau serikat hampir secara universal ditolak oleh para software engineer. Karena tidak ada konsekuensi jika tidak menganggap IEEE serius, pada praktiknya tidak ada yang benar-benar menganggapnya serius. Akibatnya, tidak ada mekanisme untuk memaksa atau mengatur praktik secara mandiri seperti pada teknik sipil atau teknik biomedis, dan bahkan di bidang-bidang itu pun mekanisme tersebut hanya dimanfaatkan sekadarnya.
Secara keseluruhan, kondisi pengembangan perangkat lunak saat ini sudah sepenuhnya terputus dari akar-akarnya yang dulu sangat luhur dan filosofis, dan pada dasarnya digerakkan oleh perusahaan-perusahaan yang memprioritaskan sistem yang menghasilkan uang bagi orang-orang berduit. Jadi “hal yang baik” nyaris tidak ada hubungannya dengan hal yang diberi insentif.
“Jika kamu menunjukkan kepadaku flowchart [kode] dan menyembunyikan tabel [struktur data], aku akan terus kebingungan. Jika kamu menunjukkan kepadaku tabel, biasanya aku tidak memerlukan flowchart. Karena itu akan menjadi jelas.” — Fred Brooks
Menyamakannya 1:1 dengan tabel dasar sangat membatasi, dan menurut saya menghasilkan model yang kehilangan daya ekspresi yang disediakan bahasa modern
Ini pada dasarnya adalah sudut pandang pemrograman fungsional dan teori kategori.
Ada suatu objek data, dan ia memberikan batasan tentang bagaimana strukturnya dapat ditransformasikan. Lalu seluruh logika program menjadi soal transformasi yang mempertahankan struktur tersebut.
Transformasi menjadi lebih sederhana dan lebih mudah dinalar, hingga akhirnya yang tersisa adalah graf dengan transformasi sebagai edge dan struktur sebagai node. Secara umum ini lebih mudah dinalar daripada program imperatif sembarang
Sudut pandang pemrograman fungsional lebih dekat pada gagasan bahwa objek tidak boleh ditransformasikan dan perubahan harus dihindari, dan itu terpisah dari pembahasan ini. Inti teori kategori adalah menangani pola hubungan yang muncul bersama di berbagai bidang matematika, dan sama sekali tidak berkaitan dengan hal yang dibahas di sini. Mungkin yang dimaksud adalah teori tipe, tetapi itu pun tidak terkait
Kesimpulan yang pernah saya tarik adalah ini. Semua pekerjaan yang kita lakukan dalam kode kemungkinan besar akan bertahan jauh lebih singkat daripada satu keputusan yang baik tentang data.
https://www.swyx.io/data-outlasts-code-but
Prinsip ini juga berlaku di tingkat bisnis. Saya terus berurusan dengan analis bisnis yang terpaku pada proses (kode) dan tidak meluangkan waktu untuk terlebih dahulu memahami entitas serta hubungan di antaranya (data).
Akibatnya, ketika tiba saatnya membangun sesuatu, mereka tidak dapat berkomunikasi dengan pengembang tentang seperti apa seharusnya model data. Proses diimplementasikan, sementara model data bukannya dirancang dengan cermat, melainkan dirakit secara ad hoc saat itu juga