Использовали ли DTO (Data Transfer Object) и зачем
Что проверяют
Понимаете ли вы, зачем разделять модели по слоям, и можете ли объяснить это на своём проекте, а не определением из книги. Следом обычно просят показать маппинг или спрашивают, не слишком ли много получается одинаковых классов.
Как отвечать
В Android под DTO почти всегда понимают сетевую модель: класс, в который десериализуется ответ API через Retrofit и kotlinx.serialization, Moshi или Gson. Типичная раскладка по слоям:
- DTO (
UserDto): повторяет JSON как есть, с@SerialName("first_name"), nullable-полями и строками вместо enum; - Entity (
UserEntity): таблица Room со своими аннотациями@Entityи@PrimaryKey; - доменная модель (
User): чистый Kotlin без аннотаций, только то, что нужно приложению; - UI-состояние: данные, готовые к показу, с отформатированными датами и суммами.
Между слоями стоят функции маппинга вроде UserDto.toDomain(), и в них же решается, что делать с пришедшим null или неизвестным значением. Выигрыш в том, что переименование поля на бэкенде правится в одном DTO и маппере, а экраны о нём не узнают. Плата: больше классов и кода маппинга, поэтому в небольшом приложении слои иногда осознанно объединяют.
Отвечайте на своём примере: какой API, что поменялось на сервере и сколько кода это затронуло. Если отдельных DTO у вас не было, скажите честно и объясните, в какой момент вы бы их ввели.
Где спотыкаются
Говорят, что DTO сокращает число сетевых запросов. Это смысл исходного паттерна из серверной разработки, а на клиенте количество запросов определяет API: объединить пользователя и заказы в один ответ может только бэкенд.
Используют Gson с Kotlin-классами и не знают, что он создаёт объект в обход конструктора. Поле, объявленное non-null, получает null, значения по умолчанию игнорируются, и падение случается далеко от парсинга.
Забывают про R8: без @SerializedName или keep-правил Gson после обфускации перестаёт находить поля в релизной сборке, хотя в отладочной всё работает.