I love software... I've been writing code since 2019 and I enjoy every bit of it, because it gives me a completely free space. There is never just one way to do something; it is almost impossible to find a second person who would write your code exactly the way you did. I take great pleasure in following the newest technologies and in this never-ending process of learning.
One of the longest and most heated debates in programming is static versus dynamic typing. I have definitely seen plenty of arguments from both sides, but very few of them were actually reasonable and convincing. Most of the time it is a lot of noise dressed up as logic, just an effort to be right.
Today I want to talk about exactly that. I want to take this out of the realm of abstract belief and show, with the code itself, why static typing gives me the safety I am looking for.
Of course, people do switch sides. We have all watched someone swim in the lawless comfort of dynamic languages their whole life and suddenly become a champion of strict type checking. As they say, the newer the faith, the brighter the flame.
But my attachment to static types is not a passing fad. Yes, the syntax can be intimidatingly complex at times; you may have to play something like a game of chess with the compiler. But at the end of the day, those strict rules give you an unmatched safety net. Let me show what I mean through Python, the popular kid of the dynamic world, and Rust, the armored knight of the static world.
In a dynamic language like Python there is incredible freedom when you handle data:
def greet_user(user):
# Python doesn't know up front what 'user' is.
# A dictionary, a custom object, or just a plain string?
# We only find out when that line actually runs.
return user.get("name") + " logged in!"
# During development everything looks great and fast.
# But if you pass the wrong kind of value...
# greet_user("Ahmet") # BOOM! Runtime error!That "we'll see when it runs" mindset is exactly the part that doesn't fit my style. In a complex system, the chance of control slowly slipping out of your hands, that feeling of uncertainty, bothers me.
Now put a static structure like Rust against it, one that puts memory management at the center and where you draw the boundaries of everything up front:
// What the data is and its boundaries are clearly defined.
struct User {
name: String,
is_active: bool,
}
// With impl blocks we strictly define what this data can do
// and the ownership rules around it.
impl User {
fn greet(&self) -> String {
format!("{} logged in!", self.name)
}
}
fn main() {
let user = User {
name: String::from("Ahmet"),
is_active: true,
};
// Pass the wrong type to a function and the code won't even compile.
// No surprises blowing up at runtime, no memory leaks.
println!("{}", user.greet());
}I like defining my variables tightly, having the compiler check me, and writing systems as solid as armor, free of memory leaks. Designing data structures and their capabilities up front, like in the Rust example, stops the code I write from causing me trouble later, right from the start.
In the past I was one of those who believed static typing was the "one true way" in software. But over time I realized something: what makes software so fascinating is the very sense of freedom and variety that drew me into this world in the first place. If we were all bound to the same rules and architectural approaches, the canvas where we show our creativity would turn into a dull factory.
Someone else may love writing code in a flexible language, in a flow, without worrying about boundaries. And at the end of the day we can both ship amazing applications. I'm happy in my safe, predictable, error-free static world; let others keep building in the flexibility of the dynamic one. After all, what keeps the software ecosystem alive is that everyone gets to draw their own unique path.