Implementing Business Logic
Using Worker and Observer
This document explains how to write and use domain-level business logic in Baselines using two core primitives:
Worker— for one-time business operationsObserver— for continuous or reactive business state
If you are implementing custom business logic in the domain layer, this is the entry point.
Why Worker and Observer Exist
Baselines enforces a strict separation between UI, domain logic, and data access.
Business logic must:
- be explicit
- be testable
- fail safely
- not depend on UI or platform code
Worker and Observer provide a standardized way to express business intent while enforcing these rules.
When to Use Which
| Scenario | Use |
|---|---|
| Fetch data once | Worker |
| Submit or mutate data | Worker |
| Trigger an action | Worker |
| Observe state over time | Observer |
| React to data changes | Observer |
| Stream updates to UI | Observer |
Writing a Worker
A Worker represents a single business operation.
It:
- runs once
- returns a
Result - safely captures failures
- always reports success or failure explicitly
Important: Exception Handling
It is safe and intentional to throw exceptions inside a Worker.
Any exception thrown from doWork:
- will not crash the app
- is automatically captured
- is returned as
Result.Failure - is handled via
onFailure { ... }
This allows you to use exceptions for clear control flow in domain logic without leaking crashes into the UI layer.
Example
kotlin1// Domain layer2@Inject3class GetStartRoute(4 private val checkAuthenticated: CheckAuthenticated,5) : Worker<Unit, NavRoute>() {67 override suspend fun doWork(params: Unit): NavRoute {8 val authenticated = checkAuthenticated(Unit).getOrThrow()9 return if (authenticated) {10 AppNavRoutes.Home11 } else {12 AppNavRoutes.Auth13 }14 }15}1617// Usage18@Inject19class StartRouteInitializer(20 private val getStartRoute: GetStartRoute,21) : AsyncInitializer {2223 override suspend fun init() {24 getStartRoute(Unit)25 .onSuccess { /* Assign the default start route */ }26 .onFailure { /* Handle error state explicitly */ }27 }28}