10 poin oleh GN⁺ 4 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • Desain perangkat lunak dipelajari lebih mendalam saat memegang tanggung jawab di proyek nyata dan ketika masalah menjadi urusan sendiri, dibanding lewat kuliah
  • Conway’s Law adalah sudut pandang bahwa perangkat lunak mengulang struktur sosial organisasi, dan perbedaan antara kode ilmiah dan kode industri juga bisa muncul dari struktur insentif
  • rust-analyzer memudahkan kontributor berdaya ungkit tinggi untuk fokus berkat build yang cepat, dukungan stable, tanpa dependensi C, dan pengujian yang selesai dalam hitungan detik
  • rust-analyzer melindungi fitur-fitur independen dengan catch_unwind dan menurunkan ambang PR, tetapi menerapkan standar kualitas yang jauh lebih ketat pada spine inti
  • Struktur eksperimental bisa menjadi kenyataan jangka panjang, dan rust-analyzer pun berlanjut dari prototipe arsitektur LSP menjadi pemeliharaan satu compiler lagi

Desain perangkat lunak paling baik dipelajari di lapangan

  • Desain perangkat lunak lebih baik dipelajari saat memegang tanggung jawab dalam proyek nyata dan menyelesaikan masalah secara langsung, daripada lewat kuliah formal
  • Dibanding saat mengambil peran “arsitek” di kelas desain universitas dan proyek mata kuliah, pembelajaran benar-benar mulai ketika masalah desain menjadi urusan sendiri di IntelliJ Rust, proyek nyata keduanya
  • Di IntelliJ Rust ada beberapa kesalahan, tetapi tidak fatal, dan banyak hal bisa dipelajari dari proses itu
  • Rekayasa perangkat lunak juga punya sisi yang cukup sederhana sehingga orang yang penasaran bisa memahaminya dengan memikirkan prinsip dasar dan membaca berbagai tulisan

Struktur insentif dan Conway’s Law

  • Conway’s Law adalah sudut pandang bahwa perangkat lunak mengulang struktur sosial organisasi yang membuatnya
  • Perbedaan antara perangkat lunak industri dan kode ilmiah mungkin bukan berasal dari pengetahuan membangun perangkat lunak itu sendiri, melainkan dari struktur insentif yang mendorong orang membuat perangkat lunak
  • Situasi seperti “PhD yang harus menerbitkan paper dalam 3 bulan” bisa menjadi faktor penting yang membentuk wujud kode ilmiah
  • Secara umum ada dua cara untuk merespons struktur insentif
  • Merancang atau menggerakkan insentif proyek

    • Kesempatan untuk merancang atau menyesuaikan struktur insentif proyek memang jarang, tetapi ketika ada, dampaknya besar
    • Inti dari TIGER_STYLE bukan pada daftar aturannya sendiri, melainkan pada konteks sosial yang membuat aturan-aturan itu menjadi pilihan yang baik
  • Jika tidak bisa diubah, beradaptasilah dengan batasannya

    • Struktur insentif hampir tidak pernah diberikan sesuai keinginan kita, dan jika tidak bisa diubah maka kita harus beradaptasi dengannya
    • Bahkan dalam proyek perangkat lunak industri, hampir tidak pernah ada “waktu untuk melakukannya dengan benar”, jadi kita harus melakukan yang terbaik dalam batasan yang ada

Cara rust-analyzer menyelaraskan struktur dan partisipan

  • rust-analyzer adalah proyek yang memiliki kedalaman sekaligus keluasan
  • Pada sisi dalam, sifatnya sebagai compiler memungkinkan proyek ini menarik kontributor yang hebat dan berdedikasi
  • Pada sisi luas, IDE klasik memiliki banyak fitur khusus tujuan tertentu, sehingga cocok bagi orang yang sedang belajar Rust atau kontributor akhir pekan yang sulit terlibat secara konsisten untuk menghabiskan satu atau dua jam memperbaiki ketidaknyamanan mereka sendiri
  • Alasan rust-analyzer bersikeras agar tidak memerlukan build rustc, bisa dibangun di stable, tidak punya dependensi C, dan seluruh test suite selesai dalam beberapa detik adalah untuk menarik kontributor berdaya ungkit tinggi
  • Sistem build dipoles agar orang bisa fokus pada pekerjaan borrow checker tanpa terdistraksi hal lain
  • Untuk menarik kontributor akhir pekan, bagian dalam rust-analyzer dibagi menjadi beberapa fitur independen, dan tiap fitur dilindungi saat runtime dengan catch_unwind
  • Ambang untuk PR fitur diturunkan menjadi “jalur bahagia berjalan dan ada test”, dan dianggap masih bisa diterima meskipun kode terkait crash
  • Namun ada dua syarat
    • Masalah kualitas harus terisolasi di dalam fitur individual dan tidak menyebar ke bagian lain
    • Crash saat runtime tidak boleh terlihat oleh pengguna; untuk itu, fitur rust-analyzer berjalan di atas snapshot immutable dan tidak boleh mencemari data
  • Sebaliknya, standar kualitas yang jauh lebih ketat diterapkan pada spine inti yang menopang fitur-fitur tersebut

Risiko struktur eksperimental menjadi kenyataan jangka panjang

  • Saat beradaptasi alih-alih memperbaiki struktur insentif, kita perlu waspada bahwa masa depan tidak pasti dan biasanya terwujud dengan cara yang paling tidak nyaman
  • Motivasi awal rust-analyzer adalah menghindari pekerjaan menulis satu compiler paralel lagi di dalam IntelliJ Rust, serta memverifikasi lewat prototipe arsitektur yang lebih baik untuk LSP lalu mengembalikan pelajarannya ke rustc
  • Karena itu, kode tersebut sangat eksperimental, termasuk sampai ke bagian intinya
  • Pada akhirnya, proyek ini justru harus memelihara satu compiler lagi
  • Demikian pula, proyek uutils bermula sebagai tujuan utama bagi orang-orang yang belajar Rust, lalu menjadi implementasi coreutils untuk Ubuntu

Bahan dan buku yang layak dirujuk

  • Tidak ada satu buku tunggal berisi jawaban benar, dan praktik nyata tampaknya merupakan unsur yang wajib
  • Boundaries by Gary Bernhardt
    • Berisi saran konkret yang kuat dan menjadi bahan yang memicu eksplorasi di tingkat yang lebih tinggi
  • How to Test
    • Pentingnya testing langsung bisa dipahami, tetapi butuh waktu lama untuk mengakui bahwa banyak nasihat testing yang sering dikutip tidak praktis, lalu membentuk konsep tentang cara yang benar-benar bekerja
  • ∅MQ guide dan tulisan Pieter Hintjens
    • Bahan yang memperkenalkan cara berpikir ala Conway’s Law
    • Arsitektur pengembangan fitur rust-analyzer adalah bentuk penerapan optimistic merging
  • Reflections on a decade of coding by Jamii
    • Membahas hal-hal yang sangat meta, dan sangat bagus sampai dijadikan item pertama di kumpulan tautan
  • Blog Ted Kaminski
    • Ditulis dalam bentuk catatan untuk buku yang tidak ada, dan merupakan hal yang paling dekat dengan teori yang konsisten tentang pengembangan perangkat lunak
  • Software Engineering at Google dan The Philosophy of Software Design karya Ousterhout

1 komentar

 
GN⁺ 4 jam lalu
Komentar Hacker News
  • Jika diringkas jadi cheatsheet, desain yang baik seharusnya membuat satu ide meresap ke seluruh sistem dan bergerak ke arah meminimalkan kejutan
    Jika sistem mengizinkannya, orang pada akhirnya akan memakainya seperti itu, dan solusi yang dimulai dengan “kalau semua orang mau cukup melakukan X” bukanlah solusi
    Pisahkan bagian yang mentransformasikan data dan bagian yang menggunakannya, model data bertahan lebih lama daripada kode, dan coupling adalah akar dari banyak masalah
    Versioning tidak bisa dihindari, state harus ditampilkan secara eksplisit, dan setiap informasi harus punya satu sumber kebenaran tunggal
    Luangkan lebih banyak waktu untuk penamaan, jika sulit diuji berarti desainnya salah, dan keputusan yang tidak didokumentasikan akan disesali
    Komunikasi itu mahal jadi harus dibenarkan sebelum dibayar, dan pekerjaan engineer adalah menyelesaikan masalah dengan heuristik di tengah informasi yang tidak lengkap

    • Sebagian besar isi ini tampaknya sebenarnya tidak terlalu berkaitan dengan arsitektur perangkat lunak, mungkin yang relevan hanya sebatas “isolasi sebagian sistem”
      Tulisan itu sendiri juga tidak terlalu konsisten jika dilihat dari sudut pandang arsitektur perangkat lunak
      4+1 architecture view adalah kerangka konseptual yang bagus untuk memikirkan gambaran besar jika UML disisihkan, dan seri Pattern-Oriented Software Architecture juga merangkum dengan baik berbagai arsitektur yang dicapai orang
      Grady Booch juga pernah membuat software architecture handbook, tetapi sekarang tampaknya hampir berhenti, dan dulu di mailing list-nya mereka mencatat arsitektur sistem besar dari perusahaan atau proyek open source berskala besar
      Jika menggali materi seperti ini, kita bisa melihat bahwa arsitektur dibentuk sesuai fokus yang berbeda seperti skala, keselamatan, performa, interoperabilitas, fail-safe, dan setiap tujuan punya trade-off yang realistis
    • Saya tidak setuju dengan semuanya, tetapi kalau menambahkan beberapa hal, tujuan utama perangkat lunak adalah menyelesaikan masalah yang ada di depan mata, dan tujuan sekundernya adalah menyelesaikan masalah masa depan yang kemungkinan besar muncul dengan usaha seminimal mungkin
      Jika lebih baik menurut tolok ukur ini, maka meski terlihat seperti desain buruk, sebenarnya itu desain yang baik
      Interface harus dibuat mudah digunakan dengan benar dan sulit digunakan dengan salah, dan perlu memikirkan bagaimana orang yang tidak mengenal proyek akan memakainya
      Kode yang benar harus mudah ditulis dan kode yang mencurigakan harus menonjol, dan bug harus digeser sejauh mungkin ke kiri
      Daripada memperbaiki satu bug, lebih baik menghilangkan kelas bug, dan karena interface lebih sulit diubah daripada implementasi, jika interfacenya benar maka implementasi yang jelek pun tidak masalah
      Komentar dan dokumentasi harus menjelaskan mengapa kode berbentuk seperti itu, dan meski tampaknya ada cara yang lebih sederhana, jika ada batasan tertentu yang membuatnya tidak bisa dipakai maka hal itu harus ditinggalkan
      Dari sudut pandang data, jangan mengulang; jika fakta yang sama disimpan di banyak tempat, pada akhirnya akan tidak sinkron dan menimbulkan bug
      Keluar dari jalan yang sudah teraspal punya biaya, dan meskipun itu boleh dilakukan jika benar-benar bernilai, biaya itu tidak boleh diremehkan
      Sering kali teknologi yang membosankan dan tampak lebih buruk justru adalah teknologi yang lebih baik, dan yang harus dinilai dengan expected value bukan “apakah ini layak dilakukan?” melainkan “dibanding melakukan hal lain, apakah ini layak dilakukan?”
      Meski merasa diri lebih pintar daripada orang lain, ada masalah yang tidak bisa diselesaikan hanya dengan kecerdasan, dan ada masalah yang memang tidak bisa ditemukan sampai benar-benar meledak, jadi kita harus belajar dari kesalahan orang lain
      Friksi adalah pembunuh diam-diam
    • Migrasi data itu tak terelakkan jadi harus direncanakan sejak awal, dan ini adalah konsekuensi dari versioning
      Perencanaan itu baik, tetapi kadang kita memang harus mencobanya langsung, dan semuanya butuh uang
      Jika mendesain tanpa mempertimbangkan biaya, nantinya kita akan dipaksa mengambil pilihan yang sulit
    • Selama lebih dari setahun membuat video game, saya sedang membangun engine yang berkelanjutan, pipeline data yang terpisah, lapisan rendering/manajemen resource yang sepenuhnya dipisah, dan cara transformasi state yang eksplisit, dan sebagian besar daftar ini berlaku begitu saja
      Bahkan untuk proyek solo, batasan engine menjadi pemandu yang mengatakan “tambahkan fitur baru aneh yang muncul saat pengujian dengan cara seperti ini”
      Jadi saya tidak perlu terus membawa dokumentasi besar seperti “kalau ingin membuat efek suara baru yang dijalankan berkali-kali pada transformasi state tertentu, lakukan seperti ini”
    • Saya bekerja di bidang ini, dan karena sisi kami memodelkan industri medis, hal ini lebih kurang abstrak dibanding bidang lain
      Perancang sistem harus memahami industrinya; tidak perlu sepenuhnya menerima istilah dan kebiasaan pemodelannya, tetapi harus memahami alasan dan sudut pandang mereka dalam melihat dataset
      Ada bagian di mana kami sengaja menyederhanakan kompleksitas pasar medis untuk menghilangkan overdefinition yang tidak perlu dan memberikan model yang lebih terpadu, tetapi perubahan seperti itu bisa kami lakukan dengan percaya diri karena kami cukup memahami domain masalahnya
      Khususnya, nama hampir tidak pernah mati
      Kadang memang mati, tetapi mengganti nama butuh usaha ekstrem, jadi sangat layak menghabiskan banyak waktu agar para pakar domain meninjau usulan penamaan cukup lama untuk memastikan tidak ada yang terlewat
      Beberapa konsep bisa dipaksakan, tetapi sisi bisnis seperti sales dan marketing akan terus menuntut istilah industri dan menekan agar model disesuaikan dengan sudut pandang industri saat ini
      Jika memutuskan untuk memutus arus itu, pemutusan tersebut harus punya niat dan tujuan yang jelas
      Sifat yang paling perlu ditekankan dalam perangkat lunak adalah maintainability
      Biaya pembuatan memang penting, tetapi biaya operasional jauh lebih berdampak karena bukan hanya infrastruktur, melainkan juga akumulasi permintaan fitur, refactoring kode, dan menjaga versi software pihak ketiga
  • Daftar rekomendasinya sering bagus seperti A Philosophy of Software Design karya Ousterhout, tetapi secara umum lebih dekat ke teori umum pengembangan perangkat lunak daripada arsitektur perangkat lunak itu sendiri
    Untuk melihat arsitektur, saya merekomendasikan karya klasik seperti Software Architecture: Perspectives on an Emerging Discipline dari Shaw/Garlan dan tulisan-tulisan Mary Shaw
    Makalah yang lebih baru seperti Myths and Mythconceptions: What Does It Mean to Be a Programming Language, Anyhow? atau Revisiting Abstractions for Software Architecture and Tools to Support Them, yang mengeksplorasi mengapa bidang arsitektur perangkat lunak tidak berkembang seperti yang diperkirakan, juga bagus
    Secara praktis, menarik untuk melihat mengapa Unix pipes and filters dan REST berhasil, serta di mana dan mengapa keduanya runtuh, dan hexagonal architecture juga merupakan hal inti
    Secara pribadi, ada juga Beyond Procedure Calls as Component Glue: Connectors Deserve Metaclass Status, yang mencoba menghubungkan arsitektur perangkat lunak dengan metaobject protocol dan melihatnya sebagai landasan baru bagi bahasa pemrograman dan pemrograman
    Itu adalah jawaban terhadap Procedure Calls Are the Assembly Language of Software Interconnection: Connectors Deserve First-Class Status karya Mary Shaw, dan menanyakan seperti apa bahasa tingkat tinggi jika procedure call adalah assembly language
    Mungkin arsitektur perangkat lunak masih punya masa depan yang lebih cerah dan praktis

    • Apa itu hexagonal architecture?
    • Pertanyaan “jika procedure call adalah assembly language, seperti apa bahasa tingkat tinggi?” membuat saya berpikir bahwa meski saya tidak begitu paham teori bahasa pemrograman dan alat rekayasa perangkat lunak, bukankah ini konsep dasar dari lambda calculus, LISP, APL, Clojure, TCL, dan sejenisnya?
      Kalau ada beberapa struktur data dan tipe, serta sekumpulan kecil fungsi dasar, sisanya tinggal dikombinasikan
      Salah satu hal yang saya sukai dari Lisp adalah bahwa tipe yang lebih kompleks, terutama yang datang dari FFI, selalu opaque
      Saya ingin melihat implementasi CLOS yang, saat Anda mendefinisikan struct di bahasa mirip C, memberi Anda sekumpulan fungsi standar
  • Cara terbaik mempelajari arsitektur bukanlah membuat proyek yang cukup besar, melainkan memeliharanya
    Dan itu pun sebaiknya dilakukan setidaknya di dua atau tiga proyek
    Jika proyek terlalu kecil, arsitektur apa pun akan berjalan baik, dan proyek “besar” lebih baik dinilai dari jumlah orang yang pernah mengerjakannya, atau lebih baik lagi jumlah timnya, daripada jumlah baris kode
    Kita perlu setidaknya dua proyek berbeda agar bisa membandingkan, dan saya juga pernah melihat orang yang terjebak puluhan tahun di satu proyek hingga tidak mengenal cara modern menyelesaikan masalah
    Namun kenyataannya, sering kali orang yang membuat proyeklah yang dipromosikan menjadi arsitek, bukan orang yang memeliharanya
    Di Google ini lebih jelas lagi, karena promosi datang dari meluncurkan hal baru, bukan dari pemeliharaan, dan sebisa mungkin lebih menguntungkan keluar tak lama setelah peluncuran
    Ironisnya, posisi terbaik untuk menjadi arsitek mungkin justru kontraktor eksternal yang ditugaskan memelihara proyek lama yang tidak ingin disentuh siapa pun di dalam perusahaan
    Mereka harus mempertahankan arsitektur dan berpindah-pindah di banyak proyek, jadi bisa membandingkan
    Hanya saja, jika mereka menagih per jam, ada risiko mereka membuat arsitektur terlalu rumit agar bisa menagih lebih banyak waktu

  • Dalam konteks seperti ini saya benar-benar merekomendasikan Architecture of Open Source Applications
    Ini adalah seri buku di mana tiap bab ditulis oleh maintainer proyek terkait, jadi kita bisa belajar arsitektur lewat contoh
    Kita bisa memahami bukan hanya apa arsitekturnya, tetapi juga batasan yang membentuknya, biasanya sejarah dan visi proyek yang berubah
    Karena keterbatasan buku multi-penulis, tidak semua bab sama bagus atau menariknya, dan semuanya sudah lama, tetapi tetap layak dibaca
    http://aosabook.org/

  • Saya ingin menghabiskan lebih banyak waktu untuk mendapatkan model mental yang lebih baik atas proyek yang saya kerjakan, tetapi ketika saya mulai membenci bahasa pemrograman, pilihan arsitektur tertentu, atau bagian yang menjadi begitu rumit sampai terasa tidak layak diberi waktu, motivasi saya langsung turun drastis
    Tergantung proyeknya, bekerja sebagai “full-stack developer” terasa seperti menghilangkan kesenangan dari pemrograman
    Saya sudah menghabiskan 40 jam seminggu menatap proyek paling membosankan yang bisa dibayangkan

    • Lebih baik dilepas saja
      Tidak ada satu pun proyek yang tanpa cela
      Dan jika bahasa pemrogramannya benar-benar masalah sebesar itu, lebih baik pindah kapal
      Saya percaya semua orang seharusnya bisa memakai banyak bahasa, tetapi pada akhirnya pilihan ada di tangan masing-masing
    • Analysis paralysis selalu berbahaya, jadi targetnya harus fleksibilitas, bukan kesempurnaan
      Kita harus memastikan keputusan yang paling banyak memakan waktu memang keputusan yang paling penting
      Struktur data yang dirancang dengan baik punya dampak jauh lebih besar pada performa dan maintainability daripada framework, bahasa, atau platform
      Secara pribadi saya bekerja dengan ADHD setiap hari, jadi saya harus terus mendorong agar kemajuan tetap terjadi, yang berarti memilih keputusan yang tidak penting lalu menuntaskannya agar bisa fokus pada sisa ruang masalah yang memang butuh pemikiran hati-hati
    • Terdengar seperti situasi yang butuh pengelolaan emosi yang lebih baik
  • Istilah seperti “clean code” atau “beautiful code” tidak terlalu membantu junior mempelajari praktik terbaik arsitektur perangkat lunak
    Ketika junior bertanya kenapa memakai ORM lalu senior menjawab “karena lebih bersih”, yang tersisa hanya tanda tanya
    Lebih baik mendefinisikan daftar tujuan yang jelas
    Kriteria seperti maintainability, performa dan skalabilitas, efisiensi, resilience, observability, testability dan apakah sudah diuji, keamanan, serta kemudahan dibaca oleh developer baru saling menyeimbangkan
    Semakin banyak kriteria yang ditambahkan, semakin mudah membuat pilihan yang lebih baik saat ragu, dan itu juga bermakna bagi orang di luar tim pengembang sehingga kita bisa sepakat dengan pelanggan tentang apa yang mereka bayar
    Sebagian besar umur proyek dihabiskan dalam mode pemeliharaan, dan itu justru pertanda baik bahwa proyeknya sukses, jadi maintainability pun bisa didefinisikan
    Titik awal yang bagus adalah kemampuan menambahkan fitur baru tanpa merusak arsitektur, atau lebih jauh lagi tanpa merusak satu pun method signature
    Kita harus sangat berhati-hati terhadap abstraksi
    Ucapan “abstraksi sering menyembunyikan betapa sederhana hal yang Anda inginkan sebenarnya” itu benar, dan ORM adalah contoh tepatnya
    Dalam kebanyakan kasus, data harus diperlakukan sebagai warga kelas satu, dan kolaborasi dengan DBA juga jadi lebih baik
    Tantangannya adalah memikirkan hal-hal di luar happy path tanpa jatuh ke premature optimization, dan itu membantu mencegah kita langsung menerjang implementasi ide bagus tanpa melihat plus minusnya
    Jika saya membayangkan orang yang akan menangani kode saya sedang menjalani hari yang sangat buruk, itu membantu saya membuatnya lebih menyenangkan untuk dibaca
    Komentar di berbagai tempat, variabel lokal yang tetap dibiarkan meski bisa dihilangkan, dan nama variabel termasuk bagian dari itu
    Framework harus dipilih dengan hati-hati; ia pelayan yang baik tetapi tuan yang buruk
    Ungkapan dalam tulisan “jadilah engineer, bukan frameworker” terasa tepat

    • Dibanding framework yang sangat opinionated, framework modular itu sangat berharga
      Saya tidak membenci opini yang kuat itu sendiri; untuk library atau tool, itu justru bisa menjadi sifat yang hebat
      Library atau tool tersebut kemungkinan besar memiliki banyak keahlian domain di wilayahnya sendiri
      Tetapi pada framework, opini yang kuat mudah berubah menjadi “karena memegang palu, semua hal terlihat seperti paku”
      Itu tidak selalu terjadi dan tidak selalu jadi masalah, tetapi jika ortodoksi dari satu domain diterapkan luas, justifikasinya yang tadinya spesifik domain bisa runtuh dalam konteks yang lebih besar
      Karena itu saya lebih suka framework yang modular, yang memungkinkan memasang ORM atau persistence integration layer lain, serta mengganti router, validator, atau komponen lain yang tidak cocok dengan masalahnya
      Ini terutama berharga jika di dalam ekosistem framework ada alternatif dari beberapa paradigma berbeda
      Dengan begitu kita bisa menemukan alat jadi yang hampir tepat, memahami kekurangannya, dan memilih opsi yang bisa dilengkapi saat diperlukan
      Demi maintainability, melawan sindrom NIH sangat penting
      Ini adalah risiko terus-menerus yang menyedot resource dengan kecepatan mengejutkan
      Pada saat yang sama, beberapa komponen memang bisa memberi manfaat besar jika disetel sendiri atau dimiliki sepenuhnya, dan bagian sulitnya adalah menentukan mana yang termasuk kategori mana
      Saya sangat sependapat dengan menaruh maintainability di urutan teratas
  • Dari sudut pandang system engineering, arsitektur perangkat lunak mirip desain perpipaan
    Sangat penting, tetapi manusia tidak tinggal di dalam pipa, melainkan di rumah yang memiliki pipa
    Jika perpipaannya tidak mempertimbangkan bagian rumah yang lain, biaya memperbaikinya bisa sangat besar

  • Tulisan yang bagus
    “Mempelajari arsitektur perangkat lunak” berarti memahami bahwa tidak ada satu jawaban benar tunggal
    Ini adalah seni sekaligus sains
    Untuk bacaan, saya merekomendasikan Simplify IT - The art and science towards simpler IT solution
    https://nocomplexity.com/documents/reports/SimplifyIT.pdf

  • Presentasi Gary Bernhardt benar-benar istimewa
    Ada banyak konsep di dalamnya yang bisa membawa ke tempat menarik lainnya