-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture
jjoonleo edited this page Sep 1, 2025
·
7 revisions
This document provides a comprehensive overview of the OnTime Flutter project's architecture, folder structure, and design patterns.
OnTime follows Clean Architecture principles with a clear separation of concerns across three main layers:
- Presentation Layer: UI components, state management (BLoC/Cubit), and navigation
- Domain Layer: Business logic, entities, use cases, and repository interfaces
- Data Layer: Repository implementations, data sources (local/remote), and data models
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PRESENTATION LAYER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β’ Screens & Components β
β β’ BLoC/Cubit (State Management) β
β β’ Navigation (GoRouter) β
β β’ Theme & Localization β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DOMAIN LAYER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β’ Entities (Business Objects) β
β β’ Use Cases (Business Logic) β
β β’ Repository Interfaces β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA LAYER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β’ Repository Implementations β
β β’ Data Sources (Remote API, Local Database) β
β β’ Data Models (JSON Serialization) β
β β’ Database Tables & DAOs β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
lib/
βββ π± presentation/ # UI Layer (Screens, Widgets, State Management)
β βββ alarm/ # Alarm and timer functionality
β βββ app/ # Main app setup and global BLoC
β βββ calendar/ # Calendar views and components
β βββ early_late/ # Early/late arrival screens
β βββ home/ # Home screen and dashboard
β βββ login/ # Authentication screens
β βββ my_page/ # User profile and settings
β βββ notification_allow/ # Notification permission
β βββ onboarding/ # User onboarding flow
β βββ schedule_create/ # Schedule creation and editing
β βββ shared/ # Shared UI components and utilities
β βββ components/ # Reusable widgets
β βββ router/ # Navigation configuration
β βββ theme/ # App theming
β βββ utils/ # UI utilities
β
βββ π’ domain/ # Business Logic Layer
β βββ entities/ # Business objects (User, Schedule, etc.)
β βββ repositories/ # Repository interfaces
β βββ use-cases/ # Business logic operations
β
βββ πΎ data/ # Data Access Layer
β βββ daos/ # Database Access Objects (Drift)
β βββ data_sources/ # Data source interfaces/implementations
β βββ models/ # API request/response models
β βββ repositories/ # Repository implementations
β βββ tables/ # Database table definitions
β
βββ π§ core/ # Core Infrastructure
β βββ constants/ # App constants and environment variables
β βββ database/ # Database configuration (Drift)
β βββ di/ # Dependency injection setup (Injectable)
β βββ dio/ # HTTP client configuration
β βββ services/ # Core services (navigation, notifications)
β βββ utils/ # Core utilities and converters
β
βββ π l10n/ # Localization files
βββ firebase_options.dart # Firebase configuration
βββ main.dart # Application entry point
- Flutter: Cross-platform mobile framework
- Dart: Programming language
- BLoC/Cubit: Business Logic Component pattern for state management
- Riverpod: Additional state management for specific use cases
- Equatable: Value equality for state objects
- Injectable: Code generation for dependency injection
- GetIt: Service locator pattern
- Drift: Type-safe SQL database library
- SharedPreferences: Simple key-value storage
- FlutterSecureStorage: Secure token storage
- Dio: HTTP client with interceptors
- JSON Annotation: JSON serialization code generation
- GoRouter: Declarative routing solution
- Material Design: Google's design system
- Flutter SVG: SVG asset support
- TableCalendar: Calendar widget
- Google Sign-In: Google OAuth integration
- Kakao SDK: Kakao social login
- Firebase Auth: Authentication backend
- Firebase Messaging: Push notifications
- Flutter Local Notifications: Local notifications
- Freezed: Code generation for immutable classes
- Build Runner: Code generation runner
- Widgetbook: Component development environment
- Screens: Full-screen widgets representing app pages
- Components: Reusable UI widgets
- BLoC/Cubit: State management following BLoC pattern
- Navigation: Declarative routing with GoRouter
- Entities: Core business objects using Freezed for immutability
- Use Cases: Single-responsibility business logic operations
- Repository Interfaces: Contracts for data access
- Repository Implementations: Concrete implementations of domain interfaces
- Data Sources: Abstraction over remote APIs and local storage
- Models: Data transfer objects with JSON serialization
// Injectable annotation for automatic registration
@Injectable()
class UserRepository implements UserRepositoryInterface {
// Implementation
}
// GetIt service locator configuration
final getIt = GetIt.instance;
@InjectableInit()
void configureDependencies() => getIt.init();// BLoC for handling user authentication state
@Injectable()
class AppBloc extends Bloc<AppEvent, AppState> {
AppBloc(this._streamUserUseCase, this._signOutUseCase)
: super(AppState(user: const UserEntity.empty())) {
on<AppUserSubscriptionRequested>(_onUserSubscriptionRequested);
on<AppSignOutPressed>(_onSignOutPressed);
}
}@JsonSerializable()
class GetUserResponseModel {
final int userId;
final String email;
final String name;
// Conversion to domain entity
UserEntity toEntity() {
return UserEntity(
id: userId.toString(),
email: email,
name: name,
);
}
}@DriftDatabase(tables: [Users, Schedules, Places], daos: [UserDao, ScheduleDao])
class AppDatabase extends _$AppDatabase {
@override
int get schemaVersion => 3;
@override
MigrationStrategy get migration => MigrationStrategy(
onCreate: (Migrator m) async => await m.createAll(),
);
}User Input β Widget β BLoC Event β Use Case β Repository β Data Source β API/DB
β
Widget β BLoC State β Use Case β Repository β Data Source β Response
Login Screen β AppBloc β SignInUseCase β UserRepository β AuthDataSource β API
β
Navigation β AppBloc β UserEntity β UserRepository β AuthDataSource β Token
Schedule Form β ScheduleBloc β CreateScheduleUseCase β ScheduleRepository
β
Database β ScheduleDao β ScheduleRepository β ScheduleEntity
- Google OAuth and Kakao Login integration
- JWT token management with secure storage
- Stream-based user state management
- Automatic token refresh via interceptors
- CRUD operations for schedules
- Calendar integration with multiple view modes
- Preparation time calculation and management
- Real-time synchronization between local and remote data
- Firebase push notifications for schedule reminders
- Local notifications for preparation alerts
- Permission handling for notification access
- Local database with Drift for offline data access
- Synchronization strategy for online/offline data consistency
- Caching mechanisms for improved performance
test/
βββ config/ # Test configuration
βββ data/ # Data layer tests
βββ helpers/ # Test utilities
- Unit Tests: Use cases, repositories, and business logic
- Widget Tests: UI components and screen interactions
- Integration Tests: End-to-end user flows
- Mocking: Using Mockito for external dependencies
- Flutter SDK: ^3.5.4
- Dart SDK: Latest stable
- Build Tools: build_runner for code generation
# Generate all code (models, dependency injection, etc.)
dart run build_runner build
# Watch for changes and regenerate
dart run build_runner watch- Android: Native Android build
- iOS: Native iOS build
- Web: Progressive Web App support
- Follow Clean Architecture principles
- Separate concerns across layers
- Use feature-based folder structure in presentation layer
- Use BLoC pattern for complex state management
- Use Cubit for simpler state scenarios
- Keep business logic in use cases, not in BLoCs
- Always use entities in the domain layer
- Convert models to entities at repository boundaries
- Implement proper error handling throughout the layers
-
Entities:
UserEntity,ScheduleEntity -
Use Cases:
GetUserUseCase,CreateScheduleUseCase -
Repositories:
UserRepository,ScheduleRepository -
BLoCs:
UserBloc,ScheduleFormBloc -
Models:
GetUserResponseModel,CreateScheduleRequestModel
- Register all dependencies using @Injectable() annotation
- Use interfaces for repository contracts
- Avoid direct dependencies between layers
-
Setup Environment
- Install Flutter SDK
- Configure IDE (VS Code/Android Studio)
- Run
flutter pub getto install dependencies
-
Code Generation
- Run
dart run build_runner build - This generates dependency injection, JSON serialization, and Freezed code
- Run
-
Database Setup
- Database migrations are handled automatically
- Local database files are created on first run
-
Understanding the Flow
- Start with
main.dartto understand app initialization - Explore
presentation/app/for global app state - Check
domain/use-cases/for business logic - Review
data/repositories/for data access patterns
- Start with
-
Making Changes
- Create new features following the existing layer structure
- Add new entities in
domain/entities/ - Implement use cases in
domain/use-cases/ - Create repository interfaces and implementations
- Build UI components in
presentation/
This architecture documentation is maintained alongside the codebase. Please update it when making significant architectural changes.