← Назад к вопросам

Что получилось найти в коде после рефакторинга

2.0 Middle🔥 241 комментариев
#Архитектура и паттерны#Опыт и софт-скиллы

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Анализ результатов рефакторинга

После проведения рефакторинга в Android-проекте удалось выявить несколько ключевых улучшений и проблем, которые были устранены. Рефакторинг — это не просто "переписывание кода", а системный процесс улучшения внутренней структуры без изменения внешнего поведения. Вот что было обнаружено и улучшено:

1. Устранение дублирования кода и повышение модульности

В исходной версии часто встречались повторяющиеся блоки логики, особенно в обработке ViewModel и Repository. Например, паттерн загрузки данных с обработкой состояния (Loading, Success, Error) был реализован в каждом ViewModel по-своему.

После рефакторинга был создан общий абстрактный класс BaseViewModel, который централизовал эту логику:

abstract class BaseViewModel<State, Action>(initialState: State) : ViewModel() {
    private val _state = MutableStateFlow(initialState)
    val state: StateFlow<State> = _state.asStateFlow()

    private val _action = MutableSharedFlow<Action>()
    val action: SharedFlow<Action> = _action.asSharedFlow()

    protected fun updateState(newState: State) {
        _state.value = newState
    }

    protected fun sendAction(newAction: Action) {
        viewModelScope.launch {
            _action.emit(newAction)
        }
    }
}

Это позволило:

  • Уменьшить количество кода в каждом конкретном ViewModel на 30-40%
  • Унифицировать обработку ошибок и состояний загрузки
  • Упростить тестирование благодаря стандартизированному интерфейсу

2. Оптимизация архитектурных слоев и зависимостей

Анализ показал нарушение принципов Clean Architecture и SOLID:

  • Repository напрямую зависели от конкретных реализаций API-клиентов
  • UseCases отсутствовали или были слабо выделены, бизнес-логика "размазывалась" между ViewModel и Repository

Результат рефакторинга — четкое разделение слоев:

Data Layer (Repository + DataSources) → Domain Layer (UseCases) → Presentation Layer (ViewModel + UI)

Пример UseCase после рефакторинга:

class GetUserProfileUseCase(
    private val userRepository: UserRepository
) {
    suspend operator fun invoke(userId: String): Result<UserProfile> {
        return userRepository.getProfile(userId)
            .map { profile -> profile.toDomainModel() }
    }
}

3. Улучшение обработки асинхронных операций и корутин

В исходном коде обнаружились проблемы:

  • Неструктурированное использование корутин (launch в разных scope без контроля)
  • Отсутствие обработки cancellation при уходе из экрана
  • "Утечки" Flow при неправильной подписке

После исправлений:

  • Введен паттерн CoroutineScope с четкой иерархией (viewModelScope, lifecycleScope)
  • Все длительные операции защищены try-catch с корректным преобразованием ошибок
  • Flow-коллекторы переведены на использование repeatOnLifecycle:
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.state.collect { state ->
            updateUI(state)
        }
    }
}

4. Упрощение и стандартизация DI (Dependency Injection)

Обнаружена "разношерстность" внедрения зависимостей: где-то Dagger/Hilt, где-то ручное создание, где-то Service Locator.

После рефакторинга:

  • Проект переведен на единый стандарт — Hilt
  • Устранены циклические зависимости через рефакторинг модулей
  • Созданы четкие @Qualifier для разных типов данных (например, Retrofit для основного API и для аналитики)

5. Повышение тестируемости и внедрение Mock-объектов

Изначальный код был трудно тестируем из-за:

  • Жестких зависимостей от реальных реализаций
  • Смешения ответственности в классах

Улучшения:

  • Ключевые классы (Repository, UseCases) теперь принимают интерфейсы, что позволяет легко подменять их в тестах
  • Введены FakeRepository и MockViewModel для unit-тестов
  • Упрощена проверка состояния через стандартизированные State-объекты

6. Устранение проблем с памятью и производительностью

Профилирование после рефакторинга показало:

  • Снижение количества создаваемых объектов в онбординге (убраны ненужные промежуточные данные)
  • Оптимизация использования Bitmap и ресурсов (введен четкий cache-паттерн)
  • Улучшение cold start времени благодаря отложенной инициализации некоторых сервисов

Ключевые метрики улучшений:

  • Уменьшение дублирования кода: с 18% до 5% (по анализу SonarQube)
  • Снижение сложности методов: средняя длина метода уменьшилась с 45 до 22 строк
  • Улучшение покрытия тестами: с 40% до 75%
  • Упрощение поддержки: новые функциональности теперь добавляются в среднем на 30% быстрее

Рефакторинг выявил, что даже в относительно хорошо структурированном проекте всегда есть возможности для улучшения модульности, тестируемости и соблюдения архитектурных принципов. Главный результат — код стал не только чище, но и более поддерживаемым, расширяемым и надёжным.