Currently, flank is putting all output data directly to console, which is useful for command-line but not for different
types of UI like the desktop.
Goal
Domain layer is producing structural output instead of direct logging to console.
Structural output from the domain layer is handled in the presentation layer.
CLI is converting structures into console logs and printing them.
API
/**
* The abstraction which allows passing output from the domain to presentation.
* Implement in domain top-level interfaces for getting access to outputting result structures.
* @property out The reference to outputting result function.
*/
interface Output {
val out: (Any) -> Unit
}
Steps
Prepare a list of logs that can be displayed by command.
Basing on a list of logs prepare corresponding structures.
Extend domain top-level using Output interface
Register A mapper in cli command.
Replace all logLn occurrences with out function call
Move the mapper to the proper package. (TODO - Consider which package is proper)
Hint
For step 2. If you have to add a new type that can be identified in the presentation layer as something that should be converted to the console log and you also have to decide where to place it, you can follow the rules:
If the type denotes the execution status of domain logic run, place this type in domain interface scope.
If the type is related to API structure, add it to this related structure scope. (This one is shown in the example)
List<Orientation> is a generic type that is losing parameter type info in runtime, so it's necessary to create a
wrapping structure that could be resolved by type matching.
Add Orientaton.Available structure for representing list available orientations the specific platform
data class Orientation(
val id: String,
val name: String,
val tags: List<String>,
) {
data class Available(
val platform: Platform,
val list: List<Orientation>
)
interface Fetch : (String, Platform) -> Available
}
Step 3
Extend using the Output interface.
interface ListAndroidOrientations : Output {
val configPath: String
}
Step 4
Add out implementation to AndroidOrientationsListCommand
class AndroidOrientationsListCommand :
Runnable,
ListAndroidOrientations {
override fun run() = invoke()
override val out = outputLogger {
when (this) {
is Orientation.Available -> list.toCliTable()
else -> throwUnknownType()
}
}
}
Step 5
Replace logLn with out call
operator fun ListAndroidOrientations.invoke() {
fetchOrientation(
AndroidArgs.loadOrDefault(Paths.get(configPath)).project,
Platform.ANDROID
).out()
}
Step 6
Consider the proper package for API structures to console output formatters - #1872
If issue #1872 isn't finished yet, place the formatters where you wish. This will be taken into account or refactored further.
Utils
fun outputLogger(map: Any.() -> String): Any.() -> Unit = {
logLn(map())
}
fun Any.throwUnknownType(): Nothing =
throw IllegalArgumentException(javaClass.toGenericString())
Motivation
Currently, flank is putting all output data directly to console, which is useful for command-line but not for different types of UI like the desktop.
Goal
API
Steps
Output
interfacecli
command.logLn
occurrences without
function callHint
For step 2. If you have to add a new type that can be identified in the presentation layer as something that should be converted to the console log and you also have to decide where to place it, you can follow the rules:
Example
Based on
ListAndroidOrientations
Step 1
List<Orientation>
- test_runner/src/main/kotlin/ftl/domain/ListAndroidOrientations.kt#L16Step 2
List<Orientation>
is a generic type that is losing parameter type info in runtime, so it's necessary to create a wrapping structure that could be resolved by type matching.Add
Orientaton.Available
structure for representing list available orientations the specific platformStep 3
Extend using the
Output
interface.Step 4
Add out implementation to
AndroidOrientationsListCommand
Step 5
Replace
logLn
without
callStep 6
Consider the proper package for API structures to console output formatters - #1872 If issue #1872 isn't finished yet, place the formatters where you wish. This will be taken into account or refactored further.
Utils