I'm using a job framework and I'm chaining several...
# getting-started
d
I'm using a job framework and I'm chaining several jobs and passing data between them. Currently, the job definitions look basically like this
Copy code
interface Job

// execute a job instance of [T] with [data]
fun <T : Job> executeJob(data: Map<String, Any?>) {
    TODO()
}

class MyJob : Job {
    // the job framework sets these variables from the data map
    lateinit var id: UUID
    lateinit var name: String

    fun doJob() {
        TODO()
    }
}
So at the start, something calls
executeJob<MyJob>(mapOf("id" to someId, "name" to someName))
. The question is how to make this typesafe, i.e. how to best associate with each
Job
the data structure it expects. The most obvious thing is to simply wrap the data inside a data class, e.g.
MyJobData
, and then for each job type define a specific execute function, e.g.
fun executeMyJob(data: MyJobData)
. I wonder, though, whether there's a more elegant/clever way how to express this
MyJob
-
MyJobData
relation in the type system.
y
Why not have
MyJob
itself take those as parameters? and then
executeJob
can simply take an instance of
T
d
Because, as I said, the way how the job instance is initialized is via setters, not by passing the job data to the constructor.
y
Is that necessary? Is this a Dependency Injection situation? Regardless, assuming that's required, you can easily express this in the type system:
Copy code
interface Job<Data> {
  var data: Data
}

// execute a job instance of [T] with [data]
fun <T : Job<Data>, Data> executeJob(data: Data) {
    TODO()
}

class MyJob : Job<MyJobData> {
    override var data: MyJobData

    fun doJob() {
        TODO()
    }
}
data class MyJobData(...)
d
Great. I guess the execute method would then be called as
Copy code
executeJob<MyJob, _>(myJobData)
1
So it's rather obvious after all. I'm probably just tired today and am lazy thinking for myself 🙂