Talks

This is Your Brain on Software

Developers are rational thinkers who take objective decisions. Yeah, sure. If that is the case, how can we disagree on so many things?

Examples are all around. Why do Rubyists and Java developers despise each others' designs? Why do people try hard to fit static typing and distributed environments? Why do Windows programmers loathe the command line? Let me try answering these questions, with a few hints from cognitive psychology.

Ancient City Ruby 2013

00:00:00.149 I was supposed to talk about Clojure, but the reason for that is that I submitted this talk a few months ago, and I wasn't able to learn enough Clojure on time. It's embarrassing, but it’s true. I mean, I can joke about it, but it really sucks.
00:00:06.420 I was left wondering why it is so hard to learn a programming language. I should know better; I've been doing this for a long time. Still, it's consistently harder than I assume every time I learn a new language. I believe the reason has to do with the way my brain and, frankly, your brain works.
00:00:32.669 This is what I'm going to talk about: why it's so hard to learn a programming language. Let me talk about your brain. Congratulations! It's beautiful. There are different models that try to explain how the brain works. Yesterday, Rustles talked about the left brain and right brain. Today, I'm going to use a slightly different model. It's a model that is inherently flawed, as it's not real, but in this case, it’s very useful. It actually won a Nobel Prize.
00:00:59.219 I'm going to use a metaphor that is custom-made for us geeks. If your brain is a computer, then there are two main processes going on inside this computer. One is a low-level kernel process, and the other one is a high-level application process. They couldn't be more different. The first difference is that the application process is self-conscious. If you ask me about myself, that is what I call 'me'. A cognitive scientist would call this my 'self'. The lower-level kernel process happens without you even knowing about it. It's just working there all the time, making weird associations.
00:01:43.500 Another important difference is that the high-level process is the logical one. It puts things in a line, analyzes data, performs calculations, and remembers statistics. On the other hand, the low-level process is emotional. It doesn't handle numbers very well, but it operates continuously, making odd associations and attempting to find patterns. It tries hard, poor thing; unfortunately, it’s not very good at that.
00:02:07.259 For example, you might be looking at me and think, 'Hey, this guy has a beard like my uncle. I like my uncle, therefore I like this guy.' It's just connecting things in a strange way. Now you might wonder: why are we built like that? I mean, we are products of evolution. Why did evolution build a system that seems so valuable yet so silly, like our emotional kernel process?
00:02:30.670 Of course, there is another trade-off. The low-level kernel process is extremely cheap and automatic. It runs all the time and is fast, enabling it to make decisions very quickly. It does get things wrong, but it does so rapidly. Meanwhile, the high-level application process requires a lot of effort. Don’t get me wrong; the automatic process can do amazing things, like driving a car automatically. Still, you can drive a car without thinking about it if you are an experienced driver.
00:03:09.100 However, if you do something that requires the slower, more expensive, and energy-consuming high-level application process, you consume real energy—sugars. It shows up in your body, believe it or not. Writing complex code causes your blood pressure to rise significantly, and your pupils to dilate. Not many things in life can make your pupils dilate apart from light variations, of course. One such thing is an orgasm, and another is seeing something shocking or thinking intensely.
00:03:38.360 So, we have these two systems, and of course, they do not work separately. The application process is conscious and logical, but it requires support and energy. The kernel process is subconscious; it operates all the time and is emotionally driven. Now, guess who is making most of the decisions? Both processes are, but the low-level process has an unfair advantage. It's always on. You cannot turn it off, even if you try.
00:04:06.590 It prepares data that the high-level process will use to reason with. Therefore, it generates 'float' data, creating patterns based on repeatable mistakes. You don't get it wrong randomly; you tend to make the same mistakes repeatedly. The high-level process bases its logical reasoning on this unreliable 'float' data.
00:04:39.850 These two processes work together to make decisions, but many of those decisions are wrong. This tendency to err is what cognitive scientists call a bias. Now let’s move on to programming languages. Why do I think biases are important when you are learning a new programming language? When you learn a language, you have to learn a lot of things. You have to learn the syntax, which most people agree is not the hard part.
00:05:10.800 One surprisingly hard part is learning the toolset that comes with the language. We tend to take this for granted, thinking, 'Okay, I'll just learn this stuff.' However, the tools are subtly yet profoundly different from one language to another. For example, if you are a Java or C# programmer, your tool of choice is probably an IDE. You start it up, wait for a while, and eventually, it opens.
00:05:56.051 Most likely, you rarely leave the confines of that IDE for the entire day. On the other hand, if you are a Ruby programmer, your toolset likely looks more like this: a text editor, maybe a browser, and crucially, the command line. I have always been surprised and puzzled by why the command line is not more widely adopted among Java developers. They use it, yet not nearly as much as it could benefit them.
00:06:34.660 I remember working with a group of C# programmers who were really smart. I tried to convince them to use the command line, but I eventually gave up. They were resistant for reasons that didn’t make any sense—like, 'Oh no, it’s black and depressing.' Meanwhile, they spent their entire day clicking away. These are smart people; I don't understand why they resist.
00:07:01.990 Okay, here's an experiment I want you to do. Imagine you have a candle, a box of matches, and a box of pins. Your task is to attach the candle to the wall and light it. I want to see a lit candle attached to the wall. Do not set the room on fire. Don't share your solution; keep it to yourself. Think about it for twenty seconds.
00:07:20.770 Time’s up! You engaged your high-level application process, trying to follow logical reasoning. Your blood pressure likely rose, and your pupils dilated. I assume nobody in the audience was having an orgasm, but I hope you had fun. How many of you came up with a solution? A handful of you? Just in case you think this was an unlucky strike, this experiment is a well-known cognitive science study conducted with a random sample of people using real items.
00:10:12.770 They were given twenty minutes, not just twenty seconds, to come up with a solution. Only one person managed to do so. This famous experiment illustrates a cognitive phenomenon known as functional fixedness. Functional fixedness occurs when you associate an object with its traditional use, causing your low-level kernel process to essentially filter out other possible uses.
00:11:16.360 For example, when seeing the box of pins, your brain simplifies it to 'a box', disregarding the possibility that it could be a component of a solution. Interestingly, if you show people the box and pins separately, 100% of them can find the right solution. How does this apply to programming languages? For a programmer accustomed to Windows, the command line is merely an application launcher. It’s where you start applications and close them afterward.
00:12:02.180 In contrast, for a Unix programmer, the command line is a programming environment where you write code, albeit in a primitive language known as the shell. It's challenging for them to switch out of that mindset. Let me switch gears for a moment and talk about bumblebees because I like them.
00:12:59.100 This is a bumblebee, and you might recognize it. Urban legend has it that if you calculate its lift, you’d find it cannot fly because its wings are too small. However, bumblebees don't know math, and importantly, this legend has a grain of truth. If you were to create a bumblebee on a scale one-to-one, using the same proportions, that bumblebee wouldn’t be able to fly, as you'd find its wings don't provide enough lift.
00:13:40.210 This is bizarre because you would think that would be true at any size, but it isn't. Air molecules remain the same size. Micro-scale behavior is affected by how bumblebees encounter air. Essentially, air behaves differently at smaller scales, allowing bumblebees to achieve lift much better than it would seem mathematically feasible.
00:14:06.730 This is an interesting tidbit, and we’ll revisit it later. Now, let's get back to programming. When you learn a new language, another challenge you face is understanding the design philosophy behind it. Imagine you are evaluating a Java system and you peek at the code for ten minutes. What would you look for? Are there any Java programmers in the room? Alright, what would you look for?
00:14:58.960 You would likely look for small classes, right? If you find one large class that contains a lot of logic, that's a hint that the system isn't well-factored. In Java, classes should ideally have a limited number of methods. If you see a class with thousands of methods, then it’s likely doing too much and violating the Single Responsibility Principle. The number of methods in a class offers clues regarding the system's structure.
00:15:46.260 Now, imagine that Java developer is evaluating a Ruby library. For instance, with ActiveRecord, you inherit from ActiveRecord::Base and then call methods, both class methods like 'find' and instance methods like 'save'. The number of methods can be staggering—ActiveRecord::Base has over 500 class methods and about 306 instance methods. A Java programmer might look at this and think, 'Of course, it can’t possibly work!'
00:16:36.600 If a library like this is essentially one big class with nothing else, it raises questions about maintainability and potential bugs. What’s the air molecule here? It took me some time to grasp the usefulness of modules in Ruby; you quickly get the syntax but struggle with the concept. You can think of each module as a separate component that is decoupled and can be developed and tested in isolation. Together at runtime, you assemble these to create a big, complex structure, which in source code terms does not exist.
00:17:57.120 This notion presents itself every time I learn a new language. Constructs can be unique or new to me; like mixed-in modules, for instance. In cognitive science, this is related to what's called linguistic relativity—essentially, the language you speak influences how you think. This applies not just to natural languages but also to programming languages. So, you must learn the design and tools, but now we're reaching the more complex part: learning the cultural context.
00:19:18.490 I looked at various Java frameworks claiming simplicity, intentionally setting aside those that are clearly inspired by Ruby frameworks, such as Play, which is inspired by Rails. One such Java framework is Seam. It prides itself on being very productive and simple. It offers many modules and claims to be 'batteries included', yet when you print out the hello world example, it's a seven-page PDF.
00:19:57.799 The developers acknowledge that this sounds bizarre, explaining that while seven pages for 'hello world' might seem excessive, once you understand it, you can perform most tasks similarly.
00:20:02.229 This approach represents Java's culture of 'do it right.' They do not leave any stone unturned or any use case unaddressed. I remember working on the Hibernate project, which is a popular object-relational mapper for Java. Someone once complained about the configuration being slow, yet I found that hard to believe because configuration is something I barely even noticed. When we queried this user, we discovered he had tens of thousands of entities, effectively thousands of tables in a database.
00:20:39.640 Realizing their context was so far removed, I initially thought, 'We can't help them.' But the project's manager insisted that this was a legitimate use case and that we should improve our product. This illustrates that, in reality, each use case matters.
00:21:09.470 Now, you might complain that something like Sinatra doesn't meet your very specific use case. You might say that this use case is only relevant to 10% of your users. The response, however, is that you should fork the project and implement your solution or switch to another framework if Rails seems more suitable for you. This is the Ruby approach, which we can categorize as the 'keep it simple' mentality.
00:22:20.320 This doesn’t mean that Java developers enjoy complexity; nor does it imply that Ruby developers seek simplicity to the point of being useless. Each community has its approach, leading to passionate discussions over drinks. It’s common to overhear Java developers saying, 'This Ruby framework seems nice, but you wouldn’t want to use it in production, would you?' meanwhile, a Ruby developer might remark, 'Really, a seven-page hello world? Give me a break.'
00:23:08.980 This cultural clash often reveals a cognitive bias known as ethnocentrism. This bias posits that one’s values are the superior values, leading individuals to measure others according to their principles. So, for those in different communities, whether they prefer the elegance of Ruby or the robustness of Java, this bias can lead to misunderstandings.
00:24:16.490 When you learn something new, your instinct may be to think it cannot possibly work since it doesn't align with your values. However, the hardest part isn’t learning; it’s unlearning.
00:24:47.540 If you look at any forum with an ongoing debate, you’ll observe remarks like, 'Java is better for enterprise development.' This reflects the cognitive distortion where one process thinks, 'Java is matter-of-fact better,' while the low-level kernel process is grappling with the complex question of which language is superior for enterprise development.
00:25:33.250 The kernel process, finding this question difficult to answer, defaults by replacing it with a simpler question: 'How many enterprises do I know that have successfully implemented Java?' So, if the answer is not many, then BAM—the conclusion is Java must be better. This same bias exists in the Ruby community. For instance, the age-old criticism of Python's whitespace seems to disregard substantial and genuine merits of the language, simply because it looks unfamiliar.
00:26:47.710 The underlying reason is the tendency of the mind to substitute hard questions with easier ones. In cognitive psychology, this is known as attribute substitution. Faced with complex inquiries about a language's utility, your mind may instead ask, 'How familiar does this language look?'.
00:27:32.439 Revisiting the initial question: why is it so hard to learn a new programming language? It's challenging because of biases—functional fixedness, linguistic relativity, ethnocentrism, attribute substitution, and numerous others documented in cognitive psychology. You must constantly work to overcome these biases.
00:28:19.290 As developers, we fancy ourselves logical thinkers. Sorry, but we are not. We are influenced by biases. What can we do about it? Now that we understand that we are almost wired to have biases by design, there is a simple question along with a simplistic answer: how can one avoid cognitive biases?
00:29:02.520 Unfortunately, there isn't much that can be done from a behavioral standpoint. Actual cognitive bias mitigation research has yielded limited practical results. Of course, developing expertise in something improves the data that the kernel process uses. This is what you may call intuition or experience.
00:29:56.960 However, there is no shortcut. Even with awareness, our minds have a knack for ignoring facts, even when we know rationally that we should pay attention to them. Let me propose another experiment that demonstrates this phenomenon.
00:30:41.549 I have a rule in mind. Those three numbers conform to that rule. I challenge you to visualize what the rule may be. Formulate a hypothesis. I assure you that this sequence conforms to the rule, but there are many sequences that do as well. Think of another sequence that might test this hypothesis.
00:31:32.470 Let's try this out. For instance, if I gave you the sequence 2, 4, 6—is that in accordance with the rule? Yes! How about 1, 3, 6, 12? Does that fit the rule? No, it does not. The overarching rule here is merely that the numbers must be in increasing order. Yet, most people will create sequences that confirm the biased reasoning rather than ones that try to invalidate the hypothesis.
00:32:28.620 This tendency is characteristic of confirmation bias, which is the inclination to support what you already believe instead of attempting to disprove it. You probably haven’t noticed this bias reflecting in others yet it’s prevalent within yourself.
00:33:18.370 Next, take a look at these optical illusions. Are these two lines parallel? You know, consciously, they are—yet subconsciously, your kernel process is inferring otherwise. The same applies when I mention something unexpected; your subconscious will revert to thoughts you’re prepared for.
00:34:05.120 You will indeed get that wrong. How do we address this issue? Ultimately, you can’t avoid it. You might want to embrace it instead. That may sound fluffy, but if you're humble and recognize your probability of being wrong, it will not eliminate your biases, but it will help you manage them properly.
00:34:29.440 Understanding that you can be wrong will empower you to validate your thinking before drawing conclusions. It’s about learning to be patient with yourself. Likewise, this advice applies to others, so try to extend that kindness.
00:35:08.020 Ultimately, being polite and patient amid cognitive biases can aid your learning journey. Remember, even your logical considerations are affected by the lower-level mind processes. The next time I attend, hopefully, I’ll be prepared to talk about Clojure. Thank you!