I like Types
Last couple of weeks, I have started to watch and listen to different opinions on programming languages. There are many different opinions, and I believe thinking about them is very important. Generally, I am trying to listen to the opinions that I do not agree with to change my point of view.
However, there is one thing that I really can not understand. Why do some people hate types? It is so obvious to me that types are really useful. Yeah, maybe some insane type theoretic approaches may not be useful in practice, but I am not talking about them. I am talking about simple types that are used in many programming languages. Let me explain my arguments.
Argument 1: Developers are humans
CPUs do not care about types. Literally, they do not care about any typing rules. It just executes instructions. But it is a machine designed to work highly deterministically. On the other hand, nowadays, software is developed by humans and executed by machines. Occasionally, humans make mistakes. This is a fact of life and we can not change it. For this reason, as humans, we need to find our mistakes or logical fallacies. If we were deterministic machines, we could say that we do not need types. But as emotional and non-deterministic beings, it is not the case.
Types are very good at reducing the mistakes that we make. They are just tools that check whether we are consistent or not. Simply, if we try to call a function that takes two integers with a string, the type checker will tell us that something is wrong. Because we are contradicting ourselves. I can not see any reason why someone would not want to use such a tool. Simply, I am not so smart to remember and check all the types in my head. I need a tool or a programming language to help me.
Argument 2: They reduce Complexity
As software developers, complexity is one of our biggest enemies. We are trying to reduce the complexity of our software. Why? Again, because we are humans and we have limited cognitive abilities. We can not understand very complex systems.
To talk about complexity, let’s try to define it. We can simply say that complexity is the number of different states that a system can be in. Please note that it is a relative measure, which means that we can not say that a system is complex or not complex (according to this definition).
Types are very good at limiting the number of states that a system can be in. Let’s look at these examples:
// a may have any value. There is an infinite number of possible states
const a = true;
// a may have only two values, true or false. There are two possible states
const a: bool = true;
It is so obvious that types are limiting the explosion of states and they are reducing the complexity of our software.
Argument 3: They provide up-to-date documentation
Types are also very good at documenting our code. It helps IDEs to provide better autocompletion and type hints. Also, we know that the type documentation is always up to date because they are checked automatically by the type checker.
Argument 4: They simplify refactoring
What happens when you want to change a function signature in a large codebase? If you are using a dynamically typed programming language, you must find all the places that this function is called and change them one by one. Although in statically typed programming languages, you can change the function signature, and the type checker will tell you all the places that you need to change and you can change them one by one. We can say that IDEs are excellent at finding all the places that a function is called. But it is valid for this simple example. If you are making more complex changes, like adding a required parameter to an object which is received by the function you will not easily trace all the places that you are constructing the object. And in reality, changes are not so simple. They are more complex.
Argument 5: Abstraction and Modeling
In the early days of computing, each application was specially designed for a specific hardware. But as the number of hardware increased, it became impossible to write software for each piece of hardware. For this reason, operating systems were developed to abstract the hardware and provide a common interface for software. In this way, we save a lot of time and effort. It was the power of abstraction.
However, abstraction is not specific to operating systems. They appear almost everywhere in programming. If you are developing a web application, at least you will have a database. You may prefer to create a direct dependency on a specific database, but I think it has 2 serious disadvantages:
- Changing the database is a nightmare. Yeah, you can throw some if conditionals to handle different databases but I give you a guarantee that it will be a nightmare to maintain such a code. If you are handling this kind of problems with if conditionals, I can easily say that you are doing it wrong.
- Abstraction is not only about change, it is also about organization. Abstraction forces you to think about the problem from a more abstract perspective and it makes you code less coupled and more cohesive. Even if you will never change the database, using an abstraction over the database makes sense because it makes your code more organized.
Yeah, abstraction is not directly related to types. But types are give the ability to talk about contracts in the code level. If you are using a dynamically typed programming language, you can not talk about contracts in the code level. Yeah, you can document your contracts in plain English and take an oath that you will follow them. But please do not forget that humans are just emotional beings that are trying to be rational and consistent as possible. But they do not always succeed. For this reason, I think it is better to use a programming language that can check our contracts automatically.
Argument 6: They help to produce more optimized code
Types are also very useful for compilers to generate more optimized code. Because types provide more information about
the code to the compiler. For example, if a variable is declared as a u32
(integer between 0 and 255), the compiler can
generate more memory-efficient code instead of allocating a memory space for the worst case (which is unknown in
dynamically typed programming languages).
Conclusion
Hey guys, please think about what we are doing. As software developers, we are paid to write software, and this money comes from our customers. Our customers do not care about our programming language preferences, but they care about the functionality that we are delivering. If you are checking types at runtime, you can easily ship a code that has bugs (bugs that are related to types). We are not developing a personal project or a university project. We are delivering software that tries to solve real-world problems.
Yeah, I know types are designed to restrict us, and you can feel that you are losing your freedom. But I do not want to have this kind of freedom because everything that it permits (but the type-checker does not) is just a bug waiting to happen. Yeah, some projects may not be serious, I agree, and I do not see any problem to use dynamic typing in such projects. I am not against dynamic typing at all. I am just trying to say that we should use the right tools for the right job, and almost all commercial projects are serious jobs.
As a last word, I want to fight with my type checker instead of fighting with my customers because I can not use my customer as a tester, or I can not completely trust my testers blindly.