Klasifikasi Utang Teknis (2018)
(technology.riotgames.com)- Riot Games memandang utang teknis sebagai kode atau data yang biayanya akan ditanggung oleh developer di masa depan, dan merangkum bahasa bersama untuk menilai utang melalui kasus pengembangan League of Legends
- Kriteria evaluasinya ada tiga: dampak, biaya perbaikan, dan penularan; khususnya penularan mengacu pada sejauh mana utang menyebar seiring waktu ke sistem, data, dan praktik pengembangan lain
- Jenis utang dibagi menjadi Local Debt yang terkurung dalam implementasi internal, MacGyver Debt yang menghubungkan sementara dua sistem, Foundational Debt yang asumsi mendalamnya tertanam dalam struktur, dan Data Debt yang kontennya menumpuk di atas cacat
- Cataclysm milik Jarvan, penggunaan berdampingan std::string dan AString, penggunaan Lua oleh BlockBuilder, serta bug penamaan parameter block digunakan sebagai contoh konkret untuk masing-masing jenis
- Utang dengan tingkat penularan rendah mungkin bisa dibiarkan lama, tetapi utang dengan tingkat penularan tinggi membuat biaya perbaikan dan dampaknya membesar seiring waktu, sehingga jalur penyebarannya harus diputus sejak dini
Tiga sumbu untuk menilai utang teknis
- Utang teknis adalah “kode atau data yang biayanya akan ditanggung oleh developer di masa depan”
- Untuk memutuskan apakah suatu utang tertentu harus diperbaiki sekarang, diperbaiki nanti, atau secara realistis dibiarkan, diperlukan kriteria pengukuran bersama
- Riot menilai utang teknis dengan tiga sumbu
- impact: dampak terhadap pemain dan developer
- fix cost: waktu yang diperlukan untuk perbaikan dan risiko deployment
- contagion: seberapa jauh masalah menyebar jika dibiarkan
-
impact: biaya yang terlihat oleh pemain dan developer
- Bagi pemain, ini muncul sebagai bug, fitur yang hilang, atau perilaku tak terduga
- Bagi developer, ini terakumulasi sebagai keterlambatan implementasi, gangguan workflow, dan detail-detail tidak perlu yang harus diingat
- Di sini, developer mencakup bukan hanya engineer, tetapi juga peran yang terlibat dalam pembuatan game seperti designer dan artist VFX
- Sebagian utang menghambat engineer menulis kode baru, sementara sebagian lainnya mengganggu designer menulis script baru atau artist VFX membuat particle baru
-
fix cost: waktu implementasi dan risiko deployment
- Biaya perbaikan mencakup bukan hanya waktu pengembangan aktual, tetapi juga risiko yang muncul saat perubahan di-deploy
- Kesalahan sederhana pada satu fungsi bisa diperbaiki dalam hitungan menit, tetapi asumsi mendalam yang memengaruhi seluruh code line game bisa memakan waktu berminggu-minggu atau berbulan-bulan
- Sistem yang “salah” sekalipun mungkin sudah digunakan sebagai alat untuk membuat game yang bagus, sehingga saat diperbaiki, konten yang ada bisa rusak
- Misalnya, mengubah cara scripting engine menangani error atau cara menghitung waktu pembuatan particle dapat memengaruhi lebih dari 500 skill dari lebih dari 140 champion
-
contagion: tingkat penyebaran seiring waktu
- contagion berarti seberapa jauh utang teknis menyebar ke sistem, data, dan cara pengembangan lain ketika dibiarkan apa adanya
- Penyebaran terjadi melalui interface dengan sistem bermasalah, copy/paste data yang ditumpuk di atasnya, dan perubahan cara mengimplementasikan fitur baru
- Utang yang terisolasi dengan baik tidak memiliki perbedaan biaya besar antara diperbaiki nanti dan diperbaiki sekarang
- Utang dengan penularan tinggi makin sulit diperbaiki seiring waktu, dan makin banyak sistem terinfeksi oleh kompromi inti, dampaknya juga ikut membesar
Local Debt: black box yang hanya berantakan di bagian dalam
- Local Debt mirip dengan model pemrograman black box klasik
- Dari luar, sistem terlihat berjalan stabil, tetapi implementasi internalnya bisa saja buruk atau membingungkan
- Contoh: skill, layer jaringan, script engine
- Jika saat mengembangkan sistem di sekitarnya tidak perlu menyadari adanya utang internal, tingkat penularannya cenderung rendah
-
Analogi dunia nyata: mata manusia
- Secara struktural, mata manusia menerima gambar secara terbalik, dan saraf retina menciptakan blind spot di dekat bagian tengah masing-masing mata
- Pusat visual di otak membalik data dan mengisi blind spot, sehingga bagian otak lainnya dapat berinteraksi dengan gambar yang “benar”
- Keunikan ini terlokalisasi pada sistem mata dan saraf optik, serta mudah dihindari oleh sistem lain, sehingga berada dalam kondisi “cukup baik”
-
Kasus League: Cataclysm milik Jarvan
- Cataclysm milik Jarvan hingga saat ini masih dibuat sebagai minion
- Designer dapat menggunakan alat yang membuat “invisible minion” ketika ingin menempelkan efek gameplay pada lokasi tertentu atau sekumpulan lokasi
- RiotXypherous menjelaskan “minion” yang dimaksud di sini dalam komentar Reddit
- Game object semacam ini adalah cara yang stabil dan dipahami dengan baik untuk melacak dan menjalankan logika script
- Dinding Jarvan membutuhkan tepat 24 minion agar pemain tidak bisa keluar
- Dulu jumlahnya 12, tetapi karena pemain kadang lolos di antara dinding, Riot Exgeniar meningkatkannya menjadi 24
- Alternatifnya adalah struktur ring-terrain, yaitu satu potongan logika yang mengontrol pathability Cataclysm, yang dapat merapikan logika dan sedikit mengurangi biaya komputasi
-
Evaluasi Cataclysm
- impact: 1/5
- Fakta bahwa dinding dibuat dari minion hampir tidak berdampak pada developer lain yang membuat konten baru
- “Jarvan Ult Hitch” adalah hasil dari interaksi antara utang ini dan bug loading yang mencoba membaca definisi auto-attack yang hilang
- fix cost: 2/5
- Saat ini, custom geometry tidak dapat dibuat dengan bentuk komposit tanpa kode baru
- Untuk membuat “area trigger” berbentuk ring, diperlukan kode matematika khusus untuk perhitungan collision ring
- Riot sedang mengeksplorasi Constructive Solid Geometry untuk tujuan lain, dan ini dapat menurunkan biaya perbaikan secara signifikan
- contagion: 1/5
- Saat mengembangkan fitur, implementasi dinding Jarvan tidak perlu dipertimbangkan, sehingga ia terisolasi dengan baik
- Risiko penularannya adalah jika designer lain menyalin/menempel implementasi ini ke champion baru, dan hal itu memang sesekali terjadi
- Sebagai masalah implementasi, potensi penyebaran Cataclysm rendah dan dipahami dengan baik
- impact: 1/5
-
Cara menangani Local Debt
- Ciri khas Local Debt adalah skor contagion yang rendah
- Jika impact lebih tinggi daripada fix cost, developer yang berperan sebagai warga baik cenderung memperbaikinya sebelum terlalu lama
- Jika benar-benar tidak menular, aman untuk membiarkannya selama diperlukan
- Salah satu kesalahan besar adalah langsung menerjang Local Debt yang memicu perfeksionisme engineer tetapi tidak memiliki dampak yang cukup luas
- Karena cakupan perubahannya lokal, verifikasi perbaikan dan regression test biasanya mudah
- Contoh yang baru-baru ini diperbaiki mencakup bug terkait inhibitor, Janna’s Monsoon, dan Tear of the Goddess
- Bug yang dalam kondisi tertentu membuat inhibitor melakukan pathing champion ke koordinat 0,0,0
- Masalah ketika Janna’s Monsoon mengabaikan spell shield
- Masalah ketika Tear of the Goddess mendapatkan stack dari cast tanpa mana
MacGyver Debt: kondisi dua sistem yang direkatkan dengan lakban
- MacGyver Debt adalah jenis utang teknis yang namanya diambil dari acara TV MacGyver pada pertengahan 1980-an
- Dalam konteks utang teknis, ini berarti kondisi ketika dua sistem yang saling berbenturan “direkatkan dengan lakban” di titik-titik antarmuka di seluruh codebase
-
Analogi dunia nyata: Seattle
- Seattle dulu memiliki dua permukiman yang bersaing, masing-masing dengan grid sendiri
- Ketika kedua permukiman itu berkembang menjadi Emerald City modern, grid yang sedikit berbeda tersebut menyatu, menghasilkan blok dan bangunan berbentuk canggung serta penggunaan ruang yang tidak efisien
-
Contoh League: std::string dan AString
- Dalam codebase League, C++ std::string dan kelas kustom Riot AString hadir berdampingan
- Keduanya adalah cara untuk menyimpan, memodifikasi, dan meneruskan string
- Riot menilai std::string memicu banyak alokasi memori “tersembunyi” dan biaya performa, serta membuat penulisan kode yang buruk menjadi mudah
- AString dirancang dengan mempertimbangkan manajemen memori yang cermat
- Strategi penggantiannya adalah membiarkan kedua sistem berjalan bersama dan memungkinkan konversi satu sama lain melalui
.c_str()dan.Get() - Pada AString ditambahkan peningkatan yang membuatnya lebih mudah digunakan, dan engineer didorong untuk mengganti std::string secara mandiri saat mengubah kode
- Dengan cara ini, std::string perlahan dihapus secara bertahap, dan antarmuka “lakban” di antara kedua sistem juga berkurang seiring perapian kode
-
Evaluasi std::string vs AString
- impact: 2/5
- Sebagian besar alokasi berdampak tinggi yang terjadi pada std::string sudah dihapus melalui profiling
- Biaya utama saat ini adalah biaya peralihan mental kecil ketika mengonversi dari satu sistem ke sistem lain
- fix cost: 3/5
- Migrasi ke AString bukan sekadar find-and-replace sederhana
- AString memiliki varian khusus sesuai tujuan, seperti AStackString yang melakukan alokasi awal di memori stack, ARefString untuk referensi static string, dan AString berbasis alokasi heap
- Untuk penggantian yang tepat, seseorang harus memeriksa dan menilai tiap titik secara langsung, dan proses menghapus sistem lama secara bertahap akan panjang dan lambat
- contagion: -2/5
- Dengan membuat AString lebih mudah digunakan daripada std::string, contagion dibalik ke arah yang menguntungkan
- Setiap kali engineer melakukan check-in perubahan kode game, ada kemungkinan AString makin menyebar
- impact: 2/5
-
Cara memperbaiki MacGyver Debt
- Biaya besar MacGyver Debt sering kali berupa biaya intelektual karena harus berganti mode saat melewati batas antarsistem
- Jika terhambat karena bug atau fitur berada di sistem yang “wrong”, memindahkan titik tujuan ke sistem yang “right” umumnya bersifat langsung
- Contagion relatif antara sistem baru dan sistem lama adalah indikator kunci
- Jika keseimbangan dibalik agar sisi sistem baru lebih menular, sistem yang lebih baik pada akhirnya akan menang
- Sistem yang lebih baik secara global harus dibuat lebih menarik juga di tingkat lokal
- Jika engineer yang dikejar waktu, saat melakukan optimisasi greedy dalam pekerjaan sehari-hari, tetap memilih arah menuju kondisi akhir yang diinginkan, berarti arahnya sudah benar
- Pendekatan lain adalah brute-force refactor berskala besar; bergantung pada seberapa dekat sistem-sistem itu dapat dipetakan, sebagian atau seluruhnya mungkin bisa diperbaiki dengan clever regex
Foundational Debt: Ketika asumsi mendalam tertanam dalam keseluruhan struktur
- Foundational Debt adalah keadaan ketika suatu asumsi di bagian terdalam sistem telah tertanam dalam cara kerja keseluruhan
- Pengguna sistem yang berpengalaman bisa sulit menyadarinya karena mereka melihatnya sebagai “memang begitu adanya”
-
Analogi dunia nyata: United States Customary Units
- Orang yang dibesarkan di Amerika Serikat menghafal konversi seperti 1 mil adalah 5.280 kaki, 1 quart adalah 2 pint, dan 1 galon adalah 4 quart
- Pemerintah Amerika Serikat telah beberapa kali mempertimbangkan transisi ke sistem metrik, tetapi masih menjadi salah satu dari 7 negara yang belum mengadopsi Système International sebagai sistem pengukuran resmi
- Utang ini tertanam dalam rambu jalan, resep, sekolah dasar, dan benak orang-orang
-
Contoh League: BlockBuilder dan Lua
- Contoh Foundational Debt besar yang pernah ditangani Riot mencakup Determinism in League of Legends dan Game Data Server
- Penggunaan Lua scripting language di League juga merupakan contoh Foundational Debt
- Desainer League membuat perilaku kompleks dengan menyambungkan blok-blok fungsi menggunakan alat bernama BlockBuilder
- Blok fungsi mencakup menghitung jarak antartitik, membuat minion, memproses damage, dan berbagai script flow control
- Kumpulan operasi yang dipilih desainer beragam tetapi terbatas, dan parameter tiap operasi juga dibatasi
- Pada masa awal League of Legends, diputuskan untuk tidak menyimpan blok dan parameter dalam format sederhana yang terbatas dan sesuai untuk data, melainkan menyimpannya sebagai arrays dan tables dari bahasa Lua, yang kuat tetapi terlalu kompleks untuk tujuan ini
- Setelah itu, sekitar 10 tahun pengembangan game berjalan di atas fondasi tersebut, dan manipulasi Lua object menjadi salah satu pekerjaan paling umum di engine
-
Evaluasi BlockBuilder Lua
- impact: 4/5
- Ketidakcocokan antara Lua dan ruang masalah tersebut menimbulkan banyak biaya
- Pada setiap frame dari logika BlockBuilder, callstack tercemar oleh sekitar 6 marshalling stack frame
- Pekerjaan marshalling tidak murah dari sisi penggunaan CPU server
- Membaca diff perubahan script menjadi sulit tanpa perlu
- Untuk parsing/searching script file demi memahami fungsinya, diperlukan pemahaman yang cukup mendalam tentang bahasa Lua
- fix cost: 4/5
- Lua tertanam begitu dalam di engine sehingga sulit dihapus
- Salah satu usulan saat ini adalah membuat wrapper class yang berperilaku seperti Lua object tetapi secara internal berupa struct yang jauh lebih sederhana, lalu secara perlahan mengubah bagian dalam scripting ke bentuk yang lebih sesuai
- Pendekatan apa pun harus dilakukan dengan hati-hati dan penuh pertimbangan
- contagion: 4/5
- Setiap kali suatu sistem bersinggungan dengan scripting, sistem itu dibentuk oleh operasi dan kebutuhan Lua backend
- Scripting adalah unit logic inti di LoL
- Riot menambahkan Building Block baru rata-rata sekitar setiap 3–4 hari, dan setiap Building Block memanipulasi Lua object secara langsung
- Semakin lama Lua tidak diganti, semakin sulit mengganti Lua
- impact: 4/5
-
Cara mengurangi Foundational Debt
- Foundational Debt cenderung mendapat skor tinggi pada ketiga sumbu: impact, fix cost, dan contagion
- Fix cost yang tinggi membuat orang terus memakai sistem yang tidak sempurna, dan kadang itu memang pilihan yang benar
- Namun, karena impact dan contagion yang tinggi, memperbaiki Foundational Debt yang serius bisa menghasilkan imbalan besar
- Strategi perbaikan paling umum yang diamati di Riot adalah membangun sistem baru berdampingan dengan sistem lama
- Jika memungkinkan, ubah foundational debt yang ada menjadi MacGyver Debt, lalu gunakan conversion operation untuk berpindah antara sistem baru dan lama sambil melakukan porting secara bertahap
- Pendekatan ini membatasi paparan risiko sembari mulai memperoleh manfaat di area tertentu
- Ketika transisi seperti ini tidak memungkinkan, buat compile time switch, atau jika memungkinkan loading time switch, untuk membangun kepercayaan terhadap sistem baru
- Pendekatan compile time switch sedang digunakan dalam transisi GDS
- Pendekatan loading time switch berhasil dalam Determinism
Data Debt: Kondisi ketika konten masif menumpuk di atas cacat
- Data Debt terjadi ketika banyak konten menumpuk di atas kategori utang teknis lainnya
- Titik awalnya bisa berupa bug pada scripting system, file format yang tidak cocok untuk item, atau dua sistem yang tidak saling cocok
- Ketika konten dalam jumlah besar seperti art, scripts, dan sounds dibuat di atas cacat kode tersebut, memperbaiki utang teknis awal menjadi sangat berisiko
- Seiring waktu, mengetahui apa yang akan rusak menjadi sangat sulit sampai menyakitkan
-
Analogi dunia nyata: DNA
- Genome organisme menumpuk perlahan selama jutaan tahun melalui mutation, transcription error, dan evolutionary pressure
- Sebagian kesalahan penyalinan tidak berguna tetapi tidak berbahaya, sebagian berbahaya, dan sebagian memberikan keuntungan besar
- Sangat sulit mengetahui apa sebenarnya fungsi potongan DNA tertentu
- Kita memahami sepenuhnya apa arti base pair dan bagaimana kumpulan base pair diterjemahkan menjadi amino acid untuk protein construction
- Kita juga mulai lebih banyak memahami sebagian non-encoding role DNA
- Namun dalam lebih dari 3 miliar base pair genome manusia, masih banyak bagian yang nyaris belum kita pahami
- Episode CRISPR dari Radiolab membahas salah satu teka-teki yang baru-baru ini terpecahkan seperti itu
-
Kasus League: block parameter naming bug
- Data Debt di League of Legends paling terasa dampaknya ketika mengubah sesuatu yang semula hanya perbaikan kecil menjadi pekerjaan berat
- Para game engineer menumpuk pengetahuan mendalam tentang cara sistem game diimplementasikan, dan menjadi terampil memprediksi perubahan kode mana yang akan merusak data apa
- Data Debt adalah salah satu pertimbangan terpenting saat mengubah LoL engine
- Contoh Data Debt yang diperbaiki beberapa tahun lalu adalah bug terkait block parameter dalam BlockBuilder scripting language
- Dalam toy example, jika mencoba meningkatkan armor Owner dengan variabel dan konstanta, nilai yang diharapkan adalah 25 bonus armor, yaitu variabel Delta 20 ditambah konstanta 5
- Jika nama variabel sama dengan nama parameter, dulu hasilnya menjadi 40
- Penulis mengatakan ia juga tidak tahu mengapa bukan 45
-
Proses perbaikan sebenarnya
- Ketika engineer Champions team NoopMoney mencoba memperbaiki perilaku ini, perubahan kode sebenarnya hanya menghapus 4 baris
- Namun utang yang sangat menular membutuhkan perencanaan menyeluruh bahkan untuk perubahan kecil
- Di antara 400.000 baris script LoL, parameter numerical mana pun bisa saja sedang digandakan oleh bug ini
- Masalah yang lebih besar adalah game telah di-balance dan di-tuning sesuai nilai yang berpotensi tergandakan itu, sehingga script tersebut berjalan “correctly”
- NoopMoney harus membuat fix dapat di-toggle di Live untuk berjaga-jaga terhadap bug tak terduga
- Untuk mengidentifikasi script mana yang bergantung pada bug ini, dilakukan regex searching yang luas dan QA sweep
- Pada akhirnya masalah akibat perbaikan relatif kecil, dan hanya sejumlah kecil champion script yang perlu diubah
- Karena Data Debt, memprediksi hasilnya sulit
-
Evaluasi Parameter Naming Bug
- impact: 2/5
- Dampaknya saat terjadi kecil
- Bug ini dapat menggandakan nilai yang diteruskan dan membuang konstanta
- Ini menjadi satu lagi tribal knowledge tak berguna yang harus diingat oleh desainer dan engineer yang mengetahuinya
- Developer mindshare adalah sumber daya yang terlalu berharga untuk dibuang seperti ini
- fix cost: 2/5
- Secara keseluruhan, perbaikannya sendiri langsung
- Dengan membuat live feature toggle, keyakinan terhadap keamanan fix bisa ditingkatkan
- Bagian paling mahal adalah screening awal untuk menilai cakupan masalah agar target pengujian dapat ditentukan
- contagion: 4/5
- Yang disayangkan, bug ini menyasar perilaku yang sangat logis
- Untuk memberi damage pada unit, menyimpan nilai dalam variabel bernama “Damage” sepenuhnya logis
- Bug terpicu ketika block ApplyDamage menerima amount sebagai parameter dengan nama yang sama
- Jika orang lain men-copy/paste block tersebut untuk membuat spell serupa, bug menyebar lebih jauh
- impact: 2/5
-
Mengapa Data Debt sangat menular
- Karena Data Debt membuat dampak perubahan sulit dinilai, biaya perbaikannya umumnya dinilai tinggi
- Hal yang lebih mengkhawatirkan adalah, karena sifat data, hampir selalu tingkat penularannya sangat tinggi
- Cara membuat data baru dengan copy/paste data yang sudah ada umumnya diterima
- Saat membuat skillshot spell baru, memulai dari Ezreal’s Mystic Shot dapat sangat menghemat waktu, dan masalah pada data yang ada ikut menyebar ke data turunannya
- Karena data jarang mendapat tinjauan teknis seperti code review, meskipun praktik buruk diketahui luas, sulit untuk menyadari dan menghentikan penyebarannya
- Untuk memperbaiki masalah pada data, biasanya diperlukan verifikasi langsung oleh manusia yang punya mata dan otak; compiler dan formal logic saja tidak cukup
-
Dua pendekatan untuk memperbaiki Data Debt
- Pendekatan pertama adalah do it right checkbox
- Caranya adalah membuat toggle bagi data creator antara behavior “broken” lama dan behavior “fixed” baru
- Idealnya, fixed version dijadikan default, sedangkan old content menggunakan broken version
- Setelah itu, seperti MacGyver Debt, konten dapat dipindahkan ke versi baru melalui replacement yang lambat dan stabil
- Kekurangannya adalah muncul biaya permanen berupa semakin banyak elemen tidak perlu yang ditambahkan ke editing UI
- Pendekatan kedua adalah just fix the damn thing
- Ini adalah cara yang digunakan NoopMoney untuk parameter naming bug
- Setelah memperbaiki bug, coba perbaiki semua data yang terdampak secara berarti
- Teknik untuk membuatnya tidak terlalu menakutkan mencakup banyak grep dan regex searching untuk memahami theoretical impact, targeted testing, serta menyiapkan toggle untuk mengembalikan perilaku lama jika setelah ship ditemukan hal yang lebih buruk yang terlewat
- Determinism sangat membantu pengujian perubahan seperti ini karena memungkinkan memastikan apakah server menghasilkan hasil yang sama sebelum dan sesudah perubahan
- Pendekatan pertama adalah do it right checkbox
Ringkasan: penularan harus dimasukkan dalam evaluasi biaya
- Metrik untuk mengukur utang teknis adalah impact, fix cost, dan contagion
- impact adalah dampak terhadap pelanggan dan developer
- fix cost adalah waktu dan risiko
- contagion adalah tingkat penyebaran masalah
- Sebagian besar developer secara rutin mempertimbangkan impact dan fix cost, tetapi pembahasan contagion relatif jarang
- contagion dapat menjadi musuh terburuk developer ketika masalah meresap dalam dan semakin sulit dihapus
- Sebaliknya, jika fix dibuat lebih menular daripada masalahnya, contagion dapat diubah menjadi senjata
- Sebagian besar utang teknis yang terlihat di League dapat dirangkum dalam salah satu dari empat kategori
- Local Debt: utang seperti black box yang bagian dalamnya berantakan
- MacGyver Debt: utang ketika 2 sistem atau lebih ditempel seperti duct tape dengan conversion function
- Foundational Debt: utang ketika seluruh struktur dibangun di atas asumsi yang tidak menguntungkan
- Data Debt: utang ketika data dalam jumlah besar menumpuk di atas jenis utang lain, sehingga perbaikan menjadi berisiko dan memakan waktu
1 komentar
Komentar Hacker News
Sifat menular itu sendiri adalah alasan mengapa antarmuka merupakan salah satu elemen terpenting dalam desain dan harus dipikirkan dengan matang.
Jika implementasi yang kurang optimal menempel pada antarmuka yang indah, itu mudah dirapikan ketika ada waktu, tetapi kebalikannya hampir tidak pernah berlaku.
Kadang keduanya tidak ada.
Dalam kasus seperti ini, memaksakan modul kecil dan tanggung jawab tunggal secara komposisional dapat mencegah penularannya menjadi terlalu parah. Tidak perlu banyak pengetahuan masa depan atau waktu; cukup hindari antarmuka dengan permukaan luas ala boneka Rusia yang mengendalikan banyak variasi perilaku lewat parameter. Sebaiknya konfigurasi, parsing, dan keputusan perilaku dipindahkan ke tepi logika, dan tidak dibiarkan meresap ke seluruh model tingkat bawah.
Bahkan ketika kita secara sadar memulai dengan niat menghindari utang teknis dengan cara apa pun, melakukannya dengan benar tetap sulit dan membutuhkan lebih dari sekadar kepercayaan diri teknis atau visi arsitektur. Pada praktiknya, ini masuk ke ranah memprediksi masa depan.
Jika implementasi bodoh secara implisit dipanggang ke dalam antarmuka, sering kali itu tidak bisa diperbaiki hanya dengan mengganti implementasinya. Contoh yang terlintas adalah perilaku pengurutan dan paginasi. Developer junior, dan kini juga banyak senior yang seharusnya sudah lebih paham, kerap memulai dengan request yang memakai parameter semacam
limit/offset, yang berujung pada masalah performa mengerikan dan perilaku aneh. Cara paginasi bekerja secara efisien dan opsi pengurutan yang bisa didukung dengan performa baik pada dasarnya terikat pada bentuk data dan pilihan data store. Orang yang belum pernah melalui proses ini di lapisan bawah kecil kemungkinannya dapat membuat antarmuka tingkat atas dengan benar, kecuali ia lebih dulu mendalami implementasinya secara memadai.Dalam kebanyakan kasus saya tidak ingin melihat implementasinya, saya hanya ingin melihat antarmuka yang terdokumentasi dengan benar. Jika perilaku antarmuka tidak bisa dijelaskan dengan kata-kata sederhana, berarti ada sesuatu yang salah.
QWERTY terkenal bukan antarmuka fisik yang optimal, dan setir mobil bisa menjadi contoh serupa. Di dunia komputer, x86 adalah contoh utama antarmuka yang di permukaan tidak optimal.
Cukup mengejutkan bahwa tulisan ini ditulis oleh seorang engineering manager.
Dari para manajer yang pernah bekerja dengan saya, tidak ada yang bisa membicarakan codebase kami pada tingkat detail teknis seperti ini. Termasuk mereka yang dulunya engineer.
Namun agar adil, kami tidak pernah punya manajer yang dipromosikan dari internal, dan karena orang-orang internal, termasuk saya, tidak ingin berhenti dari engineering, kami punya kebiasaan buruk merekrut manajer dari luar.
Sepertinya jenis utang yang paling sering saya lihat tidak ada: utang pendiri.
Ini adalah utang yang dibuat para pendiri untuk meluncurkan teknologi yang cepat dan bernilai. Sesuatu yang tampak seperti buah yang mudah dipetik kemudian berubah menjadi fondasi seluruh sistem.
Dokumen pendirian banyak negara juga masuk kategori ini lol (tapi bukan USA! USA! USA!).
Utang MacGyver dan utang fondasi adalah yang paling dekat, tetapi keduanya tidak benar-benar menangkap fenomena ini.
Tulisan yang sangat bagus dari sudut pandang teknis.
Namun menurut saya ini lebih mendekati nomenklatur daripada “taksonomi”. Karena secara sengaja tidak komprehensif dan tidak saling eksklusif, meski bisa saja saya keliru. Contoh fisik untuk tiap itemnya khususnya bagus dan memberi bahan untuk dipikirkan.
Seperti biasa, ada bagian kecil yang mengganjal secara filosofis. “Tiga sumbu” di bagian awal tampak seperti pengembalian dan investasi dalam RoI tradisional, ditambah subkategori pengembalian tertentu yang berorientasi masa depan dan bersyarat. Saya menduga keputusan ini dalam praktiknya berhasil, dan praktik pengembangan video game tidak harus sepenuhnya ilmiah, tetapi sedikit lebih banyak kepastian filosofis juga tidak ada salahnya.
Ini juga pernah dibahas saat itu:
A Taxonomy of Technical Debt - https://news.ycombinator.com/item?id=16810092 - April 2018 (113 komentar)
Dan ada juga ini:
A Taxonomy of Tech Debt (2018) - https://news.ycombinator.com/item?id=39782923 - Maret 2024 (1 komentar)
Penjelasan bahwa “utang teknis didefinisikan sebagai kode atau data yang biayanya akan ditanggung developer masa depan” adalah salah satu yang terbaik yang pernah saya lihat.
Seperti semua utang, saat mengambil utang kita harus menerapkan ambang batas yang menyeimbangkan kebutuhan langsung dan biaya masa depan. Saya merasa kebanyakan orang, bukan hanya developer, melebih-lebihkan kebutuhan langsung dan meremehkan biaya masa depan.
Secara pribadi, saya hampir secara patologis membenci utang dalam bentuk apa pun. Saya bahkan bisa menghabiskan satu hari ekstra untuk memisahkan sesuatu yang mungkin berguna di masa depan. Ketika benar, kira-kira 50% waktunya, tetapi setiap kali melakukan pekerjaan seperti itu, kebiasaannya makin kuat dan alur kerja dasar saya juga menjadi lebih cepat.
Sejauh ini saya pernah bekerja di 3 “startup”, dan semuanya saya masuki setelah mereka menghasilkan pendapatan yang cukup untuk membayar gaji mendekati normal.
Hal yang paling sering saya lihat adalah beberapa pendiri mencampuradukkan secara kabur antara ide yang mereka pikirkan, apa yang benar-benar dibuat, dan bagian implementasi yang benar-benar berfungsi.
Sejak pertama kali membaca tulisan ini, saya memakai istilah menular saat menjelaskan utang teknis, dan istilah itu cukup pas.
Saya tidak yakin “utang lokal” bisa disebut utang teknis dalam situasi biasa.
Secara realistis, selalu ada bagian yang berantakan di suatu tempat, dan menyembunyikannya lewat enkapsulasi agar tidak melukai siapa pun adalah hal normal. Selama requirement tidak berubah, bagian itu hampir tidak perlu diubah, dan jika berubah, implementasi apa pun memang harus dimodifikasi, jadi itu tidak masalah.
Jika 24 instance minion dalam contoh itu bukan sekadar kurang elegan tetapi benar-benar masalah, maka justru tampaknya lebih dekat ke utang fondasi, karena “minion” telah menjadi unit dasar paling sederhana padahal mungkin ada sesuatu yang lebih ringan.
Mendorong developer untuk melakukan perubahan termasuk pada modul yang sudah tua, matang, dan tidak perlu disentuh adalah cara yang baik agar hal ini tidak menumpuk sampai menjadi masalah.
Salah satu aspek penting adalah ketika kita secara sadar mengambil utang teknis demi keuntungan jangka pendek.
Maka keuntungan itu juga menjadi sumbu lain yang harus ikut ditimbang.
Ingin membangun gedung baru sekarang dan menyelesaikan pekerjaan, alih-alih menunggu sampai punya modal 15 tahun lagi? Ambil utang.
Utang adalah alat, tetapi alat yang kuat dan berbahaya. Jika tidak mengakui dan menghormati bahwa alat itu sedang digunakan, Anda akan terluka. Atau seseorang yang menerima granat dari Anda akan terluka. Sama seperti utang sungguhan.