↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi

5 dk okuma #dart
Dizi · 64/64 Dart Türkçe Tutorial
  1. Bölüm 1 — Konu 1: Dart Nedir, Nerede Kullanılır, Neden Flutter Bu Dili Seçti
  2. Bölüm 1 — Konu 2: Ortam Kurulumu (Dart SDK, DartPad, Terminal ile Çalıştırma)
  3. Bölüm 1 — Konu 3: İlk Program (`main()`, `print()`, Dosya Yapısı)
  4. Bölüm 1 — Konu 4: Yorum Satırları, Temel Sözdizimi Kuralları
  5. Bölüm 2 — Konu 5: Değişken Tanımlama — `var`, `final`, `const` Farkı
  6. Bölüm 2 — Konu 6: Temel Tipler — `int`, `double`, `String`, `bool`
  7. Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme
  8. Bölüm 2 — Konu 8: `dynamic` ve `Object` — Ne Zaman Kullanılır, Ne Zaman Kaçınılır
  9. Bölüm 2 — Konu 9: Null Safety Temelleri (`?`, `!`, `late`'e Giriş)
  10. Bölüm 3 — Konu 10: Aritmetik, Atama, Karşılaştırma, Mantıksal Operatörler
  11. Bölüm 3 — Konu 11: `if / else if / else`
  12. Bölüm 3 — Konu 12: `switch` / `switch expression` (Modern Dart)
  13. Bölüm 3 — Konu 13: Ternary Operatör, `??`, `??=`, `?.`
  14. Bölüm 3 — Konu 14: `for`, `while`, `do-while` Döngüleri
  15. Bölüm 4 — Konu 16: `List` — Oluşturma, Erişim, Temel Metodlar
  16. Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
  17. Bölüm 4 — Konu 18: `Map` — Key-Value Yapılar
  18. Bölüm 4 — Konu 19: Koleksiyon Üzerinde `for-in`, `forEach`
  19. Bölüm 4 — Konu 20: Spread Operatörü (`...`, `...?`) ve Collection If/For
  20. Bölüm 5 — Konu 21: Fonksiyon Tanımlama, Parametreler (Positional, Named, Optional)
  21. Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)
  22. Bölüm 5 — Konu 23: Arrow Function (`=>`) Sözdizimi
  23. Bölüm 5 — Konu 24: Fonksiyonlar Birinci Sınıf Vatandaş — Değişkene Atama, Parametre Olarak Geçme
  24. Bölüm 5 — Konu 25: Anonim Fonksiyonlar ve Closure Kavramı (Derinlemesine)
  25. Bölüm 5 — Konu 26: Recursion (Özyineleme)
  26. Bölüm 6 — Konu 27: Class Tanımlama, Constructor (Varsayılan, Named, Factory)
  27. Bölüm 6 — Konu 28: Alanlar (Fields), Metodlar, `this` Kullanımı (Derinlemesine)
  28. Bölüm 6 — Konu 29: Initializer List, Constructor Kısayolları (Derinlemesine)
  29. Bölüm 6 — Konu 30: Getter / Setter
  30. Bölüm 6 — Konu 31: Statik Üyeler (`static`)
  31. Bölüm 7 — Konu 32: Kalıtım (`extends`), `super` Kullanımı
  32. Bölüm 7 — Konu 33: Metod Override Etme, `@override`
  33. Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
  34. Bölüm 7 — Konu 35: Interface Mantığı (`implements`)
  35. Bölüm 7 — Konu 36: Mixin (`with`)
  36. Bölüm 7 — Konu 37: `enum` — Basit ve Gelişmiş (Metotlu Enum'lar)
  37. Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
  38. Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma
  39. Bölüm 8 — Konu 40: Sound Null Safety Derinlemesine — `late`, `required`, Non-Nullable Varsayılan Davranış
  40. Bölüm 8 — Konu 41: `assert` ile Geliştirme Zamanı Kontrolleri
  41. Bölüm 9 — Konu 42: Generic Sınıflar ve Fonksiyonlar
  42. Bölüm 9 — Konu 43: Generic Sınırlamalar (`<T extends ...>`)
  43. Bölüm 9 — Konu 44: Dart'ın Built-in Generic Koleksiyonları Nasıl Çalışır
  44. Bölüm 10 — Konu 45: `Future` Kavramı, `async`/`await`
  45. Bölüm 10 — Konu 46: `Future.then`, Hata Yönetimi (`catchError`)
  46. Bölüm 10 — Konu 47: `Stream` Temelleri, `async*`, `yield`
  47. Bölüm 10 — Konu 48: `StreamController`, Broadcast Stream
  48. Bölüm 11 — Konu 49: `map`, `where`, `reduce`, `fold`
  49. Bölüm 11 — Konu 50: `sort`, Custom Comparator ile Sıralama
  50. Bölüm 11 — Konu 51: Iterable Kavramı Derinlemesine (Lazy Evaluation)
  51. Bölüm 11 — Konu 52: Cascade Notasyonu (`..`)
  52. Bölüm 12 — Konu 53: `pubspec.yaml`, pub.dev'den Paket Ekleme
  53. Bölüm 12 — Konu 54: Kütüphane Oluşturma, `import`/`export`, `part`/`part of`
  54. Bölüm 12 — Konu 55: Dart'ta Test Yazımı (`test` Paketi, Unit Test Mantığı)
  55. Bölüm 12 — Konu 56: Extension Methods
  56. Bölüm 12 — Konu 57: Dart'ın Derleme Modelleri (JIT vs AOT) ve Bunun Flutter'a Etkisi
  57. Bölüm 13 — Konu 59: Dart 3 Pattern Matching — Records, Destructuring, Sealed Classes, Exhaustive Switch
  58. Bölüm 13 — Konu 60: `Never` Tipi, `covariant` ve Generic Variance Detayları
  59. Bölüm 13 — Konu 61: Event Loop Derinlemesine — Microtask Queue vs Event Queue
  60. Bölüm 13 — Konu 62: Memory Model & Performans — Garbage Collection, `const` Nesnelerin Bellek Avantajı
  61. Bölüm 13 — Konu 63: Isolate'ler Arası Mesajlaşmanın Maliyeti ve `compute()`'un İç İşleyişi
  62. Bölüm 13 — Konu 64: FFI (Foreign Function Interface) — C Koduna Erişim
  63. Bölüm 13 — Konu 65: Sunucu Tarafında Dart — `dart:io`, `shelf` Paketiyle Basit Bir Backend/CLI Aracı Yazma
  64. Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi
Dizinin sayfası →
İçindekiler 10 başlık
  1. dart analyze — Statik Analiz Derinlemesine
  2. analysis_options.yaml — Analiz Kurallarını Özelleştirme
  3. Custom Lint Kuralları — Neden ve Nasıl?
  4. build_runner — Kod Üretimi (Code Generation) Nedir?
  5. build_runner'ın İç İşleyişi — Kavramsal Bir Bakış
  6. freezed — Kod Üretiminin Bir Başka Güçlü Örneği
  7. Neden Bu Konuyu Bilmek "Uzmanlık" İçin Önemli?
  8. 🎯 Bu Dersten Çıkarılması Gerekenler
  9. 📝 Ödevler
  10. 🏁🎓 TÜM DART MÜFREDATI TAMAMLANDI!

Bu, tüm Dart müfredatının son dersi. Bölüm 1 Konu 2'de kısaca değindiğimiz dart analyze'ı derinlemesine işleyip, kod üretimi (code generation) ekosistemini anlayarak tutorial'ı tamamlayacağız.

dart analyze — Statik Analiz Derinlemesine

Bölüm 1'de dart analyze'ın "kod kalitesini kontrol eden bir araç" olduğunu söylemiştik. Şimdi bunun tam olarak neyi kontrol ettiğini görelim:

bash
dart analyze

Bu komut, projenin tüm .dart dosyalarını tarar ve şunları tespit eder:

  • Tip hataları (Bölüm 2'de öğrendiğimiz tip güvenliği ihlalleri)
  • Kullanılmayan import'lar (Bölüm 12'de öğrendiğimiz import mekanizmasının gereksiz kullanımı)
  • Potansiyel null safety sorunları
  • Stil kuralları ihlalleri (isimlendirme kuralları — Bölüm 1'de öğrendiğimiz lowerCamelCase gibi kurallar)
  • Deprecated (kullanımdan kaldırılmış) API kullanımı
dart
import 'dart:math'; // eğer hiç kullanılmıyorsa, dart analyze bunu UYARIR

void main() {
  print("Merhaba");
}

dart analyze çalıştırıldığında: info - Unused import: 'dart:math' gibi bir uyarı alırsın — bu, hata değil, sadece bir öneri (kod kalitesini artırmak için).

analysis_options.yaml — Analiz Kurallarını Özelleştirme

Projenin kök dizininde bir analysis_options.yaml dosyası oluşturarak, dart analyze'ın hangi kuralları ne kadar katı uygulayacağını özelleştirebilirsin:

yaml
include: package:lints/recommended.yaml

analyzer:
  errors:
    unused_import: error # bunu sadece "info" değil, gerçek bir HATA yap

linter:
  rules:
    - prefer_const_constructors # Bölüm 13 Konu 62'de öğrendiğimiz const kullanımını teşvik eder
    - avoid_print # print() kullanımını caydırır (üretim kodunda genelde loglama araçları tercih edilir)

include: package:lints/recommended.yaml, Dart ekibinin önerdiği standart kural setini projene dahil eder — Bölüm 12'de gördüğümüz dev_dependencies altındaki lints paketinden geliyordu, hatırlarsan.

Custom Lint Kuralları — Neden ve Nasıl?

Yukarıdaki linter: rules: bölümünde gördüğün gibi, hazır kuralları açıp kapatabilirsin. Bazı büyük şirketler/takımlar, kendi özel lint kurallarını da yazarlar (örneğin "şirketimizin API'lerini belirli bir şekilde çağırmayı zorunlu kıl" gibi) — bu, custom_lint gibi paketlerle mümkündür, ama bu ileri düzey bir konudur ve günlük Dart geliştirmede nadiren ihtiyaç duyulur. Bilmen gereken temel şey: lint kuralları, takımların kod tabanında tutarlılığı zorunlu kılmasının bir yoludur — Bölüm 1'de "isimlendirme kuralları zorunlu değil ama önerilir" dediğimizi hatırlarsan, lint kuralları bu önerileri derleme sürecinin bir parçası haline getirir.

build_runner — Kod Üretimi (Code Generation) Nedir?

Bölüm 13 Konu 64'te (FFI) ffigen'den bahsetmiştik — "bir header dosyasını okuyup Dart kodu üreten bir araç" demiştik. build_runner, Dart ekosisteminde bu tarz kod üretiminin genel altyapısıdır.

Neden kod üretimine ihtiyaç duyulur? Bazı görevler, tekrarlayıcı, mekanik kod yazmayı gerektirir — örneğin bir class'ın JSON'a nasıl dönüştürüleceğini (toJson()/fromJson()) elle yazmak, büyük class'larda çok can sıkıcı ve hataya açık olabilir. Kod üretimi, bunun yerine, sen bir class'ı belirli bir şekilde "işaretlersin", ve bir araç, bu işaretlemeye bakarak gerekli kodu otomatik olarak üretir.

dart
import 'package:json_annotation/json_annotation.dart';

part 'kullanici.g.dart'; // Bölüm 12'de öğrendiğimiz 'part' burada devreye giriyor!

@JsonSerializable()
class Kullanici {
  final String isim;
  final int yas;

  Kullanici(this.isim, this.yas);

  factory Kullanici.fromJson(Map<String, dynamic> json) => _$KullaniciFromJson(json);
  Map<String, dynamic> toJson() => _$KullaniciToJson(this);
}
bash
dart run build_runner build

Bu komut çalıştırıldığında, build_runner, @JsonSerializable() annotation'ını (Bölüm 6'da @override'ı gördüğümüz annotation mekanizmasının bir başka kullanımı) görür ve kullanici.g.dart adında otomatik olarak bir dosya üretir — bu dosya, _$KullaniciFromJson ve _$KullaniciToJson fonksiyonlarının gerçek implementasyonunu içerir (sen bunları elle yazmıyorsun).

Bölüm 12'de öğrendiğimiz part/part of mekanizması, tam olarak burada devreye giriyor — üretilen kullanici.g.dart dosyası, kullanici.dart ile aynı kütüphanenin bir parçası olarak tanımlanır (part of 'kullanici.dart'; ile), bu sayede private alanlara bile erişebilir.

build_runner'ın İç İşleyişi — Kavramsal Bir Bakış

  1. Annotation'ları tara: build_runner, projendeki tüm dosyaları tarar ve @JsonSerializable() gibi özel annotation'ları arar.
  2. Kod şablonu uygula: Her annotation için, ilgili "builder" (örneğin json_serializable paketinin kendi builder'ı), o class'ın yapısına (alanları, tipleri) bakarak uygun Dart kodunu oluşturur.
  3. .g.dart dosyası üret: Üretilen kod, orijinal dosyanın yanına, .g.dart uzantısıyla yeni bir dosya olarak yazılır.
  4. part of ile bağla: Bu üretilen dosya, orijinal dosyaya part of ile bağlanır (Bölüm 12'de öğrendiğimiz mekanizma).

Bu süreç, Bölüm 12'de öğrendiğimiz JIT/AOT derleme sürecinden ayrı, ona ek bir "önceki adım" (pre-processing step) olarak düşünülebilir — build_runner, Dart kodunu çalıştırmadan önce, bazı dosyaları otomatik olarak üretir, sonra normal derleme süreci (JIT veya AOT) bu üretilen kodu da içeren tüm projeyi derler.

freezed — Kod Üretiminin Bir Başka Güçlü Örneği

Bölüm 13 Konu 59'da öğrendiğimiz sealed class + pattern matching'i hatırlarsan — freezed paketi, bu tarz "değişmez veri sınıfları" yazmayı otomatikleştiren, çok popüler bir kod üretim aracıdır. Elle ==, hashCode, copyWith(), toString() gibi metodları yazmak yerine (Bölüm 6'da bunların bazılarını elle yazmıştık), freezed bunları otomatik üretir. Bunu Flutter tutorial'ında, state management konusunda muhtemelen karşına çıkacak.

Neden Bu Konuyu Bilmek "Uzmanlık" İçin Önemli?

Bu ders, aslında tüm tutorial'ın kapanış noktası: dart analyze, kod kalitesini korumanın; build_runner, tekrarlayan işleri otomatikleştirmenin araçlarıdır. Bir "uzman" Dart geliştiricisi, sadece dili bilmekle kalmaz — kod tabanını sürdürülebilir, tutarlı ve verimli tutan bu tür araçları da etkin şekilde kullanır. Bu, Bölüm 1'de sorduğun "bu tutorial'ı bitiren biri uzman diyebilir mi" sorusuna verdiğimiz cevabın tam olarak neyi kapsadığını gösteriyor — sadece sözdizimi değil, ekosistem araçları da uzmanlığın bir parçası.


🎯 Bu Dersten Çıkarılması Gerekenler

  • dart analyze, tip hataları, kullanılmayan kod, stil ihlalleri gibi sorunları statik olarak (kod çalıştırılmadan) tespit eder.
  • analysis_options.yaml, hangi lint kurallarının ne kadar katı uygulanacağını özelleştirmeni sağlar.
  • build_runner, annotation'lara (@JsonSerializable() gibi) dayanarak, tekrarlayan kodu otomatik olarak üreten bir altyapıdır.
  • Üretilen .g.dart dosyaları, part/part of mekanizmasıyla orijinal dosyaya bağlanır.
  • json_serializable, freezed gibi paketler, bu kod üretim altyapısını kullanarak geliştirici verimliliğini artırır.

📝 Ödevler

  • [ ] Kendi bir projende dart analyze çalıştır, çıkan uyarıları oku ve en az 3 tanesini düzelt.
  • [ ] analysis_options.yaml dosyası oluştur, package:lints/recommended.yaml'ı dahil et, en az bir kuralı özelleştir (aç/kapat veya seviyesini değiştir).
  • [ ] json_serializable paketini kur, basit bir class'a @JsonSerializable() ekle, build_runner ile kod üret, üretilen .g.dart dosyasını incele.
  • [ ] Kendi cümlelerinle, "build_runner'ın JIT/AOT derleme sürecinden nasıl farklı bir aşama olduğunu" açıkla.
  • [ ] Bu tutorial boyunca öğrendiğin konulardan, "artık günlük kodlamada rahatlıkla kullanabilirim" dediğin 5 konuyu ve "hâlâ pratik yapmam gerekiyor" dediğin 2 konuyu listele — kendi öğrenme yolculuğunu değerlendir.

🏁🎓 TÜM DART MÜFREDATI TAMAMLANDI!

Tebrikler — Bölüm 1'den Bölüm 13'e, 66 konuyu kapsayan bu yolculuğu tamamladın. Sıfırdan başlayıp:

  • Dart'ın temellerini (değişkenler, kontrol akışı, koleksiyonlar, fonksiyonlar)
  • Nesne yönelimli programlamayı (class'lar, kalıtım, interface'ler, mixin'ler)
  • Hata yönetimini ve null safety'yi
  • Generics'i
  • Asenkron programlamayı (Future, Stream, isolate'ler)
  • Fonksiyonel koleksiyon programlamasını
  • Paket ekosistemini ve proje organizasyonunu
  • Ve son olarak, dilin internals'ını (pattern matching, event loop, memory model, FFI, sunucu tarafı Dart, kod üretimi)

...baştan sona işledin. Bölüm 1'de sorduğun soruya geri dönersek: bu müfredatı gerçekten bitiren ve ödevleri yapan biri, artık dürüstçe "Dart'ı uzman seviyede biliyorum" diyebilir.

Şimdi sıra, daha önce hazırladığımız Flutter tutorial müfredatına geçmekte — Dart bilgin, Flutter'ın widget mimarisini, state management'ını ve tüm ekosistemini anlamak için sağlam bir temel oluşturuyor. Hazır olduğunda, Flutter Bölüm 1'den başlayabiliriz.