Dart

Java 経験者がやりそうなスタイルガイド違反

More than 3 years have passed since last update.

Dart と Java は似ているところあるけれど、そのままの気分で書くと、公式スタイルガイドぶっちぎることがままある。大体は DartEditor が見つけてくれるんだけど、DartEditor も見つけてくれない類のスタイルガイド違反がいくつかあったので、自分が引っかかったところをメモ。

final 変数は lowerCamelCase

Dart での厳密な意味での定数は const 修飾子がついた変数であり、final が付いた変数は一度だけセットできる変数というニュアンスらしい。(きちんとした性質の違いの説明は Final and Const を参照)

このことからか、const 修飾子の変数のみが ALL_CAPS_WITH_UNDERSCORES という名前を付けること、それ以外は、たとえfinal修飾子が付いていても、lowerCamelCase で付ける。

良い:

const PI = 3.14;
const DEFAULT_TIMEOUT = 1000;
final urlScheme = new RegExp('^([a-z]+):');

class Dice {
  static final numberGenerator = new Random();
}

Dart Style Guide | Dart: Structured web apps から

ダメ:

const pi = 3.14;
const kDefaultTimeout = 1000;
final URL_SCHEME = new RegExp('^([a-z]+):');

class Dice {
  static final NUMBER_GENERATOR = new Random();
}

Dart Style Guide | Dart: Structured web apps から

関係ないけど const 使える条件厳しくてあんまり使えてないのでまだ dart 力足りてないのかもしれない。

class *Utils みたいな静的メソッド集やめろ

引っかかったわけでは無いけど、事前に core ソース読まなかったら作ってただろうなーということで書く。

Java だと状態を持たないしあちこちで使うヘルパー関数みたいなものを作りたいとき、class *Utilsclass *s (java.lang とか guava) って関連する名前のクラスを作って、静的メソッドとしてぶら下げることをよくやるのですが、Dart はそのまま関数定義できるので、そちらを使いましょう。

良い:

library utils;

num distance(num x1, num y1, num x2, num y2) {
  /* ... */
}

Dart Style Guide | Dart: Structured web apps から

ダメ:

library utils;

class GeometryUtils {
  static num distance(num x1, num y1, num x2, num y2) {
    /* ... */
  }
}

Dart Style Guide | Dart: Structured web apps から

distance って名前被りそうこわい」って時は、distance を定義した utils.dart を接頭辞付きでインポートする:

名前衝突を回避する
import 'utils.dart' as utils;

main() {
  /* ... */
  final d = utils.distance(x1, y1, x2, y2);
  /* ... */
}

Dart は mix-in できるので、そちらも選択肢としてあります。

新たなインスタンス作るのに静的メソッド使うのやめろ

代わりに名前付きコンストラクタで定義する:

良い:

class Point {
  num x, y;
  Point(this.x, this.y);
  Point.zero()
      : x = 0,
        y = 0;
}

Dart Style Guide | Dart: Structured web apps から

ダメ:

class Point {
  num x, y;
  Point(this.x, this.y);
  static Point zero() => new Point(0, 0);
}

Dart Style Guide | Dart: Structured web apps から

こうすることで「new が頭に付く文は新しいインスタンスを作る文だ」ということが分かりやすくなります。(インスタンスメソッドでも新しいインスタンス作るケースあるしこの主張はどうなんだろう。)

new した直後に初期化したかったり、インスタンスの初期化に複雑な処理だったりするときは factory 修飾子つきのコンストラクタを使う:

class Point {
  num x, y;
  Point();
  factory Point.zero() {
    final p = new Point();
    p
      ..x = 0
      ..y = 0;
    return p;
  }
}

ただ、この factory 修飾子つきコンストラクタは、null やシングルトンなインスタンスも返せてしまうので使い方に注意する必要がある。つまり new ... って書いてあるのに null やシングルトンインスタンスが
返っていくるという罠っぽい挙動になってしまう。

他に Java のつもりで書いていたらこんなのに引っかかった!みたいな話を募集中です。ひょっとしたら私が書いているかもしれないので。