diff --git a/docs/refactor/steps.md b/docs/refactor/steps.md index 29d0192d5e..39d145f75f 100644 --- a/docs/refactor/steps.md +++ b/docs/refactor/steps.md @@ -947,4 +947,4 @@ object Artifacts { interface Fetch: (Identity) -> List } -``` \ No newline at end of file +``` diff --git a/mkdocs.yml b/mkdocs.yml index 6968cdcce0..0c8ee85897 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -37,6 +37,14 @@ nav: - Secrets: flank_secrets.md - Releasing: release_process.md - Binaries for Flank's iOS: binaries_used_in_flank_io_testing.md + - High-level design: + - Overview: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl#flank-high-level-design" + - Presentation: + - Overview: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/presentation#presentation" + - CLI: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/cli#cli" + - Domain: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/domain#domain" + - Data: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/data#data" + - Adapter: "https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/adapter#adapter" theme: name: material diff --git a/test_runner/src/main/kotlin/ftl/README.md b/test_runner/src/main/kotlin/ftl/README.md new file mode 100644 index 0000000000..da98b5c4fa --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/README.md @@ -0,0 +1,17 @@ +# Flank high-level design + +Flank architecture is based on the classic [PresentationDomainDataLayering](https://www.martinfowler.com/bliki/PresentationDomainDataLayering.html) proposed by Martin Fowler. + +## Diagram + +![architecture diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank/master/docs/hld/flank-component-diagram.puml) + +## Advantages + +Basing on the model above it will be easy to: +* scale the presentation layer by adding necessary implementations. +* replace external data providers. +* separate third-party library code from the domain, for keeping code clean. +* consider each layer as a separate module if needed. +* deliver builds for different configurations. +* deliver the domain layer as a standalone library. diff --git a/test_runner/src/main/kotlin/ftl/adapter/README.md b/test_runner/src/main/kotlin/ftl/adapter/README.md new file mode 100644 index 0000000000..ce7f67f3af --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/adapter/README.md @@ -0,0 +1,10 @@ +# Adapter + +## Design + +Is defined by data, adapter only provides implementations. + +## Responsibility + +This layer is adapting external APIs of third-party libraries +to structures and interfaces, specified in the data layer. diff --git a/docs/hld/presentation/cli/readme.md b/test_runner/src/main/kotlin/ftl/cli/README.md similarity index 85% rename from docs/hld/presentation/cli/readme.md rename to test_runner/src/main/kotlin/ftl/cli/README.md index a9c5b33809..07a3bf7793 100644 --- a/docs/hld/presentation/cli/readme.md +++ b/test_runner/src/main/kotlin/ftl/cli/README.md @@ -2,17 +2,6 @@ Flank command line interface layer. -## Basics - -From the: - -* higher level of view CLI layer is a bridge between end user and business logic. -* implementation perspective it is just adapter for domain function call. - -## Package - -All CLI commands are placed in [`ftl.cli`](https://github.com/Flank/flank/tree/master/test_runner/src/main/kotlin/ftl/cli) or inside nested packages. - ## Libraries Flank command line interface is build upon the [picocli](https://picocli.info/). @@ -39,7 +28,7 @@ The class which represents the CLI command: * CAN'T * define logical operations -## Class & relations diagram +## Diagram ![cli_class_diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank/master/docs/hld/presentation/cli/cli-class-diagram.puml) diff --git a/test_runner/src/main/kotlin/ftl/data/README.md b/test_runner/src/main/kotlin/ftl/data/README.md new file mode 100644 index 0000000000..06e880df37 --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/data/README.md @@ -0,0 +1,17 @@ +# Data + +A lightweight layer of structures and interfaces. + +## Responsibility + +Declare structures and interfaces required by the domain layer. + +## Requirements + +* CAN + * define data structures + * define interfaces +* CAN'T + * declare function body +* CONSIDER + * no more than 1 package nesting diff --git a/test_runner/src/main/kotlin/ftl/domain/README.md b/test_runner/src/main/kotlin/ftl/domain/README.md new file mode 100644 index 0000000000..b59e3f4f72 --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/domain/README.md @@ -0,0 +1,56 @@ +# Domain + +Owns the business logic of the application. + +## Design + +The domain layer is exposing its own API as a collection of public suspendable extension functions, +which could be called `top-level functions`. +Each `top-level function` have its own `execution context`, +that can produce a `structured output` during the `execution` +and can be composed of one or more low-level functions. +This layer could be considered as a standalone library, +that is providing access to business logic through pure kotlin functions. + + +### Top-level function + +Is public and accessible from the root of the domain package. +Is responsible to run domain logic directly or compose it using low-level domain functions, utils, or data interfaces. +For simplification, consider a simple common interface for all top-level functions. + +```kotlin +typealias UseCase = suspend A.() -> Unit +``` + +Where `A` is a generic type that is representing the `execution context`. + +### Execution context + +The context can provide arguments for the execution and its name should reflect the related use case. + +### Low-level function + +The low-level function is useful when it comes to dividing complex top-level +functions into the composition of smaller chunks or the reuse of some logic in many top-level functions. +It is crucial in keeping the composition of low-level functions flat. +More nesting in depth, can make a code much harder to understand and maintain. + +## Responsibility + +* Contains the business logic of the application +* Provide access to the use cases through formalized API + +## Requirements + +* MUST + * define a dedicated `execution context` for each top-level function. + * keep the top-level functions directly inside `ftl.domain` package. + * keep the low-level functions inside nested packages in `ftl.domain`. +* SHOULD + * access external APIs through data layer abstraction. + * keep the `execution context` with related `top-level function` in the same file. +* CAN + * use utils directly. + * use crucial third-part utils directly (for example `gson` or `jackson`). + * specify nested packages inside `ftl.domain` for internal dependencies. diff --git a/test_runner/src/main/kotlin/ftl/presentation/README.md b/test_runner/src/main/kotlin/ftl/presentation/README.md new file mode 100644 index 0000000000..f8e92bc6b0 --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/presentation/README.md @@ -0,0 +1,30 @@ +# Presentation + +The front-end layer of the flank application. + +## Basics + +From the: + +* higher level of view the presentation layer is a bridge between end user and business logic. +* implementation perspective it is just adapter for domain function call. + +## Entry point + +The [main](https://github.com/Flank/flank/blob/master/test_runner/src/main/kotlin/ftl/Main.kt) function + +## Responsibilities + +* Converting input into public domain functions calls. +* Mapping structural results from the domain output into the output specific for the presentation. + +## Requirements + +* SHOULD + * be thin as possible + * avoid logical operations +* CAN + * base on third-part framework or library + * invoke public domain functions +* CAN'T + * access data layer directly