📚

Effective Dartを読んでみた①

2024/01/30に公開

頭が悪いので理解してなかった🙃

Dartのコードを書くルールとか文法のお作法について調べると、Effective Dartなるものに書いてあることは知っていたが、1回読んだが全く理解してなかった...
普段無意識に書いてるのもあるんですけどね〜

https://dart.dev/effective-dart

Effective Dart: Style

優れたコードで意外に重要なのは、優れたスタイルだ。一貫した命名、順序、書式は、同じコードが同じように見えるのを助ける。これは、私たちの眼システムに備わっている強力なパターンマッチングのハードウェアを活用するものだ。Dartのエコシステム全体で一貫したスタイルを使用すれば、私たち全員がお互いのコードから学び、貢献することが容易になります。

そんなもんがあるのか...

Identifiers(識別子)
Dartでは、識別子には3つの種類がある。

UpperCamelCase名は、頭文字を含む各単語の最初の文字を大文字にします。

lowerCamelCase名は、頭文字であっても常に小文字である先頭を除き、各単語の先頭文字を大文字にします。

lowercase_with_underscores名は、頭字語であっても小文字のみを使用し、_で単語を区切ります。

UpperCamelCaseを使ったDO名の型

リンター・ルール: camel_case_types

クラス、enum型、typedef、型パラメータは、各単語の最初の文字を大文字にし(最初の単語を含む)、区切り文字を使用しない。

ちょっとアレンジしてます:

見本
class SliderMenu {
  static const String menu1 = 'Menu 1';
  static const String menu2 = 'Menu 2';
  static const String menu3 = 'Menu 3';

  static const List<String> choices = <String>[
    menu1,
    menu2,
    menu3,
  ];
}

class HttpRequest {
  final String url;
  final String method;
  final Map<String, String> headers;
  final dynamic body;

  HttpRequest(this.url, this.method, this.headers, this.body);
}

enum Color { red, green, blue }

typedef OnChangeColor = Color;

class Foo {
  final Object? arg;
  const Foo([this.arg]);
}

これには、メタデータ注釈で使われることを意図したクラスも含まれる。

少しアレンジしたこんな風に@つけたのは使うらしい。

見本
class Foo {
  final Object? arg;
  const Foo([this.arg]);
}

('Hello, World!')
class A {
  void hello() {
    print('Hello from A');
  }
}

()
class B {
  void hello() {
    print('Hello from B');
  }
}

void main() {
  A a = A();
  a.hello();  // Prints: Hello from A

  B b = B();
  b.hello();  // Prints: Hello from B
}

注釈クラスのコンストラクタがパラメータを取らない場合、そのコンストラクタ用に別のlowerCamelCase定数を作成した方がよいでしょう。

見本
class Foo {
  final Object? arg;
  const Foo([this.arg]);
}

('Hello, World!')
class A {
  void hello() {
    print('Hello from A');
  }
}

()
class B {
  void hello() {
    print('Hello from B');
  }
}

const foo = Foo();


class C {
  void hello() {
    print('Hello from C');
  }
}

void main() {
  A a = A();
  a.hello();  // Prints: Hello from A

  B b = B();
  b.hello();  // Prints: Hello from B

  C c = C();
  c.hello();  // Prints: Hello from C
}

UpperCamelCaseを使用したDO名の拡張子
リンタールール: camel_case_extensions

タイプ同様、拡張子は各単語の最初の文字を大文字にし(最初の単語を含む)、セパレータは使用しない。

公式のコード書き換えてますが、extensionにgetterとメソッドをつけてます。

見本
extension MyFancyList<T> on List<T> {
  int get doubleLength => length * 2;
  void prettyPrint() {
    print('Fancy List: $this');
  }
}

extension SmartIterable<T> on Iterable<T> {
  Iterable<T> get smart => where((e) => e != null);
}

void main() {
  final myList = [1, 2, 3];
  print(myList.doubleLength); // 6
  myList.prettyPrint(); // Fancy List: [1, 2, 3]

  final mySmartList = [1, null, 2, 3];
  print(mySmartList.smart); // (1, 2, 3)
}

パッケージ名、ディレクトリ名、ソースファイル名には小文字とアンダースコアを使ってください。
リンターのルール:ファイル名、パッケージ名

ファイルシステムの中には大文字小文字を区別しないものがあり、多くのプロジェクトではファイル名をすべて小文字にする必要があります。区切り文字を使うことで、その形でも名前が読めるようになります。区切り文字としてアンダースコアを使用することで、その名前が有効な Dart 識別子であることが保証されます。

小文字とアンダースコアを使った DO 名のインポート接頭辞
リンタールール:library_prefixes

他の識別子にはlowerCamelCaseを使用すること。
リンター・ルール: non_constant_identifier_names

クラス・メンバ、トップレベル定義、変数、パラメータ、および名前付きパラメータは、最初の単語を除く各単語の最初の文字を大文字にし、区切り文字を使用しないでください。

パッケージのコードの方が良い気がするが公式のコード修正して使ってます。

見本
class HttpRequest {
  String url;
  String method;
  Map<String, String> headers;
  dynamic body;

  HttpRequest({required this.url, required this.method, required this.headers, this.body});

  void send() {
    print('Sending $method request to $url');
    print('Headers: $headers');
    print('Body: $body');
  }
}

var count = 3;

HttpRequest httpRequest = HttpRequest(url: 'http://example.com', method: 'GET', headers: {}, body: null);

void align(bool clearItems) {
  if (clearItems) {
    count = 0;
  }
  count++;
}

定数名にlowerCamelCaseを使うことを優先する。
リンター・ルール: constant_identifier_names

新しいコードでは、列挙値を含む定数変数に lowerCamelCase を使用する。

SCREAMING_CAPSは、以下のように既存のコードとの整合性を保つために使用することができます:

  • すでに SCREAMING_CAPS を使用しているファイルやライブラリにコードを追加する場合。
  • Javaコードと並列なDartコードを生成する場合、例えばprotobufsから生成される列挙型など。

まとめ

Effective Dart: Styleの解説は長いので、半分ぐらい書いてまた続きを書こうと思います。
今回はUpperCamelCaseで書くとか、_をつけるルールなどについて解説しました。普段からやってるものもありましたね😅
でも職場によって独特な書き方があったような...

変数の種類については参考になりそうな記事を書きました。

https://zenn.dev/joo_hashi/articles/ca7190ce158512

Discussion