<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Udacoding - Medium]]></title>
        <description><![CDATA[IT Training Center and Software Development - Medium]]></description>
        <link>https://medium.com/udacoding?source=rss----49122c796dd1---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Udacoding - Medium</title>
            <link>https://medium.com/udacoding?source=rss----49122c796dd1---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 04:30:35 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/udacoding" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Debugging Aplikasi Flutter dengan Membaca Error Message (Bukan Asal Googling)]]></title>
            <link>https://medium.com/udacoding/debugging-aplikasi-flutter-dengan-membaca-error-message-bukan-asal-googling-d42c9f5684a9?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/d42c9f5684a9</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Tue, 30 Dec 2025 22:55:49 GMT</pubDate>
            <atom:updated>2025-12-30T22:55:29.810Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OTHV6KmBfP3xn4FCOe6HhA.png" /></figure><p>Saat pertama kali belajar Flutter, hampir setiap error terasa seperti bencana kecil. Aplikasi crash, layar merah muncul, dan refleks pertama kita biasanya adalah <strong>copy paste error ke Google</strong>.</p><p>Masalahnya, kebiasaan ini sering membuat kita:</p><ul><li>Lompat ke StackOverflow tanpa paham konteks</li><li>Menyalin solusi yang belum tentu relevan</li><li>Menghabiskan waktu lebih lama dari yang seharusnya</li></ul><p>Padahal, Flutter sebenarnya <strong>sangat komunikatif</strong> lewat error message-nya. Jika kita mau meluangkan waktu untuk membacanya dengan benar, sebagian besar masalah bisa diselesaikan tanpa Googling sama sekali.</p><h3>Error Flutter Itu Bukan Musuh</h3><p>Banyak developer menganggap error message sebagai sesuatu yang menakutkan. Padahal di Flutter, error message justru adalah <strong>petunjuk terbaik</strong> yang kita punya.</p><p>Flutter biasanya memberikan:</p><ul><li>Jenis error yang jelas</li><li>Lokasi file dan baris kode</li><li>Penjelasan kenapa error terjadi</li><li>Bahkan saran perbaikannya</li></ul><p>Masalahnya bukan pada error-nya, tapi pada <strong>cara kita membacanya</strong>.</p><h3>Fokus ke Baris Paling Atas (Bukan yang Terpanjang)</h3><p>Kesalahan paling umum saat melihat error Flutter adalah langsung scroll ke bawah.</p><p>Padahal:</p><ul><li><strong>Baris paling atas</strong> biasanya berisi inti masalah</li><li>Baris-baris setelahnya sering hanya stack trace</li></ul><p>Contoh pola umum:</p><pre>════════ Exception caught by widgets library ════════<br>The following assertion was thrown building MyWidget:</pre><p>Kalimat setelah itu hampir selalu menjelaskan <strong>apa yang salah</strong>, bukan sekadar error acak.</p><h3>Kenali Jenis Error yang Sering Muncul</h3><p>Dengan sering membaca error, kamu akan mulai mengenali polanya.</p><p>Beberapa contoh:</p><ul><li><strong>RenderFlex overflowed</strong> → Masalah layout (biasanya Row/Column)</li><li><strong>Null check operator used on a null value</strong> → Salah asumsi data tidak null</li><li><strong>setState() called after dispose()</strong> → Lifecycle widget bermasalah</li><li><strong>Looking up a deactivated widget&#39;s ancestor</strong> → Context dipakai di waktu yang salah</li></ul><p>Begitu kamu mengenali pola ini, otakmu akan langsung tahu <strong>ke mana harus melihat</strong>.</p><h3>Perhatikan File dan Line Number</h3><p>Flutter hampir selalu memberi tahu:</p><pre>lib/presentation/pages/home_page.dart:42</pre><p>Ini bukan hiasan.</p><p>Tips penting:</p><ul><li>Buka file tersebut</li><li>Fokus di baris yang disebutkan</li><li>Jangan langsung menyalahkan widget lain</li></ul><p>Sering kali bugnya bukan di widget besar, tapi di <strong>satu parameter kecil</strong> yang salah.</p><h3>Baca Kalimat, Bukan Hanya Kata Kunci</h3><p>Error Flutter sering ditulis dalam bahasa yang cukup manusiawi.</p><p>Contoh:</p><blockquote><em>“A RenderFlex overflowed by 12 pixels on the right”</em></blockquote><p>Ini bukan sekadar error ini informasi:</p><ul><li>Widget overflow</li><li>Sebesar 12 pixel</li><li>Di sisi kanan</li></ul><p>Dari sini, kita sudah bisa menyimpulkan:</p><ul><li>Perlu Expanded, Flexible, atau Wrap</li><li>Atau ukuran widget terlalu besar</li></ul><h3>Jangan Langsung Googling, Tapi Bertanya ke Diri Sendiri</h3><p>Sebelum membuka browser, coba tanyakan:</p><ul><li>Widget apa yang sedang dirender?</li><li>Data apa yang masuk ke widget ini?</li><li>Apakah ada kemungkinan null?</li><li>Apakah ini async issue?</li></ul><p>Sering kali jawabannya sudah ada di kepala kita error hanya membantu menegaskannya.</p><h3>Googling Tetap Perlu, Tapi Setelah Paham Masalahnya</h3><p>Ini bukan berarti Googling itu buruk.</p><p>Yang salah adalah:</p><ul><li>Googling tanpa memahami error</li><li>Menyalin solusi tanpa tahu alasannya</li></ul><p>Yang benar:</p><ul><li>Baca error sampai paham inti masalah</li><li>Gunakan Google untuk <strong>pendalaman</strong>, bukan sebagai tebak-tebakan</li></ul><p>Dengan begitu, solusi yang kamu temukan akan jauh lebih relevan.</p><h3>Skill Debugging = Skill Developer Profesional</h3><p>Perbedaan developer pemula dan berpengalaman sering bukan di seberapa banyak framework yang dikuasai, tapi di <strong>cara menghadapi error</strong>.</p><p>Developer berpengalaman:</p><ul><li>Tenang saat melihat error</li><li>Membaca, bukan panik</li><li>Mengerti pola</li><li>Jarang trial-and-error buta</li></ul><p>Dan kabar baiknya: skill ini <strong>bisa dilatih</strong>, dimulai dari kebiasaan sederhana membaca error message dengan benar.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d42c9f5684a9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/debugging-aplikasi-flutter-dengan-membaca-error-message-bukan-asal-googling-d42c9f5684a9">Debugging Aplikasi Flutter dengan Membaca Error Message (Bukan Asal Googling)</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Keputusan UI Kecil di Flutter yang Membuat Aplikasi Terasa Lebih Profesional]]></title>
            <link>https://medium.com/udacoding/keputusan-ui-kecil-di-flutter-yang-membuat-aplikasi-terasa-lebih-profesional-6b04054d0ec7?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/6b04054d0ec7</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Mon, 29 Dec 2025 22:32:48 GMT</pubDate>
            <atom:updated>2025-12-29T22:32:44.166Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ILYFQSGhOF782m6nZ2uSqQ.png" /></figure><p>Saat pertama kali belajar Flutter, fokus saya adalah <strong>“UI jadi”</strong>.<br>Button bisa diklik, data tampil, halaman berpindah <em>done</em>.</p><p>Tapi setelah terlibat di project nyata dan melihat aplikasi production, saya sadar satu hal penting:</p><blockquote><em>Aplikasi terasa profesional </em><strong><em>bukan karena fitur besar</em></strong><em>, tapi karena </em><strong><em>keputusan UI kecil yang konsisten</em></strong><em>.</em></blockquote><p>Di artikel ini, saya ingin membagikan beberapa <em>small UI decisions</em> di Flutter yang sering dianggap sepele, tapi sangat berpengaruh pada kesan akhir aplikasi.</p><h3>1. Konsistensi Padding dan Spacing</h3><p>Ini kesalahan paling umum.</p><pre>Padding(<br>  padding: EdgeInsets.all(16),<br>  child: ...<br>)</pre><p>Lalu di halaman lain:</p><pre>Padding(<br>  padding: EdgeInsets.symmetric(horizontal: 20),<br>  child: ...<br>)</pre><p>Secara visual, user <strong>bisa merasakan ada yang “tidak rapi”</strong>, meskipun tidak tahu alasannya.</p><h3>Praktik yang lebih profesional:</h3><ul><li>Tentukan standar spacing: 8, 12, 16, 24</li><li>Gunakan konstanta</li></ul><pre>class AppSpacing {<br>  static const double s = 8;<br>  static const double m = 16;<br>  static const double l = 24;<br>}</pre><p>👉 <strong>UI terasa tenang dan konsisten</strong></p><h3>2. Memberi Feedback pada Setiap Interaksi</h3><p>Button yang ditekan tapi <strong>tidak memberi respon visual</strong> terasa “mati”.</p><p>Hal kecil seperti:</p><ul><li>InkWell splash</li><li>CircularProgressIndicator saat loading</li><li>Disabled state saat proses berlangsung</li></ul><pre>ElevatedButton(<br>  onPressed: isLoading ? null : onSubmit,<br>  child: isLoading<br>      ? SizedBox(<br>          height: 16,<br>          width: 16,<br>          child: CircularProgressIndicator(strokeWidth: 2),<br>        )<br>      : Text(&quot;Simpan&quot;),<br>)</pre><p>👉 User merasa aplikasi <strong>responsif dan hidup</strong></p><h3>3. Typografi Lebih Penting dari yang Kamu Kira</h3><p>Banyak aplikasi Flutter pemula:</p><ul><li>Semua teks Text() default</li><li>Ukuran dan weight acak</li></ul><p>Padahal, tipografi adalah <strong>fondasi UI</strong>.</p><h3>Minimal yang sebaiknya konsisten:</h3><ul><li>Heading</li><li>Body</li><li>Caption</li></ul><pre>ThemeData(<br>  textTheme: TextTheme(<br>    titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),<br>    bodyMedium: TextStyle(fontSize: 14),<br>    labelSmall: TextStyle(fontSize: 12, color: Colors.grey),<br>  ),<br>);</pre><p>👉 Aplikasi langsung terasa <strong>lebih rapi dan “niat”</strong></p><h3>4. Jarak Antar Elemen Lebih Penting dari Banyak Warna</h3><p>Pemula sering:</p><ul><li>Menambah warna</li><li>Menambah garis</li><li>Menambah card</li></ul><p>Padahal seringkali <strong>cukup tambahkan jarak</strong>.</p><pre>Column(<br>  crossAxisAlignment: CrossAxisAlignment.start,<br>  children: [<br>    Text(&quot;Nama Produk&quot;),<br>    SizedBox(height: 4),<br>    Text(&quot;Rp 25.000&quot;),<br>  ],<br>)</pre><p>👉 UI terasa <strong>lega dan mudah dibaca</strong></p><h3>5. Empty State &amp; Error State yang Manusiawi</h3><p>Data kosong tanpa penjelasan = kesan aplikasi belum jadi.</p><p>Bandingkan:</p><p>❌ <em>Halaman putih kosong</em><br>✅ Pesan sederhana:</p><blockquote><em>“Belum ada data. Silakan tambah item baru.”</em></blockquote><pre>Center(<br>  child: Column(<br>    mainAxisAlignment: MainAxisAlignment.center,<br>    children: [<br>      Icon(Icons.inbox, size: 48, color: Colors.grey),<br>      SizedBox(height: 8),<br>      Text(&quot;Belum ada data&quot;),<br>    ],<br>  ),<br>)</pre><p>👉 Terlihat <strong>siap production</strong>, bukan sekadar demo</p><h3>6. Animasi Kecil, Bukan Berlebihan</h3><p>Profesional UI <strong>bukan tentang animasi heboh</strong>, tapi transisi halus.</p><p>Contoh:</p><ul><li>AnimatedContainer</li><li>AnimatedOpacity</li><li>AnimatedSwitcher</li></ul><pre>AnimatedOpacity(<br>  opacity: isVisible ? 1 : 0,<br>  duration: Duration(milliseconds: 200),<br>  child: ...<br>)</pre><p>👉 Perubahan UI terasa <strong>alami dan halus</strong></p><h3>7. Status Bar dan Safe Area Tidak Dilupakan</h3><p>Hal kecil tapi sering diabaikan:</p><ul><li>Konten ketabrak notch</li><li>Status bar warna tidak cocok</li></ul><p>Gunakan:</p><pre>SafeArea(<br>  child: Scaffold(<br>    ...<br>  ),<br>);</pre><p>Dan sesuaikan SystemUiOverlayStyle.</p><p>👉 Aplikasi terasa <strong>benar-benar diperhatikan</strong></p><h3>Penutup</h3><p>Aplikasi Flutter yang profesional <strong>jarang terlihat mencolok</strong>.<br>Justru terasa:</p><ul><li>Tenang</li><li>Konsisten</li><li>Mudah digunakan</li><li>Tidak membuat user berpikir</li></ul><p>Dan semua itu sering datang dari <strong>keputusan UI kecil yang konsisten</strong>, bukan dari fitur besar.</p><blockquote>Professional apps are built from small decisions done right.</blockquote><p>Kalau kamu Flutter intern, junior, atau self-taught fokuslah pada detail-detail kecil ini.<br>Itu yang membedakan <strong>“app bisa jalan”</strong> dan <strong>“app siap dipakai user.”</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6b04054d0ec7" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/keputusan-ui-kecil-di-flutter-yang-membuat-aplikasi-terasa-lebih-profesional-6b04054d0ec7">Keputusan UI Kecil di Flutter yang Membuat Aplikasi Terasa Lebih Profesional</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Merancang Model Response API di Flutter Tanpa Kehilangan Kewarasan]]></title>
            <link>https://medium.com/udacoding/merancang-model-response-api-di-flutter-tanpa-kehilangan-kewarasan-8c5f86e20903?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/8c5f86e20903</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Mon, 29 Dec 2025 22:26:22 GMT</pubDate>
            <atom:updated>2025-12-29T22:26:21.485Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1ZUrw6PNJ-HKy2LjTRo0mA.png" /></figure><p>Jika kamu pernah mengerjakan aplikasi Flutter yang terhubung ke API, besar kemungkinan kamu pernah merasa <strong>frustrasi hanya karena model response</strong>.<br>Field terlalu banyak, struktur JSON berubah, null di mana-mana, dan error muncul entah dari mana.</p><p>Di artikel ini, saya ingin berbagi <strong>cara berpikir dan pendekatan praktis</strong> dalam merancang model response API di Flutter agar tetap rapi, aman, dan yang paling penting tidak bikin stres.</p><h3>Masalah Klasik Saat Membuat Model API</h3><p>Biasanya masalah muncul dari hal-hal berikut:</p><ul><li>Struktur JSON <strong>terlalu dalam (nested)</strong></li><li>Field <strong>opsional tapi diperlakukan wajib</strong></li><li>Backend berubah, frontend ikut rusak</li><li>Satu model dipakai untuk <strong>semua kebutuhan</strong></li><li>Terlalu banyak logic di fromJson</li></ul><p>Kalau kamu pernah menulis response.data[&#39;data&#39;][&#39;attributes&#39;][&#39;user&#39;][&#39;profile&#39;], kita senasib 😄</p><h3>Prinsip Utama: Model Itu Representasi Data, Bukan Logic</h3><p>Kesalahan paling umum adalah <strong>memasukkan terlalu banyak logic ke dalam model</strong>.</p><p>Model seharusnya:</p><ul><li>Merepresentasikan data</li><li>Mudah diparse</li><li>Mudah diuji</li><li>Mudah diubah</li></ul><p>Model <strong>bukan tempat</strong> untuk:</p><ul><li>Validasi kompleks</li><li>Conditional logic bisnis</li><li>Formatting UI</li></ul><h3>Pisahkan API Response dan Domain Model</h3><p>Ini adalah perubahan mindset paling penting.</p><p>❌ Jangan:</p><pre>class User {<br>  final String name;<br>  final String email;<br>}</pre><p>langsung dipakai untuk response API <strong>dan</strong> UI.</p><p>✅ Lakukan:</p><ul><li>UserResponse → sesuai struktur API</li><li>User → domain model untuk aplikasi</li></ul><h3>Contoh</h3><pre>class UserResponse {<br>  final String? name;<br>  final String? email;<br><br>  UserResponse({this.name, this.email});<br>  factory UserResponse.fromJson(Map&lt;String, dynamic&gt; json) {<br>    return UserResponse(<br>      name: json[&#39;name&#39;],<br>      email: json[&#39;email&#39;],<br>    );<br>  }<br>}</pre><p>Lalu map ke domain model:</p><pre>class User {<br>  final String name;<br>  final String email;<br><br>User({required this.name, required this.email});<br>  factory User.fromResponse(UserResponse response) {<br>    return User(<br>      name: response.name ?? &#39;&#39;,<br>      email: response.email ?? &#39;&#39;,<br>    );<br>  }<br>}</pre><p>Dengan ini:</p><ul><li>API berubah → hanya Response yang terdampak</li><li>UI tetap aman</li></ul><h3>Jangan Takut dengan Nullable</h3><p>Banyak developer “takut” melihat String?, int?, dan akhirnya memaksa semuanya non-null.</p><p>Padahal API <strong>tidak pernah bisa dijamin 100% stabil</strong>.</p><p>Lebih baik:</p><ul><li>Terima kenyataan → API bisa null</li><li>Tangani null di mapping layer</li><li>UI hanya menerima data yang sudah aman</li></ul><h3>Gunakan freezed atau json_serializable (Kalau Sudah Siap)</h3><p>Kalau project sudah mulai besar, menulis fromJson manual akan melelahkan.</p><p>Tools seperti:</p><ul><li>json_serializable</li><li>freezed</li></ul><p>akan sangat membantu:</p><ul><li>Mengurangi boilerplate</li><li>Lebih konsisten</li><li>Lebih aman saat refactor</li></ul><p>Tapi ingat: <strong>tool bukan solusi desain yang buruk</strong><br> Struktur tetap harus dipikirkan dengan baik.</p><h3>Jangan Jadikan Satu Model untuk Semua Endpoint</h3><p>Satu endpoint ≠ satu model universal.</p><p>Lebih baik:</p><ul><li>UserListResponse</li><li>UserDetailResponse</li><li>CreateUserResponse</li></ul><p>Daripada:</p><ul><li>UserResponse super besar dengan 30 field opsional</li></ul><p>Model kecil lebih:</p><ul><li>Mudah dipahami</li><li>Mudah dirawat</li><li>Lebih aman</li></ul><h3>Taruh Model di Tempat yang Tepat</h3><p>Struktur folder juga berpengaruh ke kewarasan.</p><p>Contoh sederhana:</p><pre>data/<br> ├─ models/<br> │   ├─ user_response.dart<br> │   └─ post_response.dart<br>domain/<br> ├─ entities/<br> │   ├─ user.dart<br> │   └─ post.dart</pre><p>Dengan ini:</p><ul><li>Layer jelas</li><li>Tidak bingung model mana untuk apa</li><li>Lebih scalable</li></ul><h3>Penutup</h3><p>Merancang model response API di Flutter <strong>bukan soal cepat selesai</strong>, tapi soal:</p><ul><li>Mudah dirawat</li><li>Mudah diubah</li><li>Tidak menyiksa diri sendiri di masa depan</li></ul><p>Sedikit usaha di awal akan menghemat <strong>banyak waktu debugging</strong> di kemudian hari.</p><p>Kalau kamu merasa model API-mu sekarang “berantakan”, tenang kita semua pernah di sana.<br>Yang penting, pelan-pelan perbaiki cara berpikirnya. 💙</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8c5f86e20903" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/merancang-model-response-api-di-flutter-tanpa-kehilangan-kewarasan-8c5f86e20903">Merancang Model Response API di Flutter Tanpa Kehilangan Kewarasan</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bagaimana Saya Menentukan di Mana Logic Seharusnya Diletakkan di Aplikasi Flutter]]></title>
            <link>https://medium.com/udacoding/bagaimana-saya-menentukan-di-mana-logic-seharusnya-diletakkan-di-aplikasi-flutter-9e6e5be99f2c?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/9e6e5be99f2c</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Sat, 27 Dec 2025 23:30:40 GMT</pubDate>
            <atom:updated>2025-12-27T23:30:38.722Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uRYCJRX6wQ1iihKjcOgiCg.png" /></figure><p>Saat pertama kali belajar Flutter, saya sering berpikir bahwa <em>selama aplikasinya jalan</em>, berarti kodenya sudah benar. Tapi semakin lama mengerjakan proyek nyata. Saya sadar bahwa pertanyaan yang jauh lebih penting bukan hanya <strong>“apakah ini bekerja?”</strong>, melainkan <strong>“apakah logic ini diletakkan di tempat yang tepat?”</strong>.</p><p>Menentukan di mana logic seharusnya hidup di aplikasi Flutter ternyata sangat berpengaruh terhadap <strong>keterbacaan kode, kemudahan maintenance, performa, dan scalability</strong>. Artikel ini adalah rangkuman cara berpikir saya sekarang dalam memutuskan hal tersebut.</p><h3>Kesalahan Awal yang Pernah Saya Lakukan</h3><p>Di awal, hampir semua logic saya taruh di dalam Widget.</p><pre>onPressed: () {<br>  setState(() {<br>    isLoading = true;<br>  });<br><br>  final result = await api.getData();<br>  data = result;<br>}</pre><p>Sekilas terlihat sederhana. Tapi ketika:</p><ul><li>logic makin panjang</li><li>widget makin kompleks</li><li>satu fitur dipakai di banyak halaman</li></ul><p>Kode mulai terasa <strong>berantakan dan sulit dirawat</strong>.</p><p>Dari sini saya mulai belajar memisahkan <em>tanggung jawab</em>.</p><h3>Prinsip Utama: Widget Hanya untuk UI</h3><p>Sekarang saya memegang satu prinsip sederhana:</p><blockquote><strong><em>Widget seharusnya fokus pada tampilan dan interaksi UI, bukan logic bisnis.</em></strong></blockquote><p>Artinya:</p><ul><li>Widget <strong>boleh</strong> memanggil logic</li><li>Widget <strong>tidak seharusnya</strong> menyimpan aturan bisnis</li></ul><p>Jika saya merasa sebuah widget:</p><ul><li>terlalu panjang</li><li>sulit dibaca</li><li>banyak if-else dan proses data</li></ul><p>Itu tanda logic-nya salah tempat.</p><h3>Jenis Logic dan Tempat yang Tepat</h3><h3>1. Logic UI → Tetap di Widget</h3><p>Logic ringan yang berkaitan langsung dengan UI masih wajar diletakkan di widget, seperti:</p><ul><li>toggle visibility</li><li>animasi sederhana</li><li>validasi tampilan</li></ul><p>Contoh:</p><pre>bool isPasswordVisible = false;</pre><p>Logic ini <strong>tidak berdampak ke data atau bisnis</strong>, jadi aman.</p><h3>2. State &amp; Event Logic → Bloc / Cubit / Riverpod</h3><p>Kalau logic mulai berkaitan dengan:</p><ul><li>fetch API</li><li>loading state</li><li>error handling</li><li>transform data</li></ul><p>Saya pindahkan ke <strong>state management</strong>.</p><p>Contoh di Cubit:</p><pre>class UserCubit extends Cubit&lt;UserState&gt; {<br>  Future&lt;void&gt; fetchUser() async {<br>    emit(UserLoading());<br>    try {<br>      final user = await repository.getUser();<br>      emit(UserSuccess(user));<br>    } catch (e) {<br>      emit(UserError(e.toString()));<br>    }<br>  }<br>}</pre><p>Widget jadi bersih:</p><pre>context.read&lt;UserCubit&gt;().fetchUser();</pre><h3>3. Business Logic → Use Case / Service</h3><p>Kalau logic sudah berupa <em>aturan bisnis</em>, misalnya:</p><ul><li>perhitungan harga</li><li>validasi khusus</li><li>keputusan berdasarkan role user</li></ul><p>Saya pisahkan ke <strong>service atau use case</strong>.</p><p>Contoh:</p><pre>class CalculateDiscount {<br>  double execute(double price, UserRole role) {<br>    if (role == UserRole.admin) {<br>      return price * 0.8;<br>    }<br>    return price;<br>  }<br>}</pre><p>Dengan ini:</p><ul><li>logic bisa dites tanpa UI</li><li>reusable</li><li>tidak tergantung Flutter</li></ul><h3>4. Data Logic → Repository &amp; Data Source</h3><p>Untuk urusan:</p><ul><li>API</li><li>database</li><li>local storage</li></ul><p>Saya selalu gunakan <strong>Repository Pattern</strong>.</p><pre>abstract class UserRepository {<br>  Future&lt;User&gt; getUser();<br>}</pre><p>Cubit/Bloc <strong>tidak peduli</strong> data datang dari mana API atau local.</p><h3>Cara Saya Memutuskan Logic Harus Pindah</h3><p>Saya biasanya bertanya pada diri sendiri:</p><ul><li>Apakah logic ini akan dipakai ulang?</li><li>Apakah logic ini bisa dites tanpa UI?</li><li>Apakah widget jadi terlalu “pintar”?</li><li>Apakah perubahan logic akan memaksa saya mengubah banyak widget?</li></ul><p>Jika jawabannya <em>ya</em>, maka logic itu <strong>harus keluar dari widget</strong>.</p><h3>Dampak Positif yang Saya Rasakan</h3><p>Setelah mulai disiplin soal ini:</p><ul><li>kode lebih rapi</li><li>debugging lebih mudah</li><li>perubahan fitur tidak merusak UI lain</li><li>onboarding ke project jadi lebih cepat</li></ul><p>Dan yang paling penting: <strong>saya lebih paham struktur aplikasi, bukan sekadar menulis widget</strong>.</p><h3>Penutup</h3><p>Menentukan di mana logic seharusnya hidup di Flutter bukan soal benar atau salah secara mutlak, tapi soal <strong>tanggung jawab dan kejelasan struktur</strong>.</p><p>Semakin cepat kita belajar memisahkan:</p><ul><li>UI</li><li>state</li><li>business logic</li><li>data</li></ul><p>Semakin siap kita menghadapi proyek Flutter di dunia nyata.</p><p>Kalau kamu juga pernah bingung soal ini, percayalah itu tanda kamu sedang naik level 🚀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e6e5be99f2c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/bagaimana-saya-menentukan-di-mana-logic-seharusnya-diletakkan-di-aplikasi-flutter-9e6e5be99f2c">Bagaimana Saya Menentukan di Mana Logic Seharusnya Diletakkan di Aplikasi Flutter</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Pengalaman Pertama Saya Melakukan Refactor Aplikasi Flutter: Apa yang Gagal dan Apa yang Berhasil]]></title>
            <link>https://medium.com/udacoding/pengalaman-pertama-saya-melakukan-refactor-aplikasi-flutter-apa-yang-gagal-dan-apa-yang-berhasil-e69a8fa2d356?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/e69a8fa2d356</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Sat, 27 Dec 2025 23:24:36 GMT</pubDate>
            <atom:updated>2025-12-27T23:24:34.775Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j9jpfaePQ7XKI5u8o-7aGA.png" /></figure><p>Refactor.<br>Satu kata yang terdengar “dewasa” di dunia software development, tapi jujur saja cukup menakutkan saat pertama kali saya melakukannya di aplikasi Flutter yang sudah berjalan.</p><p>Awalnya, aplikasi ini <em>baik-baik saja</em>. Tidak ada error fatal, fitur berjalan, dan user bisa menggunakannya. Tapi di balik layar, kodenya mulai terasa <strong>berantakan</strong>, sulit dibaca, dan makin susah dikembangkan. Di titik itulah saya sadar: refactor tidak bisa dihindari.</p><h3>Kenapa Saya Memutuskan untuk Refactor?</h3><p>Beberapa tanda bahaya yang saya rasakan:</p><ul><li>Satu file widget bisa ratusan baris</li><li>Logic API bercampur dengan UI</li><li>setState() ada di mana-mana</li><li>Takut menyentuh kode karena takut rusak</li></ul><p>Setiap kali ada request fitur baru, waktu pengerjaan terasa makin lama. Bukan karena fiturnya sulit, tapi karena <strong>kodenya tidak bersahabat</strong>.</p><p>Akhirnya, saya memutuskan: <em>lebih baik capek sekarang daripada menderita selamanya.</em></p><h3>Apa yang Salah Saat Refactor Pertama Kali</h3><h3>1. Terlalu Banyak Mengubah Sekaligus</h3><p>Kesalahan terbesar saya adalah ingin merapikan <strong>semuanya sekaligus</strong>:</p><ul><li>Struktur folder</li><li>State management</li><li>Penamaan class</li><li>Pemisahan logic</li></ul><p>Hasilnya?<br>Saya sendiri bingung dengan perubahan yang saya buat.</p><p>Dari sini saya belajar:<br> 👉 <strong>Refactor sebaiknya bertahap, bukan revolusi.</strong></p><h3>2. Tidak Paham Sepenuhnya Alur Aplikasi</h3><p>Saya refactor sebelum benar-benar memahami:</p><ul><li>Alur data dari API ke UI</li><li>Dependency antar file</li><li>State mana yang dipakai di mana</li></ul><p>Akibatnya, beberapa fitur sempat rusak dan saya harus rollback perubahan.</p><p>Pelajaran penting:<br> 👉 <strong>Pahami dulu sebelum merapikan.</strong></p><h3>3. Kurang Percaya Diri dengan Perubahan Sendiri</h3><p>Setelah refactor, saya sering berpikir:</p><blockquote><em>“Ini bener nggak ya?”<br> “Kenapa jadi begini?”</em></blockquote><p>Karena tidak ada testing otomatis, setiap perubahan terasa berisiko. Saya jadi sadar betapa pentingnya:</p><ul><li>Testing</li><li>Atau minimal manual testing yang disiplin</li></ul><h3>Apa yang Justru Berhasil dan Membuat Refactor Layak Dilakukan</h3><h3>1. Memisahkan UI dan Logic</h3><p>Langkah terbaik yang saya lakukan:</p><ul><li>UI fokus ke tampilan</li><li>Logic pindah ke Cubit / Bloc / Provider</li><li>API dipisah ke service</li></ul><p>Hasilnya:</p><ul><li>Widget lebih pendek</li><li>Kode lebih mudah dibaca</li><li>Debugging lebih cepat</li></ul><p>Ini adalah titik di mana Flutter saya mulai terasa “profesional”.</p><h3>2. Membuat Widget Reusable</h3><p>Dulu saya sering copy-paste widget yang mirip.<br>Setelah refactor, saya mulai membuat:</p><ul><li>Custom button</li><li>Custom text field</li><li>Reusable card</li></ul><p>Selain kode lebih rapi, perubahan UI jadi jauh lebih cepat.</p><h3>3. Struktur Folder Lebih Jelas</h3><p>Saya mulai mengikuti pola:</p><ul><li>presentation</li><li>logic / state</li><li>data / service</li><li>model</li></ul><p>Tidak harus sempurna, tapi <strong>konsisten</strong>.<br>Dan itu sudah sangat membantu.</p><h3>4. Aplikasi Jadi Lebih Mudah Dikembangkan</h3><p>Ini bagian paling memuaskan.</p><p>Setelah refactor:</p><ul><li>Menambah fitur lebih cepat</li><li>Bug lebih mudah dilacak</li><li>Saya tidak lagi takut membuka file lama</li></ul><p>Refactor memang tidak terlihat oleh user, tapi <strong>sangat terasa oleh developer</strong>.</p><h3>Refactor Mengubah Cara Saya Melihat Kode</h3><p>Sebelum refactor, kode hanyalah alat agar fitur jalan.<br>Setelah refactor, kode adalah:</p><ul><li>Dokumentasi</li><li>Komunikasi antar developer</li><li>Investasi jangka panjang</li></ul><p>Saya belajar bahwa kode yang rapi bukan soal gaya, tapi soal <strong>tanggung jawab</strong>.</p><h3>Penutup</h3><p>Refactor pertama saya jauh dari sempurna. Banyak salah, banyak ragu, dan cukup melelahkan. Tapi justru dari situlah saya belajar paling banyak tentang Flutter dan software development secara nyata.</p><p>Jika kamu merasa aplikasimu “jalan tapi menyakitkan”, mungkin itu tanda bahwa sudah waktunya refactor pelan-pelan, satu bagian kecil dulu.</p><p>Karena refactor bukan tentang membuat kode terlihat keren, tapi membuat hidup developer lebih waras.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e69a8fa2d356" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/pengalaman-pertama-saya-melakukan-refactor-aplikasi-flutter-apa-yang-gagal-dan-apa-yang-berhasil-e69a8fa2d356">Pengalaman Pertama Saya Melakukan Refactor Aplikasi Flutter: Apa yang Gagal dan Apa yang Berhasil</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bagaimana Gaya Ngoding Flutter Saya Berubah Setelah Masuk Software House]]></title>
            <link>https://medium.com/udacoding/bagaimana-gaya-ngoding-flutter-saya-berubah-setelah-masuk-software-house-9840fb877a1e?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/9840fb877a1e</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Thu, 25 Dec 2025 22:33:46 GMT</pubDate>
            <atom:updated>2025-12-25T22:33:45.269Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6qWVtXb_46cEqpDUWj_nIw.png" /></figure><p>Saat pertama kali belajar Flutter secara otodidak, saya merasa cukup percaya diri. Saya bisa membuat UI, menghubungkan API, dan menjalankan aplikasi tanpa error. Namun, semuanya berubah ketika saya mulai bergabung dengan sebuah <strong>software house</strong> dan mengerjakan <strong>real production project</strong>, bukan sekadar project latihan atau tutorial.</p><p>Di sinilah saya menyadari bahwa <em>bisa jalan</em> dan <em>siap produksi</em> adalah dua hal yang sangat berbeda.</p><h3>1. Dari “Yang Penting Jadi” ke “Harus Bisa Dirawat”</h3><p>Dulu, fokus saya hanyalah:</p><blockquote>UI tampil, fitur jalan, selesai.</blockquote><p>Di software house, cara berpikir ini langsung berubah. Kode tidak hanya harus berjalan hari ini, tapi juga:</p><ul><li>Mudah dipahami developer lain</li><li>Mudah di-maintain</li><li>Aman untuk diubah tanpa merusak fitur lain</li></ul><p>Saya mulai terbiasa:</p><ul><li>Memberi <strong>penamaan variabel dan class yang jelas</strong></li><li>Menghindari logika berlebihan di dalam widget</li><li>Menulis kode seolah-olah orang lain akan membacanya besok</li></ul><p>Karena memang… <em>orang lain benar-benar akan membacanya.</em></p><h3>2. UI Bukan Lagi Segalanya</h3><p>Sebagai pemula Flutter, saya sangat fokus pada UI:</p><ul><li>Padding rapi</li><li>Animasi halus</li><li>Layout responsif</li></ul><p>Tapi di dunia kerja, UI hanyalah <strong>lapisan terluar</strong>. Yang lebih penting justru:</p><ul><li>Struktur project</li><li>Alur data</li><li>State management</li><li>Error handling</li></ul><p>Saya belajar memisahkan:</p><ul><li><strong>UI layer</strong></li><li><strong>Logic / state</strong></li><li><strong>Service / API</strong></li><li><strong>Model</strong></li></ul><p>Hasilnya? Kode terasa lebih bersih dan scalable.</p><h3>3. Mulai Serius dengan State Management</h3><p>Dulu, setState() terasa cukup untuk segalanya.<br> Sekarang? Tidak lagi.</p><p>Di software house, saya mulai memahami pentingnya:</p><ul><li>Predictable state</li><li>Flow data yang jelas</li><li>Kemudahan debugging</li></ul><p>Saya belajar menggunakan:</p><ul><li>Cubit / Bloc</li><li>Riverpod</li><li>Pola loading, error, dan empty state</li></ul><p>State management bukan lagi “ribet”, tapi justru <strong>penyelamat</strong> saat aplikasi mulai kompleks.</p><h3>4. Lebih Sering Membaca Kode daripada Menulis Kode</h3><p>Hal yang tidak saya duga:</p><blockquote><em>Saya lebih banyak membaca kode orang lain daripada menulis kode sendiri.</em></blockquote><p>Dari sini saya belajar:</p><ul><li>Coding style tim</li><li>Best practice yang tidak ada di tutorial</li><li>Cara menulis kode yang <em>masuk akal</em> untuk konteks bisnis</li></ul><p>Saya juga mulai sadar pentingnya:</p><ul><li>Konsistensi</li><li>Clean code</li><li>Mengikuti standar project, bukan ego pribadi</li></ul><h3>5. Error Bukan Musuh, Tapi Bagian dari Proses</h3><p>Dulu, error terasa menakutkan.<br>Sekarang, error adalah teman sehari-hari.</p><p>Saya jadi terbiasa:</p><ul><li>Membaca stack trace dengan tenang</li><li>Mencari akar masalah, bukan hanya menutup error</li><li>Memahami <em>kenapa</em> bug terjadi</li></ul><p>Debugging bukan lagi panik, tapi proses belajar.</p><h3>6. Kode Saya Sekarang Lebih “Tenang”</h3><p>Jika dibandingkan dengan kode saya sebelum masuk software house:</p><ul><li>Lebih sedikit print()</li><li>Lebih sedikit widget besar</li><li>Lebih banyak reusable component</li><li>Lebih banyak pemisahan tanggung jawab</li></ul><p>Aplikasi terasa lebih stabil, dan saya pun lebih percaya diri saat melakukan perubahan.</p><h3>Penutup</h3><p>Masuk software house mengubah cara saya melihat Flutter bukan lagi sekadar alat untuk membuat UI, tapi sebagai <strong>alat membangun produk nyata yang dipakai banyak orang</strong>.</p><p>Perubahan gaya ngoding ini tidak terjadi dalam semalam. Ia tumbuh dari:</p><ul><li>Code review</li><li>Bug production</li><li>Diskusi dengan senior</li><li>Kesalahan yang berulang</li></ul><p>Dan menurut saya, itulah proses belajar yang sesungguhnya.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9840fb877a1e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/bagaimana-gaya-ngoding-flutter-saya-berubah-setelah-masuk-software-house-9840fb877a1e">Bagaimana Gaya Ngoding Flutter Saya Berubah Setelah Masuk Software House</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hal-Hal Tentang Flutter di Dunia Nyata yang Tidak Pernah Diajarkan di Tutorial]]></title>
            <link>https://medium.com/udacoding/hal-hal-tentang-flutter-di-dunia-nyata-yang-tidak-pernah-diajarkan-di-tutorial-5746e0ad6d2f?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/5746e0ad6d2f</guid>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Thu, 25 Dec 2025 22:29:45 GMT</pubDate>
            <atom:updated>2025-12-25T22:29:43.961Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1LsTiTpC9Dh28BZT8BsUwA.png" /></figure><p>Saat pertama kali belajar Flutter, semuanya terasa rapi dan menyenangkan.<br>Tutorial demi tutorial mengajarkan cara membuat UI, mengatur state, memanggil API, dan menjalankan aplikasi tanpa error.</p><p>Namun, semua itu berubah ketika saya mulai mengerjakan <strong>project Flutter yang benar-benar dipakai oleh pengguna</strong>.</p><p>Di sinilah saya sadar:<br><strong>tutorial hanya mengajarkan cara “membuat aplikasi berjalan”, bukan cara “bekerja di dunia nyata”.</strong></p><p>Berikut beberapa hal penting tentang Flutter di project nyata yang tidak pernah saya temui di tutorial.</p><h3>1. Kode yang Berjalan ≠ Kode yang Siap Digunakan di Tim</h3><p>Di tutorial, selama aplikasi bisa dijalankan, maka dianggap selesai.<br> Di project nyata, kode Anda akan dibaca oleh orang lain.</p><p>Hal-hal seperti:</p><ul><li>penamaan file</li><li>struktur folder</li><li>konsistensi style</li><li>pemisahan UI dan logic</li></ul><p>menjadi <strong>jauh lebih penting</strong> daripada sekadar membuat aplikasi tampil.</p><p>Saya pernah membuat satu file Flutter dengan ratusan baris kode, dan itu “berjalan”.<br>Tapi ketika code review, saya sadar: <strong>kode seperti ini sulit dirawat dan berbahaya untuk jangka panjang</strong>.</p><h3>2. UI Tidak Pernah Sepenuhnya Sesuai Figma</h3><p>Di tutorial, desain biasanya sempurna.<br>Di dunia nyata:</p><ul><li>ukuran font berubah</li><li>spacing tidak konsisten</li><li>warna sedikit berbeda</li><li>aset belum lengkap</li></ul><p>Sebagai Flutter developer, kita sering harus:</p><ul><li>menyesuaikan desain tanpa merusak UX</li><li>membuat keputusan kecil tanpa arahan jelas</li><li>berdiskusi dengan designer atau PM</li></ul><p>Saya belajar bahwa <strong>Flutter developer bukan hanya “penerjemah desain”, tapi juga problem solver UI</strong>.</p><h3>3. State Management Itu Bukan Sekadar Pilihan Library</h3><p>Di tutorial, sering muncul pertanyaan:</p><blockquote><em>“Pakai Bloc, Cubit, atau Riverpod?”</em></blockquote><p>Di project nyata, pertanyaannya berubah menjadi:</p><ul><li>Apakah state ini perlu disimpan lama?</li><li>Siapa saja widget yang butuh state ini?</li><li>Bagaimana dampaknya ke performa?</li><li>Apakah mudah dites dan dirawat?</li></ul><p>Saya belajar bahwa <strong>state management adalah tentang arsitektur dan kebiasaan tim</strong>, bukan sekadar trend.</p><h3>4. Error Itu Datang dari Hal-Hal Kecil</h3><p>Bukan error kompleks yang sering menghabiskan waktu, tapi:</p><ul><li>null value yang terlewat</li><li>context digunakan di tempat yang salah</li><li>async yang tidak ditunggu</li><li>rebuild widget yang tidak perlu</li></ul><p>Di tutorial, error jarang dibahas secara mendalam.<br>Di project nyata, <strong>debugging adalah skill utama</strong>.</p><p>Saya belajar membaca stack trace, memahami log, dan tidak panik saat aplikasi crash.</p><h3>5. API Tidak Selalu Ramah</h3><p>Tutorial biasanya menggunakan API yang:</p><ul><li>response-nya konsisten</li><li>datanya selalu lengkap</li><li>jarang error</li></ul><p>Di dunia nyata:</p><ul><li>API bisa lambat</li><li>response bisa berubah</li><li>field bisa null tanpa pemberitahuan</li><li>error message tidak jelas</li></ul><p>Hal ini mengajarkan saya pentingnya:</p><ul><li>handling loading</li><li>handling error</li><li>handling empty state</li></ul><p>UI yang baik bukan hanya saat data ada, tapi juga saat <strong>data tidak ada</strong>.</p><h3>6. Komunikasi Sama Pentingnya dengan Koding</h3><p>Ini yang paling jarang dibahas di tutorial.</p><p>Di project nyata, kita harus:</p><ul><li>menjelaskan kode ke senior</li><li>bertanya dengan cara yang tepat</li><li>menerima kritik dari code review</li><li>mengakui jika belum paham</li></ul><p>Saya belajar bahwa <strong>developer yang baik bukan yang paling jago, tapi yang paling bisa bekerja sama</strong>.</p><h3>Penutup</h3><p>Tutorial Flutter sangat membantu untuk memulai.<br>Namun, <strong>pengalaman mengerjakan project nyata adalah guru terbaik</strong>.</p><p>Dari sana saya belajar bahwa Flutter bukan hanya tentang widget dan state, tapi tentang:</p><ul><li>struktur</li><li>konsistensi</li><li>komunikasi</li><li>dan tanggung jawab terhadap kode</li></ul><p>Jika Anda merasa “tidak jago” saat pertama kali masuk project Flutter, itu normal.<br>Justru di situlah proses belajar yang sesungguhnya dimulai.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5746e0ad6d2f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/hal-hal-tentang-flutter-di-dunia-nyata-yang-tidak-pernah-diajarkan-di-tutorial-5746e0ad6d2f">Hal-Hal Tentang Flutter di Dunia Nyata yang Tidak Pernah Diajarkan di Tutorial</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Stop Copy-Paste Kode! Cara Menggunakan PHP Traits untuk Merapikan Controller Laravel]]></title>
            <link>https://medium.com/udacoding/stop-copy-paste-kode-cara-menggunakan-php-traits-untuk-merapikan-controller-laravel-7df3864637d4?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/7df3864637d4</guid>
            <category><![CDATA[problems]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[solutions]]></category>
            <dc:creator><![CDATA[Imam Pratama]]></dc:creator>
            <pubDate>Wed, 24 Dec 2025 09:12:31 GMT</pubDate>
            <atom:updated>2025-12-24T09:12:30.385Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x52PnQs4i1u38IyrpzVx-w.png" /></figure><p>Dalam ekosistem pengembangan perangkat lunak yang bergerak cepat, kita sering kali dihadapkan pada dilema klasik: kecepatan vs kualitas. Ketika tenggat waktu mendesak dan kita membutuhkan fitur yang sama di dua tempat berbeda, jalan pintas “Copy-Paste” sering menjadi godaan terbesar. Solusi ini cepat, instan, dan secara visual terlihat berfungsi.</p><p>Namun, pengalaman saya dalam menyelesaikan proyek E-Learning berbasis Laravel mengajarkan pelajaran berharga: jalan pintas ini pada akhirnya menciptakan “hutang teknis” (<em>technical debt</em>) yang bunganya harus dibayar mahal di masa depan.</p><h3>Kompleksitas di Balik Layar</h3><p>Kasus ini bermula dari pengembangan fitur <strong>Sidebar Navigasi</strong>. Sekilas, ini terlihat seperti komponen antarmuka biasa. Namun, di balik layar, sidebar ini adalah komponen yang padat logika bisnis (<em>business logic</em>). Ia tidak sekadar menampilkan menu statis, melainkan data personal yang dinamis:</p><ol><li><strong>Analisis Statistik</strong>: Sistem harus menghitung grafik progres belajar siswa dalam 30 hari terakhir.</li><li><strong>Rekomendasi Mentor</strong>: Sistem harus melakukan <em>query</em> ke database untuk mencari guru yang tersedia.</li><li><strong>Jejaring Sosial</strong>: Sistem harus memfilter daftar teman sekelas berdasarkan status langganan (Free vs Pro).</li></ol><p>Awalnya, logika kompleks ini hanya hidup di Dashboard. Namun, seiring berkembangnya kebutuhan produk, fitur ini diminta hadir di setiap lini aplikasi: saat siswa membuka materi, saat mengerjakan kuis, hingga saat melihat riwayat nilai.</p><h3>Jebakan Duplikasi dan Pelanggaran Prinsip DRY</h3><p>Tanpa strategi arsitektur yang matang, saya melakukan kesalahan fatal: saya menduplikasi blok logika tersebut ke dalam empat Controller berbeda (</p><p>Dashboard, Materi, Kuis, Progres).</p><p>Saya melanggar prinsip fundamental rekayasa perangkat lunak: <strong>DRY (Don’t Repeat Yourself)</strong>.</p><p>Dampaknya mulai terasa ketika terjadi perubahan kebutuhan bisnis. Manajemen meminta perubahan kecil pada algoritma perhitungan statistik. Apa yang seharusnya menjadi tugas ringan selama 5 menit berubah menjadi sesi “berburu kode” (<em>code hunting</em>) yang melelahkan. Saya harus:</p><ol><li>Membuka empat file berbeda.</li><li>Mencari baris kode spesifik yang tersebar di ratusan baris lainnya.</li><li>Memastikan setiap perubahan identik.</li><li>Melakukan pengujian ulang di empat halaman berbeda.</li></ol><p>Risiko <em>human error</em> meningkat drastis. Jika satu file terlewat, aplikasi menjadi tidak konsisten. Kode menjadi rapuh (<em>fragile</em>) dan sulit dirawat (<em>unmaintainable</em>).</p><h3>Transformasi Arsitektur: Mengadopsi Traits</h3><p>Saya menyadari bahwa pendekatan prosedural ini tidak lagi relevan. Saya membutuhkan solusi berorientasi objek yang elegan. Dalam PHP dan Laravel, solusi ini adalah <strong>Traits</strong>.</p><p>Berbeda dengan pewarisan kelas (<em>inheritance</em>) yang kaku secara vertikal, Traits menawarkan fleksibilitas penggunaan ulang kode secara horizontal (<em>horizontal code reuse</em>).</p><p>Saya menstandarisasi ulang kode saya dengan langkah-langkah berikut:</p><ol><li><strong>Ekstraksi Logika</strong>: Saya memindahkan seluruh logika perhitungan statistik, query mentor, dan filter teman dari Controller ke dalam satu unit terisolasi bernama HasSidebarData.</li><li><strong>Sentralisasi</strong>: Unit ini menjadi “Satu Sumber Kebenaran” (<em>Single Source of Truth</em>). Jika ada pertanyaan tentang bagaimana data sidebar diproses, jawabannya hanya ada di satu file ini.</li><li><strong>Implementasi Modular</strong>: Di Controller (Materi, Kuis, dll), saya menghapus ratusan baris kode duplikat dan menggantinya dengan satu baris deklarasi penggunaan Trait.</li></ol><h3>Dampak Jangka Panjang</h3><p>Keputusan untuk melakukan <em>refactoring</em> ini bukan sekadar soal kerapian kosmetik, melainkan investasi strategis:</p><ul><li><strong>Efisiensi Codebase</strong>: Saya berhasil memangkas redundansi secara signifikan. File Controller kini kembali ke fungsi utamanya: mengatur alur HTTP, bukan menampung logika bisnis yang berulang.</li><li><strong>Kecepatan Iterasi</strong>: Ketika ada ide fitur baru untuk sidebar, saya bisa mengimplementasikannya dalam hitungan detik untuk seluruh aplikasi, tanpa menyentuh file Controller satu per satu.</li><li><strong>Stabilitas Sistem</strong>: Potensi <em>bug</em> akibat ketidakkonsistenan kode duplikat hilang sepenuhnya.</li></ul><h3>Penutup</h3><p>Pelajaran terpenting dari proses ini adalah bahwa “selesai” bukan berarti sekadar “berjalan”. Kode yang baik adalah kode yang siap untuk tumbuh dan berubah. Meninggalkan kebiasaan <em>copy-paste</em> dan beralih ke desain modular seperti Traits adalah langkah kecil bagi <em>programmer</em>, namun lompatan besar bagi siklus hidup aplikasi yang sehat.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7df3864637d4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/stop-copy-paste-kode-cara-menggunakan-php-traits-untuk-merapikan-controller-laravel-7df3864637d4">Stop Copy-Paste Kode! Cara Menggunakan PHP Traits untuk Merapikan Controller Laravel</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Meningkatkan Performa Aplikasi Flutter: Tips Kecil dari Seorang Intern]]></title>
            <link>https://medium.com/udacoding/meningkatkan-performa-aplikasi-flutter-tips-kecil-dari-seorang-intern-83afed4e6a27?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/83afed4e6a27</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Mon, 22 Dec 2025 23:23:26 GMT</pubDate>
            <atom:updated>2025-12-22T23:23:24.781Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UuZ6MIpkuPLkiIW9m0YBsQ.png" /></figure><p>Saat pertama kali belajar Flutter, fokus saya hanya satu: <em>aplikasi bisa jalan</em>. Selama UI tampil dan fitur bekerja, rasanya sudah cukup. Namun ketika mulai magang di software house dan mengerjakan aplikasi yang dipakai banyak user, saya sadar satu hal penting: <strong>performa itu krusial</strong>.</p><p>Aplikasi yang lambat, sering rebuild, atau terasa “berat” akan langsung terasa oleh pengguna. Menariknya, banyak masalah performa Flutter sebenarnya bisa dicegah dengan kebiasaan-kebiasaan kecil. Di artikel ini, saya ingin berbagi beberapa tips sederhana yang saya pelajari sebagai Flutter intern.</p><h3>1. Jangan Asal setState()</h3><p>Sebagai pemula, setState() sering jadi senjata utama. Setiap ada perubahan data, langsung setState(). Masalahnya, setState() akan me-<em>rebuild</em> seluruh widget di dalam build().</p><p><strong>Pelajaran yang saya dapat:</strong></p><ul><li>Jangan taruh logika berat di dalam build()</li><li>Gunakan setState() hanya saat benar-benar perlu</li><li>Pisahkan widget kecil agar rebuild lebih terkontrol</li></ul><p>Contohnya, jika hanya satu bagian UI yang berubah, jadikan bagian tersebut widget terpisah.</p><h3>2. Biasakan Menggunakan const</h3><p>Awalnya saya menganggap const hanya soal gaya penulisan. Ternyata, const punya dampak ke performa.</p><p>Widget yang menggunakan const:</p><ul><li>Tidak akan di-rebuild ulang</li><li>Lebih hemat memori</li><li>Lebih optimal untuk UI statis</li></ul><p>Contoh sederhana:</p><pre>const Text(&#39;Hello Flutter&#39;);</pre><p>Kelihatannya sepele, tapi di aplikasi besar, kebiasaan ini sangat membantu.</p><h3>3. Hindari Rebuild yang Tidak Perlu</h3><p>Salah satu kesalahan saya dulu adalah menaruh terlalu banyak logika di dalam build().</p><p>Contoh yang perlu dihindari:</p><ul><li>Perhitungan data</li><li>Pemanggilan fungsi berat</li><li>Parsing atau mapping data</li></ul><p><strong>Solusinya:</strong></p><ul><li>Pindahkan logika ke initState()</li><li>Gunakan state management (Cubit, Bloc, Riverpod)</li><li>Gunakan FutureBuilder atau StreamBuilder dengan bijak</li></ul><h3>4. Gunakan ListView.builder, Bukan ListView Biasa</h3><p>Saat menampilkan list data, terutama data yang panjang, ini penting.</p><p>❌ Kurang optimal:</p><pre>ListView(<br>  children: data.map((e) =&gt; ItemWidget(e)).toList(),<br>);</pre><p>✅ Lebih optimal:</p><pre>ListView.builder(<br>  itemCount: data.length,<br>  itemBuilder: (context, index) {<br>    return ItemWidget(data[index]);<br>  },<br>);</pre><p>ListView.builder hanya merender item yang terlihat di layar, sehingga jauh lebih ringan.</p><h3>5. Perhatikan Penggunaan Gambar</h3><p>Gambar sering jadi penyebab aplikasi terasa berat.</p><p>Beberapa pelajaran yang saya dapat:</p><ul><li>Gunakan resolusi gambar sesuai kebutuhan</li><li>Hindari gambar terlalu besar untuk icon kecil</li><li>Jangan lupa placeholder dan errorWidget</li></ul><p>Gambar yang tidak dioptimalkan bisa bikin scrolling patah-patah.</p><h3>6. Jangan Takut Pakai State Management</h3><p>Awalnya saya berpikir state management itu “ribet”. Tapi setelah aplikasi mulai membesar, saya sadar justru <strong>tanpa state management, performa dan struktur jadi berantakan</strong>.</p><p>State management membantu:</p><ul><li>Mengontrol rebuild</li><li>Memisahkan UI dan logic</li><li>Membuat aplikasi lebih scalable</li></ul><p>Sebagai intern, saya mulai dari <strong>Cubit</strong>, lalu perlahan belajar <strong>Bloc</strong> dan <strong>Riverpod</strong>.</p><h3>7. Aktifkan Performance Overlay</h3><p>Flutter menyediakan tools bawaan untuk mengecek performa.</p><p>Gunakan:</p><pre>MaterialApp(<br>  showPerformanceOverlay: true,<br>)</pre><p>Dari sini saya belajar:</p><ul><li>Mana animasi yang terlalu berat</li><li>Kapan UI mulai drop frame</li><li>Bagian mana yang perlu dioptimasi</li></ul><h3>Penutup</h3><p>Sebagai Flutter intern, saya belajar bahwa performa bukan soal trik rumit atau optimasi ekstrem. Justru, <strong>kebiasaan-kebiasaan kecil</strong> yang konsisten sangat berpengaruh:</p><ul><li>Widget lebih rapi</li><li>Rebuild lebih terkontrol</li><li>Aplikasi terasa lebih smooth</li></ul><p>Flutter sudah sangat powerful. Tugas kita sebagai developer adalah menggunakan kekuatannya dengan bijak.</p><p>Kalau kamu juga masih intern atau baru belajar Flutter, tidak apa-apa membuat kesalahan. Yang penting, pelan-pelan belajar memperbaikinya 🚀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=83afed4e6a27" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/meningkatkan-performa-aplikasi-flutter-tips-kecil-dari-seorang-intern-83afed4e6a27">Meningkatkan Performa Aplikasi Flutter: Tips Kecil dari Seorang Intern</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cara Saya Debug Error Flutter Tanpa Panik]]></title>
            <link>https://medium.com/udacoding/cara-saya-debug-error-flutter-tanpa-panik-f4aaf2405ee4?source=rss----49122c796dd1---4</link>
            <guid isPermaLink="false">https://medium.com/p/f4aaf2405ee4</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[AqilFarrosAlghonim]]></dc:creator>
            <pubDate>Mon, 22 Dec 2025 23:22:50 GMT</pubDate>
            <atom:updated>2025-12-22T23:22:49.065Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7Zp6nwCiBVDjoV8pTsnZDw.png" /></figure><p>Debugging adalah bagian yang tidak terpisahkan dari kehidupan seorang Flutter developer. Tapi jujur saja di awal belajar Flutter, setiap kali aplikasi error, rasanya seperti dunia runtuh. Layar merah, log panjang, dan pesan error yang terlihat menakutkan sering kali bikin panik sebelum sempat berpikir jernih.</p><p>Seiring waktu (dan cukup banyak error), saya mulai menyadari satu hal penting: <strong>panik tidak pernah menyelesaikan error</strong>. Yang ada justru memperlambat proses debugging. Artikel ini saya tulis untuk berbagi bagaimana cara saya menghadapi error Flutter dengan lebih tenang dan sistematis.</p><h3>1. Tarik Napas, Jangan Langsung Scroll Log</h3><p>Ketika error muncul, refleks pertama saya dulu adalah langsung scroll log ke atas dan ke bawah tanpa arah. Hasilnya? Tambah bingung.</p><p>Sekarang, hal pertama yang saya lakukan adalah <strong>berhenti sejenak</strong> dan membaca error dari baris paling atas. Biasanya Flutter sudah memberikan hint yang cukup jelas tentang:</p><ul><li>Jenis error</li><li>Lokasi file</li><li>Baris kode yang bermasalah</li></ul><p>Tenang dulu, error itu cuma pesan bukan hukuman.</p><h3>2. Fokus ke Error Pertama, Bukan Efek Domino</h3><p>Satu error Flutter sering memicu banyak error lanjutan. Kesalahan umum adalah mencoba memperbaiki semuanya sekaligus.</p><p>Saya belajar untuk:</p><ul><li>Fokus ke <strong>error pertama</strong> yang muncul</li><li>Abaikan error turunan di bawahnya</li><li>Perbaiki satu masalah inti terlebih dahulu</li></ul><p>Sering kali, setelah satu error utama diperbaiki, error lainnya ikut hilang.</p><h3>3. Baca Pesan Error Seperti Membaca Instruksi</h3><p>Flutter termasuk framework yang “ramah” dalam urusan error message. Tapi hanya kalau kita benar-benar membacanya.</p><p>Contoh:</p><ul><li>setState() called after dispose()</li><li>RenderFlex overflowed by XX pixels</li><li>Null check operator used on a null value</li></ul><p>Pesan-pesan ini sebenarnya sudah menjelaskan:</p><ul><li><strong>Apa yang salah</strong></li><li><strong>Kapan terjadinya</strong></li><li><strong>Arah solusi yang mungkin</strong></li></ul><p>Saya mulai membiasakan diri membaca error <strong>kata per kata</strong>, bukan sekilas.</p><h3>4. Cek Perubahan Terakhir yang Saya Lakukan</h3><p>Kalau aplikasi error tiba-tiba, hampir selalu penyebabnya adalah:</p><blockquote><em>kode terakhir yang saya ubah</em></blockquote><p>Maka langkah standar saya:</p><ul><li>Ingat file apa yang terakhir diedit</li><li>Fokus debugging di area itu</li><li>Jika perlu, comment sementara kode tersebut</li></ul><p>Ini jauh lebih efektif daripada mencari error ke seluruh project.</p><h3>5. Gunakan print, log, dan Debugger Tanpa Rasa Bersalah</h3><p>Dulu saya merasa print() itu “tidak profesional”. Sekarang? Itu salah satu senjata utama saya.</p><p>Beberapa kebiasaan yang membantu:</p><ul><li>print() untuk cek alur data</li><li>log() untuk data yang lebih kompleks</li><li>Breakpoint di IDE untuk melihat state secara real-time</li></ul><p>Debugging bukan soal gaya, tapi soal <strong>menemukan masalah secepat mungkin</strong>.</p><h3>6. Pahami Error yang Sering Muncul</h3><p>Semakin lama menggunakan Flutter, saya mulai mengenali pola:</p><ul><li>Error async (Future, await)</li><li>Error lifecycle widget</li><li>Error null safety</li><li>Error layout (overflow, constraint)</li></ul><p>Daripada takut, saya mulai mencatat:</p><blockquote><em>“Oh, error ini pernah muncul. Dulu solusinya begini.”</em></blockquote><p>Pengalaman adalah debugger terbaik.</p><h3>7. Google &amp; Stack Overflow Itu Bagian dari Proses</h3><p>Debugging <strong>bukan ujian hafalan</strong>. Tidak ada salahnya mencari error di Google, GitHub Issues, atau Stack Overflow.</p><p>Yang penting:</p><ul><li>Pahami solusinya</li><li>Jangan sekadar copy-paste</li><li>Tahu kenapa error itu bisa terjadi</li></ul><p>Dengan begitu, error yang sama tidak akan membuat panik di kemudian hari.</p><h3>8. Terima Fakta: Error Itu Normal</h3><p>Ini mungkin poin paling penting.</p><p>Error bukan tanda kamu:</p><ul><li>Tidak pintar</li><li>Tidak cocok jadi developer</li><li>Gagal belajar Flutter</li></ul><p>Error justru tanda kamu <strong>sedang benar-benar ngoding</strong>.</p><p>Semakin sering error, semakin cepat kamu belajar asal kamu menghadapinya dengan kepala dingin.</p><h3>Penutup</h3><p>Sekarang, setiap kali Flutter menampilkan layar merah, saya tidak lagi panik. Saya melihatnya sebagai:</p><blockquote><em>“Oke, ada yang perlu dibereskan.”</em></blockquote><p>Debugging bukan musuh, tapi bagian dari perjalanan menjadi Flutter developer yang lebih matang.</p><p>Kalau kamu sedang sering error dan merasa frustrasi — tenang. Kamu sedang berada di jalur yang benar.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f4aaf2405ee4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/udacoding/cara-saya-debug-error-flutter-tanpa-panik-f4aaf2405ee4">Cara Saya Debug Error Flutter Tanpa Panik</a> was originally published in <a href="https://medium.com/udacoding">Udacoding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>