mirror of
https://github.com/AdrianKuta/KahootQuiz.git
synced 2025-09-14 17:24:21 +02:00
refactor: Relocate data module and add README
This commit moves the `model:data` module to a top-level `data` module. Additionally, a `README.md` file has been added to the project root, providing an overview of the project, architecture, build instructions, current limitations, and suggested improvements. Key changes: - Renamed Gradle module `model:data` to `data`. - Updated `settings.gradle.kts` to reflect the new module path. - Updated `app/build.gradle.kts` to depend on `projects.data` instead of `projects.model.data`. - All source files, including `QuizRepositoryImpl`, `QuizMapper`, and `RepositoryModule`, were moved from `model/data/src` to `data/src`. - Configuration files (`detekt.yml`, `lint-baseline.xml`, `build.gradle.kts`) were moved from `model/data` to `data`. - Added a new `README.md` file at the project root.
This commit is contained in:
3
.idea/gradle.xml
generated
3
.idea/gradle.xml
generated
@@ -28,9 +28,8 @@
|
||||
<option value="$PROJECT_DIR$/core" />
|
||||
<option value="$PROJECT_DIR$/core/designsystem" />
|
||||
<option value="$PROJECT_DIR$/core/network" />
|
||||
<option value="$PROJECT_DIR$/data" />
|
||||
<option value="$PROJECT_DIR$/domain" />
|
||||
<option value="$PROJECT_DIR$/model" />
|
||||
<option value="$PROJECT_DIR$/model/data" />
|
||||
<option value="$PROJECT_DIR$/ui" />
|
||||
<option value="$PROJECT_DIR$/ui/quiz" />
|
||||
</set>
|
||||
|
104
README.md
Normal file
104
README.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# KahootQuiz — Interview Challenge
|
||||
|
||||
This project is an implementation for an interview-style challenge. It demonstrates a clean, modular
|
||||
Android architecture with a focus on separation of concerns, convention plugins for Gradle, and
|
||||
pragmatic Kotlin usage.
|
||||
|
||||
## TL;DR
|
||||
|
||||
- Only image media is supported right now.
|
||||
- Slider question type is not supported.
|
||||
- There is no end/completion screen yet.
|
||||
- Errors in ViewModels are caught but not yet handled (no user-facing error states/actions).
|
||||
|
||||
## Project Overview
|
||||
|
||||
- Multi-module, clean architecture:
|
||||
- `core/` — common utilities (e.g., networking).
|
||||
- `domain/` — pure domain models and repository abstractions, domain models.
|
||||
- `data/` — repository implementations, mappers.
|
||||
- `ui/` — feature UI modules (e.g., `ui/quiz`).
|
||||
- Convention plugins are used to centralize and reuse Gradle configuration across modules (see
|
||||
`build-logic/`).
|
||||
- Kotlin-first approach using language features to keep code concise and readable.
|
||||
|
||||
## How to Build & Run
|
||||
|
||||
1. Requirements:
|
||||
- Android Studio
|
||||
- JDK 21
|
||||
- Gradle wrapper included
|
||||
2. Steps:
|
||||
- Open the project in Android Studio.
|
||||
- Sync Gradle.
|
||||
- Run the `app` configuration on a device/emulator.
|
||||
|
||||
If you prefer the command line: `./gradlew assembleDebug` and then install the generated APK.
|
||||
|
||||
## Architecture Details
|
||||
|
||||
- Data flow follows a standard clean pattern:
|
||||
- `domain.repositories.QuizRepository` defines the contract.
|
||||
- `data.QuizRepositoryImpl` uses `core.network.retrofit.QuizApi` + mappers to produce
|
||||
`domain.models.Quiz`.
|
||||
- UI consumes domain via ViewModels and exposes a `UiState`.
|
||||
- The code emphasizes separation of concerns and testability.
|
||||
|
||||
## Current Limitations & Known Issues
|
||||
|
||||
- Media support:
|
||||
- Only `image` media is supported in the quiz content.
|
||||
- Other media types are not supported.
|
||||
- Question types:
|
||||
- Slider answers are not supported yet.
|
||||
- UX flow:
|
||||
- There is no end/completion screen after the quiz finishes.
|
||||
- Error handling:
|
||||
- Exceptions are caught in ViewModels but not handled (no retry, no error UI, no telemetry hooks
|
||||
yet).
|
||||
|
||||
## Suggested Improvements
|
||||
|
||||
1. Introduce a UI-specific model for the Quiz screen
|
||||
- The domain model `Quiz` is relatively complex and currently used directly in `UiState`.
|
||||
- Add a dedicated, lean UI data class that contains only the data relevant to the quiz screen.
|
||||
- Benefits: Improved clarity for UI developers, simpler previews, easier testing/mocking, and
|
||||
better forward-compatibility when domain evolves.
|
||||
|
||||
2. Expand Unit Test Coverage
|
||||
- Currently there is only one unit test for parsing a sample JSON API response.
|
||||
- Add tests for:
|
||||
- ViewModel state transitions (loading/success/error).
|
||||
- Mapping edge cases (e.g., missing fields, unsupported media types).
|
||||
- Navigation/flow for various question types.
|
||||
|
||||
3. Error Handling Strategy
|
||||
- Map exceptions to user-friendly UI states with retry actions.
|
||||
- Add telemetry/logging hooks for observability.
|
||||
|
||||
4. Feature Completeness
|
||||
- Implement slider answer type.
|
||||
- Add an end/completion screen with score summary and restart/share options.
|
||||
- Consider support for additional media types (video/audio), with graceful fallbacks.
|
||||
5. Transitions between questions could be more smooth.
|
||||
|
||||
## What I’m Happy About
|
||||
|
||||
- I created and used convention plugins to reuse modules configuration.
|
||||
- The architecture is clean with multi-modularity and separation of concerns.
|
||||
- I leaned into Kotlin ‘sugar’ where it helps readability and conciseness — I love it.
|
||||
- Configured `Detekt` for static code analysis
|
||||
|
||||
## Extra: Related Work I Can Share
|
||||
|
||||
I can share more complex code from my private app that is published on the Google Play Store.
|
||||
Additionally, I have a secondary project — an AI Agent implemented in TypeScript using Google’s
|
||||
GenKit framework — that prepares content for that app. It leverages multiple models, vector stores,
|
||||
and embeddings to orchestrate cooperative behaviors.
|
||||
|
||||
If you’re interested, I can provide a deeper walkthrough, architectural diagrams, or selected code
|
||||
excerpts.
|
||||
|
||||
## License
|
||||
|
||||
This repository is provided as-is for interview and demonstration purposes.
|
@@ -29,7 +29,7 @@ android {
|
||||
dependencies {
|
||||
implementation(projects.core.designsystem)
|
||||
implementation(projects.domain)
|
||||
implementation(projects.model.data)
|
||||
implementation(projects.data)
|
||||
implementation(projects.ui.quiz)
|
||||
|
||||
implementation(libs.androidx.activity.compose)
|
||||
|
@@ -4,7 +4,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "dev.adriankuta.kahootquiz.model.data"
|
||||
namespace = "dev.adriankuta.kahootquiz.data"
|
||||
}
|
||||
|
||||
dependencies {
|
5
data/lint-baseline.xml
Normal file
5
data/lint-baseline.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<issues name="AGP (8.13.0-rc02)" by="lint 8.13.0-rc02" client="gradle" dependencies="false" format="6"
|
||||
type="baseline" variant="all" version="8.13.0-rc02">
|
||||
|
||||
</issues>
|
@@ -1,9 +1,9 @@
|
||||
package dev.adriankuta.kahootquiz.model.data
|
||||
package dev.adriankuta.kahootquiz.data
|
||||
|
||||
import dev.adriankuta.kahootquiz.core.network.retrofit.QuizApi
|
||||
import dev.adriankuta.kahootquiz.domain.models.Quiz
|
||||
import dev.adriankuta.kahootquiz.domain.repositories.QuizRepository
|
||||
import dev.adriankuta.kahootquiz.model.data.mappers.toDomainModel
|
||||
import dev.adriankuta.kahootquiz.data.mappers.toDomainModel
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class QuizRepositoryImpl @Inject constructor(
|
@@ -1,11 +1,11 @@
|
||||
package dev.adriankuta.kahootquiz.model.data.di
|
||||
package dev.adriankuta.kahootquiz.data.di
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dev.adriankuta.kahootquiz.data.QuizRepositoryImpl
|
||||
import dev.adriankuta.kahootquiz.domain.repositories.QuizRepository
|
||||
import dev.adriankuta.kahootquiz.model.data.QuizRepositoryImpl
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
@@ -1,6 +1,6 @@
|
||||
@file:Suppress("TooManyFunctions")
|
||||
|
||||
package dev.adriankuta.kahootquiz.model.data.mappers
|
||||
package dev.adriankuta.kahootquiz.data.mappers
|
||||
|
||||
import dev.adriankuta.kahootquiz.core.network.models.AccessDto
|
||||
import dev.adriankuta.kahootquiz.core.network.models.ChannelDto
|
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<issues format="6" by="lint 8.13.0-rc02" type="baseline" client="gradle" dependencies="false" name="AGP (8.13.0-rc02)" variant="all" version="8.13.0-rc02">
|
||||
|
||||
</issues>
|
@@ -27,6 +27,6 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
include(":app")
|
||||
include(":core:designsystem")
|
||||
include(":core:network")
|
||||
include(":data")
|
||||
include(":domain")
|
||||
include(":model:data")
|
||||
include(":ui:quiz")
|
||||
|
Reference in New Issue
Block a user