Flutter Linter Kuralları Bölüm 1: Hata Kuralları 💫 🌌 ✨

gulsenkeskin

Gülsen Keskin

Posted on February 19, 2022

Flutter Linter Kuralları Bölüm 1: Hata Kuralları 💫 🌌 ✨

“Where there are rules, there’s law“

Linting Nedir?

Linting , programatik, stilistik hatalar ve biçimlendirilmemiş kod için kaynak kodunu kontrol etme işlemidir. Mantıksal hatalar, kullanılmayan değişkenler, boş if-else ifadeleri gibi kodlama sırasında yapılan bazı yaygın ve yaygın olmayan hataları belirlemede yardımcı olur.

Linting'in amacı, kod kalitesini iyileştirebilecek gizli hatayı veya uygulamayı çalıştırırken sorunlara neden olabilecek hataları belirleme konusunda gerçek zamanlı öneriler almaktır.

Linter kuralları 3 gruba ayrılır. Bunlar:

  1. Hatalar: Olası kodlama hataları.
  2. Stil
  3. Bar: Pub paketi kurulumuyla ilgili olası sorunlar .

Her kuralın ayrıca bir olgunluk düzeyi vardır.

Kuralların olgunluk düzeyleri de 3'e ayrılır. Bunlar:

Kararlı-Stable
Bu kuralların kullanımı güvenlidir ve Dart dilinin en son sürümleriyle işlevsel oldukları doğrulanmıştır. Deneysel olarak işaretlenmedikçe veya kullanımdan kaldırılmadıkça tüm kurallar kararlı olarak kabul edilir.

Deneysel-Experimental
Bu kurallar halen değerlendirme aşamasındadır ve hiçbir zaman istikrara kavuşturulamayabilir. Bunları dikkatli kullanmanız gerekir.

Kullanımdan kaldırıldı-Deprecated
Bu kurallar artık kullanım için önerilmemektedir ve gelecekteki bir linter yayınında kaldırılabilir.

Hata kuralları

Hata kuralları, kodunuzdaki olası hataları ve diğer hataları tanımlar.

Always_use_package_imports

lib/. içindeki dosyalar için relative imports'dan (göreli içe aktarmalardan) kaçının.

Aynı üyeyi iki farklı şekilde içe aktarmaktan kaçınmak için lib/dizindeki dosyalar için mutlak içe aktarmayı (absolute imports) kullandığınızdan emin olun.

Doğru kullanım:

import 'package:foo/bar.dart';
import 'package:foo/baz.dart';
import 'package:foo/src/baz.dart';
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

import 'baz.dart';
import 'src/bag.dart'
import '../lib/baz.dart';
Enter fullscreen mode Exit fullscreen mode

avoid_dynamic_calls

"dynamic" bir hedefte method çağrılarından veya property erişimlerinden kaçının.

Açıkça veya dolaylı olarak statik olarak yazılan dynamic bir obje üzerindeki method çağrılarından veya özellik(propertie) erişimlerinden kaçının. Dinamik çağrılar, her çalışma zamanı ortamında ve derleyicide biraz farklı olarak ele alınır, ancak çoğu üretim modu (ve hatta bazı geliştirme modları), dinamik çağrılarla ilişkili hem derleme boyutu hem de çalışma zamanı performans sorunlarına sahiptir.

Ek olarak, "dynamic" yazılan hedefler, çoğu statik analizi devre dışı bırakır.

Yanlış kullanım:

void explicitDynamicType(dynamic object) {
  print(object.foo());
}

void implicitDynamicType(object) {
  print(object.foo());
}

abstract class SomeWrapper {
  T doSomething<T>();
}

void inferredDynamicType(SomeWrapper wrapper) {
  var object = wrapper.doSomething();
  print(object.foo());
}

void callDynamic(dynamic function) {
  function();
}

void functionType(Function function) {
  function();
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void explicitType(Fooable object) {
  object.foo();
}

void castedType(dynamic object) {
  (object as Fooable).foo();
}

abstract class SomeWrapper {
  T doSomething<T>();
}

void inferredType(SomeWrapper wrapper) {
  var object = wrapper.doSomething<Fooable>();
  object.foo();
}

void functionTypeWithParameters(Function() function) {
  function();
}
Enter fullscreen mode Exit fullscreen mode

avoid_empty_else

Boş else ifadelerinden kaçının.

Yanlış kullanım:

if (x > y)
  print("1");
else ;
  print("2");
Enter fullscreen mode Exit fullscreen mode

avoid_print

Üretim kodunda "print" çağrılarından kaçının.

void f(int x) {
  print('debug: $x');
  ...
}
Enter fullscreen mode Exit fullscreen mode

avoid_returning_null_for_future

Future için null döndürmekten kaçının.

avoid_slow_async_io

Yavaş asenkron dart:io yöntemlerinden kaçının.

Aşağıdaki asenkron I/O methodlarını kullanmaktan kaçının, çünkü bunlar senkron emsallerine göre çok daha yavaştır.

• Directory.exists
• Directory.stat
• File.lastModified
• File.exists
• File.stat
• FileSystemEntity.isDirectory
• FileSystemEntity.isFile
• FileSystemEntity.isLink
• FileSystemEntity.type

Yanlış kullanım:

import 'dart:io';

Future<Null> someFunction() async {
  var file = File('/path/to/my/file');
  var now = DateTime.now();
  if ((await file.lastModified()).isBefore(now)) print('before'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

import 'dart:io';

Future<Null> someFunction() async {
  var file = File('/path/to/my/file');
  var now = DateTime.now();
  if (file.lastModifiedSync().isBefore(now)) print('before'); // OK
}
Enter fullscreen mode Exit fullscreen mode

avoid_type_to_string

Sonuçlar küçültülebileceğinden üretim kodunda ".toString()" kullanmaktan kaçının.

Yanlış kullanım:

void bar(Object other) {
  if (other.runtimeType.toString() == 'Bar') {
    doThing();
  }
}

Object baz(Thing myThing) {
  return getThingFromDatabase(key: myThing.runtimeType.toString());
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void bar(Object other) {
  if (other is Bar) {
    doThing();
  }
}

class Thing {
  String get thingTypeKey => ...
}

Object baz(Thing myThing) {
  return getThingFromDatabase(key: myThing.thingTypeKey);
}
Enter fullscreen mode Exit fullscreen mode

avoid_types_as_parameter_names

Tipleri paremetre adı olarak kullanmaktan kaçının.

Yanlış kullanım: m(f(int));
Doğru kullanım: m(f(int v));

avoid_web_libraries_in_flutter

Flutter web plugin paketleri dışında yalnızca web kitaplıkları kullanmaktan kaçının.

Web eklentileri olmayan Flutter paketlerinde web kitaplıkları, dart:html, dart:js ve dart:js_util kullanmaktan kaçının. Bu kitaplıklar bir web context dışında desteklenmez; bunlara bağlı olan işlevsellik Flutter mobil runtime da başarısız olur ve Flutter web'de kullanılmaları genellikle önerilmez.

Web kitaplığı erişimine şu durumlarda izin verilir:

• web'i desteklenen bir context olarak bildiren plugin paketleri

aksi takdirde, dart:html, dart:js ve dart:js_util'in import edilmesine izin verilmez.

cancel_subscriptions

dart.async.StreamSubscription örneklerini iptal edin.

StreamSubscription örneklerinin (instance) iptal edilmesi, bellek sızıntılarını ve beklenmeyen davranışları (unexpected behavior) önler.

Yanlış Kullanım:

class A {
  StreamSubscription _subscriptionA; // LINT
  void init(Stream stream) {
    _subscriptionA = stream.listen((_) {});
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction() {
  StreamSubscription _subscriptionF; // LINT
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

class B {
  StreamSubscription _subscriptionB; // OK
  void init(Stream stream) {
    _subscriptionB = stream.listen((_) {});
  }

  void dispose(filename) {
    _subscriptionB.cancel();
  }
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunctionOK() {
  StreamSubscription _subscriptionB; // OK
  _subscriptionB.cancel();
}
Enter fullscreen mode Exit fullscreen mode

close_sinks

Sink örneklerini kapatmak, bellek sızıntılarını(memory leaks) ve beklenmeyen davranışları(unexpected behavior) önler.

Yanlış kullanım:

class A {
  IOSink _sinkA;
  void init(filename) {
    _sinkA = File(filename).openWrite(); // LINT
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction() {
  IOSink _sinkF; // LINT
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

class B {
  IOSink _sinkB;
  void init(filename) {
    _sinkB = File(filename).openWrite(); // OK
  }

  void dispose(filename) {
    _sinkB.close();
  }
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunctionOK() {
  IOSink _sinkFOK; // OK
  _sinkFOK.close();
}
Enter fullscreen mode Exit fullscreen mode

comment_references

Yalnızca belge yorumlarındaki kapsam tanımlayıcılarına (scope identifiers) başvurun.

Değişken, method veya köşeli parantez içinde adlar yazarsanız, dartdoc adı arar ve belgelerine bağlanır. Tüm bunların işe yaraması için, parantez içine alınmış belgelerdeki tüm tanımlayıcıların kapsam içinde olduğundan emin olun.

Örneğin:

Doğru kullanım:

/// [a] veya [b]'den büyük olanı döndürün.
int max_int(int a, int b) { ... }
Enter fullscreen mode Exit fullscreen mode

Öte yandan, outOfScopeId'in kapsam dışı olduğunu varsayarsak:

Yanlış kullanım:

/// [value], [outOfScopeId] değerinden büyükse true değerini döndürün.
bool isOutOfRange(int value) { ... }
Enter fullscreen mode Exit fullscreen mode

Köşeli parantez yorum biçiminin, açıklamaların oldukça doğal bir biçim kullanarak bildirimlere başvurmasına izin verecek şekilde tasarlandığını, ancak keyfi ifadelere izin vermediğini unutmayın. Özellikle, köşeli parantez içindeki kod referansları, aşağıdakilerden herhangi birini içerebilir:

• Tanımlayıcının comment kapsamındaki herhangi bir tanımlayıcı(identifier) olduğu tek bir tanımlayıcı (doküman yorumlarında kapsamda ne olduğuna ilişkin spesifikasyona bakın),

• ilk tanımlayıcının kapsamdaki bir sınıfın adı ve ikincisinin sınıfta bildirilen bir üyenin adı olduğu bir nokta ile ayrılmış iki tanımlayıcı,

• tek bir tanımlayıcı ve ardından bir parantez çifti, burada tanımlayıcı kapsamdaki bir sınıfın adıdır (sınıfın adsız constructor'ına atıfta bulunmak için kullanılır),

• veya bir nokta ile ayrılmış ve ardından bir çift parantez ile ayrılmış iki tanımlayıcı; burada ilk tanımlayıcı kapsamdaki bir sınıfın adı ve ikincisi adlandırılmış bir constructor'ın adıdır (kesinlikle gerekli değildir, ancak tutarlılık için izin verilir).

control_flow_in_finally

Son bloklarda kontrol akışı kullanmaktan kaçının.
Son bloklarda kontrol akışının kullanılması, kaçınılmaz olarak, hata ayıklaması zor olan beklenmeyen davranışlara neden olacaktır.

Doğru kullanım:

class Ok {
  double compliantMethod() {
    var i = 5;
    try {
      i = 1 / 0;
    } catch (e) {
      print(e); // OK
    }
    return i;
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

class BadReturn {
  double nonCompliantMethod() {
    try {
      return 1 / 0;
    } catch (e) {
      print(e);
    } finally {
      return 1.0; // LINT
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

class BadContinue {
  double nonCompliantMethod() {
    for (var o in [1, 2]) {
      try {
        print(o / 0);
      } catch (e) {
        print(e);
      } finally {
        continue; // LINT
      }
    }
    return 1.0;
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

class BadBreak {
  double nonCompliantMethod() {
    for (var o in [1, 2]) {
      try {
        print(o / 0);
      } catch (e) {
        print(e);
      } finally {
        break; // LINT
      }
    }
    return 1.0;
  }
}
Enter fullscreen mode Exit fullscreen mode

diagnostic_describe_all_properties
Debug methodlarında tüm public property'leri implemente edin.

Diagnosticable'ın uygulayıcıları, çalışma zamanında hata ayıklanabilirliğini iyileştirmek için bir debugFillProperties(...) veya debugDescribeChildren(...) methodu tüm public özelliklere başvurmalıdır.

Yanlış kullanım:

class Absorber extends Widget {
  bool get absorbing => _absorbing;
  bool _absorbing;
  bool get ignoringSemantics => _ignoringSemantics;
  bool _ignoringSemantics;
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
    // Missing reference to ignoringSemantics
  }
}  
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

class Absorber extends Widget {
  bool get absorbing => _absorbing;
  bool _absorbing;
  bool get ignoringSemantics => _ignoringSemantics;
  bool _ignoringSemantics;
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
    properties.add(DiagnosticsProperty<bool>('ignoringSemantics', ignoringSemantics));
  }
}  
Enter fullscreen mode Exit fullscreen mode

empty_statements

Boş ifadelerden kaçının.

Boş ifadeler genellikle bir hatayı gösterir.

Örneğin,

Yanlış kullanım:

if (complicated.expression.foo());
  bar();
Enter fullscreen mode Exit fullscreen mode

Dart formatı ile biçimlendirilen hata bariz hale gelir:

if (complicated.expression.foo()) ;
bar();

Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

if (complicated.expression.foo())
  bar();
Enter fullscreen mode Exit fullscreen mode

invariant_booleans

Koşullu ifadeler koşulsuz olarak true veya false olarak değerlendirilmemelidir.

Bu kural şu anda deneyseldir. (experimental)

Derleme zamanında çıkarılabilecek koşulları test etmeyin veya aynı koşulu iki kez test etmeyin.

False'dan başka bir şey olamayacak bir koşul kullanan koşullu ifadeler, kod bloklarını işlevsiz hale getirme etkisine sahiptir. Koşul, true dışında hiçbir şeyi değerlendiremezse, koşullu ifade tamamen gereksizdir ve kodu daha az okunabilir hale getirir. Kodun programcının amacı ile uyuşmaması oldukça olasıdır. Ya koşul kaldırılmalı ya da her zaman true veya false olarak değerlendirilmemesi ve gereksiz testler yapmaması için güncellenmelidir.

Yanlış kullanım:

// foo aynı ifadede bara hem eşitdir hem de eşit olamaz
if(foo == bar && something && foo != bar) {...}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void compute(int foo) {
  if (foo == 4) {
    doSomething();
   // bu noktada foo'nun 4'e eşit olduğunu biliyoruz, bu nedenle sonraki koşul her zaman false
    if (foo > 4) {...}
    ...
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void compute(bool foo) {
  if (foo) {
    return;
  }
  doSomething();
  // burada foo'nun değeri her zaman false'dır
  if (foo){...}
  ...
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void nestedOK() {
  if (foo == bar) {
    foo = baz;
    if (foo != bar) {...}
  }
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void nestedOk2() {
  if (foo == bar) {
    return;
  }

  foo = baz;
  if (foo == bar) {...} // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void nestedOk5() {
  if (foo != null) {
    if (bar != null) {
      return;
    }
  }

  if (bar != null) {...} // OK
}
Enter fullscreen mode Exit fullscreen mode

iterable_contains_unrelated_type

İlişkisiz(unrelated) türlerin referanslarıyla Iterable.contains çağrısı.

Yanlış kullanım:

void someFunction() {
  var list = <int>[];
  if (list.contains('1')) print('someFunction'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction3() {
  List<int> list = <int>[];
  if (list.contains('1')) print('someFunction3'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction8() {
  List<DerivedClass2> list = <DerivedClass2>[];
  DerivedClass3 instance;
  if (list.contains(instance)) print('someFunction8'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

abstract class SomeIterable<E> implements Iterable<E> {}

abstract class MyClass implements SomeIterable<int> {
  bool badMethod(String thing) => this.contains(thing); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction10() {
  var list = [];
  if (list.contains(1)) print('someFunction10'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction1() {
  var list = <int>[];
  if (list.contains(1)) print('someFunction1'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction4() {
  List<int> list = <int>[];
  if (list.contains(1)) print('someFunction4'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction5() {
  List<ClassBase> list = <ClassBase>[];
  DerivedClass1 instance;
  if (list.contains(instance)) print('someFunction5'); // OK
}

abstract class ClassBase {}

class DerivedClass1 extends ClassBase {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction6() {
  List<Mixin> list = <Mixin>[];
  DerivedClass2 instance;
  if (list.contains(instance)) print('someFunction6'); // OK
}

abstract class ClassBase {}

abstract class Mixin {}

class DerivedClass2 extends ClassBase with Mixin {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction7() {
  List<Mixin> list = <Mixin>[];
  DerivedClass3 instance;
  if (list.contains(instance)) print('someFunction7'); // OK
}

abstract class ClassBase {}

abstract class Mixin {}

class DerivedClass3 extends ClassBase implements Mixin {}
Enter fullscreen mode Exit fullscreen mode

list_remove_unrelated_type

İlişkisiz türlerin referanslarıyla remove çağrısı.

Parametre türünden farklı türde bir örnekle(instance) listede remove yöntemini çağırmayın.

Bunu yapmak, liste elemanları üzerinde == öğesini çağırır ve büyük olasılıkla false döndürür.

Yanlış kullanım:

void someFunction() {
  var list = <int>[];
  if (list.remove('1')) print('someFunction'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction3() {
  List<int> list = <int>[];
  if (list.remove('1')) print('someFunction3'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction8() {
  List<DerivedClass2> list = <DerivedClass2>[];
  DerivedClass3 instance;
  if (list.remove(instance)) print('someFunction8'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

abstract class SomeList<E> implements List<E> {}

abstract class MyClass implements SomeList<int> {
  bool badMethod(String thing) => this.remove(thing); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction10() {
  var list = [];
  if (list.remove(1)) print('someFunction10'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction1() {
  var list = <int>[];
  if (list.remove(1)) print('someFunction1'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction4() {
  List<int> list = <int>[];
  if (list.remove(1)) print('someFunction4'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction5() {
  List<ClassBase> list = <ClassBase>[];
  DerivedClass1 instance;
  if (list.remove(instance)) print('someFunction5'); // OK
}

abstract class ClassBase {}

class DerivedClass1 extends ClassBase {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction6() {
  List<Mixin> list = <Mixin>[];
  DerivedClass2 instance;
  if (list.remove(instance)) print('someFunction6'); // OK
}

abstract class ClassBase {}

abstract class Mixin {}

class DerivedClass2 extends ClassBase with Mixin {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction7() {
  List<Mixin> list = <Mixin>[];
  DerivedClass3 instance;
  if (list.remove(instance)) print('someFunction7'); // OK
}

abstract class ClassBase {}

abstract class Mixin {}

class DerivedClass3 extends ClassBase implements Mixin {}
Enter fullscreen mode Exit fullscreen mode

literal_only_boolean_expressions
Boole ifadesi yalnızca literal'lerden oluşur.

False'dan başka bir şey olamayacak bir koşulu kullanan koşullu ifadeler (conditional statements), kod bloklarını işlevsiz hale getirme etkisine sahiptir. Koşul, true dışında hiçbir şeyi değerlendiremezse, koşullu ifade tamamen gereksizdir ve kodu daha az okunabilir hale getirir. Kodun programcının amacı ile uyuşmaması oldukça olasıdır. Ya koşul kaldırılmalı ya da her zaman true veya false olarak değerlendirilmemesi için güncellenmelidir.

Yanlış kullanım:

void bad() {
  if (true) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (true && 1 != 0) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (1 != 0 && true) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (1 < 0 && true) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (true && false) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (1 != 0) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (true && 1 != 0 || 3 < 4) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void bad() {
  if (1 != 0 || 3 < 4 && true) {} // LINT
}
Enter fullscreen mode Exit fullscreen mode

NOT: (;;) eşdeğerine tercih edilen while (true) { } deyimi için bir istisna yapılmıştır.

Doğru kullanım:

void good() {
  while (true) {
    // Do stuff.
  }
}
Enter fullscreen mode Exit fullscreen mode

no_adjacent_strings_in_list

Listede bitişik stringleri kullanmayın.

Doğru kullanım:

List<String> list = <String>[
  'a' +
  'b',
  'c',
];
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

List<String> list = <String>[
  'a'
  'b',
  'c',
];
Enter fullscreen mode Exit fullscreen mode

no_duplicate_case_values

Aynı değerde birden fazla case kullanmayın.

Bu genellikle bir yazım hatası veya constant'ın değiştirilmiş değeridir.

Doğru kullanım:

const int A = 1;
switch (v) {
  case A:
  case 2:
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

const int A = 1;
switch (v) {
  case 1:
  case 2:
  case A:
  case 2:
}
Enter fullscreen mode Exit fullscreen mode

no_logic_in_create_state

"createState" içine herhangi bir mantık koymayın.

createState() uygulamaları, bir state nesnesinin yeni bir örneğini (instance) döndürmeli ve başka bir şey yapmamalıdır. Widget alanı aracılığıyla durum erişimi tercih edildiğinden, verilerin özel constructor parametreleri kullanılarak state nesnelerine iletilmesinden de kaçınılmalıdır ve , state constructor'ına hiçbir argüman iletilmemelidir.

Yanlış kullanım:

MyState global;

class MyStateful extends StatefulWidget {
  @override
  MyState createState() {
    global = MyState();
    return global;
  } 
}
Enter fullscreen mode Exit fullscreen mode
class MyStateful extends StatefulWidget {
  @override
  MyState createState() => MyState()..field = 42;
}
Enter fullscreen mode Exit fullscreen mode
class MyStateful extends StatefulWidget {
  @override
  MyState createState() => MyState(42);
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

class MyStateful extends StatefulWidget {
  @override
  MyState createState() {
    return MyState();
  }
}
Enter fullscreen mode Exit fullscreen mode

prefer_relative_imports

lib/ altındaki dosyalar için relative import'u tercih edin.

Relative(göreceli) ve absolute(mutlak) içe aktarmaların her ikisini birden kullanırken aynı üyenin iki farklı şekilde içe aktarıldığı bir durumla karşılaşılması mümkündür.
Bundan kaçınmak için lib/ klasöründeki dosyalar için sürekli olarak relative importları (göreceli içe aktarmaları) kullandığınızdan emin olun.

Doğru kullanım: import 'bar.dart';

Yanlış kullanım: import 'package:my_package/bar.dart';

prefer_void_to_null

Void'in çalışacağı yerlerde Null türünü kullanmayın.

Yanlış kullanım:

Null f() {}
Future<Null> f() {}
Stream<Null> f() {}
f(Null x) {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void f() {}
Future<void> f() {}
Stream<void> f() {}
f(void x) {}
Enter fullscreen mode Exit fullscreen mode

Bazı istisnalar, özel işlev türlerinin formüle edilmesini içerir:

Null Function(Null, Null);

ve herhangi bir map veya list türü için read-only konumlara geçmek için güvenli olan empty literal'ler (değişmezler) yapmak için:

<Null>[];
<int, Null>{};
Enter fullscreen mode Exit fullscreen mode

test_types_in_equals

Türlerin test edilmemesi, sınıfınızın tüketicileri için beklenmeyen null pointer (boş işaretçi) istisnalarına (exceptions) neden olabilir.

Doğru kullanım:

class Field {
}

class Good {
  final Field someField;

  Good(this.someField);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    return other is Good &&
        this.someField == other.someField;
  }

  @override
  int get hashCode {
    return someField.hashCode;
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

class Field {
}

class Bad {
  final Field someField;

  Bad(this.someField);

  @override
  bool operator ==(Object other) {
    Bad otherBad = other as Bad; // LINT
    bool areEqual = otherBad != null && otherBad.someField == someField;
    return areEqual;
  }

  @override
  int get hashCode {
    return someField.hashCode;
  }
}
Enter fullscreen mode Exit fullscreen mode

throw_in_finally

Son bloklarda istisna(exceptions) atmaktan kaçının.

Nihai bloklarda istisnalar atmak, hata ayıklaması zor olan beklenmeyen davranışlara(unexpected behavior) neden olacaktır.

Doğru kullanım:

class Ok {
  double compliantMethod() {
    var i = 5;
    try {
      i = 1 / 0;
    } catch (e) {
      print(e); // OK
    }
    return i;
  }
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

class BadThrow {
  double nonCompliantMethod() {
    try {
      print('hello world! ${1 / 0}');
    } catch (e) {
      print(e);
    } finally {
      throw 'Find the hidden error :P'; // LINT
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

unnecessary_statements

Gereksiz ifadeler kullanmaktan kaçının.

Açık bir etkisi olmayan ifadeler genellikle gereksizdir veya bölünmelidir.

Örneğin,

Yanlış kullanım:

myvar;
list.clear;
1 + 2;
methodOne() + methodTwo();
foo ? bar : baz;
Enter fullscreen mode Exit fullscreen mode

Bunun gibi kodlar eksik bir düşünceyi gösterir ve bir hatadır.

Doğru kullanım:

some.method();
const SomeClass();
methodOne();
methodTwo();
foo ? bar() : baz();
return myvar;
Enter fullscreen mode Exit fullscreen mode

unrelated_type_equality_checks

Eşitlik operatörünü ilişkisiz türlerin referanslarını karşılaştırırken kullanmayın.

Hiçbirinin diğerinin alt türü olmadığı bir türün referanslarını karşılaştırmak, büyük olasılıkla false döndürür ve programcının amacını yansıtmayabilir.

package:fixnum'daki Int64 ve Int32, int2in sağ tarafta olması koşuluyla int ile karşılaştırmaya izin verir. Lint, buna özel bir durum olarak izin verir.

Yanlış kullanım:

void someFunction() {
  var x = '1';
  if (x == 1) print('someFunction'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction1() {
  String x = '1';
  if (x == 1) print('someFunction1'); // LINT
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void someFunction13(DerivedClass2 instance) {
  var other = DerivedClass3();

  if (other == instance) print('someFunction13'); // LINT
}

class ClassBase {}

class DerivedClass1 extends ClassBase {}

abstract class Mixin {}

class DerivedClass2 extends ClassBase with Mixin {}

class DerivedClass3 extends ClassBase implements Mixin {}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction2() {
  var x = '1';
  var y = '2';
  if (x == y) print(someFunction2); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction3() {
  for (var i = 0; i < 10; i++) {
    if (i == 0) print(someFunction3); // OK
  }
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction4() {
  var x = '1';
  if (x == null) print(someFunction4); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction7() {
  List someList;

  if (someList.length == 0) print('someFunction7'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction8(ClassBase instance) {
  DerivedClass1 other;

  if (other == instance) print('someFunction8'); // OK
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction10(unknown) {
  var what = unknown - 1;
  for (var index = 0; index < unknown; index++) {
    if (what == index) print('someFunction10'); // OK
  }
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

void someFunction11(Mixin instance) {
  var other = DerivedClass2();

  if (other == instance) print('someFunction11'); // OK
  if (other != instance) print('!someFunction11'); // OK
}

class ClassBase {}

abstract class Mixin {}

class DerivedClass2 extends ClassBase with Mixin {}
Enter fullscreen mode Exit fullscreen mode

unsafe_html

Güvenli olmayan HTML API'lerinden kaçının.

• Bir AnchorElement öğesinin href alanına doğrudan atama
• Bir EmbedElement, IFrameElement, ImageElement veya ScriptElement • öğesinin src alanına doğrudan atama
• Bir IFrameElement öğesinin srcdoc alanına doğrudan atama
• Element'in createFragment yöntemini çağırma
• Window open methodunu çağırma
• Element'in setInnerHtml yöntemini çağırma
• Element.html constructor'ını çağırma
• DocumentFragment.html constructor'ını çağırma

Yanlış kullanım:

var script = ScriptElement()..src = 'foo.js';
Enter fullscreen mode Exit fullscreen mode

use_build_context_synchronously

Asenkron boşluklarda BuildContexts kullanmayın.

BuildContext'i daha sonra kullanmak üzere saklamak, teşhis edilmesi zor çökmelere yol açabilir. Asenkron boşluklar örtük olarak BuildContext'i depolar ve kod yazarken gözden kaçırılır.

Bir StatefulWidget'tan bir BuildContext kullanıldığında, asenkron bir boşluktan sonra mounted property kontrol edilmelidir.

Doğru kullanım:

void onButtonTapped(BuildContext context) {
  Navigator.of(context).pop();
}
Enter fullscreen mode Exit fullscreen mode

Yanlış kullanım:

void onButtonTapped(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 1));
  Navigator.of(context).pop();
}
Enter fullscreen mode Exit fullscreen mode

Doğru kullanım:

class _MyWidgetState extends State<MyWidget> {
  ...

  void onButtonTapped() async {
    await Future.delayed(const Duration(seconds: 1));

    if (!mounted) return;
    Navigator.of(context).pop();
  }
}
Enter fullscreen mode Exit fullscreen mode

use_key_in_widget_constructors

Widget constructor'larında key kullanın.

Public widget'lar oluştururken key kullanmak iyi bir yoldur.

Yanlış kullanım:
class MyPublicWidget extends StatelessWidget {}

Doğru kullanım:

class MyPublicWidget extends StatelessWidget {
  MyPublicWidget({Key? key}) : super(key: key);
}
Enter fullscreen mode Exit fullscreen mode

valid_regexps

Geçerli bir regular expression syntax'ı kullanın.

Regular expression (normal ifade örnekleri) oluştururken geçerli regular expression söz dizimini kullanın.

Geçersiz syntax ile oluşturulan düzenli ifadeler, çalışma zamanında bir FormatException oluşturacaktır, bu nedenle bunlardan kaçınılmalıdır.

Yanlış kullanım: print(RegExp(r'(').hasMatch('foo()'));

Doğru kullanım: print(RegExp(r'\(').hasMatch('foo()'));

Bu yazıda Linter kurallarının ilk grubu olan error kurallarını inceledik. Bir sonraki yazıda stil kurallarını inceleyeceğiz.

References:
https://medium.com/podiihq/setting-up-lint-rules-in-dart-flutter-1ebbed0418a6
https://medium.flutterdevs.com/lint-rules-in-flutter-efbcf05daeb5
https://dart.dev/tools/linter-rules#directives_ordering
https://dart-lang.github.io/linter/lints/
https://sourcelevel.io/blog/what-is-a-linter-and-why-your-team-should-use-it

💖 💪 🙅 🚩
gulsenkeskin
Gülsen Keskin

Posted on February 19, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related