# Frontend Convention ###### tags: Naming, rules > 為了得到一致且高品質的code space > 在前端開發時,盡可能的去符合這份文件 [ToC] ## 命名原則 ### ==0: 取有意義的名字== - ❌ Don't ```dart=1 void abc(); List aList =[]; class AAAA{} ``` - ✅ Do ```dart=1 void buildTable(); List productList =[]; List products =[]; class UserRepository{} ``` ### 1: 檔案名稱為 'example_example.ext' - ❌ Don't ```dart Example Example.ext // 使用下畫線分隔單字 Example_Example.ext // 所有單字皆為小寫 ``` - ✅ Do ```dart example_example.ext ``` ### 2: 類別(class)名稱為 'ExampleOne' - ❌ Don't ```dart=1 class exampleOne{} // 使用大駝峰(UpperCamelCase) class Example_One{} // 使用大駝峰(UpperCamelCase)且不使用符號 ``` - ✅ Do ```dart=1 class ExampleOne{} ``` --- ## linter 規則 ### 1: avoid_single_cascade_in_expression_statements > 不要單獨使用cascade expression - ❌ Don't ```dart=1 o..m(); ``` - ✅ Do ```dart=1 o.m(); ``` ### 2: cascade_invocations > 當使用same reference時,使用cascade expression - ❌ Don't ```dart=1 SomeClass someReference = SomeClass(); someReference.firstMethod(); someReference.secondMethod(); ``` - ❌ Don't ```dart=1 SomeClass someReference = SomeClass(); // ... someReference.firstMethod(); someReference.aProperty = value; someReference.secondMethod();; ``` - ✅ Do ```dart=1 SomeClass someReference = SomeClass() ..firstMethod() ..aProperty = value ..secondMethod(); ``` - ✅ Do ```dart=1 SomeClass someReference = SomeClass(); // ... someReference ..firstMethod() ..aProperty = value ..secondMethod(); ``` ### 3: avoid_classes_with_only_static_members > 建立有明確意義的class, 並提供class method > 若需要global 的variable 或是method > **請直接寫在class 外** - ❌ Don't ```dart=1 class DateUtils { static DateTime mostRecent(List<DateTime> dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } } class _Favorites { static const mammal = 'weasel'; } ``` - ✅ Do ```dart=1 DateTime mostRecent(List<DateTime> dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } const _favoriteMammal = 'weasel'; ``` ### 4: camel_case_extensions && camel_case_types > 大寫所有單字的第一個字,並不使用separator - ✅ Do ```dart=1 extension MyFancyList<T> on List<T> { // ... } extension SmartIterable<T> on Iterable<T> { // ... } ``` - ✅ Do ```dart=1 class SliderMenu { // ... } class HttpRequest { // ... } typedef num Adder(num x, num y); ``` ### 5: avoid_function_literals_in_foreach_calls > **避免**使用 forEach() > forEach loop 是透過lambda function 執行迴圈,在async/await 下會顯得不便 > 在Dart裡,如果你想要iterate seq, 最直接的方法就是使用迴圈 - ❌ Don't ```dart=1 people.forEach((person) { // ... }); ``` - ✅ Do ```dart=1 for (var person in people) { // ... } ``` :::info 需要注意的是,規則是寫'function literal',若你想要傳入已存在的function 給每一個element forEach() 是可以被接受的 ::: - ✅ Do ```dart=1 void del(person){...} // ... people.forEach(print); people.forEach(del); ``` ### 6: directives_ordering > 把 "dart:" 的import 放在其它import 的前面 - ❌ Don't ```dart=1 import 'package:bar/bar.dart'; import 'package:foo/foo.dart'; import 'dart:async'; // LINT import 'dart:html'; // LINT ``` - ❌ Don't ```dart=1 import 'dart:html'; // OK import 'package:bar/bar.dart'; import 'dart:async'; // LINT import 'package:foo/foo.dart'; ``` - ✅ Do ```dart=1 import 'dart:async'; // OK import 'dart:html'; // OK import 'package:bar/bar.dart'; import 'package:foo/foo.dart'; ``` > 把 "package:" 的import 放在相對路徑import 之前 - ❌ Don't ```dart=1 import 'a.dart'; import 'b.dart'; import 'package:bar/bar.dart'; // LINT import 'package:foo/foo.dart'; // LINT ``` - ❌ Don't ```dart=1 import 'package:bar/bar.dart'; // OK import 'a.dart'; import 'package:foo/foo.dart'; // LINT import 'b.dart'; ``` - ✅ Do ```dart=1 import 'package:bar/bar.dart'; // OK import 'package:foo/foo.dart'; // OK import 'a.dart'; import 'b.dart'; ``` > 分隔 export 和其餘全部import - ❌ Don't ```dart=1 import 'src/error.dart'; export 'src/error.dart'; // LINT import 'src/string_source.dart'; ``` - ✅ Do ```dart=1 import 'src/error.dart'; import 'src/string_source.dart'; export 'src/error.dart'; // OK ``` > 對每個區塊alphabetically sort - ❌ Don't ```dart=1 import 'package:foo/bar.dart'; // OK import 'package:bar/bar.dart'; // LINT import 'a/b.dart'; // OK import 'a.dart'; // LINT ``` - ✅ Do ```dart=1 import 'package:bar/bar.dart'; // OK import 'package:foo/bar.dart'; // OK import 'a.dart'; // OK import 'a/b.dart'; // OK ``` ### 7: prefer_interpolation_to_compose_strings > 組成字串時,使用 '$' 傳入字串或是數值 - ❌ Don't ```dart=1 'Hello, ' + name + '! You are ' + (year - birth) + ' years old.'; ``` - ✅ Do ```dart=1 'Hello, $name! You are ${year - birth} years old.'; ``` ### 8: prefer_is_empty && prefer_is_not_empty > ==千萬不要用length 來判斷集合內是否為空== > 使用length 去確認集合是否為空,會相當的time-consuming > 使用isEmpty 和isNotEmpty 會更快並更具可讀性 - ❌ Don't ```dart=1 if (lunchBox.length == 0) return 'so hungry...'; if (words.length != 0) return words.join(' '); ``` - ✅ Do ```dart=1 if (lunchBox.isEmpty) return 'so hungry...'; if (words.isNotEmpty) return words.join(' '); ``` ### 9: prefer_equal_for_default_values > 因為Dart 的向後版本支援原因,Dart 允許使用 : 和 = 當作預設值的separator > 為了一致性,請使用 = - ❌ Don't ```dart=1 void insert(Object item, {int at: 0}) { ... } ``` - ✅ Do ```dart=1 void insert(Object item, {int at = 0}) { ... } ``` ### 10: unnecessary_lambdas > 當tear-off 可以使用時,不要建立lambda function - ❌ Don't ```dart=1 names.forEach((name) { print(name); }); ``` - ✅ Do ```dart=1 names.forEach(print); ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up