Anuchit Chalothorn

Human Knowledge Belongs to The World

ลดโค้ดซ้ำใน Flutter ด้วย Widgets


11 Mar 2025, 13:55

การเขียนแอปพลิเคชันใน Flutter สามารถทำให้เกิดการเขียนโค้ดซ้ำๆ ในบางสถานการณ์ได้ เช่น การสร้าง UI ที่มีลักษณะคล้ายกันหลายครั้ง หรือการทำงานกับข้อมูลที่มีรูปแบบเดียวกันในหลายๆ ส่วนของแอป หากเรามีวิธีการที่ดีในการจัดการกับการซ้ำซ้อนนี้ จะช่วยให้โค้ดดูสะอาดและสามารถบำรุงรักษาได้ง่ายขึ้น ในบทความนี้เราจะมาดู การสร้าง Widget ช่วยลดโค้ดซ้ำๆ และทำให้โค้ดของเราเป็นระเบียบมากขึ้น

1. Custom Widget

การสร้าง Custom Widget เป็นวิธีที่ดีที่สุดในการลดโค้ดซ้ำใน Flutter หากคุณพบว่า UI ของแอปพลิเคชันมีลักษณะเหมือนกันในหลายๆ ส่วน คุณสามารถสร้าง Custom Widget ที่สามารถนำไปใช้ในหลายๆ ที่ได้ ตัวอย่างเช่น

class CustomButton extends StatelessWidget {
            final String label;
            final VoidCallback onPressed;
          
            CustomButton({required this.label, required this.onPressed});
          
            @override
            Widget build(BuildContext context) {
              return ElevatedButton(
                onPressed: onPressed,
                child: Text(label),
              );
            }
          }
          

ในตัวอย่างนี้ เราสร้าง CustomButton ที่สามารถใช้ซ้ำได้ในทุกๆ ที่ที่ต้องการปุ่มที่มีลักษณะเหมือนกัน เพียงแค่เปลี่ยน label และ onPressed ก็สามารถใช้งานได้ทันที

2. Higher-Order Widgets

Higher-Order Widgets (HOCs) เป็นวิธีที่ช่วยในการสร้าง Widget ที่สามารถรับ Widget อื่นๆ เป็นพารามิเตอร์และคืนค่าผลลัพธ์ที่มีการปรับเปลี่ยนจาก Widget นั้นๆ ตัวอย่างเช่น

Widget withPadding(Widget child) {
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: child,
            );
          }
          

ในตัวอย่างนี้ เราสร้างฟังก์ชันที่ใช้ห่อหุ้ม Widget อื่นๆ ด้วย Padding ซึ่งสามารถใช้ซ้ำได้ทุกที่ที่ต้องการใช้ Padding รอบๆ Widget

3. Reusable Layouts

บางครั้งเรามีเลย์เอาท์ที่เหมือนกันในหลายๆ หน้าของแอป เช่น การแสดงรายการที่มีหัวข้อและเนื้อหา ในกรณีนี้ เราสามารถสร้าง Widget ที่ใช้ซ้ำได้อย่างง่าย เช่น

class ListItem extends StatelessWidget {
            final String title;
            final String subtitle;
          
            ListItem({required this.title, required this.subtitle});
          
            @override
            Widget build(BuildContext context) {
              return ListTile(
                title: Text(title),
                subtitle: Text(subtitle),
              );
            }
          }
          

ในกรณีนี้ ListItem เป็น Widget ที่สามารถใช้ซ้ำในหลายๆ หน้าของแอปพลิเคชันเพื่อแสดงข้อมูลที่มีโครงสร้างเดียวกัน

4. State Management Widgets

การจัดการสถานะ (State Management) เป็นอีกหนึ่งวิธีที่สามารถลดโค้ดซ้ำใน Flutter ได้ โดยการสร้าง Widget ที่สามารถแชร์สถานะได้ในหลายๆ จุดของแอป ตัวอย่างเช่น การใช้ Provider หรือ Riverpod เพื่อจัดการสถานะที่ใช้ซ้ำได้ทั่วทั้งแอป

ตัวอย่างเช่นการสร้าง ChangeNotifier เพื่อแชร์สถานะของแอป

class Counter extends ChangeNotifier {
            int _count = 0;
          
            int get count => _count;
          
            void increment() {
              _count++;
              notifyListeners();
            }
          }
          

จากนั้นใน Widget ที่ต้องการใช้งาน

class CounterWidget extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              final counter = Provider.of<Counter>(context);
          
              return Column(
                children: [
                  Text('Count: ${counter.count}'),
                  ElevatedButton(
                    onPressed: counter.increment,
                    child: Text('Increment'),
                  ),
                ],
              );
            }
          }
          

วิธีนี้คุณสามารถใช้สถานะเดียวกันในหลายๆ จุดของแอป โดยไม่ต้องเขียนโค้ดใหม่ซ้ำๆ

ListView.builder และ GridView.builder

ในกรณีที่คุณต้องการแสดงรายการหรือข้อมูลจำนวนมาก วิธีที่ดีที่สุดในการลดโค้ดซ้ำคือการใช้ ListView.builder หรือ GridView.builder ซึ่งจะช่วยให้คุณสร้างรายการที่มีความยืดหยุ่นสูงและใช้งานซ้ำได้ โดยไม่ต้องสร้าง ListTile หรือ GridTile ใหม่ทุกครั้งที่มีการแสดงผล

ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(items[index]),
              );
            },
          )
          

สรุป

การลดโค้ดซ้ำใน Flutter เป็นสิ่งที่สำคัญมากในการทำให้โค้ดของคุณสะอาดและบำรุงรักษาง่ายขึ้น โดยการใช้ Custom Widget, Higher-Order Widgets, Reusable Layouts, State Management Widgets, และ ListView.builder หรือ GridView.builder คุณสามารถลดการซ้ำซ้อนของโค้ดได้ และทำให้แอปของคุณยืดหยุ่นและมีประสิทธิภาพมากขึ้น

หวังว่าบทความนี้จะช่วยให้คุณเห็นวิธีการที่สามารถลดโค้ดซ้ำใน Flutter และทำให้การพัฒนาแอปพลิเคชันของคุณง่ายขึ้น!

Refactoring Code ให้สะอาดใน Flutter


09 Mar 2025, 11:58

Refactoring เป็นกระบวนการปรับปรุงโค้ดให้สะอาดขึ้นโดยไม่เปลี่ยนพฤติกรรมของโปรแกรม ซึ่งช่วยให้โค้ดอ่านง่าย ดูแลรักษาง่าย และลดความซับซ้อน ในบทความนี้เราจะมาดูกันว่าเราสามารถรีแฟกเตอร์โค้ดใน Flutter ได้อย่างไร

1. แยก Widget ออกเป็น Component

โค้ด UI ที่มีขนาดใหญ่และอยู่ในไฟล์เดียวกันอาจทำให้ดูยุ่งยาก เราสามารถแยก UI ออกเป็น StatelessWidget หรือ StatefulWidget ตามความเหมาะสม

ตัวอย่างก่อน Refactor

class MyHomePage extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return Scaffold(
                appBar: AppBar(title: Text('Home')),
                body: Column(
                  children: [
                    Container(
                      padding: EdgeInsets.all(16),
                      child: Text('Welcome to Flutter!'),
                    ),
                    ElevatedButton(
                      onPressed: () {},
                      child: Text('Click Me'),
                    ),
                  ],
                ),
              );
            }
          }
          

หลังจาก Refactor

class MyHomePage extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return Scaffold(
                appBar: AppBar(title: Text('Home')),
                body: Column(
                  children: [
                    WelcomeText(),
                    CustomButton(),
                  ],
                ),
              );
            }
          }
          
          class WelcomeText extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return Container(
                padding: EdgeInsets.all(16),
                child: Text('Welcome to Flutter!'),
              );
            }
          }
          
          class CustomButton extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return ElevatedButton(
                onPressed: () {},
                child: Text('Click Me'),
              );
            }
          }
          

2. ใช้ Provider หรือ Riverpod จัดการ State

หากแอปของคุณมี state ที่ซับซ้อน ลองใช้ Provider หรือ Riverpod แทนการใช้ setState() กับ StatefulWidget เยอะเกินไป

ตัวอย่างการใช้ Riverpod

final counterProvider = StateProvider<int>((ref) => 0);
          
          class CounterScreen extends ConsumerWidget {
            @override
            Widget build(BuildContext context, WidgetRef ref) {
              final count = ref.watch(counterProvider);
          
              return Scaffold(
                appBar: AppBar(title: Text('Counter')),
                body: Center(
                  child: Text('Count: $count'),
                ),
                floatingActionButton: FloatingActionButton(
                  onPressed: () => ref.read(counterProvider.notifier).state++,
                  child: Icon(Icons.add),
                ),
              );
            }
          }
          

3. ใช้ Extensions ช่วยลดโค้ดซ้ำซ้อน

Extensions ช่วยให้เราสามารถขยายความสามารถของ class ที่มีอยู่โดยไม่ต้องสร้างคลาสใหม่

ตัวอย่างการใช้ Extension Method กับ BuildContext

extension ContextExtensions on BuildContext {
            void showSnackBar(String message) {
              ScaffoldMessenger.of(this).showSnackBar(
                SnackBar(content: Text(message)),
              );
            }
          }
          

การใช้งาน

context.showSnackBar('Hello Flutter!');
          

4. จัดระเบียบโครงสร้างโค้ดให้ดี

  • แยกไฟล์ออกเป็นโฟลเดอร์ตามฟีเจอร์ เช่น features/home/, features/auth/
  • ใช้ naming conventions ที่สม่ำเสมอ เช่น home_screen.dart, login_controller.dart
  • ใช้ constants.dart สำหรับค่าคงที่ที่ใช้ร่วมกัน

สรุป

การทำ Refactoring ช่วยให้โค้ดของเราดูแลรักษาง่ายขึ้น และทำให้ทีมสามารถทำงานร่วมกันได้อย่างมีประสิทธิภาพ ลองนำเทคนิคเหล่านี้ไปใช้ในโปรเจคของคุณ แล้วโค้ด Flutter ของคุณจะสะอาดและเป็นระเบียบมากขึ้น!

เทคนิค Deploy แอปให้เร็วขึ้น


09 Mar 2025, 11:58

การ Deploy แอปพลิเคชันเป็นขั้นตอนสำคัญที่ส่งผลโดยตรงต่อประสบการณ์ของผู้ใช้และความสามารถของทีมพัฒนา ยิ่ง Deploy ได้เร็วขึ้น ทีมก็สามารถส่งมอบฟีเจอร์ใหม่และแก้ไขข้อผิดพลาดได้อย่างมีประสิทธิภาพ บทความนี้จะนำเสนอเทคนิคที่จะช่วยให้การ Deploy แอปเร็วขึ้น ทั้งสำหรับแอปมือถือ (Flutter) และเว็บแอปพลิเคชัน

1. ใช้ CI/CD Pipeline

การตั้งค่า Continuous Integration (CI) และ Continuous Deployment (CD) ช่วยให้การ Deploy เป็นไปโดยอัตโนมัติ ลดข้อผิดพลาดจากมนุษย์ และเพิ่มความรวดเร็ว ตัวอย่างเครื่องมือที่นิยมใช้ ได้แก่

  • GitHub Actions
  • Bitrise (สำหรับแอปมือถือ)
  • Codemagic (สำหรับ Flutter)
  • Jenkins หรือ GitLab CI/CD

การใช้ CI/CD ทำให้เราสามารถ Build, Test และ Deploy ได้อัตโนมัติหลังจาก Push โค้ดไปยัง Repository

2. เปิดใช้งาน Fastlane สำหรับแอปมือถือ

Fastlane เป็นเครื่องมือช่วยให้การ Deploy แอป iOS และ Android รวดเร็วขึ้น โดยสามารถทำงานอัตโนมัติ เช่น

  • Build และ Sign แอป
  • อัปโหลดไปยัง App Store หรือ Google Play
  • จัดการ Certificate และ Provisioning Profile

ตัวอย่างการใช้ Fastlane สำหรับ Flutter

fastlane add_plugin flutter_version
          fastlane ios beta # Deploy iOS Beta
          fastlane android beta # Deploy Android Beta
          

3. ใช้ Incremental Builds เพื่อลดเวลา Build

Incremental Builds ลดเวลาการ Compile โค้ดใหม่ทั้งหมด ตัวอย่างเช่น

  • Flutter: ใช้คำสั่ง flutter build apk --split-per-abi เพื่อลดขนาดไฟล์และลดเวลาการ Build
  • Web: ใช้ Webpack หรือ Vite ในโหมด Production เพื่อลดเวลา Bundle และ Optimize โค้ด

4. เปิดใช้งาน Code Push สำหรับอัปเดตแบบ OTA

หากแอปเป็น Flutter หรือ React Native สามารถใช้ Code Push (ผ่าน Microsoft App Center) เพื่ออัปเดตโค้ดแบบ Over-the-Air (OTA) ได้โดยไม่ต้องรอการอนุมัติจาก App Store หรือ Play Store

ตัวอย่างการใช้ Code Push:

appcenter codepush release-react -a YOUR_APP_NAME -d Production
          

5. ลดขนาดแอปเพื่อลดเวลาอัปโหลด

ขนาดของไฟล์ Build มีผลต่อเวลาในการ Deploy และติดตั้งแอป วิธีลดขนาดแอปมีดังนี้

  • ใช้ ProGuard และ R8 เพื่อลดขนาดโค้ด (สำหรับ Android)
  • เปิดใช้งาน App Thinning บน iOS
  • ใช้คำสั่ง flutter build appbundle --obfuscate --split-debug-info=./debug_info เพื่อลดขนาดโค้ดและเพิ่มความปลอดภัย

6. Deploy แบบ Zero Downtime

หากเป็นเว็บแอปพลิเคชัน สามารถใช้ Blue-Green Deployment หรือ Canary Deployment เพื่อลด Downtime ขณะ Deploy

  • Blue-Green Deployment: มี 2 เวอร์ชันของแอป (Blue และ Green) และเปลี่ยนเส้นทางไปยังเวอร์ชันใหม่เมื่อพร้อม
  • Canary Deployment: ปล่อยอัปเดตให้ผู้ใช้บางกลุ่มก่อน แล้วค่อย ๆ ขยายไปยังผู้ใช้ทั้งหมด

ตัวอย่าง Canary Deployment บน Kubernetes

apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: my-app
          spec:
            replicas: 3
            selector:
              matchLabels:
                app: my-app
            template:
              metadata:
                labels:
                  app: my-app
              spec:
                containers:
                - name: my-app
                  image: my-app:v2.0.0
          

สรุป

การ Deploy แอปให้เร็วขึ้นสามารถทำได้โดยใช้เครื่องมือและแนวทางที่เหมาะสม เช่น

  • การใช้ CI/CD Automation
  • Fastlane สำหรับการ Deploy แอปมือถือ
  • Incremental Builds เพื่อลดเวลา Compile
  • Code Push สำหรับการอัปเดตแบบ OTA
  • การลดขนาดแอปเพื่อลดเวลาอัปโหลด
  • Deploy แบบ Zero Downtime เพื่อลดผลกระทบต่อผู้ใช้

หากนำเทคนิคเหล่านี้ไปใช้ จะช่วยให้ทีมพัฒนาสามารถส่งมอบแอปได้เร็วขึ้น ลดข้อผิดพลาด และเพิ่มประสิทธิภาพการทำงาน

Reskill / Upskill สำหรับนักพัฒนา ที่จะย้ายมาเขียน Flutter


04 Mar 2025, 21:39

Flutter เป็นเฟรมเวิร์กสำหรับการพัฒนาแอปพลิเคชันที่ Google พัฒนาและดูแล โดยสามารถใช้เขียนแอปได้ทั้ง iOS, Android, Web และ Desktop ด้วยโค้ดชุดเดียวกัน จุดเด่นของ Flutter คือความเร็วในการพัฒนา UI ที่ยืดหยุ่น และประสิทธิภาพสูงเนื่องจากใช้เอนจินเรนเดอร์ของตัวเอง

หากคุณเป็นนักพัฒนาที่ต้องการปรับตัว (Reskill) หรือพัฒนาทักษะเพิ่มเติม (Upskill) ในการสร้างแอปพลิเคชัน การเรียนรู้ Flutter อาจเป็นทางเลือกที่เหมาะสมสำหรับคุณ

ทักษะพื้นฐานที่จำเป็นสำหรับ Flutter

1. การเขียนโปรแกรมด้วย Dart

Flutter ใช้ภาษา Dart ซึ่งเป็นภาษาที่ Google พัฒนาขึ้นเพื่อการพัฒนาแอปแบบรวดเร็ว มีลักษณะใกล้เคียงกับภาษา C, Java และ JavaScript หากคุณมีพื้นฐานจากภาษาเหล่านี้อยู่แล้ว การเรียนรู้ Dart จะไม่ใช่เรื่องยาก

สิ่งที่ควรศึกษา

  • พื้นฐานของภาษา Dart (Variables, Functions, Classes, Async/Await)
  • Null Safety
  • การจัดการ List และ Map
  • Future และ Stream

2. พื้นฐาน UI และการออกแบบ Widget

Flutter ใช้แนวคิดของ Widget เป็นหลัก ทุกองค์ประกอบของ UI คือ Widget เช่น ปุ่ม ข้อความ หรือแม้แต่โครงสร้างของหน้าแอป ดังนั้นคุณต้องเข้าใจการทำงานของ

  • StatelessWidget vs StatefulWidget
  • Layout และ Widget พื้นฐาน เช่น Column, Row, Stack, ListView
  • การใช้ Theme และ Custom Widget

3. State Management

การจัดการสถานะ (State Management) เป็นเรื่องสำคัญมากสำหรับแอปพลิเคชันขนาดกลางถึงใหญ่ ใน Flutter มีหลายวิธีในการจัดการสถานะ เช่น

  • setState (เหมาะสำหรับแอปขนาดเล็ก)
  • Provider (ได้รับความนิยมมาก ใช้งานง่าย)
  • Riverpod (เป็นทางเลือกที่ยืดหยุ่น)
  • BLoC (เหมาะสำหรับแอปที่มีโครงสร้างซับซ้อน)

นักพัฒนาสายต่าง ๆ ควร Upskill อย่างไร?

  • นักพัฒนา Native Android (Java/Kotlin)

    • เรียนรู้ภาษา Dart ซึ่งโครงสร้างคล้าย Kotlin มาก
    • ทำความเข้าใจหลักการของ Widget-based UI แทน XML-based UI ของ Android
    • ศึกษาการทำงานของ Flutter กับ Platform Channel เพื่อเชื่อมต่อกับโค้ด Java/Kotlin
  • นักพัฒนา iOS (Swift/Objective-C)

    • เรียนรู้ Dart และโครงสร้างของ Flutter ซึ่งแตกต่างจาก UIKit
    • ศึกษาการจัดการ UI แบบ declarative ซึ่งแตกต่างจาก UIKit ที่เป็น imperative
    • เรียนรู้การเชื่อมต่อกับ iOS Native ผ่าน MethodChannel
  • นักพัฒนา Web (JavaScript, React, Angular, Vue)

    • ปรับแนวคิดจาก HTML/CSS มาเป็น Widget-based UI
    • ศึกษา Flutter Web และการทำงานของ CanvasKit
    • ทำความเข้าใจการจัดการ State ที่คล้าย Redux (เช่น Provider หรือ Riverpod)
  • นักพัฒนา Backend (Node.js, Go, Python, Java)

    • ศึกษา Dart และวิธีการเรียก API ด้วย http หรือ Dio
    • ทำความเข้าใจ JSON Serialization และการจัดการ Model
    • ศึกษาการทำงานร่วมกับ Firebase หรือ Backend อื่น ๆ

เครื่องมือที่แนะนำ

  • Flutter SDK – ใช้สำหรับพัฒนาและรันแอป
  • Dart DevTools – เครื่องมือ Debugging
  • Android Studio / Visual Studio Code – IDE ยอดนิยมสำหรับการเขียน Flutter
  • Flutter Inspector – ใช้สำหรับตรวจสอบ UI และ Layout
  • Firebase – ใช้สำหรับ Authentication, Database, Cloud Messaging

เส้นทางการเรียนรู้ Flutter สำหรับมือใหม่

ระยะที่ 1: ทำความรู้จักกับ Dart และพื้นฐาน Flutter

  • ศึกษาภาษา Dart และ Syntax พื้นฐาน
  • เข้าใจแนวคิดของ Widget และการจัด Layout
  • ลองสร้างแอปง่าย ๆ เช่น To-Do List หรือ Calculator

ระยะที่ 2: เรียนรู้ State Management และ API

  • ศึกษาการจัดการสถานะ เช่น Provider หรือ Riverpod
  • ฝึกใช้ HTTP requests และจัดการ JSON
  • เรียนรู้ Navigation และการทำงานของ Multi-Screen

ระยะที่ 3: พัฒนาแอปจริงและ Deploy

  • เชื่อมต่อแอปกับ Firebase หรือ API อื่น ๆ
  • เพิ่มฟีเจอร์ Authentication และ Database
  • ทดสอบและปรับแต่ง UI/UX
  • Deploy แอปขึ้น Play Store / App Store

สรุป

Flutter เป็นทางเลือกที่ยอดเยี่ยมสำหรับนักพัฒนาที่ต้องการสร้างแอปพลิเคชันที่สามารถรันได้บนหลายแพลตฟอร์ม โดยใช้โค้ดชุดเดียวกัน หากคุณมีพื้นฐานจากสายพัฒนาใดมาก่อน สามารถปรับตัวได้ไม่ยาก โดยเริ่มต้นจากการเรียนรู้ Dart, Widget และ State Management แล้วค่อย ๆ ลงมือพัฒนาแอปจริง

หากคุณต้องการเปลี่ยนสายหรือเพิ่มทักษะให้กับตัวเอง Flutter เป็นทักษะที่ควรเรียนรู้ และมีความต้องการสูงในตลาดงานปัจจุบัน

Handle Error ใน Flutter อย่างมือโปร


04 Mar 2025, 21:39

การจัดการข้อผิดพลาด (Error Handling) เป็นสิ่งสำคัญสำหรับการพัฒนาแอปพลิเคชันที่เสถียรและใช้งานได้ดี ใน Flutter เราสามารถจัดการข้อผิดพลาดได้หลายรูปแบบ ไม่ว่าจะเป็นการจับข้อผิดพลาดที่เกิดจากโค้ด การจัดการ Exception หรือการแสดงผลข้อผิดพลาดให้กับผู้ใช้

ในบทความนี้ เราจะมาดูกลยุทธ์และแนวทางปฏิบัติที่ดีที่สุดในการจัดการข้อผิดพลาดใน Flutter อย่างมืออาชีพ

ประเภทของข้อผิดพลาดใน Flutter

  • Compile-time Errors เป็นข้อผิดพลาดที่ตรวจพบได้ในระหว่างการคอมไพล์ เช่น การใช้ตัวแปรที่ไม่ได้ประกาศ หรือเรียกใช้เมธอดที่ไม่มีอยู่

  • Runtime Errors เกิดขึ้นขณะรันแอป เช่น NullPointerException หรือ IndexOutOfBoundsException

  • Logical Errors เกิดจากการทำงานที่ไม่เป็นไปตามที่คาดหวัง เช่น คำนวณผิด หรือแสดงข้อมูลผิดพลาด

การจัดการข้อผิดพลาดใน Flutter

ใช้ Try-Catch จัดการข้อผิดพลาด

Flutter รองรับการใช้ try-catch เพื่อจับและจัดการข้อผิดพลาดที่เกิดขึ้นใน runtime

void fetchData() {
            try {
              throw Exception('เกิดข้อผิดพลาด');
            } catch (e) {
              print('Error: $e');
            }
          }
          

หากเป็นข้อผิดพลาดที่เกี่ยวข้องกับ async และ await ควรใช้ try-catch คู่กับ Future ดังนี้:

Future<void> fetchDataAsync() async {
            try {
              await Future.delayed(Duration(seconds: 2));
              throw Exception('เกิดข้อผิดพลาดจาก async');
            } catch (e) {
              print('Error: $e');
            }
          }
          

ใช้ FlutterError.onError จัดการข้อผิดพลาด

สำหรับการจัดการข้อผิดพลาดที่เกิดขึ้นใน Flutter เราสามารถใช้ FlutterError.onError เพื่อจับข้อผิดพลาดระดับ global:

void main() {
            FlutterError.onError = (FlutterErrorDetails details) {
              print('Flutter Error: ${details.exception}');
            };
            runApp(MyApp());
          }
          

ใช้ Error Widget แสดงข้อผิดพลาดให้ผู้ใช้

หาก Widget เกิดข้อผิดพลาด สามารถใช้ ErrorWidget.builder เพื่อกำหนดการแสดงผลข้อผิดพลาด:

void main() {
            ErrorWidget.builder = (FlutterErrorDetails details) {
              return Center(child: Text('มีบางอย่างผิดพลาด'));
            };
            runApp(MyApp());
          }
          

ใช้ Catcher จัดการข้อผิดพลาด

สามารถใช้แพ็กเกจ catcher เพื่อบันทึกและรายงานข้อผิดพลาดได้ง่ายขึ้น

dependencies:
            catcher: ^0.7.0
          

ตัวอย่างการใช้งาน

void main() {
            CatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [ConsoleHandler()]);
            Catcher(MyApp(), debugConfig: debugOptions);
          }
          

สรุป

  • ใช้ try-catch จับข้อผิดพลาดในโค้ด
  • ใช้ FlutterError.onError จับข้อผิดพลาดที่เกิดขึ้นในแอป
  • ใช้ ErrorWidget.builder เพื่อแสดงข้อความแจ้งข้อผิดพลาดให้ผู้ใช้
  • ใช้แพ็กเกจ catcher เพื่อบันทึกและรายงานข้อผิดพลาด

การจัดการข้อผิดพลาดที่ดีช่วยให้แอปมีเสถียรภาพมากขึ้น และมอบประสบการณ์การใช้งานที่ดีแก่ผู้ใช้ หวังว่าบทความนี้จะช่วยให้คุณสามารถ Handle Error ใน Flutter ได้อย่างมือโปร!

Flutter Performance Boost - ปรับแต่งแอปให้เร็ว แรง ลื่น


03 Mar 2025, 21:35

เมื่อแอป Flutter เริ่มช้า หน่วง หรือกระตุก ปัญหาส่วนใหญ่มาจากการบริหารจัดการ Widget และ State ที่ไม่มีประสิทธิภาพ มาดู 5 เทคนิคที่ช่วยให้แอปของคุณทำงานได้ลื่นไหลขึ้น

1. ใช้ const ให้มากขึ้น

การใช้ const ช่วยลดการสร้าง Widget ใหม่ซ้ำๆ ทำให้ Flutter ไม่ต้อง Render ใหม่โดยไม่จำเป็น

ตัวอย่าง

❌ ไม่ใช้ const

Widget build(BuildContext context) {
            return Text('Hello');
          }
          

✅ ใช้ const

Widget build(BuildContext context) {
            return const Text('Hello');
          }
          
          

การใช้ const Flutter จะเก็บ Widget ไว้ในหน่วยความจำและนำกลับมาใช้ใหม่

2. หลีกเลี่ยงการเรียก setState() โดยไม่จำเป็น

setState() รีเฟรช Widget Tree ทั้งหมด อาจทำให้ UI ช้าลง โดยเฉพาะถ้ามีหลาย Widget การใช้ ValueNotifier หรือ State Management อื่นๆ ช่วยให้ UI อัปเดตเฉพาะส่วนที่จำเป็น

ตัวอย่าง

❌ รีเฟรชทั้ง Widget Tree

setState(() {
            counter++;
          });
          

✅ ใช้ ValueNotifier หรือ Bloc

ValueNotifier<int> counter = ValueNotifier(0);
          
          counter.value++;
          

3. ใช้ ListView.builder แทน ListView ธรรมดา

ListView ปกติโหลด Widget ทั้งหมดในคราวเดียว อาจทำให้แอปใช้หน่วยความจำมากเกินไป ช่วยให้โหลดเฉพาะรายการที่แสดงผลบนหน้าจอ

ตัวอย่าง

ListView ปกติ

ListView(
            children: items.map((item) => ListTile(title: Text(item))).toList(),
          )
          

✅ ใช้ ListView.builder โหลดทีละรายการ

ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              return ListTile(title: Text(items[index]));
            },
          )
          

4. เปิดใช้งาน Flutter DevTools เพื่อตรวจสอบประสิทธิภาพ

ใช้ Flutter DevTools เพื่อตรวจสอบว่า Widget ถูก Rebuild บ่อยเกินไปหรือไม่

  • เปิด DevTools และดูที่ “Rebuild Tracker”
  • หลีกเลี่ยงการ Rebuild ที่ไม่จำเป็น

5. ใช้ SizedBox แทน Container ถ้าไม่ต้องการตกแต่ง

Container มีคุณสมบัติที่หลากหลาย แต่ถ้าต้องการแค่กำหนดขนาด ให้ใช้ SizedBox แทน ช่วยลด Overhead และทำให้ UI ทำงานได้เร็วขึ้น

ตัวอย่าง

❌ ใช้ Container โดยไม่จำเป็น

Container(width: 100, height: 50)
          

✅ ใช้ SizedBox

SizedBox(width: 100, height: 50)
          

Unit Test สำคัญแค่ไหน?


03 Mar 2025, 21:35

Unit Test เป็นหัวใจสำคัญของการพัฒนาซอฟต์แวร์ที่มีคุณภาพ โดยเฉพาะใน Flutter ซึ่งเป็นเฟรมเวิร์กยอดนิยมสำหรับการพัฒนาแอปพลิเคชันแบบ Cross-platform การเขียน Unit Test ช่วยให้มั่นใจว่าโค้ดทำงานได้อย่างถูกต้อง ลดโอกาสเกิดบั๊ก และทำให้การพัฒนาแอปมีความยืดหยุ่นมากขึ้น

ทำไม Unit Test จึงสำคัญ?

  1. ตรวจสอบความถูกต้องของโค้ด - ป้องกันการทำงานผิดพลาดของฟังก์ชันหลัก
  2. ลดความผิดพลาดเมื่อต้องเปลี่ยนแปลงโค้ด - ทำให้การ refactor โค้ดเป็นไปอย่างมั่นใจ
  3. เพิ่มความน่าเชื่อถือของแอปพลิเคชัน - ลดบั๊กก่อนที่โค้ดจะถูกนำไปใช้งานจริง
  4. รองรับการทำงานร่วมกับ CI/CD - ช่วยให้สามารถตรวจสอบโค้ดอัตโนมัติก่อนนำขึ้น production

ตัวอย่างการเขียน Unit Test ใน Flutter

ติดตั้งแพ็กเกจ flutter_test

Flutter มีแพ็กเกจ flutter_test มาให้พร้อมใช้งานอยู่แล้ว หากต้องการใช้งาน ให้ตรวจสอบว่า pubspec.yaml มีการอ้างอิงแพ็กเกจดังนี้

# pubspec.yaml
          dev_dependencies:
            flutter_test:
              sdk: flutter
          

สร้างฟังก์ชันที่ต้องการทดสอบ

สมมติว่าเรามีคลาส Calculator ที่มีเมทอด add และ subtract

class Calculator {
            int add(int a, int b) => a + b;
            
            int subtract(int a, int b) => a - b;
          }
          

สร้างไฟล์ Unit Test

สร้างไฟล์ใหม่ในโฟลเดอร์ test/ เช่น calculator_test.dart

import 'package:flutter_test/flutter_test.dart';
          import 'package:my_app/calculator.dart'; // นำเข้าไฟล์ที่ต้องการทดสอบ
          
          void main() {
            group('Calculator', () {
              final calculator = Calculator();
          
              test('should return correct addition result', () {
                expect(calculator.add(2, 3), 5);
                expect(calculator.add(-1, 1), 0);
              });
          
              test('should return correct subtraction result', () {
                expect(calculator.subtract(5, 3), 2);
                expect(calculator.subtract(10, 7), 3);
              });
            });
          }
          

รัน Unit Test

ใช้คำสั่งต่อไปนี้ใน Terminal เพื่อรัน Unit Test

flutter test
          

หากโค้ดทำงานถูกต้อง คุณจะเห็นผลลัพธ์ที่แจ้งว่าการทดสอบทั้งหมดผ่านเรียบร้อย

สรุป

Unit Test มีความสำคัญอย่างยิ่งต่อการพัฒนาแอปพลิเคชันด้วย Flutter เพราะช่วยให้โค้ดมีคุณภาพ ลดโอกาสเกิดบั๊ก และเพิ่มความมั่นใจในการพัฒนาแอป นักพัฒนาควรฝึกเขียน Unit Test อย่างสม่ำเสมอ เพื่อให้แอปพลิเคชันมีความเสถียร พร้อมสำหรับการใช้งานจริง และรองรับการเปลี่ยนแปลงในอนาคต

เขียน API Call ให้เร็วขึ้นใน Flutter


01 Mar 2025, 20:31

การเรียก API เป็นหนึ่งในกระบวนการที่ส่งผลต่อประสิทธิภาพของแอป Flutter หากทำได้ไม่ดี อาจทำให้แอปโหลดช้าและประสบการณ์ใช้งานแย่ลง มาดูวิธีปรับปรุงให้เร็วขึ้นกัน!

1. ใช้ Concurrent Requests

แทนที่จะเรียก API ทีละตัว ให้ใช้ Future.wait() เพื่อเรียกหลาย API พร้อมกัน ใช้เมื่อ API ไม่ต้องรอข้อมูลจากกันและกัน

Future<void> fetchData() async {
            final results = await Future.wait([
              http.get(Uri.parse('https://api.example.com/user')),
              http.get(Uri.parse('https://api.example.com/posts')),
            ]);
          
            final userData = jsonDecode(results[0].body);
            final postsData = jsonDecode(results[1].body);
          
            print(userData);
            print(postsData);
          }
          

2. เปิดใช้ HTTP Keep-Alive

ลดเวลาการเชื่อมต่อใหม่ทุกครั้งด้วย HttpClient แทน http library ปกติ วิธีนี้ช่วยลด Latency ได้ โดยเฉพาะเมื่อมีการเรียก API บ่อย

final client = HttpClient()..idleTimeout = const Duration(seconds: 15);
          
          Future<void> fetchData() async {
            final request = await client.getUrl(Uri.parse('https://api.example.com/data'));
            final response = await request.close();
            final responseBody = await response.transform(utf8.decoder).join();
          
            print(responseBody);
          }
          

3. ใช้ Compression (Gzip)

บีบอัดข้อมูลตอบกลับ ลดขนาด Payload เซิร์ฟเวอร์ต้องรองรับ Gzip ด้วย

final response = await http.get(
            Uri.parse('https://api.example.com/data'),
            headers: {'Accept-Encoding': 'gzip'},
          );
          

4. ใช้ Cache ลดจำนวน API Calls

ลดภาระเซิร์ฟเวอร์ เหมาะกับข้อมูลที่ไม่เปลี่ยนแปลงบ่อย

import 'package:shared_preferences/shared_preferences.dart';
          
          Future<String?> getCachedData() async {
            final prefs = await SharedPreferences.getInstance();
            return prefs.getString('cached_response');
          }
          
          Future<void> fetchData() async {
            final cachedData = await getCachedData();
            if (cachedData != null) {
              print('ใช้ Cache: $cachedData');
              return;
            }
          
            final response = await http.get(Uri.parse('https://api.example.com/data'));
            final responseBody = response.body;
          
            final prefs = await SharedPreferences.getInstance();
            prefs.setString('cached_response', responseBody);
          
            print('เรียก API: $responseBody');
          }
          

5. ใช้ Compute() ลดการบล็อก UI

เหมาะสำหรับ JSON ขนาดใหญ่ ช่วยให้ UI ไม่กระตุก

import 'dart:convert';
          import 'package:flutter/foundation.dart';
          
          Future<void> fetchData() async {
            final response = await http.get(Uri.parse('https://api.example.com/data'));
            final parsedData = await compute(parseJson, response.body);
            print(parsedData);
          }
          
          List<dynamic> parseJson(String body) {
            return jsonDecode(body);
          }
          

สรุป

  • ใช้ Future.wait() เรียก API พร้อมกัน
  • ใช้ HttpClient ลด Latency
  • เปิดใช้ Gzip Compression
  • Cache ข้อมูลที่ใช้ซ้ำ
  • ใช้ compute() ลดโหลดงาน UI

ทำตามเทคนิคเหล่านี้ แล้วแอปของคุณจะโหลด API ได้เร็วขึ้น

สายงาน Flutter Developer มีอะไรบ้าง?


01 Mar 2025, 09:45

Flutter เป็นเฟรมเวิร์กสำหรับการพัฒนาแอปพลิเคชันที่ได้รับความนิยมอย่างมาก โดยเฉพาะในสายงาน Mobile Development แต่จริง ๆ แล้วการเป็น Flutter Developer ไม่ได้จำกัดอยู่แค่การพัฒนาแอปบนมือถือเท่านั้น แต่ยังสามารถต่อยอดไปสู่การพัฒนาแอปพลิเคชันบนแพลตฟอร์มอื่น ๆ รวมถึงการทำงานในบทบาทที่หลากหลายมากขึ้นอีกด้วย ในบทความนี้ เราจะพามาทำความรู้จักกับสายงานต่าง ๆ ที่เกี่ยวข้องกับ Flutter Developer และแนวทางการเติบโตในอาชีพนี้

1. Mobile App Developer (Android/iOS) สายงานหลักของ Flutter Developer คือการพัฒนาแอปพลิเคชันสำหรับมือถือทั้งระบบ Android และ iOS โดยใช้ Flutter นักพัฒนาในสายงานนี้จะต้องเชี่ยวชาญในการออกแบบ UI/UX, การจัดการ state และการเชื่อมต่อกับ API ต่าง ๆ เพื่อให้แอปทำงานได้อย่างราบรื่น นอกจากนี้ การทำให้แอปรองรับ Offline Mode และการ Optimize ประสิทธิภาพก็เป็นทักษะที่สำคัญอีกด้วย

2. Web Developer (Flutter Web) Flutter ไม่ได้ใช้แค่กับ Mobile App เท่านั้น แต่ยังสามารถพัฒนา เว็บแอปพลิเคชัน ได้อีกด้วย นักพัฒนาในสายนี้จะต้องเข้าใจแนวทางการพัฒนาเว็บ เช่น การทำ Responsive Design, การทำให้แอปโหลดเร็วขึ้น (Performance Optimization) และการรองรับ Progressive Web Apps (PWA) นอกจากนี้ การทำ SEO และการเชื่อมต่อกับ API สำหรับเว็บแอปก็เป็นสิ่งที่ควรคำนึงถึง

3. Desktop App Developer (Windows/macOS/Linux) Flutter รองรับการพัฒนา แอปพลิเคชันบนเดสก์ท็อป ด้วยเช่นกัน ไม่ว่าจะเป็น Windows, macOS หรือ Linux นักพัฒนาในสายนี้จะต้องมีความเข้าใจเกี่ยวกับการทำงานของ OS ที่แตกต่างกัน รวมถึงการเชื่อมต่อกับ API พื้นฐานของระบบปฏิบัติการ เช่น การเข้าถึงไฟล์ระบบ การทำงานร่วมกับอุปกรณ์ภายนอก (เช่น เครื่องพิมพ์, กล้อง, หรือไมโครโฟน) และการสร้าง UI ที่เหมาะกับเดสก์ท็อป

4. Embedded Systems Developer Flutter สามารถใช้พัฒนาแอปพลิเคชันบน Embedded Systems เช่น IoT devices, Smart Display และอุปกรณ์เฉพาะทางได้ นักพัฒนาที่ทำงานในสายนี้ต้องมีความรู้เกี่ยวกับฮาร์ดแวร์และการทำงานของระบบ Embedded รวมถึงการเขียนโค้ดที่มีประสิทธิภาพสูงเพื่อให้แอปทำงานได้บนอุปกรณ์ที่มีทรัพยากรจำกัด นอกจากนี้ ยังต้องเข้าใจการเชื่อมต่ออุปกรณ์กับเซ็นเซอร์และระบบควบคุมอื่น ๆ

5. Full-stack Developer (Flutter + Backend) สำหรับผู้ที่ต้องการพัฒนาแอปพลิเคชันแบบ Full-stack การใช้ Flutter ร่วมกับ Backend Frameworks เช่น Node.js, Firebase, Supabase, Appwrite หรือ Golang ก็เป็นทางเลือกที่ดี นักพัฒนาในสายนี้จะต้องมีความเข้าใจทั้งฝั่ง Frontend และ Backend รวมถึงการออกแบบ API ที่มีประสิทธิภาพ การจัดการฐานข้อมูล และการทำให้ระบบรองรับผู้ใช้จำนวนมากได้ (Scalability)

6. Plugin & Package Developer Flutter มีระบบ แพ็กเกจ และ ปลั๊กอิน สำหรับขยายความสามารถของแอป นักพัฒนาในสายนี้จะเน้นการสร้าง Flutter Package หรือ Native Plugin เพื่อช่วยให้ผู้ใช้สามารถเข้าถึงฟีเจอร์เฉพาะของระบบปฏิบัติการได้ เช่น การเข้าถึง Bluetooth, การใช้ Machine Learning, หรือการทำงานร่วมกับอุปกรณ์ภายนอก การเป็น Plugin Developer ต้องมีความเข้าใจทั้ง Flutter และภาษาพื้นฐานของแพลตฟอร์มนั้น ๆ เช่น Kotlin/Java สำหรับ Android และ Swift/Objective-C สำหรับ iOS

7. DevOps & CI/CD for Flutter นักพัฒนาในสาย DevOps จะโฟกัสที่การทำให้การพัฒนาและปล่อยแอปเป็นไปอย่างอัตโนมัติผ่านระบบ CI/CD (Continuous Integration & Continuous Deployment) เช่น GitHub Actions, Codemagic หรือ Fastlane เพื่อให้แอปสามารถ Build, Test และ Deploy ได้ง่ายขึ้น นอกจากนี้ นักพัฒนา DevOps ควรมีความรู้เกี่ยวกับ Containerization (Docker) และการใช้ Cloud Services เช่น Firebase Hosting หรือ AWS Amplify

8. QA Engineer / Tester for Flutter ตำแหน่ง QA Engineer หรือ Tester จะดูแลด้านคุณภาพของแอปพลิเคชัน โดยใช้เครื่องมือทดสอบ เช่น Flutter Test, Widget Testing, Integration Testing และ UI Automation เพื่อให้มั่นใจว่าแอปทำงานได้ถูกต้องตามที่ออกแบบ นอกจากนี้ QA Engineer ยังต้องเข้าใจการทำ Performance Testing และ Security Testing เพื่อให้แอปมีเสถียรภาพและปลอดภัยต่อการใช้งาน

9. UI/UX Designer ที่เชี่ยวชาญ Flutter แม้ว่าจะไม่ใช่ตำแหน่งของนักพัฒนาโดยตรง แต่ UI/UX Designer ที่เข้าใจการทำงานของ Flutter สามารถออกแบบ UI ที่ใช้งานได้จริงและเหมาะสมกับแพลตฟอร์มต่าง ๆ ได้ดีกว่า นักออกแบบที่เข้าใจหลักการของ Material Design และ Cupertino จะช่วยให้การพัฒนาแอปเป็นไปได้อย่างราบรื่นมากขึ้น

สรุป สายงานของ Flutter Developer มีความหลากหลายและครอบคลุมหลายด้าน ไม่ว่าจะเป็น Mobile, Web, Desktop, Embedded Systems, Full-stack, DevOps, QA หรือแม้แต่การพัฒนาแพ็กเกจและปลั๊กอิน ใครที่สนใจในสายงานนี้สามารถเลือกเส้นทางที่เหมาะสมกับตนเองได้ตามความถนัดและความสนใจ

เทคนิค Flutter 5 แนวทางเขียนโค้ดให้สะอาดและมีประสิทธิภาพ


28 Feb 2025, 08:54

Flutter เป็นเฟรมเวิร์กที่ช่วยให้การพัฒนาแอปพลิเคชันรวดเร็วและมีประสิทธิภาพ อย่างไรก็ตาม การรักษาคุณภาพของโค้ดให้สะอาดและเข้าใจง่ายเป็นสิ่งสำคัญเพื่อให้การบำรุงรักษาและการขยายโค้ดในอนาคตทำได้ง่ายขึ้น บทความนี้จะกล่าวถึง 5 แนวทางหลัก ที่ช่วยให้โค้ด Flutter ของคุณเป็นระบบและอ่านง่ายขึ้น พร้อมทั้งเสริมรายละเอียดและตัวอย่างเพิ่มเติมเพื่อให้คุณสามารถนำไปประยุกต์ใช้ได้อย่างมีประสิทธิภาพ

1. แยก UI ออกจาก Business Logic ด้วย State Management

การรวม UI และ Business Logic ไว้ด้วยกันทำให้โค้ดซับซ้อนและยากต่อการบำรุงรักษา การใช้ State Management เช่น Provider, Bloc, หรือ Riverpod ช่วยให้สามารถจัดการสถานะของแอปพลิเคชันได้เป็นระบบและลดความซับซ้อนของ UI

ตัวอย่างการใช้งาน Provider

class CounterNotifier extends ChangeNotifier {
            int _count = 0;
            int get count => _count;
          
            void increment() {
              _count++;
              notifyListeners();
            }
          }
          

ใน UI ควรใช้ Consumer หรือ Selector เพื่อลดการเรนเดอร์ที่ไม่จำเป็น

Consumer<CounterNotifier>(
            builder: (context, counter, child) {
              return Text('${counter.count}');
            },
          )
          

ทำไมการแยก State สำคัญ?

  • ลดโค้ดที่ซับซ้อนใน UI ทำให้โค้ดอ่านง่ายขึ้น
  • ง่ายต่อการทดสอบ (Unit Test และ Widget Test)
  • ช่วยให้สามารถใช้ State ร่วมกันระหว่าง Widget หลายตัวได้

2. ใช้ Extension Methods เพื่อปรับแต่ง Widget อย่างมีประสิทธิภาพ

Extension Methods ช่วยให้สามารถเพิ่มฟังก์ชันให้กับ Widget ได้โดยไม่ต้องแก้ไขโค้ดต้นฉบับ ทำให้โค้ดสะอาดขึ้นและมีโครงสร้างที่ดีขึ้น:

extension PaddingExtension on Widget {
            Widget withPadding([EdgeInsets padding = const EdgeInsets.all(8)]) {
              return Padding(padding: padding, child: this);
            }
          }
          

สามารถใช้งานได้ง่ายขึ้น

Text("Hello, Flutter!").withPadding();
          

ข้อดีของ Extension Methods

  • ทำให้โค้ดสั้นลงและอ่านง่ายขึ้น
  • ลดความซ้ำซ้อนในการใช้ Padding, Margin หรือ Styling อื่น ๆ
  • สามารถนำไปใช้กับ Widget ใดก็ได้

3. ใช้ Custom Widget เพื่อลดความซ้ำซ้อนของโค้ด

หากพบว่า UI มีโค้ดซ้ำกันหลายจุด ควรแยกออกเป็น Custom Widget เพื่อให้โค้ดหลักสะอาดขึ้นและง่ายต่อการนำกลับมาใช้ใหม่

class CustomButton extends StatelessWidget {
            final String label;
            final VoidCallback onPressed;
          
            const CustomButton({
              required this.label,
              required this.onPressed,
            });
          
            @override
            Widget build(BuildContext context) {
              return ElevatedButton(
                onPressed: onPressed,
                child: Text(label),
              );
            }
          }
          

แทนที่จะเขียนโค้ดซ้ำๆ สามารถเรียกใช้ได้ง่ายขึ้น

CustomButton(
            label: "กดเลย!",
            onPressed: () {},
          )
          

ประโยชน์ของการใช้ Custom Widget

  • ลดความซ้ำซ้อนในโค้ด ทำให้โค้ดอ่านง่ายขึ้น
  • เพิ่มความสามารถในการนำโค้ดกลับมาใช้ใหม่ (Reusability)
  • ทำให้การเปลี่ยนแปลงโค้ดง่ายขึ้นโดยไม่ต้องแก้หลายที่

4. ใช้ Named Routes เพื่อจัดการการนำทางอย่างเป็นระบบ

การใช้ Named Routes ช่วยให้การนำทางในแอปเป็นระบบและลดการใช้ Navigator.push ที่กระจัดกระจายไปทั่วโค้ด

void main() {
            runApp(MaterialApp(
              initialRoute: '/',
              routes: {
                '/': (context) => HomePage(),
                '/details': (context) => DetailsPage(),
              },
            ));
          }
          

เรียกใช้งานได้ง่ายขึ้นและลดโค้ดที่ไม่จำเป็น

Navigator.pushNamed(context, '/details');
          

ข้อดีของ Named Routes

  • ทำให้โค้ดดูเป็นระเบียบมากขึ้น
  • สามารถเปลี่ยนเส้นทางการนำทางได้จากที่เดียว
  • ช่วยให้สามารถใช้ deep linking ได้ง่ายขึ้น

5. ใช้ Linting และ Code Formatter เพื่อให้โค้ดได้มาตรฐาน

การใช้ Flutter Linter และ Code Formatter ช่วยลดข้อผิดพลาดและทำให้โค้ดเป็นระเบียบ ควรตั้งค่า analysis_options.yaml เพื่อเปิดใช้งาน linting

include: package:flutter_lints/flutter.yaml
          

นอกจากนี้ ควรใช้ flutter format เพื่อลดโค้ดที่ไม่เป็นมาตรฐาน

เครื่องมือที่ช่วยให้โค้ดสะอาดขึ้น

  • dart analyze เพื่อตรวจสอบข้อผิดพลาดในโค้ด
  • flutter format . เพื่อจัดระเบียบโค้ดอัตโนมัติ
  • pre-commit hooks เพื่อป้องกันการ commit โค้ดที่ไม่เป็นระเบียบ

สรุป

แนวทางทั้ง 5 ข้อนี้ช่วยให้โค้ด Flutter ของคุณสะอาด เป็นระบบ และง่ายต่อการบำรุงรักษา

  1. แยก UI ออกจาก Business Logic ด้วย State Management เช่น Provider หรือ Bloc
  2. ใช้ Extension Methods เพื่อขยายความสามารถของ Widget และลดโค้ดซ้ำซ้อน
  3. ใช้ Custom Widget เพื่อลดความซ้ำซ้อนและเพิ่มการนำกลับมาใช้ใหม่
  4. ใช้ Named Routes เพื่อจัดการ Navigation อย่างเป็นระบบและรองรับ deep linking
  5. ใช้ Linting และ Code Formatter เพื่อรักษาคุณภาพโค้ดและลดข้อผิดพลาด

การนำแนวทางเหล่านี้ไปใช้จะช่วยให้โค้ดของคุณมีคุณภาพสูงขึ้น และสามารถทำงานร่วมกับทีมได้อย่างมีประสิทธิภาพมากขึ้น รวมถึงช่วยให้การพัฒนาแอปเป็นไปอย่างรวดเร็วและมีโครงสร้างที่ดีขึ้น

สร้างหนังสือ E-Book จากไฟล์ Markdown (อีกแล้ว)


23 Feb 2025, 22:41

ผมเขียนหนังสือเล่มใหม่เอาไว้ทำเป็นหนังสือตัวอย่าง จะได้หาวิธีที่สะดวกในการสร้างไฟล์ EPUB, PDF ให้ออกมาได้สวยๆ สักที หลังจากทดลองกับหนังสือสูตรลัด Bloc ไปก็พบว่าผลลัพท์น่าพอใจ แต่ติดอยู่อย่างเดียวคือ EPUB reader ของแต่แพลทฟอร์มมันแสดงผลออกมาไม่เหมือนกันฟอนต์ที่แปะไปกับไฟล์ EPUB ถูกเอาออกไปด้วย บางแพลทฟอร์มก็เอาไฟล์ไปทำ sample โดยไป render EPUB ออกมาใหม่แถมเปลี่ยนสไตล์ของเอกสารไปด้วย ก็เลยทำให้เละกันไปใหญ่ จากปัญหาที่เจอก็เลยต้องทำไฟล์ให้ครบ แล้วไปลุ้นตอนที่แอปของแต่ละแพลทฟอร์ม render ออกมายังไง

แก้ปัญหายังไง?

  • ใช้ pandoc แปลงไฟล์ markdown ทั้งหมดเป็น EPUB สำหรับหนังสือ

  • ใช้ pandoc แปลงไฟล์ markdown เฉพาะหน้าปก ปกใน บทนำ บทที่ 1 เป็น EPUB สำหรับตัวอย่างหนังสือ

  • ใช้ ebook-convert (Calibre) แปลงไฟล์ 2 ส่วน ออกมาเป็น PDF

    • ปกใน บทนำ
    • เนื้อหาพร้อมสารบัญท้ายเล่ม
  • ใช้ pdfcpu ตัดต่อไฟล์ แล้วรวม หน้าปก ปกใน บทนำ สารบัญ เนื้อหา ปกหลัง เป็นหนังสือ PDF

  • ใช้ pdfcpu เลือกหน้าเฉพาะ 20 หน้าแรก มาทำเป็นไฟล์ตัวอย่างหนังสือ

ทั้งหมดเขียนเป็น script ง่ายๆ run ทีเดียวได้ไฟล์ครบเลย ถามถามว่าทำไมอยากเขียน script เองทั้งๆ ที่ไอ่ของแบบนี้มันมีให้ดาวน์โหลดมาใช้งานอยู่แล้ว ก็ต้องตอบว่าอยากได้อะไรที่มันตรงกับความต้องการมากกว่า ครั้งหน้าคงได้เขียน CI/CD ใน GitHub Actions ละ

สรุป commit ใน GitHub


22 Jan 2025, 12:33

เมื่อต้นเดือนที่ผ่านมามี developer หลายคนโพสภาพ GitHub Stats ก็เลยไปลองกดเล่นดูบ้าง ได้ผลลัพท์ประมาณนี้

กดไปทำภาพสวยๆ ที่ postspark

จัดการไฟล์ PDF ด้วย pdfcpu


20 Jan 2025, 14:12

เมื่อโพสที่แล้วเล่าเรื่องสร้าง ebook จากไฟล์ Makrdown กันไปแล้ว แต่ยังไม่ค่อยสมบูรณ์เท่าไร เนื่องจากยังขาดเลขหน้าและหน้าสารบัญในไฟล์ PDF ถ้าใช้ Calibre สร้างสารบัญให้มันจะไปกองอยู่ท้ายเอกสาร และถ้าให้ Calibre ใส่เลขหน้าให้มันก็จะใส่เลขหน้าไปจนถึงหน้าสารบัญ ก็เลยต้องทำ post process เอง ซึ่งถ้าใช้ Latex ก็ไม่น่าจะยากอะไรเพราะ pandoc สามารถอ่าน template Latex และแปลงไฟล์ออกมาได้ แต่เนื่องจากเราหนีจาก Latex ก็เลยต้องทำ post process แทน

วันนี้มาแนะนำ pdfcpu เป็นเครื่องมือเอาไว้ใช้จัดการไฟล์ pdf เขียนด้วยภาษา Go ทำงานได้รวดเร็วมาก มีฟีเจอร์หลายตัวที่น่าสนใจ เช่น สร้างไฟล์, รวมไฟล์, แยกไฟล์, ใส่ stamp ลงเอกสาร ฯลฯ ลองไปดู document กันได้

แนวทางการใช้งาน

  • รวมไฟล์ markdown แล้วแปลงเป็นไฟล์ EPUB (แบบมีปกและรองปก) และไฟล์ EPUB (ไม่มีปก) ตั้งต้นสำหรับแปลงไฟล์ PDF
  • ใช้ Calibre แปลงไฟล์ EPUB ออกมาเป็น PDF พร้อมใส่หน้าสารบัญท้ายเล่ม
  • ใช้ pdfcpu แบ่งหน้าออกเป็น 3 ส่วน รองปก เนื้อหา และ สารบัญ
  • ใช้ pdfcpu ใส่เลขหน้าในส่วนเนื้อหา
  • ใช้ pdfcpu รวมไฟล์ หน้าปก รองปก สารบัญ เนื้อหาที่ใส่เลขหน้า

เอ่อ ทำไฟล์เอกสารแล้วเอามาต่อกันเลยแบบนี้ ใช้ word processer ดีกว่ามั๊ย T_T

ลดแบบไม่ลด


16 Jan 2025, 11:57

ลดราคาแบบไม่ลดราคา อยากทำแบบนี้เป็นบ้าง ตามกฏคือ

  • หนังสือที่วางขายภายใน 30 วันก่อนเริ่มแคมเปญ ไม่สามารถนำมาเข้าร่วมแคมเปญได้
  • หนังสือที่มีการแก้ไขราคาภายใน 30 วันก่อนเริ่มแคมเปญ ไม่สามารถนำมาเข้าร่วมแคมเปญได้
  • หนังสือที่สมัครเข้าร่วมแคมเปญจะใช้เวลา 1-2 วันทำการในการอนุมัติหนังสือ

ถ้าจะทำแบบนี้ต้องมีหนังสือเรื่องเดียวกัน 2 เล่ม ตั้งราคาสูงเอาไว้แล้วเอามาลดราคาช่วงแคมเปญใช่มะ

จะเขียน Jaspr ต่อกับ Firebase database ยังไง


10 Jan 2025, 14:07

ลูกเพจถามคำถามนึงน่าสนใจเลยเอามา blog ไว้สักหน่อย คำถามคิอจะเขียน Jaspr ต่อกับ Firebase database ยังไง ผมคิดว่าคำถามนี้น่าสนใจเพราะหลายคนอาจเข้าใจว่า เขียน Dart แล้วจะเรียกใช้แพคเกจ FlutterFire ใน pub.dev ได้เลย แต่อย่าลืมว่าแพคเกจใน pub.dev มีแพคเกจสำหรับ Dart SDK และ Flutter SDK

ถ้ามาลองพิจารณาดูว่า Jaspr Dart Web Framework พอ build ออกมา จะได้เป็น html, css, javascript ซึ่งเป็นส่วน frontend ทั้งหมด (Client side, Server site และ Static site) ดังนั้น แพคเกจที่มีโอกาสใช้งานได้จะต้องเป็น

  • Dart SDK ไม่มี Flutter SDK หรือ Flutter UI มาปน
  • แพคเกจที่มี Javascript Interop รองรับ Web platform

แต่ช้าก่อน ในข่วงขั้นตอนการ build จะสร้างส่วน pre-render สำหรับสร้างเป็น javascript ด้วย ดังนั้นหากมีการเรียกใช้แพคเกจที่ไม่รองรับ ก็ไม่สามารถ build ได้ วิธีการง่ายที่สุดมี 2 วิธี

  • Jaspr ในโหมด Server แต่เรียกใช้แพคเกจที่เป็น Dart เพียวๆ และแพคเกจที่มี javascript interop แยกออกมา กรณีนี้ต้องไล่ดูว่ามีแอบไปเรียกใช้ Flutter SDK ในส่วน UI มั๊ย
  • Jaspr ในโหมด Server และเรียกใช้ backend ผ่าน REST API เป็นต้น

คำตอบของคำถามนี้คือ Jaspr เป็น Dart Web Framework เวลาใช้งานต้องคิดแบบ Web เท่านั้น อย่าเอา Flutter มาปนเด็ดขาด

อืมมม คิดไปคิดมา นี่งานงอกนะ

  • ถ้าใช้ Jaspr ร่วมกับ Dart backend อย่าง shelf, dart_frog ต้องไปทำ backend เชื่อมต่อกับ Firebase อีกที
  • ถ้าใช้ Jaspr ร่วมกับ Cloud Functions งานก็งอกไปอีกแบบ
  • ถ้าใช่ javascript interop ก็ต้องจัดการ app state เพิ่มเติม

ก็คงต้องเลือกดูว่างานงอกแบบไหนดีกว่ากัน

หนังสือที่จะออกในปี 2025


07 Jan 2025, 18:30

วางแผนออกหนังสือไว้ตั้งแต่ปีที่แล้วทั้งอัพเดทหนังสือเล่มเก่าและเขียนเล่มใหม่ เปิดต้นปีมาก็ออกหนังสือ สูตรลัด Bloc ไป 1 เล่มแล้ว ที่เหลือที่มีคิวไว้อีก 7 เล่ม ได้แก่

  • Hasura DDN
  • AI GenKit
  • ServerPod 3
  • Appwrite 2
  • Jaspr UI Component
  • GetX 5
  • FlutterPi

ปีนี้เขียนแค่ 8 เล่มก็พอแล้ว ซื้อหนังสือได้ที่ - http://bit.ly/3UJlIYs

OpenTyphoon Dart Package


04 Jan 2025, 09:20

ผมได้ทดลองใช้งาน LLM ภาษาไทยตัวนึง คือ OpenTyphoon จากที่ได้ทดลองพบว่าตอบคำถามได้เร็วมากและเข้าใจภาษาไทยได้เป็นอย่างดี ถามภาษาไทยตอบภาษาไทย ไม่มีหลุดเหมือน LLM ตัวอื่นๆ รู้สึกประทับใจมาก ก็เลยทำ Dart package ไว้ใช้ร่วมกับโปรเจคเก่าๆ เช่น ytThumbnail, snThumbnail และออกแบบวิธีการเรียกใช้เหมือนกับ Gemini แต่ยังขาด 2 ฟีเจอร์

  • Chat
  • Stream message

คงทะยอยทำไปเรื่อยๆ กดไปลองเล่นกันได้ที่ GitHub anoochit/opentyphoon และที่ pub.dev

แปลง Mermaid diagrame เป็นไฟล์ภาพ


03 Jan 2025, 10:30

เมื่อปีที่แล้วทำ template สำหรับสร้าง E-Book จากไฟล์ Markdown เปลี่ยนเป็น EPUB และ PDF ไป แต่ขาดเรื่อง Diagrame ไปนิดนึงเลยมาเพิ่มให้ เขียน Mermaid diagrame ลงใน Markdown เหมือนเดิม แล้วใช้ Mermain Cli แปลง diagrame ในไฟล์ markdown ออกมาเป็นภาพ และสร้างไฟล์ markdown ที่แก้ไขเรียบร้อยแล้วออกมา และเอาไฟล์นี้ไปสร้างเป็น E-book ตามปกติ

แปลง markdown เป็นภาพ (แบบไม่มีเอกสาร Markdown)

mmdc -i <MARKDOWN_DOC_FILENAME>.md -o IMAGE_NAME_PREFIX.png
          

แปลง markdown เป็นภาพ พร้อมเอกสาร markdown ใหม่ (แบบมีเอกสาร Markdown)

mmdc -i <MARKDOWN_DOC_FILENAME>.md --outputFormat=png -o <ANOTHER_MARKDOWN_DOC_FILENAME>.md
          

กดไปดูเพิ่มเติมกันได้ที่ Cookbook Template

มาทำ UI Component ให้ Jaspr กัน


31 Dec 2024, 09:15

จากที่เคยเล่าให้ฟังในโพสที่แล้วเรื่องไปทำ Jaspr UI Component มาเพิ่ม เนื่องจากออกแบบไม่ค่อยดีเลยทำให้การปรับแต่ง UI ทำได้ไม่ละเอียด ในเอกสารของ Jaspr แนะนำให้ส่งออก DomComponent อยากจะทำ Tag ใส่ stylesheet อะไรก็ใส่ไปได้เลย มีโปรเจคนึง (จำชื่อไม่ได้) ใช้ DomComponent แล้วทำเป็น Tag ที่ใช้งานประจำ เช่น H1, P, Img เป็นต้น ซึ่งก็น่าสนใจดี

Component div(List<Component> children,
              {Key? key,
              String? id,
              String? classes,
              Styles? styles,
              Map<String, String>? attributes,
              Map<String, EventCallback>? events}) {
            return DomComponent(
              tag: 'div',
              key: key,
              id: id,
              classes: classes,
              styles: styles,
              attributes: attributes,
              events: events,
              children: children,
            );
          }
          

ถ้าเทียบกับ Flutter Widget มันก็คนละเรื่อง แต่การออกแบบจะคล้ายๆ กัน Widget ใน Flutter จะเป็นการส่งไปวาดบน Skia แต่ Jaspr Component ส่ง Tag ไปวาดใน Browser ก็ขึ้นอยู่กับการออกแบบ Library ให้เหมาะกับการเรียกใช้งานละ

แปลงไฟล์ backup Wordpress มาเป็น Markdown


30 Dec 2024, 08:08

หลังจากยกเลิกบริการ Hosting และ Backup Wordpress เอาไว้นานแล้วจนคิดว่าน่าจะเอามาทำเป็น static web ได้แล้วมั๊ย? เพราะตั้งใจว่าปีหน้าจะเริ่มกลับมาเขียน Blog ในเชิงเทคนิคบ้าง ก็เลยเริ่มจากเรื่องนี้เลยละกัน เมื่อต้นปีหาเครื่องมือแปลงได้ละเป็น wordpress-export-to-markdown วิธีการใช้งานก็ง่ายมากๆ ใช้คำสั่ง

npx  wordpress-export-to-markdown --post-folders=false --prefix-date=true
          

ที่ชอบคือมันไปโหลดไฟล์ภาพมาให้ด้วยถ้าลิงค์ของไฟล์ภาพยังอยู่นะประทับใจเลย ไฟล์ที่ได้จะมี front matter แปะที่หัวมาด้วยสไตล์ Jekyll เอาไปใช้กับ Jekyll หรือเครื่องมือ Static Website ต่างๆ ได้เลย สะดวกมาก

สำรวจพฤติกรรมโปรแกรมเมอร์ในโซเชียล


28 Dec 2024, 21:13

สมัยก่อนผมมักจะคุยกับเพื่อนๆ เรื่องชุมชนออนไลน์แบบที่เป็น web forum ว่า ชุมชน "ขอบคุณครับ" เพราะว่ามีคนมาโพสความรู้ไว้ในกระทู้ แล้วก็มีคนมาโพสตอบกระทู้ว่า "ขอบคุณครับ" ยาวๆ ต่อกันลงไป ไม่มีคน contibute อะไร ถ้าจะมีก็หน้าเดิมๆ จนเลิกเขียนกันไป

โดยส่วนตัวผมเขียน blog เป็นหลัก ถึงช่วงหลังๆ ปี 2018-2024 ไม่ค่อยได้เขียนเพราะหน้าที่ตำแหน่งงานเปลี่ยนไปแล้วก็ไม่ได้เขียนอะไรอีกเลย แต่ก็รู้สึกว่าชุมชนออนไลน์แบบเดิมๆ มันหายไป

ช่วงนี้ก็เลยนึกสนุกอยากทดสอบพฤติกรรมโปรแกรมเมอร์ว่าจะ willing to share knowledge กันมากน้อยแค่ไหน จะตอบเฉพาะสาวๆ มั๊ย หรือจะหงุดหงิดถ้ามีคนถามคำถามแบบมือใหม่ที่ไม่ค่อยรู้เรื่องอะไร ผลก็ตามนี้

สำรวจพฤติกรรมโปรแกรมเมอร์ใน "กลุ่มนักเขียนโปรแกรม" สนุกดี

  • คนที่ willing มาตอบคำถามก็ตอบเคลียร์ (3-4 คนได้)
  • คนที่อยากมาตอบเฉยๆ ไม่ได้ช่วยแก้ปัญหาอะไรก็เยอะ
  • คนที่ตอบแบบเข้ารหัส แบบเอาไปถอดรหัสเอาเองก็มี
  • มีแบบ RTFM ด้วย
  • มีโพสเชิงบูลลี่ กดหัวเราะ ก็มี

พอละหมดสนุกแล้ว ปั่นต้นฉบับต่อ 😅

ทำอะไรบ้างในปี 2024


28 Dec 2024, 16:53

สรุปปีนี้เป็นปีที่ทำตามความตั้งใจคือไม่เน้นเรื่องรับงานมากจนเกินไป ปีนี้เลยทำแค่ 2 โปรเจค ใครมาขอคำปรึกษาก็พยายามให้ความรู้ไปตามที่คนมาถามจะรับได้ ถึงแม้ว่าเขาจะมาถามเฉยๆ แล้วไปจ้างคนอื่นก็ไม่เป็นไรถือว่าเป็นวิทยาทาน (แต่จดชื่อไว้นะ)

มาสรุปจากความตั้งใจในปีที่แล้วกันก่อน

  • เขียนหนังสือเพิ่ม 4 เล่ม
  • อัพเดทหนังสือ 9 เล่ม
  • ทำคอร์สออนไลน์ GetX Crash Course เพิ่ม
  • เอา Facebook account เก่ากลับมาได้ และรวมเพจเก่าเข้ามาทำให้ยอดคนกด like ในเพจลดลง ก็เริ่มต้นกันใหม่ ช่วงเดือนกันยายน
  • Live ในเพจ Dart แบบ Dart Dart ได้เกือบทุกสัปดาห์ ยอดคนกด like 2,659 คน ยอดเข้าชม 94,640 ครั้ง ตั้งแต่ 21 กันยายนถึง 28 ธันวาคม 2024
  • คนเข้าไม่ถึงเพจเพราะโดนปิดกั้น เลยพยายามโพสทุกวัน แต่ก็ไม่ได้ผลอะไร ต้องจ่าย Blue Checkmark กับจ่ายโฆษณา อันนี้ยังทำใจไม่ได้
  • ยอดคนดูวิดีโอใน YouTube ยังแซงวิดีโอที่เป็นอันดับหนึ่งและอันดับสองในช่องไม่ได้ คอนเทนต์ความรู้ในช่องตัวเองยังสู้คอนเทนต์ความสนุกในช่องตัวเองไม่ได้
  • หัดทำวิดีโอสั้น เอาลง YouTube, Facebook
  • หัดเล่น Tiktok ลองลงวิดีโอสั้นรายวัน
  • ตัดสินใจเลิกเช่า Hosting และย้าย Blog ไป Firebase Hosting
  • Reskill เขียน HTML และ CSS ใหม่ หัดใช้ CSS Framework
  • จากที่ Reskill เลยไปทำ Jaspr UI Component ที่ใช้การ wrap DiasyUI กับ Jaspr UI เดิม ได้ความรู้หลายเรื่องจากโปรเจคนี้
  • ทำเว็บจาก Flutter for Web และย้ายมาเป็น Jaspr Dart Web Framework แทน
  • รวมตัวอย่างที่ Live ในแต่ละสัปดาห์ รวมไว้ในเว็บ UiKits
  • ช่วงต้นปีเอาโปรเจคที่โดนเท ตัดเฉพาะ core function ที่เป็นประโยชน์และน่าสนใจมาเล่าใน Live
  • ทำแอป snThumbnail, ytThumbail integrate กับ AI ทั้งในส่วน Text Generation และ Image Generation ได้เครื่องมือเอาไว้ใช้งานไม่ต้องจ่ายเงินเพิ่มในบริการเหล่านี้อีก
  • เปลี่ยนเครื่องมือเขียนหนังสือจาก Google Docs เป็น Markdown จะได้แก้ปัญหาเรื่องไฟล์ EPUB ให้จบสักที
  • จากข้างบน ทำเครื่องมือออกมาใช้งานเป็น publishing tool ตัวนึง
  • ช่วงต้นปีไป Reskill โดยเข้ารีต VGV เรียนรู้เครื่องมือใหม่ๆ หลายอย่าง
  • ตัดสินใจไม่ไปหาหมอแล้ว เพราะรู้แล้วว่าไม่ได้ต้องการรักษาโรคประจำตัว แค่อยากไปหาหมอเพราะขอยามากกว่า และอาการก็ไม่ได้ดีขึ้น ยังคงมีอาการหลงๆ ลืมๆ ยังคงมีความรู้สึกดำดิ่งซึมเศร้าแบบไม่มีสาเหตุ ไม่รู้จะแก้ยังไงไม่อยากกินยาแล้ว

ปีหน้าจะเป็นปีที่ชีวิตยากลำบากมากขึ้นอย่างเห็นได้ชัด

  • ลดรายจ่ายที่ไม่จำเป็น
  • อัพเดทหนังสือที่ค้างอยู่ 2 เล่ม
  • หางานหาเงินจริงจังมากขึ้น เพราะหนังสือยอดขายลดลง
  • วางแผนคอนเทนต์ใหม่ เขียนหนังสือทำคอนเทนต์ตามนิชของตลาดให้มากขึ้น
  • Live น้อยลง ทำวิดีโอสั้นกระชับตรงจุดให้มากขึ้น
  • อัพเดทคอร์สออนไลน์ใหม่
  • เขียน blog ด้านเทคนิคให้มากขึ้น

ถ้านึกอะไรออกจะมาใส่เพิ่มละกัน

สรุปมหากาพย์ EPUB


28 Dec 2024, 09:40

สรุปมหากาพย์ EPUB ซึ่ง confirm แล้วว่า แต่ละแพลตฟอร์ม

  • เรนเดอร์ออกมาไม่เหมือนกัน ทั้งๆ ที่ไส้ข้างในที่เป็นไฟล์ html, css
  • แตกไฟล์ ใส่ DRM เคลียร์ css ประกอบร่างใหม่
  • ฟอนต์โดนเอาออก บังคับให้ใช้ฟอนต์ในแอปมาแสดงผล
  • ตั้ง line height ทำให้แอปตั้งค่าระยะห่างระหว่างบรรทัดไม่ได้
  • ตั้งขนาดตัวอักษรปกติ (12-16) เวลาเพิ่ม/ลดขนาดตัวอักษร แอปจะเพิ่ม/ลดค่าให้ทีละน้อยๆ จะกลายเป็นเพิ่มขนาดตัวอักษรได้อย่างเดียว ลดขนาดตัวอักษรไม่ได้

แพลตฟอร์มที่เรนเดอร์ออกมาดีที่สุด คือ Google Play Books ถึงจะโดนเอาฟอนต์ออก แต่การเรนเดอร์หน้าเอกสารก็ยังดูดีอยู่

สรุปผลประกอบการใน GitHub สักหน่อย


27 Dec 2024, 22:07

ผ่านมา 1 ปีสรุปกิจกรรมใน GitHub สักเล็กน้อย โปรเจคส่วนใหญ่เป็นโปรเจคที่ให้คำปรึกษาลูกค้าและโปรเจคส่วนตัว ระยะหลังใช้ MIT License มากขึ้น ใช้ AGPL, GPL, LGPL น้อยลง ส่วนโปรเจคลูกค้าส่วนใหญ่จะใช้ Repository ของลูกค้าอยู่แล้ว

ปีหน้ามีโปรเจคหลักและเป็นโอเพนซอร์สมากขึ้น

ยังไม่สรุปมหากาพย์ EPUB


25 Dec 2024, 18:21

ยังไม่สรุปมหากาพย์ EPUB แต่ก็ใกล้ละ หลังจากเปลี่ยนมาเขียนต้นฉบับด้วย EPUB งานก็งอกหลายอย่างเลย ตอนเขียนไม่ลำบากเท่าไร แต่ต้องพก notebook ไว้ด้วย เพราะแก้ไขไฟล์แบบออนไลน์ไม่ได้ ยกเว้นจะไปต่อกับ IDX หรือแก้ไฟล์ผ่าน GitHub อีกเรื่องคือการสร้างไฟล์ EPUB, PDF ผมคิดว่า PDF ปัญหาน้อยกว่านิดหน่อย ถ้าใช้เทมเพลตของ pandoc ก็จบได้เร็ว แต่ถ้าทำเทมเพลตเองก็ต้องไปเขียนสไตล์หรือทำเทมเพตเพิ่มเติมตอนนี้ยังไม่อยากทำขนาดนั้น ก่อนจะบ่นไปไกลสรุปเรื่องอัพโหลดไฟล๋นิดนึง

  • meb อัพโหลดไฟล์ EPUB ไม่ได้ แจ้ง File upload failed
  • Google Play Books อัพโหลดผ่านทั้ง EPUB, PDF
  • Hytext อัพโหลดผ่านทั้ง EPUB, PDF ยังต้องรอคอนเฟิร์มอีกครั้ง
  • Pinto อัพโหลดผ่านทั้ง EPUB, PDF ยังต้องรอคอนเฟิร์มอีกครั้ง
  • Naiin อัพโหลด PDF ได้ แต่ไฟล์ EPUB ไม่รู้ว่าอัพโหลดได้ที่ไหน
  • ChulaBook ต้องแจ้งพนักงานของศูนย์หนังสืออัพโหลดไฟล์ให้ คิดว่าไม่น่าจะมีปัญหา

ถ้าได้ข้อสรุปเพิ่มเติมจะมาอัพเดทข้อมูลอีกรอบ

ติดตั้ง SAMBA ใน Raspberry Pi แบบเร็วๆ


23 Dec 2024, 17:14

ช่วงนี้เร่งหนังสือเพราะเปลี่ยนมาใช้ markdown เขียนต้นฉบับแล้ว แต่ยังไม่ได้ทำ build workflow สำหรับ GitHub Action เลยใช้วิธีการเสียบ thumbdrive ก๊อปปี้ไฟล์จาก labtop มา tablet ปกติจะใช้เสียบสายแล้วส่งไฟล์ผ่าน Calibre ตอน gen ไฟล์ แต่ตอนนี้มีแต่ gen script เลยต้องก๊อปปี้ไฟล์แทน :(

ไปค้นลังเจอ SSD 2 อันเลย backup disk ไว้อันนึง พอดีได้คุยกับพี่เอ๋อวยชัย แห่ง Linux Home Server แนะนำเรื่อง NAS ก็เลยงงๆ ว่าต้องลง SAMBA มั๊ย สุดท้ายไปค้น RPI ได้มา 3 ตัว เย้ยยยยย จะดองเยอะอะไรขนาดนั้น ก็เอามาตัวนึงมี SDCard จิ้มไว้อยู่แล้ว เลยสั่ง dist update ได้ linux kernel 6 มาสวยเลย กดลง docker แป๊ปๆ ก็ได้ใช้ละ พอได้ docker มาก็จัด SAMBA เลย

แปะ docker-compose.yaml ไว้นิดนึง

services:
            samba:
              image: dockurr/samba
              container_name: samba
              environment:
                NAME: "Data"
                USER: "samba"
                PASS: "sambamamba"
              ports:
                - 445:445
              volumes:
                - /home/storage:/storage
          

สรุปได้ SAMBA ไว้แชร์ไฟล์ระหว่าง PC กับ tablet แบบเร็วๆ ละ :)

เครื่องมือเขียนหนังสือตัวใหม่อีกรอบ


22 Dec 2024, 17:14

เคยเล่าไปในpost ที่แล้วว่าเปลี่ยนเครื่องมือในการเขียนหนังสือใหม่ ครั้งนี้มาเล่าเรื่องตัว สคริป generate ไฟล์ EPUB, PDF นิดนึง เพราะใช้สูตรโกงไว้ เนื่องจากที่เครื่องไม่มี LaTex เลยใช้การแปลงจาก Markdown ไปเป็น EPUB ก่อน แล้วค่อยแปลง EPUB ออกมาเป็น PDF อีกทีนึง แต่ปัญหามันไม่ได้จบแค่นั้นเพราะ pandoc ที่สร้างไฟล์ EPUB ออกมาดันเป็น EPUB รุ่นเก่า (ต้องไปแก้ template ใหม่) ทดลองเอาไฟล์ขึ้น Google Play Books แล้วไม่รอด ... เหนื่อยใจเลย ไฟล์ PDF ไม่มีปัญหาอะไร ส่วนแพลตฟอร์มอื่นๆ ก็คงต้องรอลุ้นว่าจะได้ไหม เอาเป็นว่าปั่นต้นฉบับเสร็จตอนไหนก็คงได้รู้ว่า ไฟล์ EPUB ที่สร้างออกมา ใช้งานกับแพลตฟอร์มไหนได้บ้าง

โน๊ตไว้นิดนึง ผมทำเทมเพลตไว้ยังไม่ได้เขียน workflow สำหรับ GitHub Actions น่าจะอีกสักพักล่ะ

เปลี่ยนเครื่องมือเขียนหนังสืออีกแล้ว


16 Dec 2024, 16:25

ผมกลับมาเขียนหนังสือด้วย Markdown อีกรอบรู้สึกคาใจเรื่อง EPUB มาก จริงๆ ส่งไฟล์ docx ไปให้แพลทฟอร์มทำไฟล์ให้ก็ได้ แต่อยากทำเองมากกว่า เพราะยังไงก็เขียน Markdown อยู่แล้วก็เลย ใช้เขียนหนังสือด้วยเลยน่าจะดี จากที่ได้ทดลองแปลงไฟล์จาก Markdown เป็น EPUB นี่ทำได้อยู่แล้ว จะได้ไฟล์ EPUB ที่คลีนมาก ไฟล์ที่ได้มีขนาดเล็กกว่าการแปลงไฟล์จาก docx ไปเป็น EPUB มาก

จากครั้งที่แล้วใช้ IDE ในเว็บเขียนและ export ไฟล์ออกมาเป็น Markdown แล้วมาแปลงเป็น EPUB แบบ manual ครั้งนี้เขียนเขียนเป็น script สร้างไฟล์ก่อน คิดว่าจะเอาไปใส่ใน GitHub Actions เวลา build ไฟล์จะได้สะดวกมากขึ้น

เครื่องมือสำหรับแปลงไฟล์ใช้ pandoc เหมือนเดิม การแปลงไฟล์ Markdown ไป EPUB ด้วย pandoc เราสามารถใช้ template, css, font ที่เราต้องการได้ ก็เลยทำไฟล์ EPUB ได้สะดวกหน่อย แต่ไฟล์ PDF จะต้องใช้ pdf engine อย่างเช่น LaTex ร่วมด้วย

ผมไม่ได้เขียน LaTex มานานมากและลืมหมดแล้ว ก็เลยใช้ Calibre ช่วยแปลงจาก EPUB เป็น PDF แทน เพราะใส้ใน EPUB เป็น html อยู่แล้ว แปลงไฟล์ได้ง่ายมากกว่า ไฟล์ PDF ที่ได้ออกมาใช้ได้ดีเลย เราสามารถตั้งค่าเพิ่มเติมได้หลายอย่าง เช่น metadata, font, page size, page margin ฯลฯ แต่เรื่องการใส่เลขหน้า ใส่สารบัญ สลับหน้า ฯลฯ ต้องใช้ pdf tools ตัวอื่นมาทำภายหลัง

ผมก็เลยเขียนสคริป python เอา py2pdf, report มาตัดต่อไฟล์ ใส่เลขหน้า ฯลฯ แต่ bookmark ที่สร้างจาก pandoc หายเกลี้ยง 555 สรุปว่ามีงานงอกเพิ่ม เดี๋ยวคงได้หาวิธีที่ดีกว่านี้

ทำ Dart Package เอาไว้เยอะ แต่ลืมว่ามีอะไรบ้าง


10 Dec 2024, 10:20

ทำ Dart Package ไว้เยอะ เพราะไล่ patch เอาไว้ใช้สำหรับโปรเจคที่ทำในตอนนั้น ซึ่งโดยปกติก็จะส่ง patch ไปให้ upstream โดยตรง ไม่ได้ fork มาทำ package ใหม่ ส่วนจะได้ merge เข้า upstream ไหม ผมก็ไม่ได้สนใจไปตามดู จริงๆ ก็ไม่ได้สนใจล่ะ และก็มี Dart Package อีกจำนวนนึง ที่เขียนเอาไว้ใช้เอง publish ใน pub.dev และเอาไป "เล่า" ใน Live ได้

พอมีน้องท่านนึงถามมา ก็นึกไม่ออกเลยเพราะไม่ได้รวมไว้เป็นที่เป็นทาง เท่าที่ได้รวมไว้ ใน uikits template เป็นตัวอย่างแอปที่ live ในแต่ละสัปดาห์ มีบางส่วนที่เป็นเนื้อหาเกี่ยวกับการสร้าง Dart Package ก็จะรวมอยู่ไว้ที่เดียวกัน บางส่วนก็อยู่ใน GitHub แต่ไม่ได้รวมไว้ใน uikits และ pub.dev ก็เลยกลายเป็นว่า "ลืม" เอาเป็นว่าไปตามดูที่ uikits และ pub.dev ละกัน

เพจ Dart แบบ Dart Dart Live ครบ 200 ตอนแล้ว


09 Dec 2024, 10:32

เพจ Dart แบบ Dart Dart Live ครบ 200 ตอนแล้ว ถ้าจะนับกันจริงๆ ก็คงมากกว่า 200 ตอน เพราะมีช่วงนึงที่โดนขโมยแอคเคาท์ไปก็เลยต้องเปิดเพจใหม่ ตอนแรกที่เปิดเพจมาก็คิดว่าจะทำเป็น VLog มาเล่าเรื่อง Dart, Flutter ทุกวันอังคาร ระยะหลังๆ ไม่ค่อยมีงานจ้าง ก็เลยเอางานเก่าๆ คำถามจากลูกเพจ มาทำเป็นกรณีศึกษา และเพิ่มเนื้อหาสอดแทรกเข้าไป เพื่อให้เหมาะกับการเอาไปเล่าในเพจ

นอกจาก Live ทุกวันอังคารแล้วก็คงมีงานหนังสือที่เขียนๆ หยุดๆ พอๆ กัน Course Online เพราะเทคโนโลยีมันขยับไปไวมาก เนื้อหาไม่เท่าไรเพราะเปลี่ยนไม่เยอะมาก มีแต่เพิ่มเนื้อหามากกว่า แต่รูปภาพเนี่ยเปลี่ยนเยอะเลย ก็เลยดองไว้นานมาก คิดว่าน่าจะทะยอยอัพเดทละ

นึกสนุกไปทำ Jaspr UI Component งานงอกเลย


08 Dec 2024, 17:04

ตัดสินใจเขียนหนังสือสูตรลัด Jaspr เพราะคิดว่าโปรเจคนี้แปลกและน่าสนใจดี จนได้ใช้ Jaspr, Tailwind CSS และไปเขียน Component สำหรับ Jaspr มาจำนวนนึง แต่เนื่องจากไม่ได้เขียน Website นานมากแล้ว ก็เลยออกแบบ Component ได้ไม่ดีเท่าไร ตั้งค่าได้น้อยไปนิด แต่ก็ได้ประสบการณ์ที่ดี

Jaspr UI Component ใช้ Tailwind CSS และ DaisyUI ทำให้ขึ้นโครงของ UI Component ได้ง่ายขึ้น แต่ตอนออกแบบไม่ได้ทำเผื่อเรื่องตั้งค่าก็เลยปรับแต่งได้น้อยไปนิดหน่อย ตอนนี้มี Component 50 ตัว ครอบคลุมการใช้งานพื้นฐาน เรียกได้ว่าหยิบเอามาประกอบร่างได้เลย :) หลังจากที่ทำ Jaspr UI Component ไปแล้วก็เลยอัพเดท Website ที่ทำจาก Flutter for Web มาเป็น Jaspr สำหรับ WebApp บางตัวยังคงใช้ Flutter for Web อยู่

เว็บ UIKits Library รวมตัวอย่าง UI และงาน demo บลาๆ


09 Sep 2024, 20:02

มีลูกเพจทักมาบอกว่าอยากให้รวมตัวอย่างแอปใน Live ทุกๆ สัปดาห์ เอาจริงๆ ตัวอย่างมันเยอะมาก Live มา 190 ตอนแล้ว T_T ก็เลยเอาโปรเจค UIKits มาปัดฝุ่นก่อน แล้วทำเว็บ Library แบบกด copy code ในหน้าเว็บได้เลย เอามาใส่ก่อน แล้วค่อยทะยอยเอาตัวอย่างแอปมาขึ้นอีกที ใครสนใจก็กดไปดูกันได้ที่ UIKits Library

Backup ข้อมูลใน Firebase FireStore และเอามาใช้งานกับ Emulators


21 Aug 2024, 22:24

พอดีต้องย้ายข้อมูลจาก Firebase เอามาใช้งาน dev ที่เครื่องตัวเองเพราะว่าติดเรื่อง AppCheck เลยไม่อยากไปตั้งค่า debug บ่อยๆ เพราะเดียวจะลืมเอาออก ก็เลย export ข้อมูลมาทำงานที่เครื่องตัวเองดีกว่า

เครื่องมือที่ต้องใช้ได้แก่ Firebase CLI, gcloud CLI

  1. ล็อกอิน Firebase
firebase login
          
  1. เรียกใช้งาน project ของคุณ
firebase use your-project-name
          
  1. สั่ง export ข้อมูลไปเก็บไว้ใน Cloud Storage
gcloud firestore export gs://your-project-name.appspot.com/<your-choosen-folder-name>
          
  1. สั่ง copy ไฟล์จาก Cloud Storage ลงมาที่เครื่อง
gsutil -m cp -r gs://your-project-name.appspot.com/<your-choosen-folder-name> /path/to/some/folder
          

เข้าไปที่ folder ของคุณ

cd /path/to/some/folder
          

จากนั้นเปลี่ยนชื่อไฟล์ metadata เป็น firestore_export.overall_export_metadata

mv your-choosen-folder-name.overall_export_metadata firestore_export.overall_export_metadata
          

แล้ว copy ไฟล์ที่ได้เอาไปใช้งาน

cp -R * /path/to/workspace/emulator/emulators_data/firestore_export/
          

เรียกใช้ Firebase Emulator ด้วยตำสั่ง

firebase emulators:start --import=./emulators_data/firestore_export --export-on-exit
          

แอปแบบ


03 Apr 2024, 00:38

เมื่อเดือนมีนาไปก่อเรื่องไว้ พอดีก็อยากได้ความเห็นจากชาวโซเชียล เรื่องของการทำแอปแบบ Agoda, Lazada, Shopee บลาๆ ประเด็นคือ มีคนมาให้วิเคราะห์และทำใบเสนอราคาบ่อย คือ ทำใบเสนอราคาแล้วหายไปเลยก็บ่อยมาก บางทีก็เอาเอกสารที่เราวิเคราะห์เอาไปจ้างคนอื่น ทั้งๆ ที่เราเป็นคนวิเคราะห์ขั้นต้นให้

ความเห็นจากชาวโซเชียลก็เละเทะตามคาด หลายคนก็บอกว่าเนี่ยราคาประเมินแบบนี้ไม่พอหรอกเข้าเนื้อแน่นอน บางท่านก็มาคอมเม้นแบบว่าเพื่อนทำอยู่ได้เดือนละ 100,000 ราคานี้ไม่ได้แน่นอน บางท่านก็บอกว่าแค่ database ก็ไม่พอแล้ว ฯลฯ ซึ่งก็เละเทะดี ผมชอบ...

ที่บอกว่าชอบ เพราะจะได้เอาคอมเม้นต่างๆ เหล่านี้ไปให้ ไอ่คนที่ชอบมาให้ทำใบเสนอราคาแอปแบบ ไปไล่อ่านดูว่าไอ่ราคาที่อยากจ่ายน่ะ ชาวโซเชียลยังบอกเลยว่ามันไม่พอเฟ้ย และไอ่ที่คิดราคาให้แต่ละครั้งเนี่ยราคาใกล้เคียงสำหรับเริ่มต้นมากแล้ว

แปะลิงค์ไว้สักหน่อย

ปล. อ.เดฟ มาโพสตอบ ในโพสของชาวโซเชียล(แชร์โพสไป) ซึ่งก็ใช้แนวทางที่ผมประเมินราคาแบบเร็วๆ ล่ะ ลองอ่านดูแล้วจะเข้าใจ

EPUB เราไม่เท่ากัน ภาค 3


24 Mar 2024, 11:05

พยายามทำไฟล์ EPUB มาหลายรอบ เนื่องจากรูปแบบ EPUB บน Google Play Books และบน meb แตกต่างกัน ก็เลยพยายามไฟล์ EPUB ให้อัพโหลดบน Google Play Books ให้ได้ก่อน ปีที่แล้วใช้วิธีการ export ไฟล์ epub จาก Google Docs มาแก้ไขเรื่อง Table of Content ใน Sigil นิดหน่อย แล้วอัพโหลดไปที่ Meb และ Google Play Books ได้ แต่ยังติดปัญหาเรื่องขนาดตัวอักษรและสไตล์อื่นๆ ที่ฝังมากับไฟล์ EPUB ซึ่งก็แน่นอนว่า Tag มันดูยุ่งเยิงไปหมด

ครั้งนี้เลยใช้วิธีการปกติคือ export ไฟล์ docx จาก Google Docs แล้วใช้ Calibre สร้างไฟล์ EPUB ให้ โดยที่สั่ง clear style ที่ไม่จำเป็นออก เช่น font เพราะเราจะใช้ font ที่มีอยู่ในเครื่องหรือแอปในการแสดงผล อาจจะไม่สวยเท่าต้นฉบับ แต่การ render ทำได้ดีกว่าแน่นอน อีกเรื่องคงเป็นขนาดภาพ ระยะ indent ของ bullet list และ ordered list เป็นต้น

จากที่ลองทดสอบสร้างไฟล์ EPUB แล้วลอง Edit ดูพบว่า CSS ที่สร้างออกมาไม่ค่อยคงที่ ขึ้นอยู่กับ style ที่ใช้ในเอกสารด้วย ซึ่งก็ยังไม่มีวิธีแก้แบบอัตโนมัติ แต่ถ้าจะให้เอกสารมันดูสะอาด ก็คงต้องใช้ Markdown แล้วแปลงไปเป็น EPUB จะดีกว่ามาก แต่ครั้งนี้ก็ได้ประสบการณ์ที่ดี อ้อ ยังไม่ได้ลองอัพโหลดไปที่ meb ว่าใช้ได้ไหม แต่ที่แน่ๆ Google Play Books ใช้ได้แล้ว

แก้ Error Ports are not available ใน Windows


23 Feb 2024, 10:57

เจอปัญหาเรื่อง Port ชนใน Docker แต่ไม่ได้มีการเรียกใช้ port นั้นเลยสัก service ก็เลยสงสัย ก็ปรากฎว่ามันไปอยู้ใน reserve port ของ WinNAT ซะงั้น

Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:5432 -> 0.0.0.0:0: listen tcp 0.0.0.0:5432: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
          

ให้ดูรายการ port ก่อนว่าถูกจองไว้ไหม

netsh interface ipv4 show excludedportrange protocol=tcp
          

ใช้ terminal สิทธิ์ admin สั่ง stop WinNet ไปก่อน

net stop winnat
          

จากนั้นถอดรายการ port ที่เราจะใช้ออก

netsh int ipv4 add excludedportrange protocol=tcp startport=5432 numberofports=1
          

จากนั้น start service WinNat กลับขึ้นมาคืน

net start winnat
          

แค่นี้ก็เรียบร้อยละ

อัพเดทหนังสือ


23 Feb 2024, 10:57

ผมเขียนหนังสือมาครบ 10 เล่มแล้ว ก็เลยได้โอกาสอัพเดทหนังสือเล่มเก่าด้วย ช่วงนี้ก็เลยไล่ทะยอยอัพเดทหนังสือ ตามลำดับดังนี้

  • สูตรลัด Dart Frog
  • สูตรลัด Dart 3
  • สูตรลัด Flutter
  • สูตรลัด FlutterFire
  • สูตรลัด GetX
  • สูตรลัด Hasura
  • Material Design 3

สำหรับคนที่ซื้อหนังสือจาก Meb ก็สามารถอัพเดทหนังสือได้เลย

เขียนหนังสือสูตรลัด Serverpod


10 Feb 2024, 09:57

ช่วงต้นเดือนมกราคมที่ผ่านมา Serverpod ประกาศออกรุ่น 1.2 ก็รู้สึกดีใจที่โปรเจคนี้มันยังไม่เจ๊ง เอ่อ...เจ๊งตอนนี้ก็คงไม่ได้เพราะกวาดเงินนักลงทุนไปหลายราย พอมาดูรายละเอียดที่อัปเดทมาก็ประทับใจ เพราะมีฟีเจอร์ที่ขาดหายไปหลายตัว เช่น migration, websocket, file upload เป็นต้น แต่ด้วยความที่ lead developer ทำงานกับ Zynga และเคยอยู่ในทีม Flutter ที่ Google มาก่อน สไตล์การทำ feature release น่ากลัวมาก คือ ออก feature ใหม่ doc ไม่อัพเดท แล้วก็ไล่ patch ไปเรื่อยๆ แล้วเขียน doc ไล่ตามหลัง ก็เลยต้องชั่งใจว่าจะเขียนหนังสือเล่มนี้ดีมั๊ย สุดท้ายก็เขียนจนได้ เพราะดู roadmap แล้วไม่น่าจะมีอะไร breaking change แล้ว ใครสนใจหนังสือสูตรลัด Serverpod ก็ซื้อกันได้ที่ Meb เหมิอนเดิม

ทำอะไรบ้างในปี 2023


27 Dec 2023, 17:04

ปกติปลายปีก็จะเขียน New Year's resolution และทำ After Action Review ของปีนั้นซึ่งในปีนี้ก็ทำงานน้อยมาก และรายได้ก็น้อยลงเช่นกัน

  • อัดรายการวิทยุครบสัญญาจ้าง 9 เดือน (จำนวนตอนรายการครอบคลุมถึง 12 เดือน)
  • รับงานทำ Solution 4 งาน โดนเท 3 งาน ปิดได้ 1 งาน
  • เขียนหนังสือเพิ่มอีก 6 เล่ม รวมทั้งหมด 9 เล่ม (จากที่ตั้งใจไว้ 12 เล่ม)
  • Live ในเพจ Dart แบบ Dart Dart สัปดาห์ละ 1 ครั้ง ตอนนี้มีทั้งหมด 154 ตอน
  • ทำเว็บ uLearning เปิดคอร์สเรียนออนไลน์ มีผู้ใช้ 79 คน
  • ตัดสินใจไม่ต่ออายุ Web Hosting เปลี่ยนมาใช้ SPA และ Markdown แทน
  • ให้คำปรึกษาแบบไม่คิดเงินเยอะมากอีกหน่อยต้องเก็บเงินละ
  • เปิดโปรเจคโอเพนซอร์สเข้าร่วมโครงการ HacktoberFest ครั้งที่ 10 ปีนี้สนุกและได้ความรู้

ปีหน้าทำแผนงานที่ยังไม่ได้ทำจริงจังอีกหลายตัว

  • คอร์สออนไลน์เน้นทำโปรเจค
  • Live ในเพจ Dart แบบ Dart Dart เน้นเนื้อหาเข้มข้นมากขึ้น
  • รื้องานที่โดนเทเอามาทำโซลูชั่นขาย
  • เขียนหนังสือเพิ่ม 3 เล่ม
  • อัพเดทเนื้อหาหนังสือ 4 เล่ม

หมดงาน


09 Oct 2023, 16:39

หมดสัญญาจ้างจัดทำรายากรวิทยุซึ่งก็ไม่รู้ว่าจะมีอีกไหม ก็เลยคิดว่าน่าจะได้เวลาเอาโปรเจคที่โดนเทเอามาทำขายบ้างน่าจะดี ซึ่งบางโปรเจคได้เริ่มงานออกแบบไปบางส่วนแล้ว บางโปรเจคก็โดนเทตั้งแต่ส่งใบเสนอราคา แต่ก็ไม่เป็นไรเดินหน้าต่อไป โปรเจคไหนขายได้ก็ทำขาย อันไหนขายไม่ได้อย่างน้อย งานออกแบบก็ขายได้

ปีนี้ทำ checklist ว่าจะต้องทำอะไรบ้างใน 6 เดือนแรก นี่ก็เข้าเดือนที่ 10 แล้ว คงมีแต่เรื่องเอาโปรเจคเก่าๆ มาทำต่อนี่แหละ ส่วนเรื่องคอร์สออนไลน์คงต้องพักสักหน่อย เพราะงานวิดีโอเหนื่อยกว่างานเขียนหนังสือและงานทำต้นแบบ เพราะต้องเตรียมเนื้อหา ตัวอย่าง อัดวิดีโอ ตัดต่อ อีก 3 เดือนสุดท้ายของปีคงตะลุยทำโปรเจตที่โดนเทออกมาขายล่ะ

อัพเดทโครงการ μLearning


26 Jul 2023, 21:37

ตัดสินใจรื้อโครงการ μLearning รอบที่ 3 ซึ่งทำไปทำมาได้เหมือนระบบเหมือนเดิมซะงั้น เอาเป็นว่า μLearning ยังคงแนวคิดเป็นเว็บ eCommerce มากกว่า eLearning ซึ่งก็แน่นอนว่าเอาผลิตภัณฑ์ที่มี มาต่อยอดขายผ่านเว็บ μLearning นั่นเอง ซึ่งมีสินค้าอยู่ 3 กลุ่ม คือ

  1. คอร์สเรียนออนไลน์แบบเรียนผ่านวิดีโอ
  2. หนังสือซึ่งปกติก็จำน่ายผ่าน
  3. โปรเจคสำเร็จรูปพร้อมใช้งาน

วางแผนเรื่องนี้มาหลายเดือนซึ่งคอนแรกจะเอาไปขึ้นขายที่ Envato แต่ก็ยังไม่ได้เอาไปขายสักที ก็เลยตัดสินใจทำเว็บ eCommerce ขายเองละกัน ก็เลยมาเป็น μLearning นี่แหละ สำหรับใครที่อยากลงทะเบียนเรียนก็ กดลิงค์ https://learn.redlinesoft.net ได้เลย

ใช้ Prisma Dart บน Docker


10 Jul 2023, 21:16

ตัดสินใจเขียนหนังสือ Dart Frog เพราะเห็นว่าเครื่องมือมันเจ๋งดี คิดว่าจะเอามาใช้งานร่วมกับ Prisma ก็เลยเขียนหนังสือไปด้วย ได้ทดลองอะไรใหม่ๆ ไปด้วย สิ่งที่น่าสนใจของ Dart Frog คือความยืดหยุ่น โดยเฉพาะเรื่อง route นี่เท่ห์มาก ทำ dynamic route จากชื่อไฟล์ได้ด้วย

ปัญหาที่เจอถัดมาคือการ build ซึ่ง build ออกมาได้สวยงามมาก มี Dockerfile ออกมาพร้อมเลย แต่ว่าถ้าเอาไปใช้งานจริง เช่น ใช้งานกับ Prisma จำเป็นต้อง generate code จาก Prisma ก่อน อีกเรื่องคือ prisma query-engine-debian-openssl-1.1 ก็เลยทำให้ได้ เขียน Dockerfile ใหม่ยกแผง ทั้ง Dockerfile และ Docker compose ด้วย แต่โดยไอเดียของการ Deploy บน Cloud Run และ App Platform ทำได้ดีมากเลย แต่ก็นั่นแหละถ้าต้องเชื่อมต่อกับระบบฐานข้อมูลด้วย Prisma ก็งานงอกเหมือนเดิม

Prisma เราไม่เท่ากัน


06 Jul 2023, 12:41

มีน้องแนะนำ Prisma ได้ลองเล่นบน Next.js แล้วชอบมาก พอมีคน port ไป Dart ก็รู้สึกตื่นเต้น เพราะใช้คำสั่งจาก prisma cli ได้ สร้าง schema ทำ migration ได้ และใช้ prisma studio ได้เหมือนเดิม ก็ Prisma แหละ แต่ที่เพิ่มเติมคือ ตอน build client จากเพิ่มที่เป็น JS ก็กลายมาเป็น Dart ORM แทน สั่ง generate client มาใช้งานได้เลย เรียกได้ว่าสุดประทับใจ

แต่... มันไม่เหมือน Prisma บน Next.js ซะทีเดียว ก็เลยใช้ feature อย่างเช่น select, include ไม่ได้ ซึ่งก็น่าเสียดายมากๆ แต่ถ้าถามว่าชอบไหม ก็ชอบล่ะ แต่การเอาไปใช้จริงจังอาจจะต้องเขียนเพิ่มเติมอีกเยอะ เช่น select และ include เป็นต้น

Dart ฝั่ง Server มีโปรเจคไหนน่าเล่นบ้าง


03 Jul 2023, 12:19

ช่วงนี้ได้เล่น Dart ฝั่ง Server มาหลายตัว ตั้งแต่ช่วงปลายปี 2018 เป็นต้นมาที่มีนักพัฒนาซอฟต์แวร์โอเพ่นซอร์สหลายคนทำโปรเจคออกมาเยอะ ทั้งไปรอดและไปไม่รอด ก็เลยมารวบรวมไว้สักหน่อย

  1. Aqueduct
  2. Jaguar
  3. Angel Framework
  4. Get Server
  5. Shelf
  6. Serverpod
  7. Dart Frog

โดยส่วนตัวยังชอบ Angel, Get Server อยู่ ส่วน Dart Frog กำลังเล่นและทดลองใน use case ต่างๆ อยู่

EPUB เราไม่เหมือนกัน


24 May 2023, 11:47

หลังจากพยายามสร้างไฟล์ EPUB จากหลากหลายวิธี ก็ทำสำเร็จ อัพโหลดไปได้ทั้ง Google Play Books และ Meb ผมก็พยายามใส่ font เข้าไปด้วยจะได้เอาฟอนต์มาใช้ได้เลย กลายเป็นว่า Meb ไม่ render font ที่ใส่เข้าไปซะงั้น แถมยัง render ข้อความออกมาไม่ค่อยจะสวยเท่าไร แต่ใน Google Play Books ออกมาสวยงามมว๊าก

เอาเป็นว่าทำสำเร็จครึ่งนึงละกัน ไว้คราวหน้าพยายามใหม่ สำหรับ Meb ก็คงต้องแก้ไขเรื่องการจัดหน้าใหม่และอาจจะให้ Meb ทำไฟล์ EPUB ให้จริงๆ ล่ะ

ยังคาใจเรื่อง EPUB อยู่


22 May 2023, 10:02

ผมใช้ Google Docs เป็นหลักในการเขียนหนังสือและทำเอกสารต่างๆ ล่าสุดก็ยอมติดตั้ง WPS Office เพื่อใช้อ่านไฟล์ docx และ xlsx แต่ก็ยังไม่ย้ายไปใช้ WPS Office นะ เพราะชีวิตยังอยู่บน online มากกว่า offline ขนาดเขียน blog ยังเขียนใน GitHub เลย T_T

ล่าสุดก็พยายามหาข้อมูลเรื่องการจัดหน้าหนังสือก็ไปเจอ YouTube Channel ของน้องโม Sensei Gokko หรือ โมณฌา ก็เลยได้ความรู้ด้านการทำหนังสือ ebook แบบจริงๆ น้องเป็นนักเขียนของสำนักพิมพ์แจ่มใส มีผลงานหลายเล่มการันตีได้เลยว่า "เมพ" จริง หลังจากดูวิธีการกับเทคนิดการจัดหน้าหนังสือก็ปรับเอามาใช้กับ Google Docs ได้เลย เพราะวิธีการตั้งค่าไม่แตกต่างกันมาก

เรื่อง EPUB เป็นเรื่องที่คาใจมาก เพราะผมยังทำไฟล์อัพโหลดไป Google Play Books กับ meb ไม่ได้ มี error เหมือนกับ format ของ EPUB ไม่ตรงเวอร์ชั่น ผมไม่แน่ใจว่า meb ใช้ EPUB2 หรือ EPUB3 แต่เท่าที่ลอง พังทั้งคู่ T_T จากที่ดูวิธีการของน้องโม ก็สรุปได้ว่า "ให้ meb ทำให้" และ ทำ "ไฟล์ตัวอย่างหนังสือ" แยกจากไฟล์หนังสือ อาจจะดูหลายขั้นตอน แต่ก็ขึ้นอยู่กับรูปแบบและเนื้อหาของหนังสือด้วย

สำหรับผมที่ลอง epub กับ Google Play Books ก็พบว่าไม่สามารถแยกไฟล์ออกเป็นบทๆ ได้ เจอ error ยาวเหยียดเรื่อง link ไฟล์ xhtml ก็เลยใช้ Google Docs export ออกมาเป็น epub แล้วไปแก้ไข Metadata + Bookcover ใน Sigil แทน หรือจะใช้ Calibre ก็ได้ แต่อย่าสั่ง flatten ไฟล์ ก็สามารถอัพโหลดหนังสือแบบ epub ขึ้น Google Play Books ได้แบบปกติ

นอกจากเรื่องเทคนิคการทำหนังสือ ebook ก็ยังมีข้อมูลต่างๆ ที่คนทำหนังสือ ebook น่าจะรู้ เช่น การอัพโหลดไฟล์ การจด ISBN สำหรับหนังสือเป็นเล่ม และเป็น ebook เป็นต้น คิดว่าใครอยากทำหนังสือ ebook ก็แนะนำให้ไปติดตามน้องโมกันได้

สร้างไฟล์ EPUB จาก Google Docs


07 May 2023, 10:02

ผมใช้ Google Docs เขียนหนังสือเพราะมันสะดวกมาก ใช้ tablet หรือ notebook ก็สามารถเขียนหนังสือได้ที่สำคัญคือใช้งานแบบออฟไลน์ได้ด้วย และ export ไฟล์ได้หลายรูปแบบมี EPUB ด้วย จากที่พยายาม export ไฟล์แบบ EPUB มาหลายครั้ง พบว่ามีปัญหาเรื่องรูปแบบเอกสารที่ไม่ตรงกับ style ที่ตั้งค่าไว้ เอกสารก็เลยดูเละ อีกเรื่องก็เป็นเรื่อง cover และ metadata ของไฟล์ EPUB มันตั้งค่ายากมาก และ Google Docs ไม่รองรับซะด้วย

ผมก็เลยพยายามทำไฟล์ EPUB อีกรอบ อยากสร้างไฟล์ EPUB ได้เอง จะได้ไม่ต้องให้ทาง platform ทำให้ ซึ่ง meb มีบริการสร้างไฟล์ EPUB ด้วยนะ หลังจากค้นหาวิธีสร้างไฟล์ EPUB ก็ได้เจอเครื่องมือแบบออนไลน์หลายตัว เช่น designrr และ fiverr ดูน่าสนใจมาก แต่ก็ไม่ได้ลองใช้งาน

สุดท้ายก็เลยได้ใช้เครื่องมืออย่าง Sigil ใช่เลย เครื่องมือโบราณที่ใช้สร้างไฟล์ EPUB นี่แหละ วิธีการคือ export ไฟล์ Google Docs มาเป็น EPUB แล้วใช้ sigil แก้ไข style sheet ในไฟล์ EPUB เพิ่ม cover เพิ่ม metadata ของหนังสือใน sigil ได้เลย อ้อที่สำคัญที่สุดคือ ไฟล์ต้นฉบับใน Google Docs ไม่ต้องจัดหน้าสวยงาม ใส่แค่ style sheet เพื่อเรียงลำดับหัวข้อเอาไว้ก็พอ เพราะยังไงก็ต้องมาแก้ไขไฟล์ใน sigil กรณีที่หัวข้อมันกระโดดอยู่แล้ว

ตอนนี้ก็ได้วิธีสร้างไฟล์ EPUB แล้ว หนังสือเล่มต่อไปคงทำเป็น EPUB ก่อน แล้วค่อยไปจัดหน้ากระดาษใหม่อีกรอบแล้วทำเป็นไฟล์ pdf ได้ประสบการณ์ใหม่จากการเขียนหนังสือเพิ่มอีก

เขียน Blog สั่ง Auto Update ผ่าน GitHub Actions


04 May 2023, 12:00

หลังจากพยายามเขียน Blog ด้วย Flutter for Web มาสักพัก ก็พอจะเข้าใจล่ะว่า Flutter for Web มันไม่ค่อยเหมาะกับ Web Content โดยเฉพาะ Blog นี้ตรงตัวเลย คือ ไม่เหมาะอย่างมาก หลายคนมักจะพูดเรื่อง SEO บลาๆ ซึ่งผมเองก็ใช้ WordPress มาตลอดเลยนึกไม่ค่อยออกเท่าไร WordPress มันทำให้หมดก็เลยไม่มีความรู้ด้านนี้เท่าไร แต่ก็นั่นแหละ โจทย์คือ ไม่ต่ออายุ Hosting และเขียน Web แบบครึ่งๆ กลางๆ โดยใช้ Flutter for Web และ Firebase Hosting นี่จะทำยังไง

ได้ไอเดียมาจาก Jekyll และ Hugo มา ก็เลยเขียน Markdown และข้อมูลของหน้า แยกเป็นไฟล์ย่อยๆ แล้วให้ CI สั่ง generate ไฟล์ที่จำเป็นออกมา เช่น sitemap.xml, rss.xml, markdown content ที่เป็น markdown ล้วนๆ ตอนแสดงผลก็เรียกไฟล์ออกมาแสดงผล เป็นเว็บแบบ SPA (Single Page Applications) ซึ่งก็น่าจะพอถูไถไปได้ แต่อย่าเพิ่งพูดถึง SEO หรือแบ่งเป็นหน้าๆ เพราะตอนนี้ เอาแค่หน้าเดียวก่อนละกัน

ประเด็นเรื่อง Flutter for Web นี้มีหลายเรื่องต้องคิด ทั้ง State ของหน้า ทั้ง Routing ของหน้า จำได้ว่าทำ Web Microlearning ใช้ Flutter for Web นี่ต้องคิดหลายมุม แต่ก็ได้ best practice มาในเรื่อง State Management ก็เป็นเรื่องที่แปลกใหม่ดี

เล่ายาวไปไกล กลับมาเรื่อง Blog ที่เขียน ก็นั่นแหละถ้า CI/CD อยู่บน Github ก็ใช้ Github Actions สั่งสร้างไฟล์ต่างๆ และ build Flutter Web application พร้อม deploy ไปยัง Firebase Hosting ซึ่งดูง่ายมากๆ คิดว่าน่าจะต้องทำแบ่งหน้า ไม่ก็สั่ง generate จาก HTML template น่าจะดี ... เขียนไปเขียนมา กลายเป็น Hugo เวอร์ชั่น Dart ซะงั้น ^o^

เขียนหนังสือ


04 May 2023, 12:00

ปีที่แล้วตั้งใจเขียนหนังสือ 3 เล่ม ก็เร่งปั่นต้นฉบับออกมาให้ทันตามความตั้งใจ สำหรับปีนี้จะเขียนเพิ่มอีก 4 เล่ม รวม 7 เล่ม ซึ่งก็ใกล้ครบแล้ว หนังสือที่วางจำหน่ายแล้ว มีดังนี้

  1. สูตรลัด Flutter
  2. สูตรลัด GetX
  3. สูตรลัด FlutterFire
  4. สูตรลัด Hasura
  5. คู่มือประกอบการเรียน Flutter Crash Course
  6. Material Design 3

เหลือเล่มที่ยังเขียนไม่เสร็จอยู่ 3 เล่ม

  1. สูตรลัด Strapi
  2. Flutter Plugin ที่น่าใช้งาน
  3. สูตรลัด Dart 3

คิดว่าจะเขียนหนังสือสูตรลัด Dart 3 ให้เสร็จก่อน Dart 3 ตัวเต็มจะออก แต่ไอ่หนังสือ Fundamental นี่เขียนยากจริงๆ :D

ทดสอบ Blog ใหม่


04 May 2023, 12:00

เนื่องจากไม่ได้ต่ออายุ Hosting เลยพยายามหาวิธีเขียน Blog แบบรวดเร็ว ตอนแรกก็คิดว่าจะ redirect ไปที่ Medium แต่คิดไปคิดมา อยากทดลองอะไรใหม่ๆ ก็เลยลองทำ static blog จาก Flutter for Web ดู blog อาจจะดูแห้งๆ แต่ก็คิดว่าน่าจะลองทำดู ถ้าไม่รอดก็คงไปใช้ Medium เหมือนเดิม สิ่งที่พยายามทำคือ พยายามไม่ทำอะไรเยอะ เช่น ไม่อยากทำ backend ทั้ง server ทั้ง web backend, ไม่อยากลง Wordpress, อยากได้ blog สไตล์ Ghost แต่ก็ไม่อยากลง ghost cli เป็นต้น ก็นั่นแหละ ก็เลยตัดสินใจไม่ต่ออายุ Hosting และย้ายมาใช้ Firebase + Flutter for Web แทน

แล้วไอ่ blog ที่อยากได้แบบมีเงื่อนไขเยอะแยะนี่คืออะไร ประเด็นก็คืออยากย้ายทุกอย่างเป็นออนไลน์ แบบกึ่ง static web กึ่งออนไลน์ กึ่งออฟไลน์ เก็บข้อมูลลงใน GitHub และใช้ GitHub Actions build web ออกมาให้ เอาล่ะ ยังไงก็ต้องลองดู ถ้าเบื่อแล้วก็คงย้ายไป Meduim เหมือนเดิมละมั๊ง หรือไม่ก็ไม่เขียน blog ไปอีกสักพัก

กลับมาเขียนหนังสือ


10 Sep 2022, 12:00

เคยเขียนหนังสือ PHP, MySQL ตอนปี 3 ป.ตรี ตอนนั้นจะเอาไปพิมพ์ที่สำนักพิมพ์ Witty Group แต่ต้นฉบับเขียนเสร็จช้ากว่านักเขียนอีกท่านนึงก็เลยไม่ได้ตีพิมพ์ T_T จากนั้นก็เลยไม่ได้เขียนอะไรออกมาจริงจัง มีเขียน blog บ้าง จนมาทำงานที่ SIPA รับหน้าที่พัฒนาระบบปฏิบัติการ Suriyan Desktop และ Chantra OpenSource Software for Windows และดูแลเครื่อง Server ของโครงการทั้ง Suriyan, Chantra และเว็บ thaiopensource.org

ก็เลยมีเรื่องให้เขียน blog เรื่อยๆ ซึ่งส่วนใหญ่จะเป็นข่าวในแวดวง Open Source และงานพัฒนา Software ที่ทำอยู่ในรูปแบบ tutorial หลังจากมาทำงานที่ depa ก็ไม่ได้ดูแล thaiopensource.org อีกเลย งานเขียนส่วนใหญ่ก็ไม่ได้ทำ ทำแต่เอกสารการประชุม ตอนนี้ออกจาก depa มาครบ 3 ปีแล้ว ก็รับงานจ้างไปเรื่อยๆ

ช่วงนี้ว่างงาน ไม่มีงานจ้างพัฒนาซอฟต์แวร์ ก็เลยคิดว่าน่าจะหาอะไรทำหารายได้ ถ้ารองานคงไม่ได้ง่ายๆ ซึ่งส่วนใหญ่จะไม่จ้าง T_T ก็เลยได้ลองอะไรใหม่ๆ เช่น Live ในเพจ Dart แบบ Dart Dart และ กลับมาเขียนหนังสืออีกครั้ง ครั้งนี้ไม่ได้เขียนกับสำนักพิมพ์แล้วเพราะคงไม่ได้ตีพิมพ์อีกแน่นอน อีกอย่างกระแสการอ่านผ่าน ebook จาก app ในมือถือ และ tablet สะดวกกว่ามาก ก็เลยเขียนหนังสือขายลง platform ต่างๆ น่าจะดีกว่า

เขียนหนังสืออะไรดี นั่นสิ ปกติก็เขียน tutorial มาตลอด พยายามเขียนในรูปแบบเนื้อหา ก็รู้สึกอึดอัด ไม่สนุกและเขียนไม่ออก ก็เลยกลับมาเขียนเชิง tutorial เหมือนเดิม และเพิ่มความเสียดสีเข้าไปนิดหน่อย คือ ถ้าไม่ชอบอ่านก็ก๊อปโค้ดวางละกัน ก็เลยกลายเป็น “หนังสือชุดสูตรลัดก๊อปวาง” โดยเริ่มจากหนังสือ

  1. สูตรลัด Flutter – เขียน Flutter ง่ายๆ จากโค้ดตัวอย่าง
  2. สูตรลัด GetX – ใช้งาน GetX อย่างเข้าใจและประยุกต์ใช้งานได้จริง
  3. สูตรลัด FlutterFire – เขียน Flutter กับ Firebase ได้อย่างเซียน
  4. สูตรลัด Angel Framework

เล่ม 3-4 ทะยอยเขียนเรื่อยๆ ปล. งานสอนออนไลน์ Flutter Crash Course ยังรับสมัครอยู่เรื่อยๆ กำลังเปิด Season 3 เป็นเรียนผ่าน Video