This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

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.

  1. Route — This is a thing that can be visited via the navigation structure.
  2. Destination - a Route as viewed by Compose Destinations.
  3. Screen — This is a user-visible description of a route. Contains things like “title” or menus
  4. Tab — A top level Composable for the application. Typically stand alone.

Injectables

  1. Repository — A collection of related injections
  2. DefaultRepository — the production copy of data used. May not exist and instead be something like ResourcesRepository, NetworkRepository, etc.

Parseable / Serialisable

For data which needs to be serialised:

  1. __DatumOnDiskStructure — the data structure closest to that which will be read.
  2. __DatumParsed — the data in the form most useful for internal processing
  3. ___DatumTransformed - the data in middle or final format
  4. ___DatumUIState — the data as presented to the UI. Should not be further transformed.

Naming Convention

  1. 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

  1. Use the official Kotlin style
  2. 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

  1. Follow editorconfig or other automatic formatters. If they conflict it is a bug and should be fixed.