Flutter — Membangun Proyek Boilerplate yang sempurna dari awal

Dec 01 2022
Kredit: Nguyễn Thành Minh (Pengembang Android) Kita semua pernah ke sana — yang saya maksud adalah kita semua mencoba membuat proyek boilerplate baik untuk pekerjaan atau sebagai proyek pribadi. Proyek boilerplate yang baik akan menghemat banyak waktu kita dengan menyelesaikan masalah umum seperti memanggil API, memproses data dari database, dan mungkin yang paling penting — membuat kode kita teratur dan konsisten sehingga orang dapat lebih mudah mencoba memahami kode kita.

Kredit: Nguyễn Thành Minh (Pengembang Android)

Kita semua pernah ke sana — yang saya maksud adalah kita semua mencoba membangun proyek boilerplate baik untuk pekerjaan atau sebagai proyek pribadi. Proyek boilerplate yang baik akan menghemat banyak waktu kita dengan menyelesaikan masalah umum seperti memanggil API, memproses data dari database, dan mungkin yang paling penting — membuat kode kita teratur dan konsisten sehingga orang dapat lebih mudah mencoba memahami kode kita. Seri ini dimaksudkan untuk membagikan proyek boilerplate yang telah saya buat, gunakan, dan pelihara selama dua tahun terakhir. Tidak hanya itu, saya akan membagikan pendekatan saya untuk mengkodekannya, serta solusi untuk masalah umum yang mungkin muncul. Dengan demikian, ini adalah bagian 1: Menjelajahi Proyek.

Lihat di Github

Arsitektur Proyek

1. Fitur

Fitur yang dibangun dalam proyek ini:

  • Arsitektur: Arsitektur Bersih
  • Manajemen negara: flutter_bloc
  • Navigasi: auto_route
  • DI: get_it , dapat disuntikkan
  • API REST: dio
  • GraphQL: artemis , graphql_flutter
  • Basis data: kotak objek
  • Preferensi Bersama: encrypt_shared_preferences
  • Kelas data: dibekukan
  • Lint: dart_code_metrics , flutter_lints
  • CI/CD: Tindakan Github, Pipa Bitbucket
  • Uji Unit: mocktail , bloc_test
  • Paging: infinite_scroll_pagination
  • Kegunaan : rxdart , dartx , async
  • Generator aset: flutter_gen_runner , flutter_launcher_icons , flutter_native_splash
  • Fitur lain: coba ulang permintaan API yang gagal secara otomatis, token penyegaran,…

Untuk menjalankan proyek ini sebagaimana dimaksud, versi Flutter Anda harus (tepatnya) 3.3.9 dan Melos versi 2.8.0 harus diinstal. Jika Anda ingin memiliki Konvensi Git untuk tim Anda, Anda juga dapat memasang lefthook . Saya akan berbicara tentang Melos dan Lefthook di bagian selanjutnya dari seri ini. Untuk saat ini, inilah cara menjalankan proyek.

Catatan: Saya menggunakan VSCode dan macOS jadi saya tidak dapat menjamin itu juga akan berfungsi di Android Studio atau Windows.

2.1. Menginstal Melos

Clean Architecture mengharuskan kita untuk membagi proyek menjadi beberapa modul (paket), oleh karena itu kita memerlukan alat untuk mengelola paket — Melos. Untuk menginstal Melos:

dart pub global activate melos 2.8.0

export PATH="$PATH:<path to flutter>/flutter/bin"
export PATH="$PATH:<path to flutter>/flutter/bin/cache/dart-sdk/bin"
export PATH="$PATH:~/.pub-cache/bin"

Setelah menginstal Melos, Anda harus menjalankan perintah make gen_envatau dart run tools/gen_env.dart. Ini adalah alat yang saya buat sendiri, untuk membuat envfolder agar kita dapat mendeklarasikan rahasia seperti Google API_KEY, kredensial autentikasi dasar, dll. Alat ini akan membaca nilai dalam .envfile lalu memasukkannya ke dalam dart-definebendera saat aplikasi Flutter diaktifkan dijalankan atau dibangun.

Folder env dan file .env yang sesuai dengan lingkungannya

2.3. Menghasilkan file

Setelah kita mendapatkan envfoldernya, sekarang kita hanya perlu menjalankan perintah make sync. Ini adalah singkatan dari tiga perintah:

melos bootstrap
melos run l10n
melos run force_build_all

Selanjutnya, perintah melos run l10nmembantu menghasilkan kelas Sdari .arbfile dalam resourcesmodul.

Terakhir, perintah melos run force_build_allmembantu menghasilkan file .g.dart, .freezed.dartdll. pada semua paket yang memiliki pustaka build_runner.

Sekarang, jalankan make run_devuntuk menjalankan aplikasi dan selamat menikmati!

3. Arsitektur Proyek

Secara keseluruhan, kami memiliki 6 modul (paket)

  • Aplikasi
  • Domain
  • Data
  • Sumber daya
  • Bersama
  • Penginisialisasi

3.1. Modul Aplikasi

Di sinilah kita akan mengkodekan UI dan Bloc kita. Selain itu, ini adalah tempat kami menyimpan sumber daya seperti Warna, Dimensi, dan Gaya Teks. Ini juga tempat kita akan mendeklarasikan fungsi main() kita sebagai titik masuk untuk menjalankan aplikasi kita.

Modul aplikasi

Kedua folder app_icondan splashberisi file app-icon.yamlsehingga splash.yamlkita dapat mengonfigurasi ikon aplikasi dan layar splash seperti yang diinstruksikan oleh pustaka flutter_launcher_icons dan flutter_native_splash .

appFolder tersebut berisi AppBloc, yang merupakan Blok yang disediakan di MaterialApp, tempat semua layar di aplikasi dapat mengambil data, dengan kata lain; itu seperti Blok yang dibagikan ke semua layar. Anda dapat menggunakan AppBlocuntuk tugas-tugas yang perlu memperbarui UI semua layar seperti pengaturan bahasa, mode gelap/pengalihan mode terang.

Folder adalah basetempat kita akan membuat kode kelas dasar seperti BasePageState, BaseBloc, BaseEventdan BaseState.

Folder shared_viewtersebut adalah tempat saya akan membuat kode UI yang dibagikan di antara banyak layar, dan kemudian dapat digunakan untuk proyek lain. Misalnya: app_text_field, circle_imageadalah tampilan grup umum yang terlihat di layar Login dan Daftar.

Folder common_viewtersebut adalah tempat saya akan membuat kode UI yang dibagikan di antara banyak layar, dan kemudian dapat digunakan untuk proyek lain. Misalnya, common_dialog, common_app_bar, common_scaffolddapat digunakan kembali di banyak proyek, meskipun kami mungkin ingin menyesuaikannya sedikit untuk pencocokan gaya.

Folder configtersebut adalah tempat saya akan memanggil fungsi konfigurasi untuk modul aplikasi sepertiFirebase.initializeApp()

Folder diini untuk pengaturan DI untuk modul aplikasi.

Folder exception_handlerakan menangani semua pengecualian dalam proyek.

Folder tersebut helperberisi kelas Pembantu yang digunakan secara eksklusif untuk modul aplikasi.

Folder navigationadalah tempat kami akan mendeklarasikan layar serta dialog dan lembar bawah yang digunakan dalam aplikasi.

Folder resourceadalah tempat kami akan mendeklarasikan sumber daya untuk UI seperti Warna, Dimensi, dan Gaya Teks.

Folder uiadalah tempat saya akan memberi kode UI dan Blok untuk setiap layar.

Folder utilstersebut adalah tempat saya akan mengkodekan fungsi utils yang digunakan secara eksklusif untuk modul aplikasi.

3.2. Modul Domain

Modul domain

Mirip dengan modul aplikasi, folder configdan dimelayani tujuan serupa di modul domain.

Folder tersebut entityberisi entitas kelas seperti Pengguna dan Pemesanan.

Folder navigationtersebut memiliki AppNavigatorkelas, yang bertanggung jawab untuk push, replace, dan poplayar.

Folder repositoryadalah tempat kami akan mendeklarasikan kelas Repositori Abstrak dalam proyek.

Folder usecaseadalah tempat kami akan mendeklarasikan Kasus Penggunaan dalam proyek.

3.3. Modul Data

Modul data

Demikian pula, folder configdan dimelayani tujuan yang sama di sini.

Folder tersebut graphqlberisi .graphqldan schema.graphqljika proyek Anda menggunakan GraphQL. File build.yamltersebut digunakan untuk mengonfigurasi file yang dihasilkan yang terkait dengan GraphQL.

Folder tersebut repositoryberisi kelas Implementasi Repositori. Ini juga berisi beberapa folder:

  • converter: untuk pengkodean kelas Konverter
  • mapper: untuk kelas coding Mapper yang kemudian digunakan untuk memetakan model data menjadi Entitas
  • model: untuk pengkodean kelas model data
  • source: untuk kelas dasar pengkodean seperti RestApiClient, GraphQlApiClient serta menyediakan sumber data dalam proyek seperti AppApiService, AppDatabase, AppSharedPreferences, LocationDataSource
Modul Sumber Daya

Ini adalah modul sederhana, hanya berisi .arbfile yang menyediakan Strings untuk lokalisasi. Modul ini disuntikkan ke dalam dua modul lain, appsehingga domainkelas UI, Bloc, Entity, dan Use Case dapat digunakan.

3.5. Modul Bersama

Modul Bersama

Seperti namanya, modul ini menyediakan konstanta, kelas pengecualian khusus, kelas pembantu, mixin, dan fungsi utils untuk digunakan modul lain.

3.6. Modul Penginisialisasi

Modul Inisialisasi

Modul ini hanya berisi kelas AppInitializer. Kelas ini bertanggung jawab untuk mengumpulkan semua konfigurasi dari modul lain ke dalam sebuah init()fungsi; Fungsi main()hanya perlu memanggil init()fungsi ini untuk mengambil semua konfigurasi dari semua modul.

3.7. Folder dan file lain

Folder .githubini untuk mengonfigurasi CI/CD jika proyek Anda menggunakan Github Actions.

Folder .lefthookdan file lefthook.ymladalah untuk mengonfigurasi konvensi Git menggunakan pustaka lefthook.

Folder .vscodeini untuk mendeklarasikan pengaturan VSCode yang digunakan untuk proyek ini.

Folder .envini untuk mendeklarasikan rahasia untuk setiap lingkungan.

Folder tersebut toolsberisi alat yang saya buat.

File analysis_options.yamlini untuk mendeklarasikan aturan linter dari dua pustaka flutter_lints dan dart_code_metrics .

File bitbucket-pipelines.ymlini untuk mengonfigurasi CI jika proyek Anda menggunakan Bitbucket Pipelines.

File makefilemelacak semua perintah yang digunakan dalam proyek. Misalnya, perintah make formatmembantu memformat semua kode dengan .dartekstensi file di dalam proyek. Ada banyak lagi perintah seperti make testyang menjalankan Unit Test pada semua modul.

File melos.yamlini untuk mengkonfigurasi Melos.

Kesimpulan

Mengapa kita perlu membuat modul lain hanya untuk konfigurasi init? Apa itu mapper, entitas, dan use case class? Saya akan membahasnya di bagian kedua seri ini — Clean Architecture.