Law of Demeter with examples in Kotlin | by Fabrizio Di Napoli | Nov, 2023
First of all, what is Law of Demeter?
It’s also called Demeter’s law or LoD or Principle of Least Knowledge or “don’t talk to strangers”.
It was discovered in 1987 in Northeastern University, Boston, by Ian Holland
Here is the general formulation of the law:
- Only talk to your immediate friends.
- Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.
- Or: Each unit should only talk to its friends; Don’t talk to strangers.
So, we’re easily violating this law and we don’t even notice most of the times.
Here is an example:
data class Car(val name: String, val engine: Engine)data class Engine(val cc: CylinderCapacity, val power: Power)
data class CylinderCapacity(val value: Int)
data class Power(val value: Int)
fun main() {
val car = Car(name = "Polo", engine = Engine(cc = CylinderCapacity(value = 2000), power = Power(200)))
println(car.engine.power.value)
}
The fact that Car knows about Power and we can access the value in it directly through Car, is a violation of Law of Demeter. Why?
Let’s review the law:
Only talk to your immediate friends. Car’s immediate friends is Engine, not what’s contained in Engine (CylinderCapacity and Power)
Here is a possible way to fix it:
data class Car(private val name: String, private val engine: Engine) {
fun power(): String {
return "Car $name has ${engine.power()}"
}
}data class Engine(private val cc: CylinderCapacity, private val power: Power) {
fun power(): String {
return "${power.value}hp"
}
}
data class CylinderCapacity(val value: Int)
data class Power(val value: Int)
fun main() {
val car = Car(name = "Polo", engine = Engine(cc = CylinderCapacity(value = 2000), power = Power(200)))
println(car.power())
}
So first of all let’s make some property private, it will help to avoid making them accessible from “strangers”:
data class Car(private val name: String, private val engine: Engine) {data class Engine(private val cc: CylinderCapacity, private val power: Power) {
and expose them this way:
data class Car(private val name: String, private val engine: Engine) {
fun power(): String {
return "Car $name has ${engine.power()}"
}
}data class Engine(private val cc: CylinderCapacity, private val power: Power) {
fun power(): String {
return "${power.value}hp"
}
}
fun main() {
val car = Car(name = "Polo", engine = Engine(cc = CylinderCapacity(value = 2000), power = Power(200)))
println(car.power())
}
There are a lot of benefits but I’d like to highlight couple of them here.
Loose Coupling
Car is not directly coupled with Power. It’s true that Car knows about the concept of power, but it’s semantically correct since any Car has “power”, but the definition, rules, etc. are within the Engine.
For instance in the example the power is expressed in hp (Horse Power), so if we want to change that we just need to change Engine (maybe is better to move it to Power class? Maybe.), not Car.
data class Engine(private val cc: CylinderCapacity, private val power: Power) {
fun power(): String {
return "${power.value}hp"
}
}// From hp to kW.
data class Engine(private val cc: CylinderCapacity, private val power: Power) {
fun power(): String {
return "${power.value}kW"
}
}
Here we’ve changed the power from hp to kW.
Encapsulation
Very similar to the previous point, if you change Power, should not affect Car. In this case we want to change Engine to take into account different types of powers (fuel vs hybrid for instance).
data class Car(private val name: String, private val engine: Engine) {
fun power(): String = "Car $name has ${engine.power()}"
}data class Engine(private val cc: CylinderCapacity, private val powerSources: List<PowerSource>) {
fun power(): String = "${powerSources.sumOf { it.power() }}hp"
}
data class CylinderCapacity(private val value: Int)
data class ElectricPowerSource(private val value: Int) : PowerSource {
override fun power() = value
}
data class FuelPowerSource(private val value: Int) : PowerSource {
override fun power() = value
}
interface PowerSource {
fun power(): Int
}
fun main() {
val powerSources = listOf(
ElectricPowerSource(300),
FuelPowerSource(200),
)
val car = Car(name = "Polo", engine = Engine(cc = CylinderCapacity(value = 2000), powerSources = powerSources))
println(car.power())
}
Even if in this case the logic is really dirty, no change is required in Car, since it’s just calling the .power() method that is calling the engine’s one that is encapsulating the complexity of calculating the power of the engine, that could come from multiple power sources.
println(car.power())
Did you like this article?
Related Posts
Leave a Reply Cancel reply
Categories
- ! Без рубрики (1)
- ++PU (1)
- 1 (1)
- 1w (1)
- 1win Brazil (1)
- 1win India (1)
- 1WIN Official In Russia (1)
- 1win Turkiye (1)
- 1xbet egypt (1)
- 2ankarafayansustasi.net_may (1)
- ankarafayansustasi.netsiteai apr (1)
- Artificial intelligence (1)
- Arts & Entertainment, Photography (1)
- belugasitesi_mAY (1)
- BH_TOPsitesi apr (1)
- BHsitesy_may (2)
- Blog (3)
- Bookkeeping (14)
- Bootcamp de programação (2)
- Bootcamp de programación (2)
- BT_TOPsitesi apr (1)
- casino (5)
- casinom-hub (1)
- casinom-hub.comsitesi apr (3)
- colombian mail order brides (1)
- Cryptocurrency exchange (2)
- Dinamobet_next (1)
- Disease & Illness, Colon Cancer (1)
- Dumanbet (1)
- Dumanbet_next (1)
- Finance, Insurance (1)
- FinTech (5)
- Forex Trading (11)
- Galabet (1)
- Health & Fitness, Fitness Equipment (1)
- Hitbet (1)
- Home & Family, Crafts (1)
- Home & Family, Gardening (1)
- Internet Business, Audio-Video Streaming (1)
- Internet Business, Ecommerce (1)
- Internet Business, Email Marketing (1)
- Internet Business, Internet Marketing (1)
- IT Вакансії (1)
- IT Образование (5)
- IT Освіта (1)
- latin women dating (1)
- mail order bride (1)
- Mars bahis (2)
- Matadorbet (1)
- minimiri.comsitesi apr (3)
- Mobile App Development (771)
- Mostbet Russia (1)
- New Post (1)
- News (1)
- PB_TOPsitesi apr (1)
- PBsitesi_may (1)
- Pusulabet (1)
- redmirepool.bizsitesi apr (2)
- redmirepoolsitesi_may (1)
- Reference & Education, College (1)
- Reference & Education, Sociology (1)
- Rokusitesi apr (1)
- Sober living (6)
- Society, Divorce (1)
- Software development (7)
- Superbetin (1)
- Tempobet_next (1)
- thelongeststride.comsitesi apr (1)
- tipobet-turkiyesitesi apr (1)
- Ultrabet (1)
- Uncategorized (1)
- Игра (2)
- казино (1)
- Криптовалюты (1)
- Новости Криптовалют (1)
- Финтех (7)
- Форекс Брокеры (9)
- Форекс обучение (2)