Frankenstein dalam pemrograman adalah kode yang disusun dari bagian-bagian yang tidak kompatibel dari berbagai teknologi, gaya, dan arsitektur. Menurut penelitian ThoughtWorks Technology Radar (2024), 28% proyek besar menunjukkan tanda-tanda sindrom Frankenstein — eklektisisme arsitektural yang muncul ketika tidak ada visi teknis yang terpadu. Dengan analogi dari novel Mary Shelley, kode semacam itu berfungsi, tetapi pemeliharaannya menjadi mimpi buruk.
Poin Penting
Frankenstein (Frankenstein code, Frankenstein pattern) adalah antipattern di mana sistem perangkat lunak disusun dari bagian-bagian yang tidak dirancang untuk bekerja bersama. Seperti monster Frankenstein, kode semacam itu mungkin berfungsi, tetapi jelek, tidak terduga, dan berbahaya pada perubahan sekecil apapun.
Istilah ini berasal dari literatur: dalam novel Mary Shelley “Frankenstein, or the Modern Prometheus” (1818), seorang ilmuwan menciptakan makhluk hidup dari fragmen tubuh orang yang berbeda. Dalam pemrograman, analoginya tepat — pengembang mengambil potongan dari berbagai framework, library, bahasa, dan merekatkannya, menghasilkan sesuatu yang berfungsi tetapi mengerikan.
Perbedaan Frankenstein dari kode spaghetti terletak pada skala dan sifat masalahnya. Kode spaghetti adalah struktur kusut dalam satu tumpukan teknologi. Frankenstein adalah eklektisisme pada tingkat arsitektur: teknologi yang berbeda, paradigma yang tidak kompatibel, pendekatan yang bertentangan dalam satu sistem.
Arsitektur microservices memungkinkan penggunaan teknologi yang berbeda untuk layanan yang berbeda, tetapi dengan syarat batas yang jelas dan protokol komunikasi yang terstandarisasi. Frankenstein adalah pencampuran kacau tanpa batas: REST dan GraphQL dalam satu controller, dua ORM dalam satu modul, SQL dan NoSQL untuk entitas yang sama.
Tidak adanya pemimpin teknis atau arsitek adalah akar penyebab. Ketika dalam sebuah proyek tidak ada yang bertanggung jawab atas integritas arsitektur, setiap pengembang memilih alat “untuk dirinya sendiri”. Satu suka Spring, yang kedua suka Guice, yang ketiga suka DI buatan sendiri. Hasilnya adalah campuran arsitektural.
Penggabungan proyek adalah penyebab umum kedua. Dua tim mengembangkan modul mereka secara independen menggunakan tumpukan yang berbeda. Ketika modul-modul tersebut perlu digabungkan menjadi satu aplikasi, mereka hanya “direkatkan” dengan adapter dan lapisan perantara. Hasilnya adalah Frankenstein.
Akuisisi perusahaan adalah skenario ketiga. Perusahaan A membeli perusahaan B dan ingin mengintegrasikan produknya ke dalam produknya sendiri. Alih-alih menulis ulang — merekatkan melalui API, database bersama, dan solusi sementara. Dalam setahun, sistem berubah menjadi monster yang tidak dipahami siapa pun.
| Penyebab | Deskripsi | Hasil tipikal |
|---|---|---|
| Tidak ada arsitek | Setiap pengembang memilih tumpukannya sendiri | 3 klien HTTP berbeda dalam satu modul |
| Penggabungan proyek | Dua produk digabungkan menjadi satu | Dua ORM, dua cara logging |
| M&A | Akuisisi perusahaan dengan produknya | Hibrida dari berbagai arsitektur dan gaya |
| Eksperimen | Introduksi teknologi baru tanpa strategi | Fitur Java 8 + Java 21 dalam satu file |
| Keputusan politik | Pemaksaan teknologi dari atas tanpa konteks | Framework Enterprise untuk skrip sederhana |
Pengembang berpengalaman yang ingin mencoba teknologi baru di produksi sering menjadi sumber Frankenstein. Alih-alih membatasi eksperimen pada modul terisolasi, mereka memasukkan kode eksperimental ke bagian kritis sistem.
Contoh klasik adalah penggunaan beberapa ORM dalam satu aplikasi. Beberapa modul menggunakan Hibernate, beberapa menggunakan MyBatis, dan beberapa menggunakan query JDBC langsung. Transaksi menjadi tidak terkendali, cache menjadi tidak konsisten, dan pengembang baru tidak tahu pendekatan mana yang harus dipilih untuk fitur baru.
Contoh kedua adalah pencampuran gaya arsitektural. Dalam controller REST API terdapat panggilan layanan SOAP, query SQL langsung, akses sistem file, dan generasi HTML. Aplikasi semacam itu tidak mungkin diuji, diperluas, atau didokumentasikan.
Contoh ketiga adalah tumpukan teknologi di mana Python digunakan untuk backend, Node.js untuk microservice, C# untuk klien desktop, dan Java untuk aplikasi Android, sementara semua logika bisnis tersebar di antara mereka tanpa pembagian tanggung jawab yang jelas.
// frankenstein — gaya dan teknologi campuran
// callbacks, Promises, dan async/await digabungkan
// callbacks
db.query("SELECT * FROM users", function(err, rows) {
if (err) handleError(err);
// Promise di dalam callback
fetch("/api/data").then(function(data) {
// async/await di dalam then
(async () => {
const result = await processData(data);
sendResponse(result);
})();
});
});
// kode bersih — gaya async/await seragam
async function getUserData(userId) {
const user = await db.query("SELECT * FROM users WHERE id = ?", [userId]);
const data = await fetch("/api/data/" + userId);
return await processData(user, data);
}
Satu database digunakan secara bersamaan sebagai SQL relasional (dengan normalisasi) dan sebagai NoSQL berorientasi dokumen (dengan kolom JSON). Sebagian query melalui ORM, sebagian melalui stored procedure, sebagian melalui SQL langsung dari kode. Skema database tidak terdokumentasi, migrasi saling bertabrakan.
Kompleksitas onboarding adalah akibat pertama. Pengembang baru harus menguasai 5 bahasa, 3 framework, 2 gaya arsitektur untuk memahami cara kerja sistem. Onboarding berlarut-larut dari minggu menjadi bulan. Menurut LinkedIn (2023), proyek dengan eklektisisme teknologi kehilangan karyawan baru 2 kali lebih sering.
Ketidakpastian perilaku adalah akibat kedua. Perubahan pada microservice Python tiba-tiba dapat merusak modul Java karena mereka menggunakan database bersama tanpa kontrak yang jelas. Debugging masalah seperti itu membutuhkan pengetahuan simultan tentang semua teknologi dalam tumpukan.
Keamanan adalah akibat ketiga. Setiap teknologi dalam tumpukan memerlukan konfigurasi keamanan, patch, dan monitoring sendiri. Mempertahankan keamanan pada tingkat yang dapat diterima untuk 5–6 teknologi heterogen hampir tidak mungkin. Salah satunya pasti akan rentan.
SonarQube dapat mengukur hutang teknis, tetapi tidak dapat mengukur “hutang arsitektural” — ketidakcocokan komponen. Hutang ini tidak muncul dalam peringatan linter, tetapi dalam ketidakmampuan untuk menambahkan fitur baru tanpa mengubah tiga modul berbeda yang ditulis dalam teknologi berbeda.
Langkah pertama dan terpenting adalah menunjuk arsitek atau tech lead yang bertanggung jawab atas integritas tumpukan teknologi. Orang ini memiliki hak veto atas introduksi teknologi baru tanpa tinjauan arsitektural. Bukan demokrasi, tetapi keputusan tunggal yang bertanggung jawab atas teknologi kunci.
Kedua — terapkan proses Architecture Decision Record (ADR). Setiap keputusan arsitektural signifikan (pemilihan database, framework, protokol) didokumentasikan sebagai teks pendek: konteks, alternatif yang dipertimbangkan, keputusan yang diambil, konsekuensi. ADR disimpan di repositori dan tersedia untuk seluruh tim.
Ketiga — tetapkan prinsip “satu tugas — satu alat”. Untuk permintaan HTTP — satu klien. Untuk ORM — satu library. Untuk logging — satu framework. Pengecualian hanya diizinkan melalui ADR dengan justifikasi. Jika Axios sudah ada di proyek — jangan tambahkan fetch, jika SLF4J sudah ada — jangan menulis melalui System.out.
Eksperimen diizinkan, tetapi di lingkungan terisolasi. Tunjuk modul atau layanan yang dapat ditulis ulang dengan teknologi baru tanpa mempengaruhi sistem lainnya. Jika eksperimen berhasil — standarisasi melalui ADR. Jika tidak — hapus tanpa konsekuensi.
Inventarisasi adalah langkah pertama. Buat peta lengkap tumpukan teknologi: framework, library, bahasa, protokol apa yang digunakan, di modul mana, dan untuk tugas apa. Anda akan melihat skala masalah: alat duplikat, teknologi saling bertentangan, dependensi tidak terpakai.
Standarisasi adalah langkah kedua. Pilih satu alat untuk setiap tugas. Misalnya: hanya Hibernate untuk ORM, hanya SLF4J + Logback untuk logging, hanya REST untuk API. Dokumentasikan standar dalam ADR. Mulai penggantian dari modul di mana eklektisisme menyebabkan masalah paling banyak.
Strategi Parallel Run adalah langkah ketiga. Alat lama dan baru berjalan paralel sampai yang baru membuktikan keandalannya. Misalnya, klien HTTP lama dan baru bekerja bersamaan, tetapi yang baru hanya untuk sebagian permintaan. Setelah periode stabilisasi, yang lama dihapus.
// frankenstein — tiga pendekatan HTTP dalam satu proyek
// Modul A: OkHttp
OkHttpClient client = new OkHttpClient().newCall(request);
// Modul B: RestTemplate (Spring)
restTemplate.getForObject(url, String.class);
// Modul C: java.net.HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
// pendekatan seragam: RestTemplate untuk sync, WebClient untuk reactive
@Autowired
private RestTemplate restTemplate;
public String callApi(String url) {
return restTemplate.getForObject(url, String.class);
}
Pemimpin teknis adalah alat utama dalam memerangi Frankenstein. Bukan manajer, bukan arsitek di menara gading, tetapi pengembang praktis yang menulis kode, me-review PR, dan membuat keputusan arsitektural. Tanpa orang seperti itu, proyek pasti akan tergelincir ke eklektisisme teknologi.
RFC (Request for Comments) adalah proses yang dipinjam dari komunitas Open Source. Sebelum introduksi teknologi signifikan, penulis menulis RFC: masalah, solusi yang diusulkan, alternatif, rencana implementasi. Tim berdiskusi, memberikan suara, menerima atau menolak. RFC menciptakan transparansi dan mencegah keputusan arsitektural “diam-diam”.
Radar teknologi (Technology Radar dari ThoughtWorks) adalah alat untuk mengkategorikan teknologi: Adopt, Trial, Assess, Hold. Tim secara teratur meninjau radar dan memperbarui status. Ini membantu membedakan “tren” dari “bermanfaat” dan menghindari introduksi teknologi yang belum teruji ke dalam kode kritis.
Kualitas arsitektur yang paling penting adalah konsistensi. Bahkan alat yang tidak terbaik yang digunakan di seluruh proyek lebih baik daripada alat terbaik yang hanya digunakan di satu modul. Konsistensi mengurangi beban kognitif, menyederhanakan onboarding, dan membuat kode dapat diprediksi.
Pertanyaan yang Sering Diajukan
Polyglot persistence adalah penggunaan sadar database yang berbeda untuk tugas yang berbeda (PostgreSQL untuk transaksi, Redis untuk cache, Elasticsearch untuk pencarian). Frankenstein adalah pencampuran kacau tanpa strategi. Perbedaannya terletak pada adanya keputusan arsitektural: polyglot adalah rencana, Frankenstein adalah ketiadaannya.
Ya, dan ini adalah masalah umum. Ketika setiap microservice menggunakan bahasa, database, protokol, dan pendekatan deployment sendiri tanpa standar terpusat — muncullah Frankenstein terdistribusi. Untuk microservices, standar umum penting: protokol seragam (REST/gRPC), format log seragam, observability terpusat.
Jangan melarang — arahkan. Minta penulis RFC untuk: menjelaskan mengapa solusi yang ada tidak sesuai, alternatif apa yang dipertimbangkan, bagaimana migrasi akan dilakukan. Seringkali dalam proses menulis RFC, pengembang sendiri menyadari bahwa teknologi baru tidak diperlukan. Jika RFC meyakinkan — implementasikan, tetapi dengan rencana dan batasan.
Pertama inventarisasi, lalu standarisasi. Jangan mencoba menulis ulang semuanya sekaligus. Tunjuk satu lapisan (misalnya klien HTTP atau logging), pilih alat seragam, tulis ADR, dan migrasi secara bertahap. Metode Strangler Fig — ganti komponen lama satu per satu tanpa menghentikan aplikasi.
Semakin sedikit, semakin baik. Idealnya — satu bahasa, satu framework, satu database, satu cara logging. Realistis — 2–3 bahasa (dengan pemisahan jelas), 1–2 database, 1–2 framework. Setiap teknologi tambahan meningkatkan beban kognitif tim dan biaya pemeliharaan.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga