This is the multi-page printable view of this section. Click here to print.
Docs
1 - Code Structure
The code is structured as follows. It isn’t perfect (as there are not yet any tests) but should be generally followed.
Prefer dividing code by use case first and then by “type”. For example prefer encyclopedia/viewModels
instead of the reverse.
See naming for more details on naming.
Component Structure
Each component should be isolated from each other and not directly depend on anything outside of specific directories. Frustratingly kotlin does not make this easy to enforce.
data
This should have no dependency on Compose whatsoever
model
- Should not depend on android libraries at all
repository
presentation
view
viewmodel
sidecar
section
Contains special information for external consumption. Exception to the isolated rule. For example application
depends
on it. Other sections may use data here to navigate.
api
If the component provides information to other component.
Special Components
application
This is the high level application. It can depend on nearly anything else but should likely limit itself to the
section
and api
and similar. Long term, this can be enforced. Nothing should depend on this.
infrastructure
Low level components used to build the application. Only application
should directly depend on this but may provide
Singletons for everything else.
components
Components and utilities useful for all Components.
common
Utilities, state, etc, that all Components rely on. Does not currently exist and merged with application
TODO: make into chart
TODO: make into multi-module project so that `internal` actually helps.
3 - Object Naming
This is aspirational as I’ve tried a few different ways of doing this and not everything matches the naming scheme yet.
Navigation
Route
— This is a thing that can be visited via the navigation structure.Destination
- a Route as viewed by Compose Destinations.Screen
— This is a user-visible description of a route. Contains things like “title” or menusTab
— A top level Composable for the application. Typically stand alone.
Injectables
Repository
— A collection of related injectionsDefaultRepository
— the production copy of data used. May not exist and instead be something likeResourcesRepository
,NetworkRepository
, etc.
Parseable / Serialisable
For data which needs to be serialised:
__DatumOnDiskStructure
— the data structure closest to that which will be read.__DatumParsed
— the data in the form most useful for internal processing___DatumTransformed
- the data in middle or final format___DatumUIState
— the data as presented to the UI. Should not be further transformed.
Naming Convention
- Prefer collections to have plurals. This makes looping with a singular slightly more readable. The class should be singular. For example:
enum class NavigableScreen {
ABC,
DEF,
;
}
val listOfScreens = listOf(ABC, DEF)
private fun loopScreens(screens: List[NavigableScreen]) {
listOfScreens.forEach { screen ->
// ...
}
}
Code Style & Convention
The following applies in order. Anything later overrides anything earlier
- Use the official Kotlin style
- Use the official Android style
A. Avoid expression body functions unless they are clearly more readable
B. Avoid putting lambdas outside of the signature except for Compose or similar DSLs.
C. Prefer trailing commas wherever possible. I’d like to exclude some specific cases but the automated tools don’t make this easy
- Follow editorconfig or other automatic formatters. If they conflict it is a bug and should be fixed.