Follow

Follow

# Code Smell 208 - Null Island

## You can avoid null if you try

Maxi Contieri⭐⭐⭐
·Apr 19, 2023·

• Problems
• Solutions
• Context
• Sample Code
• Detection
• Tags
• Conclusion
• Relations
• Disclaimer

TL;DR: Don't use null for real places

# Problems

• Coupling

• Unexpected Results

# Solutions

1. Model the unknown location with polymorphism

# Context

Null Island is a fictional place, which is located at the coordinates 0°N 0°E, at the intersection of the Prime Meridian and the Equator in the Atlantic Ocean.

The name "Null Island" comes from the fact that this location represents the point where a lot of GPS systems place any data that has missing or invalid location coordinates.

In reality, there is no landmass at this location, and it is actually in the middle of the ocean.

This point has become a popular reference for geographic information systems (GIS) and mapping software, as it serves as a way to filter out errors in location data.

# Sample Code

## Wrong

``````class Person(val name: String, val latitude: Double, val longitude: Double)

fun main() {
val people = listOf(
Person("Alice", 40.7128, -74.0060), // New York City
Person("Bob", 51.5074, -0.1278), // London
Person("Charlie", 48.8566, 2.3522), // Paris
Person("Tony Hoare", 0.0, 0.0) // Null Island
)

for (person in people) {
if (person.latitude == 0.0 && person.longitude == 0.0) {
println("\${person.name} lives on Null Island!")
} else {
println("\${person.name} lives at (\${person.latitude}, \${person.longitude}).")
}
}
}
``````

## Right

``````abstract class Location {
abstract fun calculateDistance(other: Location): Double
}

class Coordinates(val latitude: Double, val longitude: Double) : Location() {
override fun calculateDistance(other: Location): Double {
val earthRadius = 6371.0 // kilometers
val latDistance = Math.toRadians(latitude - other.latitude)
val lngDistance = Math.toRadians(longitude - other.longitude)
val a = sin(latDistance / 2) * sin(latDistance / 2) +
sin(lngDistance / 2) * sin(lngDistance / 2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
}
}

class UnknownLocation : Location() {
override fun calculateDistance(other: Location): Double {
throw IllegalArgumentException("Cannot calculate distance from unknown location.")
}
}

class Person(val name: String, val location: Location)

fun main() {
val people = listOf(
Person("Alice", Coordinates(40.7128, -74.0060)), // New York City
Person("Bob", Coordinates(51.5074, -0.1278)), // London
Person("Charlie", Coordinates(48.8566, 2.3522)), // Paris
Person("Tony Hoare", UnknownLocation()) // Unknown location
)

val rio = Coordinates(-22.9068, -43.1729) // Rio de Janeiro coordinates

for (person in people) {
try {
val distance = person.location.calculateDistance(rio)
println("\${person.name} is \${distance} kilometers from Rio de Janeiro.")
} catch (e: IllegalArgumentException) {
println("\${person.name} is at an unknown location.")
}
}
}
``````

# Detection

[X] Semi-Automatic

We can check for special numbers used as nulls

• Null

# Conclusion

Don't use Null to represent real objects

# Disclaimer

Code Smells are my opinion.

The billion dollar mistake of having null in the language. And since JavaScript has both null and undefined, it's the two billion dollar mistake.

Anders Hejlsberg