Skip to content

abdullah017/flutter-refactoring-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flutter Refactor Örneği: StatefulWidget'tan Riverpod'a

Bu proje, Flutter'da state yönetimi ve kod yapısını iyileştirmek için yapılan bir refactor (yeniden düzenleme) sürecini göstermektedir. Proje, basit bir hava durumu uygulaması üzerinden StatefulWidget ve setState kullanımından, modern ve güçlü bir state management kütüphanesi olan Riverpod'a geçişi adım adım sergilemektedir.

https://medium.com/@abdullahtas/flutter-dart-projelerinde-refactoring-94b2a9598915 https://medium.com/@abdullahtas/flutter-refactoring-prati%C4%9Fi-00c10749fba4

Bu döküman, projenin amacını, yapılan değişiklikleri, kullanılan teknolojileri ve projenin nasıl çalıştırılacağını detaylı bir şekilde açıklamaktadır.

Proje Hakkında

Projenin temel amacı, Flutter uygulamalarında sürdürülebilir, test edilebilir ve ölçeklenebilir bir kod yapısının nasıl oluşturulacağını göstermektir. Bu amaçla, aşağıdaki konulara odaklanılmıştır:

  • State Yönetimi: setState'in getirdiği zorluklardan kaçınarak, Riverpod ile state'i merkezi ve reaktif bir şekilde yönetmek.
  • Kod Yapısı: Kodun daha modüler ve okunabilir hale getirilmesi için sorumlulukların ayrılması (Separation of Concerns).
  • Immutable (Değişmez) Modeller: freezed paketi ile veri modellerini değişmez ve güvenli hale getirmek.
  • Test Edilebilirlik: Yazılan kodun birim testler (unit tests) ile kolayca test edilebilir olmasını sağlamak.

Proje Yapısı

Proje, refactor öncesi ve sonrası durumu net bir şekilde görebilmeniz için lib klasörü altında before ve after olarak ikiye ayrılmıştır.

lib/
├── after/         # Refactor edilmiş modern kod yapısı
│   ├── data/
│   │   └── weather_repository.dart
│   ├── models/
│   │   └── weather_models.dart
│   ├── providers/
│   │   └── weather_provider.dart
│   └── after_weather_page.dart
├── before/        # Başlangıçtaki StatefulWidget kodu
│   └── before_weather_page.dart
└── main.dart      # Uygulamanın başlangıç noktası

before Klasörü

Bu klasördeki before_weather_page.dart dosyası, tüm mantığın tek bir StatefulWidget içinde olduğu, setState ile state yönetiminin yapıldığı başlangıç noktasını temsil eder. Bu yaklaşım, küçük uygulamalar için hızlı bir başlangıç sunsa da, uygulama büyüdükçe şu gibi sorunlara yol açar:

  • State Dağınıklığı: State, UI kodunun içinde kaybolur ve yönetimi zorlaşır.
  • Test Zorluğu: UI ve iş mantığı iç içe olduğu için test yazmak karmaşıklaşır.
  • Gereksiz Rebuild'ler: setState çağrıldığında tüm widget ağacının yeniden çizilmesi performans sorunlarına neden olabilir.

after Klasörü

Bu klasör, Riverpod ve diğer modern pratikler kullanılarak yeniden düzenlenmiş kodu içerir. Kod, sorumluluklarına göre aşağıdaki gibi ayrılmıştır:

  • data/weather_repository.dart: API istekleri gibi veri kaynaklarıyla ilgili tüm mantığı içerir. Bu sayede, veri getirme işlemleri UI katmanından tamamen soyutlanmıştır.
  • models/weather_models.dart: freezed paketi kullanılarak oluşturulmuş, API'den gelen veriyi temsil eden değişmez (immutable) veri modelini içerir.
  • providers/weather_provider.dart: Riverpod provider'larını tanımlar. Bu provider'lar, WeatherRepository'yi kullanarak veriyi çeker ve state'i yönetir.
  • after_weather_page.dart: UI katmanıdır. ConsumerWidget kullanarak provider'ları dinler ve state'deki değişikliklere göre UI'ı günceller. İş mantığından arındırılmış, sadece UI çiziminden sorumlu bir yapıdadır.

Kullanılan Teknolojiler ve Kavramlar

Riverpod ile State Yönetimi

Riverpod, Flutter uygulamaları için modern, derleme zamanında güvenli (compile-safe) ve test edilebilir bir state management çözümüdür. Bu projede Riverpod'ı şu amaçlarla kullandık:

  • Dependency Injection (Bağımlılık Enjeksiyonu): WeatherRepository gibi bağımlılıkları provider'lar aracılığıyla UI katmanına enjekte ederek, kodun modüler ve test edilebilir olmasını sağladık.
  • Reaktif State Yönetimi: FutureProvider kullanarak asenkron veri getirme işlemlerini (API istekleri gibi) kolayca yönettik. FutureProvider, loading, data ve error gibi durumları otomatik olarak ele alarak UI'da bu durumları güvenli bir şekilde işlememizi sağlar.
  • Performans: Sadece state'i dinleyen widget'ların yeniden çizilmesini sağlayarak gereksiz rebuild'lerin önüne geçtik.

Freezed ile Değişmez Veri Modelleri

freezed, Dart için güçlü bir kod üreticisidir. Veri modellerini (data classes) değişmez (immutable) hale getirir ve copyWith, == operatorü, toString gibi standart metodları otomatik olarak oluşturur. Bu projede freezed'i şu avantajları için kullandık:

  • Güvenilirlik: Değişmez nesneler, state'in beklenmedik şekillerde değişmesini engelleyerek hataları azaltır.
  • Kod Tekrarını Önleme: Boilerplate kodları (standart, tekrarlayan kodlar) otomatik olarak üreterek geliştirme sürecini hızlandırır.
  • JSON Serileştirme: json_serializable ile entegre çalışarak, API'den gelen JSON verisini kolayca Dart nesnelerine dönüştürmemizi sağlar.

Test Edilebilirlik ve Mockito

Refactor sürecinin en önemli hedeflerinden biri de test edilebilirliği artırmaktır. Riverpod ve bağımlılık enjeksiyonu sayesinde, iş mantığını UI'dan ayırarak test yazmayı kolaylaştırdık.

test klasörü altında bulunan weather_provider_test.dart dosyası, weatherProvider'ın davranışını test eder. Bu testte:

  • mockito: WeatherRepository'nin sahte (mock) bir versiyonunu oluşturmak için kullanılır. Bu sayede, testimiz gerçek API'ye istek atmadan, kontrolümüz altındaki sahte verilerle çalışır.
  • ProviderContainer: Riverpod provider'larını bir test ortamında çalıştırmak ve state'lerini okumak için kullanılır.
  • Test Senaryoları: Provider'ın başarı (data), yükleniyor (loading) ve hata (error) durumlarını doğru bir şekilde yönetip yönetmediği test edilir.

Projeyi Çalıştırma

Projeyi yerel makinenizde çalıştırmak için aşağıdaki adımları izleyin:

  1. Projeyi Klonlayın:

    git clone <proje-linki>
    cd flutter_refactor_example
  2. Bağımlılıkları Yükleyin:

    flutter pub get
  3. Kod Üretimini Çalıştırın: Proje, freezed ve mockito gibi kod üreticileri kullandığı için, gerekli dosyaları oluşturmak üzere aşağıdaki komutu çalıştırmanız gerekmektedir. Bu komut, *.g.dart ve *.freezed.dart gibi dosyaları üretecektir.

    flutter pub run build_runner build --delete-conflicting-outputs
  4. Uygulamayı Başlatın:

    flutter run

Testleri Çalıştırma

Projenin birim testlerini çalıştırmak için aşağıdaki komutu kullanabilirsiniz:

flutter test

Bu komut, test klasöründeki tüm testleri çalıştıracak ve sonuçları konsolda gösterecektir.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages