Ответ
DTO (Data Transfer Object) — это простой объект, предназначенный исключительно для передачи данных между различными слоями приложения или между клиентом и сервером. В моих Flutter-проектах DTO обычно используются для десериализации JSON-ответов от API.
Типичная реализация DTO во Flutter/Dart:
import 'dart:convert';
// DTO для пользовательских данных с API
class UserDto {
final String id;
final String email;
final String firstName;
final String lastName;
final DateTime createdAt;
UserDto({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.createdAt,
});
// Фабричный конструктор для десериализации JSON
factory UserDto.fromJson(Map<String, dynamic> json) {
return UserDto(
id: json['id'] as String,
email: json['email'] as String,
firstName: json['first_name'] as String,
lastName: json['last_name'] as String,
createdAt: DateTime.parse(json['created_at'] as String),
);
}
// Метод для сериализации в JSON
Map<String, dynamic> toJson() => {
'id': id,
'email': email,
'first_name': firstName,
'last_name': lastName,
'created_at': createdAt.toIso8601String(),
};
// Преобразование DTO в доменную модель
User toDomain() {
return User(
id: UserId(id),
email: Email(email),
fullName: '$firstName $lastName',
registrationDate: createdAt,
);
}
}
// Пример использования с http-пакетом
Future<UserDto> fetchUser(String userId) async {
final response = await http.get(
Uri.parse('https://api.example.com/users/$userId'),
);
if (response.statusCode == 200) {
final jsonData = jsonDecode(response.body) as Map<String, dynamic>;
return UserDto.fromJson(jsonData);
} else {
throw Exception('Failed to load user');
}
}
Ключевые характеристики DTO в моей практике:
- Содержат только данные и методы преобразования
- Обычно immutable (все поля
final) - Включают методы
fromJson/toJsonдля работы с API - Отделены от бизнес-логики и UI-логики
- Могут отличаться от доменных моделей структурой полей
Ответ 18+ 🔞
Да ты послушай, что за модная хуйня эта DTO! Это ж просто объект-перевозчик, как грузовик без кабины — только кузов с данными и всё. Нужен, чтобы таскать инфу между сервером и клиентом, или между слоями приложения. В моих Flutter-проектах они в основном для того, чтобы JSON от API разобрать, ёпта.
Вот как это обычно выглядит, смотри:
import 'dart:convert';
// DTO для пользовательских данных с API
class UserDto {
final String id;
final String email;
final String firstName;
final String lastName;
final DateTime createdAt;
UserDto({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.createdAt,
});
// Фабричный конструктор для десериализации JSON
factory UserDto.fromJson(Map<String, dynamic> json) {
return UserDto(
id: json['id'] as String,
email: json['email'] as String,
firstName: json['first_name'] as String,
lastName: json['last_name'] as String,
createdAt: DateTime.parse(json['created_at'] as String),
);
}
// Метод для сериализации в JSON
Map<String, dynamic> toJson() => {
'id': id,
'email': email,
'first_name': firstName,
'last_name': lastName,
'created_at': createdAt.toIso8601String(),
};
// Преобразование DTO в доменную модель
User toDomain() {
return User(
id: UserId(id),
email: Email(email),
fullName: '$firstName $lastName',
registrationDate: createdAt,
);
}
}
// Пример использования с http-пакетом
Future<UserDto> fetchUser(String userId) async {
final response = await http.get(
Uri.parse('https://api.example.com/users/$userId'),
);
if (response.statusCode == 200) {
final jsonData = jsonDecode(response.body) as Map<String, dynamic>;
return UserDto.fromJson(jsonData);
} else {
throw Exception('Failed to load user');
}
}
А теперь по сути, что это за зверь такой:
Во-первых, это просто контейнер. Доверия ебать ноль к нему в плане логики — он только данные держит и методы для их преобразования. Все поля final, то есть неизменяемые, чтоб никто по ходу дела не накосячил.
Во-вторых, у него обязательно есть fromJson и toJson. Это как переводчик с языка API на человеческий, я тебя умоляю. Прилетает какая-то манда с ушами в виде JSON, а DTO её аккуратно разбирает по полочкам.
И главное — он отделён от всей бизнес-логики! Это как будто ты заказываешь пиццу: курьер (DTO) привозит коробку, но готовить и есть её будешь уже сам дома, в своей доменной модели. DTO — не повар, он только доставщик. В рот меня чих-пых, какая простая концепция, а сколько пользы!
И да, структура полей в DTO может вообще не совпадать с твоей внутренней моделью. API может называть поле first_name, а у тебя в приложении оно будет givenName. Да похуй, DTO как раз для этого и нужен — чтобы этот барьер преодолеть. Преобразовал и забыл.