Code Smell 208 - Don't Use Null for Real Places

Code Smell 208 - Don't Use Null for Real Places

You can avoid null if you try TL;DR: Don't use null for real places Problems 😔 Tight Coupling Unexpected Results Solutions 😃 Model unknown locations polymorphically Context 💬 Null Island is a fictional place that sits at 0°N 0°E, at the intersection of the Prime Meridian and the Equator in the Atlantic Ocean. Many GPS systems place data with missing or invalid coordinates at this exact point. That's where the name "Null Island" comes from. There's no landmass at this location. It's open ocean. This point has become a popular reference for geographic information systems (GIS) and mapping software, because it helps filter out errors in location data. Data visualization specialists started using the term around 2008, after noticing that failed geocoding requests and invalid coordinate entries often defaulted to (0, 0). Natural Earth, a public domain mapping dataset, deliberately includes a fictional one-square-meter island at that exact point to help catch geocoding errors. The trick works: researchers have found more than 300,000 Flickr photos and countless social media posts geotagged to Null Island, and during the COVID-19 pandemic, Johns Hopkins' tracking dashboard plotted confirmed cases there whenever the real location was missing. 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 abstract fun ifKnownOrElse(knownAction: (Location) -> Unit, unknownAction: () -> Unit) } class EarthLocation(val latitude: Double, val longitude: Double): Location() { override fun calculateDistance(other: Location): Double { val earthRadius = 6371.0 val latDistance = Math.toRadians( latitude - (other as EarthLocation).latitude) val lngDistance = Math.toRadians( longitude - other.longitude) val a = sin(latDistance / 2) * sin(latDistance / 2) + cos(Math.toRadians(latitude)) * cos(Math.toRadians(other.latitude)) * sin(lngDistance / 2) * sin(lngDistance / 2) val c = 2 * atan2(sqrt(a), sqrt(1 - a)) return earthRadius * c } override fun ifKnownOrElse(knownAction: (Location) -> Unit, unknownAction: () -> Unit) { knownAction(this) } } class UnknownLocation : Location() { override fun calculateDistance(other: Location): Double { throw IllegalArgumentException( "Can't calculate distance" + " from an unknown location.") } override fun ifKnownOrElse(knownAction: (Location) -> Unit, unknownAction: () -> Unit) { unknownAction() } } class Person(val name: String, val location: Location) fun main() { val people = listOf( Person("Alice", EarthLocation(40.7128, -74.0060)), // New York City Person("Bob", EarthLocation(51.5074, -0.1278)), // London Person("Charlie", EarthLocation(48.8566, 2.3522)), // Paris Person("Tony", UnknownLocation()) // Unknown location ) val rio = EarthLocation(-22.9068, -43.1729) // Rio de Janeiro coordinates for (person in people) { person.location.ifKnownOrElse( { location -> println("${person.name} is " + "${location.calculateDistance(rio)} kilometers " + "from Rio.") }, { println("${person.name} is at an unknown " + "location.") } ) } } Detection 🔍 [X] Semi-Automatic You can check for special numbers used as nulls Null Level 🔋 [X] Intermediate Why the Bijection Is Important 🗺️ Real coordinates map to real places on Earth. That is the bijection between your model and the MAPPER. When you reuse (0, 0) to mean "unknown location," you collapse two different concepts into a single representation. A real point in the Atlantic Ocean and the absence of data aren't the same thing, and your model shouldn't pretend they are. Modeling the unknown location as its own type keeps the mapping honest. Real coordinates always mean a real place, and missing data gets its own explicit representation instead of borrowing one that already means something else. AI Generation 🤖 AI generators create this smell often. When you ask for a location class, they default to primitive latitude and longitude doubles and reach for (0.0, 0.0) as a convenient placeholder for missing data, the same shortcut developers take under deadline pressure. AI Detection 🧲 AI generators rarely catch this smell on their own. Unless you explicitly ask for a type that represents unknown locations, they treat (0.0, 0.0) as a normal default value and won't suggest polymorphism unless you request it. Try Them! 🛠 Remember: AI Assistants make lots of mistakes Suggested Prompt: Replace the (0.0, 0.0) sentinel value with a polymorphic Location type that separates known coordinates from an explicit unknown location Without Proper Instructions 📵 ChatGPT Claude Perplexity Copilot You Gemini DeepSeek Meta AI Grok Qwen With Specific Instructions 👩‍🏫 ChatGPT Claude Perplexity Copilot You Gemini DeepSeek Meta AI Grok Qwen Conclusion 🏁 Don't use Null to represent real objects Relations 👩‍❤️‍💋‍👨 https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxvi https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxxii More Information 📕 A research buoy once sat right at 0°N 0°E collecting climate data until 2021, and the exact antipode of Null Island, at 0°N 180°E, is nicknamed "Antinull Island." 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 This article is part of the CodeSmell Series.

Original Source

Read the full article at Hackernoon →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.