2022/5/30/Dart/Effective Dart/UsagePart2

 

<<Part1へ戻る


Functions

In Dart, even functions are objects. Here are some best practices involving functions.

Dartでは関数もオブジェクトです。関数に関するベストプラクティスを見て行きましょう。


DO use a function declaration to bind a function to a name.

Modern languages have realized how useful local nested functions and closures are. It’s common to have a function defined inside another one. In many cases, this function is used as a callback immediately and doesn’t need a name. A function expression is great for that.

モダンな言語は、ローカルの入れ子関数とクロージャーがいかに有用であるかを認識しています。 関数を別の関数の内部で定義するのが一般的です。 多くの場合、この関数はすぐにコールバックとして使用され、名前は必要ありません。 関数式はそのために最適です。

 

But, if you do need to give it a name, use a function declaration statement instead of binding a lambda to a variable.

ただし、名前をつける必要がある場合は変数に無名関数を代入するよりも、関数定義をしましょう。

good↓

void main() {
  void localFunction() {
    ...
  }
}

 

bad↓

void main() {
  var localFunction = () {
    ...
  };
}

 


DON’T create a lambda when a tear-off will do.

When you refer to a function, method, or named constructor but omit the parentheses, Dart creates a tear-off—a closure that takes the same parameters as the function and invokes the underlying function when you call it. If all you need is a closure that invokes a named function with the same parameters as the closure accepts, don’t manually wrap the call in a lambda.

関数、メソッド、または名前付きコンストラクターを参照しているが括弧を省略した場合、Dartはティアオフを作成します。これは、関数と同じパラメーターを受け取り、呼び出したときに基になる関数を呼び出すクロージャーです。 必要なのがクロージャが受け入れるのと同じパラメータで名前付き関数を呼び出すクロージャだけである場合は、呼び出しをラムダで手動でラップしないでください。

good↓

var charCodes = [68, 97, 114, 116];
var buffer = StringBuffer();

// Function:
charCodes.forEach(print);

// Method:
charCodes.forEach(buffer.write);

// Named constructor:
var strings = charCodes.map(String.fromCharCode);

// Unnamed constructor:
var buffers = charCodes.map(StringBuffer.new);

 

bad↓

var charCodes = [68, 97, 114, 116];
var buffer = StringBuffer();

// Function:
charCodes.forEach((code) {
  print(code);
});

// Method:
charCodes.forEach((code) {
  buffer.write(code);
});

// Named constructor:
var strings = charCodes.map((code) => String.fromCharCode(code));

// Unnamed constructor:
var buffers = charCodes.map((code) => StringBuffer(code));

結局、goodの書き方でbadのコードと全く同じことができます、ということ。


DO use = to separate a named parameter from its default value.

For legacy reasons, Dart allows both : and = as the default value separator for named parameters. For consistency with optional positional parameters, use =.

歴史的な経緯で、Dartは名前付き引数のデフォルト値の指定に: と =の両方が使えます。しかし、オプショナルポジショナルパラメータとの整合性のため=を使うようにしましょう。

//good
void insert(Object item, {int at = 0}) { ... }

 

//bad
void insert(Object item, {int at: 0}) { ... }

 




Variables

The following best practices describe how to best use variables in Dart.

Dartで正しく変数を使用する方法を見ていきましょう。


DO follow a consistent rule for var and final on local variables.

Most local variables shouldn’t have type annotations and should be declared using just var or final. There are two rules in wide use for when to use one or the other:

ローカル変数のほとんどは、型アノテーションを付けず、varかfinalで宣言する必要があります。どのような場合にどちらを使うかについては、広く使われている2つのルールがあります。

 

  • Use final for local variables that are not reassigned and var for those that are.

再代入する事がないローカル変数はfinalを使う。再代入する可能性があるローカル変数はvarを使う。

  • Use var for all local variables, even ones that aren’t reassigned. Never use final for locals. (Using final for fields and top-level variables is still encouraged, of course.)

再代入しないローカル変数にもvarを使う。ローカル変数にfinalを使うことはない。(もちろんフィールドやトップレベル変数にfinalを使うことは推奨される。)

 

Either rule is acceptable, but pick one and apply it consistently throughout your code. That way when a reader sees var, they know whether it means that the variable is assigned later in the function.

どちらのルールでも構いませんが、どちらかを選び、コード全体に一貫して適用してください。そうすれば、読者はvarを見たときに、その変数が関数内で後に代入されることを意味するのかどうかが分かります。

 


When designing a class, you often want to expose multiple views into the same underlying state. Often you see code that calculates all of those views in the constructor and then stores them:

クラスを設計するとき、多くの場合、同じ基礎的な状態に対して複数のビューを公開したいと思うでしょう。多くの場合、コンストラクタでこれらのビューをすべて計算し、それらを保存するコードを見かけます。

//bad
class Circle {
  double radius;
  double area;
  double circumference;

  Circle(double radius)
      : radius = radius,
        area = pi * radius * radius,
        circumference = pi * 2.0 * radius;
}

This code has two things wrong with it. First, it’s likely wasting memory. The area and circumference, strictly speaking, are caches.

このコードは2つの点で間違っています。まず、メモリを浪費している可能性が高い。面積と円周率は、厳密に言えばキャッシュです。

 

They are stored calculations that we could recalculate from other data we already have. They are trading increased memory for reduced CPU usage. Do we know we have a performance problem that merits that trade-off?

これらは、すでに持っている他のデータから再計算できる結果をわざわざ計算して保存しています。 彼らはCPU使用率を減らすために増加したメモリを交換しています。 そのトレードオフに値するパフォーマンスの問題があることを私たちは知っていますか?

 

Worse, the code is wrong. The problem with caches is invalidation—how do you know when the cache is out of date and needs to be recalculated? Here, we never do, even though radius is mutable. You can assign a different value and the area and circumference will retain their previous, now incorrect values.

さらに悪いことに、このコードは間違っています。キャッシュの問題点は、キャッシュが有効か無効か、という点です。あなたはどうやって、「cacheが古いので再計算する必要がある」ということを認識しますか?

それを知る術がありません。radiusがミュータブル(可変)であっても、です。このコードだとradiusに新しい値を代入する事ができますが、その際、自動的にareaとcicumferenceも再計算されるわけではない。一番最初にセットされた値のままです。それは間違った値ということになります。

 

To correctly handle cache invalidation, we would need to do this:

cacheの無効性を正しく修正するには、私たちは下記のようにする必要があります。

//bad
class Circle {
  double _radius;
  double get radius => _radius;
  set radius(double value) {
    _radius = value;
    _recalculate();
  }

  double _area = 0.0;
  double get area => _area;

  double _circumference = 0.0;
  double get circumference => _circumference;

  Circle(this._radius) {
    _recalculate();
  }

  void _recalculate() {
    _area = pi * _radius * _radius;
    _circumference = pi * 2.0 * _radius;
  }
}

 

That’s an awful lot of code to write, maintain, debug, and read. Instead, your first implementation should be:

これは(実行結果は望んだものとなるが、)書き込み、保守、デバッグ、および読み取りに要するコードが多すぎますね。 正しい実装は下記のようにすべきです。

//good
class Circle {
  double radius;

  Circle(this.radius);

  double get area => pi * radius * radius;
  double get circumference => pi * 2.0 * radius;
}

This code is shorter, uses less memory, and is less error-prone. It stores the minimal amount of data needed to represent the circle. There are no fields to get out of sync because there is only a single source of truth.

このコードは短く、メモリの使用量も少なく、エラーも発生しにくい。円を表現するのに必要な最低限のデータ量を保存します。一つの真実のデータの源に基づいているので、データが保持しているデータが古くて無効になるようなこともありません。

 

In some cases, you may need to cache the result of a slow calculation, but only do that after you know you have a performance problem, do it carefully, and leave a comment explaining the optimization.

時間のかかる計算のキャッシュを保持する必要があるケースもあるかもしれません。しかし、それはパフォーマンスの問題が存在することを確認した時にのみ、慎重に修正して、そして最適化の説明をコメントで残しましょう。




Members

In Dart, objects have members which can be functions (methods) or data (instance variables). The following best practices apply to an object’s members.

Dartのオブジェクトは関数(メソッド)またはデータ(インスタンス変数)のメンバーを保持します。オブジェクトのメンバーに関して下記のベストプラクティスが適用されます。


DON’T wrap a field in a getter and setter unnecessarily.

不必要にフィールドをゲッタとセッタでラップしない。

 

In Java and C#, it’s common to hide all fields behind getters and setters (or properties in C#), even if the implementation just forwards to the field. That way, if you ever need to do more work in those members, you can without needing to touch the call sites. This is because calling a getter method is different than accessing a field in Java, and accessing a property isn’t binary-compatible with accessing a raw field in C#.

JavaやC#ではすべてのフィールドを(あるいはC#ではプロパティを)ゲッターとセッターで隠すことは一般的です。そうすれば、そのメンバーでさらに仕事をする必要が出てきても、コールサイト(呼び出し箇所)に触れる必要がありません。

 

This is because calling a getter method is different than accessing a field in Java, and accessing a property isn’t binary-compatible with accessing a raw field in C#.

工事中🏗

 

Dart doesn’t have this limitation. Fields and getters/setters are completely indistinguishable. You can expose a field in a class and later wrap it in a getter and setter without having to touch any code that uses that field.

Dartではこの制限はありません。フィールドとゲッタ/セッタは完全に区別がつきません。クラスの中でフィールドを公開し、後でそれをゲッターとセッターでラップすれば、そのフィールドを使用するコードに触れる必要はありません。

//good
class Box {
  Object? contents;
}

 

//bad
class Box {
  Object? _contents;
  Object? get contents => _contents;
  set contents(Object? value) {
    _contents = value;
  }
}

 


PREFER using a final field to make a read-only property.

読み取り専用フィールドにするためにfinalキーワードを使いましょう。

If you have a field that outside code should be able to see but not assign to, a simple solution that works in many cases is to simply mark it final.

外部のコードから見えるが、割り当てられないフィールドが必要なら、多くの場合、単純にfinalとマークすることで解決します。

//good
class Box {
  final contents = [];
}

 

//bad
class Box {
  Object? _contents;
  Object? get contents => _contents;
}

 

Of course, if you need to internally assign to the field outside of the constructor, you may need to do the “private field, public getter” pattern, but don’t reach for that until you need to.

もちろん、コンストラクターの外部のフィールドに内部的に割り当てる必要がある場合は、「プライベートフィールド、パブリックゲッター」パターンを実行する必要がありますが、必要になるまでそのパターンに到達しないでください。

工事中🏗


CONSIDER using => for simple members.

シンプルなメンバには=>を使いましょう。

 

In addition to using => for function expressions, Dart also lets you define members with it. That style is a good fit for simple members that just calculate and return a value.

Dartでは、関数式に=>を使用するだけでなく、それを使用してメンバーを定義することもできます。 このスタイルは、値を計算して返すだけの単純なメンバーに適しています。

//good
double get area => (right - left) * (bottom - top);

String capitalize(String name) =>
    '${name[0].toUpperCase()}${name.substring(1)}';

 

People writing code seem to love =>, but it’s very easy to abuse it and end up with code that’s hard to read.

コードを書く人は=>を愛しているように見えますが、それを乱用するのは非常に簡単で、読みにくいコードになってしまいます。

 

If your declaration is more than a couple of lines or contains deeply nested expressions—cascades and conditional operators are common offenders—do yourself and everyone who has to read your code a favor and use a block body and some statements.

あなたの宣言コードが、複数行のコードやネストの深い式である場合、カスケード記法やコンディショナルオペレーターの使用はやめるべきです。あなた自身、あるいはあなたのコードを読むすべての人のために、ブロックボディを使い、複数行のコードを書きましょう。

//good
Treasure? openChest(Chest chest, Point where) {
  if (_opened.containsKey(chest)) return null;

  var treasure = Treasure(where);
  treasure.addAll(chest.contents);
  _opened[chest] = treasure;
  return treasure;
}

 

//bad
Treasure? openChest(Chest chest, Point where) => _opened.containsKey(chest)
    ? null
    : _opened[chest] = (Treasure(where)..addAll(chest.contents));

 


You can also use => on members that don’t return a value. This is idiomatic when a setter is small and has a corresponding getter that uses =>.

また、値を返さないメンバーに対しても => を使用することができます。これは、セッターが小さく、それに対応するゲッターが => を使っている場合によく使われる表現です。

num get x => center.x;
set x(num value) => center = Point(value, center.y);

上記の他にPoint型のcenterフィールドが存在する前提だと思われる。


DON’T use this. except to redirect to a named constructor or to avoid shadowing.

 

JavaScript requires an explicit this. to refer to members on the object whose method is currently being executed, but Dart—like C++, Java, and C#—doesn’t have that limitation.

JavaScriptではメソッドが実行されているときに(つまりメソッドのボディ内で)、メンバのオブジェクトを参照するにはthis.を明示的に記述する必要があります。しかしDartでは、(C++,Java,C#のように)その制約はありません。

 

There are only two times you need to use this.. One is when a local variable with the same name shadows the member you want to access:

this.を使う必要があるケースが二つあります。一つ目はフィールド名とローカル変数名(あるいは引数名)が同じ場合です。

下記のbadサンプルではBoxクラスのフィールドvalueと、メソッドupdateの引数名valueが同じなので、updateメソッドのボディ内で

引数valueを表すのにvalue、

フィールドvalueを表すのにthis.value

としないとどちらを参照しているのか区別できないからthis.を使っている。

void update(Object? newValue) {
 value = newValue; 
}

上記のように定義すればthis.を使わなくても済む。別にどちらでも良い。

//bad
class Box {
  Object? value;

  void clear() {
    this.update(null);
  }

  void update(Object? value) {
    this.value = value;
  }
}

 

//good
class Box {
  Object? value;

  void clear() {
    update(null);
  }

  void update(Object? value) {
    this.value = value;
  }
}

 


The other time to use this. is when redirecting to a named constructor:

もう一つのthis.を使うケースは、名前付きコンストラクタへリダイレクトする時です。

//bad
class ShadeOfGray {
  final int brightness;

  ShadeOfGray(int val) : brightness = val;

  ShadeOfGray.black() : this(0);

  // This won't parse or compile!
  // ShadeOfGray.alsoBlack() : black();
}

 

//good
class ShadeOfGray {
  final int brightness;

  ShadeOfGray(int val) : brightness = val;

  ShadeOfGray.black() : this(0);

  // But now it will!
  ShadeOfGray.alsoBlack() : this.black();
}

Note that constructor parameters never shadow fields in constructor initializer lists:

コンストラクタのイニシャライザリスト内では名前の衝突は起きないことに注意してください。

//good
class Box extends BaseBox {
  Object? value;

  Box(Object? value)
      : value = value,
        super(value);
}

This looks surprising, but works like you want. Fortunately, code like this is relatively rare thanks to initializing formals and super initializers.

これはびっくりされるかも知れませんが、期待通りの挙動になります。幸運なことに、イニシャライジングフォーマルやスーパーイニシャライザーのおかげでこういうコードを書くことは稀です。

value = value

となっているが、どちらも同じものを指しているので名前衝突にはならない。

どうでもいいが、上記のようなコードだと親クラスのBaseBoxでvalueをセットするような実装が一般的な気がする。そうするとBoxクラスのvalueにセットする必要があるのかなあ、という気がするが、BaseBoxクラスの定義が見られないと何とも言えない。


DO initialize fields at their declaration when possible.

可能ならフィールドの宣言時に初期化しましょう。

 

If a field doesn’t depend on any constructor parameters, it can and should be initialized at its declaration. It takes less code and avoids duplication when the class has multiple constructors.

フィールドがコンストラクタのパラメータに依存していない場合、フィールドを宣言時に初期化できますし、そうすべきです。コードが少なくなりますし、クラスが複数のコンストラクタを持つ時に重複を避ける事ができます。

badサンプルではstartの初期化コードを二箇所で書いているが、これは

goodサンプルのように一箇所にまとめられる。

//bad
class ProfileMark {
  final String name;
  final DateTime start;

  ProfileMark(this.name) : start = DateTime.now();
  ProfileMark.unnamed()
      : name = '',
        start = DateTime.now();
}

 

//good
class ProfileMark {
  final String name;
  final DateTime start = DateTime.now();

  ProfileMark(this.name);
  ProfileMark.unnamed() : name = '';
}

 

Some fields can’t be initialized at their declarations because they need to reference this—to use other fields or call methods, for example. However, if the field is marked late, then the initializer can access this.

例えば別のフィールドやメソッド呼び出しを使ってあるフィールドを初期化する場合などは、thisにアクセスする必要があるので宣言時に初期化できません。しかし、そのフィールドの宣言にlateキーワードを使えば、イニシャライザはthisにアクセスできます。

 

Of course, if a field depends on constructor parameters, or is initialized differently by different constructors, then this guideline does not apply.

もちろん、フィールドがコンストラクタパラメータに依存している場合や、フィールドが異なるコンストラクタに異なる方法で初期化される場合などはこのガイドラインは当てはまりません。




Constructors

The following best practices apply to declaring constructors for a class.

クラスのコンストラクタには下記のベストプラクティスが適用されます。


DO use initializing formals when possible.

可能ならイニシャライジングフォーマルを使いましょう。

 

Many fields are initialized directly from a constructor parameter, like:

イニシャライジングフォーマルを使えば、下記のように複数のフィールドを直接コンストラクタのパラメータから初期化できます。

//bad
class Point {
  double x, y;
  Point(double x, double y)
      : x = x,
        y = y;
}

 

We’ve got to type x four times here to define a field. We can do better:

badサンプルだとxを四回タイプしていますが、下記のようにした方が良いですね。

//good
class Point {
  double x, y;
  Point(this.x, this.y);
}

 

This this. syntax before a constructor parameter is called an “initializing formal”.

このコンストラクタパラメータの前にthis.と記述する記法が「イニシャライジングフォーマル」です。

 

You can’t always take advantage of it. Sometimes you want to have a named parameter whose name doesn’t match the name of the field you are initializing. But when you can use initializing formals, you should.

常に利用できるとは限りません。 初期化するフィールドの名前と名前が一致しない名前付きパラメーターが必要な場合があります。 ただし、initializing formalを使用する場合は、そうする(同じ名前にする)必要があります。

 


DON’T use late when a constructor initializer list will do.

Sound null safety requires Dart to ensure that a non-nullable field is initialized before it can be read.

健全なnull safetyはDartに対して、「non-nullableなフィールドは読み取られる前に初期化されていること」を要求します。

 

Since fields can be read inside the constructor body, this means you get an error if you don’t initialize a non-nullable field before the body runs.

コンストラクタのボディ内からフィールドにアクセスできるので、これは「コンストラクタのボディが実行される前にnon-nullableなフィールドを初期化しないとエラーが出る」ということを意味します。

エラーの原因について、ここでの説明と、diagnostic-messagesでの説明が微妙に違うような気がしないでもない。リンク先では、「フィールド宣言時に暗黙的にnullで初期化されるのでその時点でエラー」という説明。

 

You can make this error go away by marking the field late. That turns the compile-time error into a runtime error if you access the field before it is initialized. That’s what you need in some cases, but often the right fix is to initialize the field in the constructor initializer list:

フィールドをlateで宣言することでこのエラーを出なくする事ができます。しかしそれだと、仮にlateフィールドが初期化される前にアクセスしてしまうと実行時エラーが出てしまう。(不注意があると実行時エラーになる、ということ)

こうすることが必要なケースもあるでしょうが、多くの場合で正しい修正は「コンストラクタのイニシャライザリストで初期化する」事です。

 

The initializer list gives you access to constructor parameters and lets you initialize fields before they can be read.

イニシャライザリストを使えば、コンストラクタのパラメータにアクセスする手段を得られ、フィールドが読み取られる前に初期化する事が可能になります。

 

So, if it’s possible to use an initializer list, that’s better than making the field late and losing some static safety and performance.

ですから、イニシャライザリストを使うことが可能な場合は、フィールドをlateにして静的解析による安全性やパフォーマンスを犠牲にするよりもベターな選択肢となります。

//bad
class Point {
  double x, y;
  
  Point.polar(double theta, double radius){
    x = cos(theta) * radius;
    y = sin(theta) * radius;
  }
}

//クラス定義時点で
//line 13 • Non-nullable instance field 'y' must be initialized. (view docs)
//Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
//上記エラーが出る(xについても同様)。

diagnostic-messages

詳しくは上記のリンク先の説明の通り。

x・yは、フィールド宣言時に暗黙的(自動的)にnullで初期化される。しかしxも

yもnon-nullable型なので矛盾、エラー、ということになる。

「いや、だからコンストラクタで初期化しようとしているんでしょ?」と思われる方も多いと思いますが、それでは遅いようです。もう、そういうふうにできているから、としか言いようがないんだと思います。

じゃあどうすれば良いか。その答えがこの箇所。

//解決策1 : lateで宣言する。
//bad
class Point {
  late double x, y;
  
  Point.polar(double theta, double radius){
    x = cos(theta) * radius;
    y = sin(theta) * radius;
  }
  
}

これでエラーは出なくなるが、ここではbadサンプルとして挙げられている。

 

//解決策2 : イニシャライザリストで初期化する。
//good
class Point {
  double x, y;
  Point.polar(double theta, double radius)
      : x = cos(theta) * radius,
        y = sin(theta) * radius;
}

これでエラーは出なくなる。

 

//解決策3: 宣言時に初期化する。
class Point {
  double x = 0, y = 0;
  
  Point.polar(double theta, double radius){
    x = cos(theta) * radius;
    y = sin(theta) * radius;
  }
}

今回x、yがmutable(可変、finalが付いてない)(Point自体がmutable、と表現すべきか)なので、上記のようにx,yの宣言時に初期化してもエラーは出なくなる。


DO use ; instead of {} for empty constructor bodies.

In Dart, a constructor with an empty body can be terminated with just a semicolon. (In fact, it’s required for const constructors.)

Dart では、空のボディを持つコンストラクタはセミコロンだけで終了させることができます。(実際、const コンストラクタでは必須です)。

//good
class Point {
  double x, y;
  Point(this.x, this.y);
}

 

//bad
class Point {
  double x, y;
  Point(this.x, this.y) {}
}

 


DON’T use new.

newキーワードを使わないようにしましょう。

工事中🏗

 


DON’T use const redundantly.

constを使いすぎないようにしよう。

In contexts where an expression must be constant, the const keyword is implicit, doesn’t need to be written, and shouldn’t. Those contexts are any expression inside:

式がconstant(コンパイル時定数)になることが明らかな場合、constキーワードは暗黙的に使用(認識)されるので明示的に書く必要はありませんし、書くべきではありません。

Those contexts are any expression inside:

下記のような状況が含まれます。

  • A const collection literal.

constなコレクションリテラル

  • A const constructor call

constコンストラクタの呼び出し

  • A metadata annotation.

メタデータアノテーション

  • The initializer for a const variable declaration.

constな変数(定数)の初期化

  • A switch case expression—the part right after case before the :, not the body of the case.

switch-case文、caseの後ろ、:の前。caseのボディではない。

(Default values are not included in this list because future versions of Dart may support non-const default values.)

(将来のDartのバージョンでnon-constデフォルト値をサポートする可能性があるので、デフォルト値はこのリストの中に含まれません。)

 

Basically, any place where it would be an error to write new instead of const, Dart 2 allows you to omit the const.

基本的に、constの代わりにnewを書き込むのがエラーになる場所であれば、Dart2ではconstを省略できます。

//good
const primaryColors = [
  Color('red', [255, 0, 0]),
  Color('green', [0, 255, 0]),
  Color('blue', [0, 0, 255]),
];

 

//bad
const primaryColors = const [
  const Color('red', const [255, 0, 0]),
  const Color('green', const [0, 255, 0]),
  const Color('blue', const [0, 0, 255]),
];

代入演算子の右辺のListがconstでなければならないのは自明だし、constな

Listのすべての要素はconst値でなければならないので、それらにわざわざconstキーワードを書かせるのも冗長、という事か。




Error handling

Dart uses exceptions when an error occurs in your program. The following best practices apply to catching and throwing exceptions.

Dartではプログラムでエラーが発生したときは例外を使います。例外のスローやキャッチについてのベストプラクティスを見ていきましょう。


AVOID catches without on clauses.

on句のないキャッチはやめよう。

A catch clause with no on qualifier catches anything thrown by the code in the try block.

on句の無いcatch節はtryブロック内でスローされたすべてのエラーをキャッチします。

 

Pokémon exception handlingis very likely not what you want.

上記のサンプルのような状況はあなたの望むものではないでしょう。

 

Does your code correctly handle StackOverflowError or OutOfMemoryError?

あなたはStackOverflowError or OutOfMemoryErrorを正しくハンドリングしていますか?

 

If you incorrectly pass the wrong argument to a method in that try block do you want to have your debugger point you to the mistake or would you rather that helpful ArgumentError get swallowed?

そのtryブロックのメソッドに間違った引数を誤って渡した場合、デバッガーに間違いを指摘させたいですか、それとも有用なArgumentErrorを飲み込んでもらいたいですか?

 

Do you want any assert() statements inside that code to effectively vanish since you’re catching the thrown AssertionErrors?

投げられたAssertionErrorsをキャッチしているので、そのコード内のassert()ステートメントを効果的に消滅させたいのでしょうか?

 

The answer is probably “no”, in which case you should filter the types you catch.

キャッチしたタイプをフィルタリングする必要があるケースでは、答えはおそらく「いいえ」です。

 

In most cases, you should have an onclause that limits you to the kinds of runtime failures you are aware of and are correctly handling.

ほとんどの場合、on節を設けて、自分が認識していて正しく処理できる種類の実行時エラーに限定する必要があります。

 

In rare cases, you may wish to catch any runtime error. This is usually in framework or low-level code that tries to insulate arbitrary application code from causing problems.

稀なケースとして、ランタイムエラーをキャッチしたい場合があります。これは通常、フレームワークや低レベルのコードにあり、任意のアプリケーションコードがを問題から遮断するためのものです。

 

Even here, it is usually better to catch Exception than to catch all types. Exception is the base class for all runtime errors and excludes errors that indicate programmatic bugs in the code.

この場合でも、通常はすべての型をキャッチするよりもExceptionをキャッチしたほうがよい。Exception はすべての実行時エラーの基本クラスであり、コードのプログラム上のバグを示すエラーは除外されます。


DON’T discard errors from catches without on clauses.

on句無しでキャッチ節からのエラーを破棄しないでください。

If you really do feel you need to catch everything that can be thrown from a region of code, do something with what you catch. Log it, display it to the user or rethrow it, but do not silently discard it.

コードの領域からスローされる可能性のあるすべてのものをキャッチする必要があると本当に感じた場合は、キャッチしたもので何かを実行してください。 ログに記録するか、ユーザーに表示するか、再スローしてください、黙って破棄するのはやめてください。


DO throw objects that implement Error only for programmatic errors.

Error を実装したオブジェクトを投げるのは、プログラム上のエラーの場合だけにしてください。

The Error class is the base class for programmatic errors. When an object of that type or one of its subinterfaces like ArgumentError is thrown, it means there is a bug in your code.

Error クラスは、プログラムエラーの基本クラスです。このタイプのオブジェクトやArgumentErrorのようなサブインターフェイスの1つがスローされたとき、それはあなたのコードにバグがあることを意味します。

 

When your API wants to report to a caller that it is being used incorrectly throwing an Error sends that signal clearly.

APIが不正に使用されていることを呼び出し元に報告したい場合、Errorを投げる(スローする)ことでそのシグナルを明確に送ることができる。

 

Conversely, if the exception is some kind of runtime failure that doesn’t indicate a bug in the code, then throwing an Error is misleading.

逆に、例外がコードのバグを示さないある種の実行時障害である場合、Errorを投げることは誤解を招くことになります。

 

Instead, throw one of the core Exception classes or some other type.

代わりに、コアExceptionクラスの1つまたは他のタイプをスローします。


DON’T explicitly catch Error or types that implement it.

 

工事中🏗

参考

usage

カテゴリーDart

コメントを残す

メールアドレスが公開されることはありません。