From 17bb6453f8bd975c2fc3cf3fb915f4a3ee2a7213 Mon Sep 17 00:00:00 2001 From: Minseok Kim Date: Sat, 25 Apr 2026 21:24:36 +0900 Subject: [PATCH] Document the dataflow principle in CODING_STYLE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The headline rule — business logic written as a single chain of transformations — is what most code-review questions about structure turn on, and it is the reason the project uses Spring WebFlux. Capture both in a top-level doc so external contributors can see the principle that frames the codebase. The doc is intentionally narrow: only the parts of style that are settled appear here. Other conventions remain unwritten until they are. --- CODING_STYLE.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 CODING_STYLE.md diff --git a/CODING_STYLE.md b/CODING_STYLE.md new file mode 100644 index 00000000..480c8b7a --- /dev/null +++ b/CODING_STYLE.md @@ -0,0 +1,59 @@ +# Coding Style + +This document captures the parts of Actionbase's coding style that are +settled. Other conventions exist in the codebase but have not yet been +formalized here; until they are, mirror the surrounding code. + +## Dataflow as the program + +Business logic in Actionbase is data being transformed: requests become +events, events get encoded, encoded data is written, and a response is +shaped from the result. Write this as a single pipeline so the flow reads +top-to-bottom in one place. + +```kotlin +// GOOD: one chain, readable in one pass. +request + .toEvents(schema) + .writeWal(ctx) + .groupBy { edge } + .flatMap { mutateGroup(it) } + .collectList() + .map(::toResponse) +``` + +When two paths share most of their flow, push the differences into +parameters and keep the shared chain intact. A small amount of duplication +is acceptable if it preserves a clear, single-pass read. + +```kotlin +// BAD: a generic pipeline runner with the real flow trapped in a lambda +// the caller passes in. The reader must jump caller → pipeline → lambda +// → caller — three hops to follow one flow. +executeMutationPipeline( + events = eventFlux, + executeGroup = { key, group -> + sort(...) -> mutate(...) -> writeCDC(...) -> handleErr(...) + }, +).map { toResponse() } +``` + +This rule decides most code-review questions about structure: prefer the +shape that lets the next reader follow the flow without jumping. + +## Spring WebFlux + +The framework choice follows from the principle above. `Mono` and `Flux` +express a transformation pipeline in code that visibly matches the +dataflow; reactive operators compose into a chain that reads in one pass. +New code in Actionbase follows this style. + +## Formatting + +Enforced by Spotless + ktlint. Before submitting, run: + +```bash +./gradlew spotlessApply +``` + +CI runs `spotlessCheck` and fails if formatting is not applied.