Don’t force your objects to construct what they need

Let’s say we have an object that handles instances of Person. For example PeopleScreen:

// Person.kt
class Person(
val name: String,
val surname: String
)
// PeopleScreen.kt
class PeopleScreen(
private val people: List<Person>
) {
fun render() {
people.forEachIndexed { index, person ->
println("${index + 1}. ${person.name}, ${person.surname}")
}
}
}
// Usage:
fun main() {
val people = listOf(
Person("Joe", "Dow"),
Person("Jill", "Doe"),
Person("Jack", "Black")
)
val screen = PeopleScreen(people)
screen.render()
}

PeopleScreen renders instances of Person so this should be the only format we provide to it. Let me explain.

Forced construction

There is a new flow that ends in opening PeopleScreen but all the information for the list of people are in a Map<String, String>. There is no reason to alter PeopleScreen in order to support this new format:

// Person.kt
class Person(
val name: String,
val surname: String
)
// PeopleScreen.kt
class PeopleScreen(
private val people: List<Person>
) {
constructor(people: Map<String,String>) : this(
people.map { entry -> Person(entry.key, entry.value) }
)
fun render() {
people.forEachIndexed { index, person ->
println("${index + 1}. ${person.name}, ${person.surname}")
}
}
}
// Usage:
fun main() {
val people = mapOf(
"Joe" to "Dow",
"Jill" to "Doe",
"Jack" to "Black"
)
val screen = PeopleScreen(people)
screen.render()
}
the new format is passed through an overloaded constructor but the same goes if we use a setter method

Why we shouldn’t do it

We could argue that by doing so we tie the object with each special format making the code hard to maintain and scale but the real reason is that we violate the SRP principle since PeopleScreen will have more than one reasons to change. One if something changes in the way we render and two if something changes in Person‘s construction.

What we should do

We should keep PeopleScreen only consuming Person and move all transformations to their own objects allowing a coordinator to transform and pass data around.