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

Приведи пример фичи реализацией которой гордишься

1.6 Junior🔥 191 комментариев
#Другое

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Пример фичи, которой я горжусь

Я хочу рассказать о реализации системы кэширования с умной инвалидацией в одном из своих проектов. Это было одновременно технически интересной задачей и ощутимо улучшило пользовательский опыт приложения.

Задача и контекст

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

Решение

Я разработал многоуровневую систему кэширования:

class CacheManager {
  final Map<String, CacheEntry> _memory = {};
  final AppDatabase _database;
  final Duration _ttl;

  Future<T?> get<T>(String key, {
    required Future<T> Function() fetch,
    required Duration? ttl,
  }) async {
    // 1. Проверяем in-memory кэш
    if (_memory.containsKey(key) && !_isExpired(_memory[key]!)) {
      return _memory[key]!.data as T;
    }

    // 2. Проверяем локальную БД
    final cached = await _database.getCached(key);
    if (cached != null && !_isExpired(cached)) {
      _memory[key] = CacheEntry(
        data: cached.data,
        expiresAt: cached.expiresAt,
      );
      return cached.data as T;
    }

    // 3. Загружаем с сервера
    try {
      final freshData = await fetch();
      final ttlDuration = ttl ?? _ttl;
      
      _memory[key] = CacheEntry(
        data: freshData,
        expiresAt: DateTime.now().add(ttlDuration),
      );
      
      await _database.cache(key, freshData, ttlDuration);
      return freshData;
    } catch (e) {
      // На ошибку возвращаем устаревшие данные
      return cached?.data as T?;
    }
  }

  Future<void> invalidate(String pattern) async {
    // Инвалидируем по паттерну (например, "user_*")
    _memory.removeWhere((key, _) => key.contains(pattern));
    await _database.invalidate(pattern);
  }

  bool _isExpired(CacheEntry entry) {
    return DateTime.now().isAfter(entry.expiresAt);
  }
}

Умная инвалидация

Когда пользователь обновляет данные, система знает, какой кэш нужно инвалидировать:

Future<void> updateProject(Project project) async {
  try {
    await _api.updateProject(project);
    
    // Инвалидируем кэши, которые содержат этот проект
    await _cacheManager.invalidate('project_${project.id}');
    await _cacheManager.invalidate('projects_list_*');
    await _cacheManager.invalidate('user_${project.ownerId}_projects');
    
    _showSuccess('Проект обновлён');
  } catch (e) {
    _showError('Ошибка при обновлении');
  }
}

Использование в приложении

Для загрузки данных с автоматическим кэшированием:

class ProjectsBloc extends Cubit<ProjectsState> {
  Future<void> loadProjects() async {
    emit(ProjectsLoading());
    
    try {
      final projects = await _cacheManager.get(
        'projects_list_${_userId}',
        fetch: () => _api.getProjects(),
        ttl: Duration(minutes: 15),
      );
      
      emit(ProjectsLoaded(projects));
    } catch (e) {
      emit(ProjectsError(e.toString()));
    }
  }
}

Результаты

До внедрения:

  • Среднее время загрузки экрана: 2-3 секунды
  • Мерцание при переходах: заметное
  • Потребление трафика: высокое

После внедрения:

  • Мгновенное отображение кэшированных данных
  • Фоновое обновление в статьях
  • Снижение трафика на 65%
  • Рейтинг приложения вырос с 4.2 до 4.6 звёзд

Почему я горжусь этой фичей

  1. Техническая сложность — система работает на трёх уровнях (memory, DB, server) с правильными приоритетами

  2. Пользовательский опыт — мгновенная загрузка данных кардинально улучшает ощущение от приложения

  3. Робастность — приложение работает даже при потере интернета, показывая свежие кэшированные данные

  4. Производительность — оптимизирована как скорость, так и потребление ресурсов

  5. Гибкость — система позволяет настраивать TTL для разных типов данных

Эта фича показала мне, что иногда наибольший вклад в качество приложения дают не сложные UI-компоненты, а продуманная архитектура и управление состоянием.

Приведи пример фичи реализацией которой гордишься | PrepBro