Android application: Difference between revisions

From Aquarium-Control
Jump to navigation Jump to search
Line 39: Line 39:
=== Layer structure ===
=== Layer structure ===
The code is separated into the following layers:
The code is separated into the following layers:
 
<code>
[module]/
[module]/


├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/data/
├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/data/


│  ├── remote/                  // Network/API service implementations (e.g., Retrofit)
│  ├── remote/                  // Folder for data retrieval functionality


│  │  └── dto/
│  │  └── dto/                 // Folder for Data Transfer Objects


│  │      └── Dto.kt
│  │      └── [module][name]Import.kt


│  │  └── UserApiService.kt
│  │  └── [module][name]Reader.kt     // Implementation of GET server request


│  ├── repository.kt
│  ├── [module][name]RepositoryImpl.kt // Repositories (implementation of interface)


├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/domain/
├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/domain/


│  ├── model/                    // Data Transfer Objects (DTOs) for network/database
│  ├── model/                    // Folder for data definition classes
 
│  │  └── [module][name].kt.    // Classes for data definition
 
│  ├── repository/              // Folder containing repository interface definitions
 
│  │  └── [module][name]Repository.kt.  // Interface defining the repository, used by view model
 
├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/presentation/
 
│  ├── entry/                    // First screen of feature
 
│  ├── [components]/            // Shared code between different screens
 
│  ├── [screen name]/            // Folder for each screen
 
│  │  └── [module][name]Screen.kt      // Composable showing the complete screen
 
│  │  └── [module][name]Composable.kt  // Composable showing elements inside the screen


│  │  └── UserDto.kt
│  │  └── [module][name]UiEvent.kt     // Sealed interface describing the communication from the composable to the view model


│  ├── local/                    // Local persistence (e.g., Room DAOs, SharedPreferences)
│  │  └── [module][name]UiState.kt      // Data class describing the content to be rendered by the composable


│  │  └── UserDao.kt
│  │  └── [module][name]ViewModel.kt   // Class implementing the view model


│  ├── mapper/                   // Functions to map DTOs to Domain models and vice-versa
│  ├── navigation/               // Folder containing class and functionality related to screen navigation


│  │  └── UserMapper.kt
│  │  └── [module]NavigationEvent.kt // One sealed class per module containing the navigation intent of the user


│  └── repository/               // IMPLEMENTATIONS of the Domain repository interfaces
│  │  └── [module]Navigator.kt  // Module-specific navigation functionality


      └── UserRepositoryImpl.kt // Implements domain.repository.UserRepository
└── build.gradle                  // Dependencies for Room, Retrofit, etc.
└── build.gradle                  // Plugins, setting, dependencies
</code>


== Test strategy ==
== Test strategy ==

Revision as of 16:26, 19 November 2025

The app is available in the Play store.

Requirements

Architecture

The app is written completely in Kotlin using Jetpack Compose, Dagger/Hilt and aiming to implement a clean architecture.

Module structure

Besides the main app module, the app consists of the following library modules:

  • balling
  • common
  • controller
  • feed
  • heating
  • info
  • overview
  • refill
  • schedule
  • timedata
  • ventilation

The main app module contains the AndroidManifest and the main activity (As of November 2025, the app only uses one activity). The activity contains the navigation NavHost in onCreate.

None of the other modules has a dependency to the main app module.

The common module provides low-level functionalities and layout elements used in various places. The following functionalities are located in common module:

  • DataFetchResult: A wrapper class indicating the status of data fetching operation (Success, Error, Loading, Empty).
  • WebApiParams, WebApiPostRequest, WebApiPostRequestExecution, WebApiUrls: Classes and objects used for communication from the app to the server.
  • ControllerProfileDao, ControllerProfileDatabase: Classes which provide Room database functionality.
  • Various classes used for dependency injection (Hilt)
  • SetValsSanityCheckResult: Class used for to communicate status of set values for heating and ventilation module.
  • ControllerProfile: Class containing the profile data of the server (address, port, credentials, ...)
  • GlobalConstants: Mainly UI-related strings (non-context-related) and some minor functional constants
  • Composable functions for the main drop down menu
  • Composable functions for the theme
  • Composable functions for hyperlinks, text edit fields, headline
  • ViewNavigationRoutes: Object containing the routing information processed in main app module
  • ScreenshotTestHelper: Helper class for executing the instrumented snapshot testing using the emulator.

Layer structure

The code is separated into the following layers: [module]/

├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/data/

│ ├── remote/ // Folder for data retrieval functionality

│ │ └── dto/ // Folder for Data Transfer Objects

│ │ └── [module][name]Import.kt

│ │ └── [module][name]Reader.kt // Implementation of GET server request

│ ├── [module][name]RepositoryImpl.kt // Repositories (implementation of interface)

├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/domain/

│ ├── model/ // Folder for data definition classes

│ │ └── [module][name].kt. // Classes for data definition

│ ├── repository/ // Folder containing repository interface definitions

│ │ └── [module][name]Repository.kt. // Interface defining the repository, used by view model

├── src/main/kotlin/com/laimburggasse/aquariumcontrol/[module]/presentation/

│ ├── entry/ // First screen of feature

│ ├── [components]/ // Shared code between different screens

│ ├── [screen name]/ // Folder for each screen

│ │ └── [module][name]Screen.kt // Composable showing the complete screen

│ │ └── [module][name]Composable.kt // Composable showing elements inside the screen

│ │ └── [module][name]UiEvent.kt // Sealed interface describing the communication from the composable to the view model

│ │ └── [module][name]UiState.kt // Data class describing the content to be rendered by the composable

│ │ └── [module][name]ViewModel.kt // Class implementing the view model

│ ├── navigation/ // Folder containing class and functionality related to screen navigation

│ │ └── [module]NavigationEvent.kt // One sealed class per module containing the navigation intent of the user

│ │ └── [module]Navigator.kt // Module-specific navigation functionality

│ └── build.gradle // Plugins, setting, dependencies

Test strategy

Unit tests

Compose preview screenshot tests

Instrumented tests

Release procedure