Published

Object updater pattern in Kotlin

Updating data is one of the most frequent use-cases in applications. But it might also be a painful task which results in a bunch of ugly code.

I recently stumbled over a typical update scenario in a Domain-Driven-Design (DDD) application. In the following, I want to show an elegant solution implemented in Kotlin (a Java version wouldn’t look much different). The solution can be described best as a variation of the builder pattern.

Scenario

In the scenario I worked on, we had to update a product. We faced the following requirements:

A product consists of a bunch of fields such as name, description, price or category.

The PIM might send duplicate updates which we also want to ignore (because any update involves a subsequent business process).

Based on those requirements our initial code looked like below. For every field we needed at least four lines of code looking nearly the same in each case. The result was a huge method with IFs and IFs and even more IFs.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

classProduct{

// ...

privatevarname:String

privatevardescription:String

// ...

fun update(command:UpdateCommand){

varupdateOccurred=false

if(command.name!=null&&this.name!=command.name){

this.name=command.name

updateOccurred=true;

}

if(command.description!=null&&this.description!=command.description){

this.description=command.description

updateOccurred=true;

}

// more fields...

if(updateOccurred){

// do some business stuff...

}

}

}

Object Updater Pattern

To solve the problem we implemented an object called Updater. It works similar to a builder:

1

2

3

4

5

val updateOccurred=Updater()

.update(this::name).toValue(command.name)

.update(this::description).toValue(command.description)

// more fields ...

.execute()// returns true or false

The implementation looks like below. It updates every field with a simple reflection based mechanism. By doing this, no public setters are needed. All checks (like the not-null-checks) are also performed by the updater object.