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)