Panduan praktis dan terstruktur mengenai panduan to-do list dengan flutter dan supabase: membuat remote service (part 4) berstandar enterprise. Pelajari konsep, implementasi kode modern, dan tips arsitektur enterprise siap produksi.
Selamat datang di seri tutorial engineering SiHubung! Pada artikel ini, kita akan membedah secara komprehensif implementasi Panduan To-Do List Dengan Flutter Dan Supabase: Membuat Remote Service (Part 4) Berstandar Enterprise dengan standar kode bersih (clean code), performa tinggi, dan arsitektur siap produksi.

Membangun aplikasi web di era modern memerlukan pondasi yang kokoh. Framework modern memberikan fleksibilitas luar biasa bagi developer untuk menghadirkan fitur kompleks secara cepat tanpa mengabaikan aspek keamanan dan keandalan sistem.

Tahapan Implementasi & Walkthrough Kode

Berikut adalah langkah demi langkah teknis yang dapat Anda ikuti langsung pada codebase Anda:

Tahap 1: Penulisan Kode & Konfigurasi

class TodoModel {
  final String id;
  final String title;
  final bool isDone;

  TodoModel({required this.id, required this.title, required this.isDone});

  factory TodoModel.fromJson(Map<String, dynamic> json) {
    return TodoModel(
      id: json['id'],
      title: json['title'],
      isDone: json['is_done'],
    );
  }

  static List<TodoModel> fromJsonToList(List<dynamic> jsonList) {
    return jsonList.map((json) => TodoModel.fromJson(json)).toList();
  }
}

Tahap 2: Penulisan Kode & Konfigurasi

import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/model/todo_model.dart';

class TodoService {
  final _client = Supabase.instance.client;

  Future<List<TodoModel>> fetchTodos() async {
    return run(() async {
      final response = await _client
          .from('todos')
          .select()
          .order('created_at', ascending: false);

      return TodoModel.fromJsonToList(response);
    });
  }

  Future<void> addTodo(String title) async {
    return run(() async {
      await _client.from('todos').insert({
        'title': title,
        'is_done': false,
        'created_at': DateTime.now().toIso8601String(),
      });
    });
  }

  Future<void> toggleDone(String id, bool isDone) async {
    return run(() async {
      await _client.from('todos').update({'is_done': !isDone}).eq('id', id);
    });
  }

  Future<void> deleteTodo(String id) async {
    return run(() async {
      await _client.from('todos').delete().eq('id', id);
    });
  }

  Future<T> run<T>(Future<T> Function() function) async {
    try {
      return await function();
    } on PostgrestException catch (error) {
      throw ServerException(message: error.message);
    } catch (error) {
      throw ServerException(message: error.toString());
    }
  }
}

class ServerException implements Exception {
  final String message;

  ServerException({this.message = 'Server error'});
}

Tahap 3: Penulisan Kode & Konfigurasi

import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/todo_model.dart';

Tahap 4: Penulisan Kode & Konfigurasi

class TodoService {
  final _client = Supabase.instance.client;

Tahap 5: Penulisan Kode & Konfigurasi

Future<List<TodoModel>> fetchTodos() async {
  return run(() async {
    final response = await _client
        .from('todos')
        .select()
        .order('created_at', ascending: false);

    return TodoModel.fromJsonToList(response);
  });
}

Tahap 6: Penulisan Kode & Konfigurasi

Future<void> addTodo(String title) async {
  return run(() async {
    await _client.from('todos').insert({
      'title': title,
      'is_done': false,
      'created_at': DateTime.now().toIso8601String(),
    });
  });
}

Tahap 7: Penulisan Kode & Konfigurasi

Future<void> toggleDone(String id, bool isDone) async {
  return run(() async {
    await _client.from('todos').update({'is_done': !isDone}).eq('id', id);
  });
}

Tahap 8: Penulisan Kode & Konfigurasi

Future<void> deleteTodo(String id) async {
  return run(() async {
    await _client.from('todos').delete().eq('id', id);
  });
}

Tahap 9: Penulisan Kode & Konfigurasi

Future<T> run<T>(Future<T> Function() function) async {
  try {
    return await function();
  } on PostgrestException catch (error) {
    throw ServerException(message: error.message);
  } catch (error) {
    throw ServerException(message: error.toString());
  }
}

Tahap 10: Penulisan Kode & Konfigurasi

class ServerException implements Exception {
  final String message;

  ServerException({this.message = 'Server error'});
}
💡 Tips Rekayasa Perangkat Lunak (SiHubung Engineering Best Practice)

Selalu gunakan pendekatan deklaratif, validasi input seawal mungkin di boundary layer, dan lakukan logging terstruktur untuk memudahkan observability ketika sistem dijalankan di lingkungan cloud produksi.

Kesimpulan

Dengan mengikuti langkah-langkah terstruktur di atas, implementasi modul Anda akan jauh lebih rapi, aman dari bug umum, serta siap diskalakan ke lingkungan produksi.

Nantikan artikel tutorial praktis lainnya seputar fullstack development, microservices, dan otomasi AI di Blog Engineering SiHubung. Selamat mencoba!