По каким правилам в Dart именуются методы?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
По каким правилам в Dart именуются методы?
В Dart существуют строгие соглашения по именованию (naming conventions), которые определены в официальном Dart style guide. Это не только вопрос стиля — эти правила помогают другим разработчикам понять назначение метода.
1. Основное правило: camelCase
Все методы в Dart именуются в camelCase (первое слово со строчной буквы, остальные с заглавной).
// ✅ Правильно
void calculateTotal() {}
String getName() {}
bool isValidEmail(String email) {}
Future<void> fetchUserData() {}
void onButtonPressed() {}
// ❌ Неправильно
void calculatetotal() {} // Не camelCase
void CalculateTotal() {} // PascalCase (для классов)
void calculate_total() {} // snake_case
void CALCULATE_TOTAL() {} // SCREAMING_SNAKE_CASE
2. Глаголы в начале
Методы обычно начинаются с глагола, который описывает действие.
// ✅ Начинаются с глагола (действия)
void calculate() {}
void validate() {}
void initialize() {}
void dispose() {}
List<User> getUsers() {}
String formatDate(DateTime date) {}
void saveData() {}
Future<void> uploadImage() {}
void removeItem(int index) {}
void toggleTheme() {}
// ❌ Неправильно — не ясно, что это метод
void users() {} // Выглядит как свойство, не метод
void data() {} // Неясно, что делает
void response() {} # Неясно, действие это или свойство
3. Логические методы (возвращают bool)
Методы, возвращающие логическое значение, обычно начинаются с:
- is — состояние
- has — наличие
- can — возможность
- should — должно ли
- would — условие
// ✅ Правильные имена для методов, возвращающих bool
bool isEmpty() {} // is + прилагательное
bool isValid() {}
bool isLoggedIn() {}
bool isLoading() {}
bool hasError() {} // has + существительное
bool hasPermission() {}
bool hasInternet() {}
bool canDelete() {} // can + глагол
bool canEdit() {}
bool canDownload() {}
bool shouldRetry() {} // should + глагол
bool shouldRefresh() {}
bool wouldCauseError() {} # would + глагол
// ❌ Неправильно
bool validate() {} # Неясно, true = valid или invalid?
bool checkEmail() {} # Неясно, что возвращает
bool user() {} # Очень неясно
4. Методы для getter/setter
В Dart есть специальный синтаксис для свойств, но иногда нужны методы.
// ✅ Свойства (если просто чтение)
class User {
final String name; // Свойство
int get age => _birthYear == null ? 0 : DateTime.now().year - _birthYear!;
// Setter
set age(int value) => _birthYear = DateTime.now().year - value;
}
// ✅ Методы (если требует логики)
class User {
String? _name;
String getName() => _name ?? 'Unknown';
void setName(String value) => _name = value;
// Или используй свойства с логикой
String get name => _name ?? 'Unknown';
set name(String value) => _name = value;
}
// ❌ Неправильные имена
void setUserName() {} # Не используй set в обычных методах
String getUserName() {} # Лучше использовать get свойство
5. Асинхронные методы (Future/Stream)
Обычно именуются как обычные методы, но часто с глаголом действия.
// ✅ Правильные имена для async методов
Future<List<User>> fetchUsers() {}
Future<void> saveData() {}
Future<String> downloadFile(String url) {}
Stream<int> countdownTimer() {}
Future<User?> getUserById(int id) {}
// ❌ Неправильно
Future<List<User>> users() {} # Неясно, что это async
Future<void> getUsersFromAPI() {} # Лишнее слово
6. Callback методы (listeners, handlers)
Обычно начинаются с on + действие.
// ✅ Правильные имена для callback'ов
void onPressed() {}
void onChanged(String value) {}
void onError(Exception error) {}
void onSuccess(User user) {}
void onItemTapped(int index) {}
void onDrawerClosed() {}
void onScrollEnd() {}
void onDataReceived(List<T> data) {}
// ❌ Неправильно
void handlePressed() {} # Используй "on" для callbacks
void pressedCallback() {} # Неинформативно
void _pressed() {} # Неясно, что это callback
7. Приватные методы (начинаются с _)
// ✅ Приватные методы также следуют camelCase
class User {
String _name = '';
// Приватный метод
void _validateEmail(String email) {}
String _formatName() => _name.trim();
bool _hasSpecialCharacters(String text) {}
// Публичный метод может вызывать приватный
void setEmail(String email) {
if (_validateEmail(email)) {
this._email = email;
}
}
}
// ❌ Неправильно
void __doubleUnderscore() {} # Не используй двойное подчёркивание
void _PRIVATE_METHOD() {} # Не используй SCREAMING_SNAKE_CASE
8. Фабричные методы (factory constructors)
Обычно именуются с глаголом (fromJSON, parse и т.д.).
// ✅ Правильные имена для factory методов
class User {
final String name;
User(this.name);
// Factory methods
factory User.fromJson(Map<String, dynamic> json) {
return User(json['name'] as String);
}
factory User.empty() {
return User('');
}
factory User.fromString(String nameAndAge) {
final parts = nameAndAge.split(':');
return User(parts[0]);
}
}
// Использование
final user1 = User.fromJson({'name': 'John'});
final user2 = User.empty();
final user3 = User.fromString('John:30');
9. Методы преобразования
Для преобразования из одного типа в другой используется to + тип.
// ✅ Правильные имена для методов преобразования
class User {
String toJson() => jsonEncode({'name': name});
Map<String, dynamic> toMap() => {'name': name};
String toString() => 'User($name)';
String toFormattedString() => 'Name: $name';
int toHashCode() => name.hashCode;
}
class DateTime {
String toIso8601String() {} # Преобразование в ISO строку
int toMillisecondsSinceEpoch() {} # Преобразование в число
}
// Использование
final user = User('John');
print(user.toString()); // User(John)
print(user.toJson()); // {"name":"John"}
10. Операторы (operators)
В Dart можно переопределять операторы, и они имеют особые имена.
// ✅ Правильные имена операторов
class Vector {
int x, y;
Vector(this.x, this.y);
// Арифметические операторы
Vector operator +(Vector other) => Vector(x + other.x, y + other.y);
Vector operator -(Vector other) => Vector(x - other.x, y - other.y);
Vector operator *(int scalar) => Vector(x * scalar, y * scalar);
Vector operator /(int scalar) => Vector(x ~/ scalar, y ~/ scalar);
// Операторы сравнения
bool operator ==(Object other) {
if (other is! Vector) return false;
return x == other.x && y == other.y;
}
int get hashCode => x.hashCode ^ y.hashCode;
// Операторы индексирования
int operator [](int index) => index == 0 ? x : y;
void operator []=(int index, int value) {
if (index == 0) x = value;
else y = value;
}
}
// Использование
final v1 = Vector(1, 2);
final v2 = Vector(3, 4);
final v3 = v1 + v2; // Vector(4, 6)
final v4 = v1 * 2; // Vector(2, 4)
11. Методы инициализации и очистки
Уточнённые имена для жизненного цикла.
// ✅ Правильные имена для lifecycle методов
abstract class BaseService {
Future<void> initialize() {} // Инициализация
Future<void> dispose() {} // Очистка
void reset() {} # Сброс состояния
void clear() {} # Очистка данных
void reload() {} # Перезагрузка
}
// В StatefulWidget
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {} // Инициализация (обязательно)
@override
void didUpdateWidget(MyWidget oldWidget) {} // Обновление
@override
void deactivate() {} # Деактивация
@override
void dispose() {} # Удаление (обязательно)
}
12. Тестовые методы
В тестах немного другие соглашения.
// ✅ Правильные имена для test методов
void main() {
test('should return user when id is valid', () {
// Arrange
// Act
// Assert
});
test('throws exception when email is invalid', () {
// Test
});
testWidgets('displays loading spinner while fetching', (WidgetTester tester) {
// Test
});
group('User repository', () {
test('returns list of users', () {});
test('caches results', () {});
});
}
Сводная таблица: Правила именования
| Тип метода | Шаблон | Пример | Возврат |
|---|---|---|---|
| Обычный | глагол + существительное | calculateTotal() | Любой |
| Boolean | is/has/can/should + прилагательное | isEmpty(), hasError() | bool |
| Callback | on + действие | onPressed(), onChange() | void/Future |
| Async | глагол + существительное | fetchUsers(), saveData() | Future |
| Преобразование | to + тип | toString(), toJson() | Тип |
| Factory | from + источник | fromJson(), fromString() | Объект класса |
| Приватный | _ + обычные правила | _validateEmail() | Любой |
| Оператор | operator + символ | operator +() | Зависит |
Linter правила для Dart
Дартовый linter (в pubspec.yaml) проверяет эти правила:
linter:
rules:
- camel_case_extensions # Расширения в camelCase
- camel_case_types # Типы в PascalCase
- library_names # Библиотеки в snake_case
- library_prefixes # Префиксы в snake_case
- non_constant_identifier_names # Переменные в camelCase
Best Practice пример
// ✅ Полный пример правильного именования
abstract class UserRepository {
Future<List<User>> getUsers(); # Fetch plural
Future<User?> getUserById(int id); # Fetch singular
Future<void> saveUser(User user); # Action
Future<void> deleteUser(int id); # Action
Stream<User> watchUser(int id); # Observe changes
}
class UserRepositoryImpl implements UserRepository {
final _api = ApiClient();
final _cache = <int, User>{};
@override
Future<List<User>> getUsers() async {
try {
return await _fetchFromAPI(); # Private helper
} catch (e) {
return _getCachedUsers(); # Private helper
}
}
@override
Future<User?> getUserById(int id) async {
if (_isCached(id)) return _cache[id]; # Private check
return await _api.getUser(id);
}
@override
Future<void> saveUser(User user) => _api.saveUser(user);
@override
Future<void> deleteUser(int id) => _api.deleteUser(id);
@override
Stream<User> watchUser(int id) => _api.watchUser(id);
// Private methods
Future<List<User>> _fetchFromAPI() => _api.getUsers();
List<User> _getCachedUsers() => _cache.values.toList();
bool _isCached(int id) => _cache.containsKey(id);
}
Резюме
Правила именования методов в Dart:
- camelCase — первое слово со строчной буквы
- Глагол в начале — описывает действие
- Boolean методы — is/has/can/should + прилагательное
- Callback методы — on + действие
- Async методы — обычное имя (Future показывает асинхронность)
- Преобразование — to + тип
- Factory методы — from + источник
- Приватные методы — _ + обычные правила
- Операторы — operator + символ
Главное правило: Имя метода должно чётко описывать, что он делает. Если не ясно из названия — переименуй!