Wise Talk App: Data Flow & Clean Architecture

Wise Talk App: Clean Architecture

Navigating the Data Flow & Project Structure

Understanding Clean Architecture

Clean Architecture organizes an application into concentric layers, promoting separation of concerns and maintainability. The most crucial principle is the Dependency Rule: dependencies can only flow inward. Inner circles (like your Domain Layer’s core business logic) should never know about outer circles (like the UI framework or specific database implementations).

In the “Wise Talk” app, this architecture ensures that core business rules remain independent of UI or data storage technologies. This document provides an interactive blueprint of this structure and illustrates how data moves through the application, making complex concepts easy to digest.

Architectural Layers & Responsibilities

The application is structured into distinct layers, each with specific responsibilities. Clicking on each layer will reveal detailed insights into its purpose and contained file types. This modular approach enhances testability, maintainability, and scalability.

Domain Layer

The innermost layer: Core business rules, entities, and abstract contracts.

Purpose:

  • Contains the application’s core logic, independent of external frameworks.
  • Defines the “what” of your application’s operations.

Structure (`lib/domain/`):

  • `models/`: Pure Dart data structures (`WiseSaying`, `LearningSession`).
  • `enums/`: Domain-specific enumerations (`ModerationStatus`).
  • `failures/`: Custom error types (`Failure`).
  • `repositories/`: Abstract repository interfaces (`WiseSayingRepository`).
  • `use_cases/`: Abstract use case interfaces (`GetWiseSayingsUseCase`).
  • `use_cases/implementations/`: Concrete use case implementations.

Data Layer

Outer layer: Handles data storage and retrieval. Concrete implementations.

Purpose:

  • Responsible for how data is actually stored, retrieved, and managed.
  • Implements the abstract repository interfaces from the Domain Layer.

Structure (`lib/data/`):

  • `repositories/`: Concrete repository implementations (`WiseSayingRepositoryImpl`).
  • `datasources/local/`: Drift database, DAOs (`wise_saying_dao.dart`), converters.
  • `datasources/remote/`: Firebase, TTS, Auth data source implementations.
  • `mappers/`: Extensions for data model conversions.
  • `extensions/`: General data-layer extensions.

Presentation Layer

Outermost layer: The User Interface and its state management.

Purpose:

  • Displays data to the user and captures user input.
  • Consumes use cases from the Domain Layer.

Structure (`lib/presentation/`):

  • `screens/`: UI screens (`home_screen.dart`).
  • `widgets/`: Reusable UI components.
  • `viewmodels/`: UI state holders (Riverpod notifiers/controllers).

Core Layer

Application-wide utilities and constants.

Purpose:

  • Houses cross-cutting concerns that don’t fit into a specific architectural layer.

Structure (`lib/core/`):

  • `utils/`: `app_logger.dart`, other utility functions.
  • `constants/`: `app_constants.dart` (API keys, default values).

End-to-End Data Flow: Wise Sayings Example

This section illustrates a typical data flow, from user interaction in the UI down to the data sources and back. We’ll trace the process for fetching a list of wise sayings, demonstrating how each layer contributes to the operation, from the Presentation Layer’s request to the Data Layer’s orchestration of local and remote sources.

1. User Action / UI Display

A screen needs to display wise sayings. It observes a Riverpod provider for the use case.

2. Use Case Call (Domain Layer)

The UI’s ViewModel calls a `GetWiseSayingsUseCase`. This use case depends only on the abstract `WiseSayingRepository`.

3. Repository Orchestration (Data Layer)

The concrete `WiseSayingRepositoryImpl` receives the request. It triggers a background sync to Firebase and immediately returns a stream from the local Drift database.

4. Local Data Source (Drift DAO)

`WiseSayingDao` queries the local SQLite database and emits a stream of `WiseSayingEntry` objects, which are mapped to domain `WiseSaying` models.

5. Remote Data Source (Firebase)

`WiseSayingFirebaseDataSourceImpl` fetches from Firestore. It handles conversions between Firebase `Timestamp` and Dart `DateTime`, and maps raw Firestore data to `WiseSaying` models. This also feeds updates to the local cache.

6. Data Flow Back Up

The `Stream` of `Either>` flows from the DAO, through the Repository and Use Case, back to the UI via Riverpod.

Key Technologies & Their Roles

The “Wise Talk” app leverages a robust set of tools, each serving a specific purpose within the Clean Architecture framework.

Dart & Flutter

The primary language and framework for cross-platform app development and UI creation.

Riverpod

Modern state management and dependency injection library, ensuring compile-time safety and testability across layers.

Dartz (Either)

Functional programming library for explicit error handling, clearly distinguishing between success (Right) and failure (Left) states.

Freezed & JSON Serializable

Code generation tools for creating immutable data models with utility methods (copyWith, equality) and efficient JSON serialization/deserialization.

Drift (SQLite)

An ORM for local SQLite database persistence, providing reactive stream capabilities for offline data and caching.

Firebase Firestore

A scalable NoSQL cloud database for storing user-generated content and enabling real-time synchronization across devices.

Cloud TTS & Translation APIs

External services integrated for high-quality text-to-speech generation and on-the-fly content translation, enhancing the learning experience.

Benefits of This Architecture

The chosen Clean Architecture, combined with the selected tools, offers significant advantages for the “Wise Talk” app’s development and long-term viability. It ensures a robust, scalable, and delightful user experience.

  • Separation of Concerns: Each layer has a well-defined responsibility, preventing tight coupling and making the codebase easier to understand and manage.
  • Testability: Each layer can be tested in isolation by mocking its dependencies (e.g., testing a use case by mocking its abstract repository interface). This leads to more reliable code.
  • Maintainability: Changes in one layer (e.g., switching databases or UI frameworks) have minimal impact on other layers, especially the core Domain Layer.
  • Scalability: The modular design simplifies adding new features, expanding content, and integrating new services without destabilizing the existing application.
  • Offline-First Capabilities: Leveraging Drift for local caching, the app can provide a seamless experience even without an internet connection, syncing data when connectivity is restored.
  • Reactive UI: Through Riverpod and streams from data sources, the user interface automatically updates in real-time as data changes, providing a dynamic and responsive experience.


mingtech.co
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.