Hello Everyone,
I am starting to lean towards the declarative programming paradigm in Kotlin, also applying design patterns.
What is Imperative Programming?
You give the computer a set of instructions to follow and the computer does what you want in an easy-to-follow sequence.
What is Declarative Programming?
As a process of constantly defining what things are. This is referred to as declarative programming.
Some of the examples I found online it seems to me is in the form of imperative style. So I tried to construct a builder design pattern in declarative way with immutability in mind.
for the code example below
I declared an interface DailySetup
with an implementation of data class DailySetuImpl
as follows.
Then create a function dailySetup
that returns an instance of DailySetup
and accepts a higher order function that can access all properties of DailySetupImpl
approach 1
fun main() {
val setup = dailySetup {
constant = 1
timeFunction = 1
timeMult = 1
}
println("calculated setup: "+setup.calculate())
}
fun DailySetup.calculate(): Int {
return (this.timeFunction*this.timeMult)+this.constant
}
interface DailySetup {
val constant: Int
val timeFunction: Int
val timeMult: Int
}
data class DailySetupImpl private constructor(
override var constant: Int = 0,
override var timeFunction: Int = 0,
override var timeMult: Int = 0
): DailySetup {
companion object {
fun default () = DailySetupImpl()
}
}
fun dailySetup(block: DailySetupImpl.()-> Unit): DailySetup {
return DailySetupImpl.default().apply(block)
}
approach 2
fun main() {
val setup = DailySetupBuilder.create {
constant = 1
timeFunction = 1
timeMult = 1
}
println("calculated setup: "+setup.calculate())
}
fun DailySetup.calculate(): Int {
return (this.timeFunction*this.timeMult)+this.constant
}
interface DailySetup {
val constant: Int
val timeFunction: Int
val timeMult: Int
}
data class DailySetupImpl private constructor(
override var constant: Int = 0,
override var timeFunction: Int = 0,
override var timeMult: Int = 0
): DailySetup {
companion object {
fun default () = DailySetupImpl()
}
}
class DailySetupBuilder {
companion object {
fun create(block: DailySetupImpl.()-> Unit): DailySetup {
return DailySetupImpl.default().apply(block)
}
}
}
approach 3
we can utilize sealed classes, sealed classes cannot be explicitly initialized
...
sealed class DailySetupImpl(
override var constant: Int = 0,
override var timeFunction: Int = 0,
override var timeMult: Double = 0.0,
override var internalObj: SetupInternalObj? = null
): DailySetup {
object DEFAULT: DailySetupImpl()
}
class DailySetupBuilder {
companion object {
fun create(block: DailySetupImpl.()-> Unit): DailySetup {
return DailySetupImpl.DEFAULT.apply(block)
}
}
}
In this way, I think, it is created via declarative way. What do you think of this approach?
Top comments (0)