Skip to content

Proposal: strengthen Tart around effect control, testing, and feature composition #189

@hkusu

Description

@hkusu

Background

Tart is already strong at two things:

  • a state-machine-oriented DSL that keeps transitions explicit
  • coroutine lifecycles tied to state variants

That makes it easy to reason about many UI/business flows.

At the same time, compared with ecosystems such as TCA and Redux Toolkit, some gaps become more visible as the app grows:

  • complex async workflow control still needs hand-written patterns
  • testing async flows is weaker than state-transition testing
  • feature composition is mostly left to ordinary Kotlin
  • UI/devtools ergonomics are intentionally small, but can feel thin at scale

This issue proposes a way to improve those areas without losing Tart's current philosophy.

Goal

Keep Tart centered on state machine + coroutine lifecycle, while adding a small set of first-class tools for the places where users currently need to hand-roll common patterns.

Proposed improvements

1. First-class effect control

Today, launch {} and state-exit cancellation are strong, but patterns such as these are still manual:

  • cancelInFlight
  • ID-based cancellation
  • latest-wins requests
  • debounce / throttle
  • explicit sequencing vs parallel orchestration helpers

Possible additions:

  • launch(id = ..., cancelInFlight = true) { ... }
  • actionLatest<...> { ... }
  • debounceAction(...)
  • throttleAction(...)

This would reduce hand-written requestId / cancellation plumbing in common async workflows.

2. TestStore-like testing API

Current helpers are useful, but async verification still feels relatively low-level.

Useful additions:

  • send(...)
  • assertState { ... }
  • receiveEvent(...)
  • advanceUntilIdle()
  • assertNoPendingWork()

The main goal is to make launch {}-driven behavior easier to verify step-by-step, not only the synchronous dispatch portion.

3. Feature composition helpers

Tart currently keeps composition mostly in ordinary Kotlin, which is simple and flexible, but larger apps often benefit from a small amount of structure.

Possible additions:

  • child feature composition helpers
  • optional child helpers
  • collection/for-each style helpers
  • parent-child event/action wiring helpers

This does not need to become a fully TCA-style composition system, but some official patterns/API would help large-scale adoption.

4. Compose/ViewStore ergonomics

The current Compose integration is intentionally small, but some additions could improve day-to-day usage:

  • derived state / selector helpers
  • binding helpers for common form-like updates
  • event handling helpers for common one-shot UI patterns
  • better scoped/derived ViewStore patterns

These could stay lightweight while reducing repetitive UI glue.

5. Debug/inspection tooling

A lightweight official inspection story would help development significantly.

Examples:

  • action/state/event timeline
  • in-flight launched coroutine inspection
  • debug tracing middleware
  • basic devtools hooks

This likely belongs in an optional module rather than tart-core.

6. Inter-store communication improvements

tart-message is useful, but the current global MessageHub approach may become harder to reason about in larger systems.

Possible directions:

  • typed/scoped channels
  • feature-local buses
  • request/reply-style helpers
  • clearer lifecycle ownership for cross-store communication

Suggested priority

  1. First-class effect control
  2. TestStore-like testing API
  3. Compose/ViewStore ergonomics
  4. Feature composition helpers
  5. Debug/inspection tooling
  6. Inter-store communication improvements

Suggested split between core and optional modules

Good candidates for tart-core

  • effect control primitives
  • minimal testing/runtime hooks needed to support better test tooling
  • small composition primitives

Better as optional modules

  • devtools / inspection UI
  • richer Compose helpers
  • expanded inter-store communication utilities

Why this direction

This keeps Tart differentiated.

Instead of becoming a clone of TCA or Redux, Tart can stay focused on:

  • explicit state transitions
  • lifecycle-aware coroutines
  • small, understandable primitives

while filling the most noticeable gaps that appear in real-world, medium-to-large applications.

Open questions

  • Which of these should be part of the core API surface vs extension modules?
  • Should effect control be expressed as launch(...) options, new DSL helpers, or middleware-like extensions?
  • How much composition support is enough before it starts fighting Tart's current simplicity?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions