Many of our day-to-day decisions when working with software are based on subjective opinions and beliefs rather than objective truth. Are you even aware of the software-related views you hold? What if you could change them on a whim? Are your beliefs useful?
When you identify a belief of yours, ask: how did you come to this belief? There must have been some experience or something you read or heard that gave you the idea in the first place. What if something else happened?
Here are some beliefs. There are a lot of people on both sides. I’m not aware of objective criteria that would show a clear winner in any case.
- Testing is good vs. testing is not worth the time.
- Static typing is good vs. static typing is bad (or not worth it).
- Estimates are worth the time, or they aren’t.
- Agile (or iterative approach) is good, or it is bad.
- Performance matters, or it mostly doesn’t matter.
- Working for big companies is better vs. working for small companies is better.
- Pair programming is good vs. pair programming is bad
- Object-oriented is the best paradigm, vs. functional is the best
Can none of these be correct in absolute terms, but are they more useful in some contexts?
Or maybe there are objective winners, but we don’t have a strong consensus about it for some reason.
It might also be that there is consensus, but it’s objectively wrong.
Imagine with sincerity holding the other side of the belief. What would change in your behavior? How would it affect your different beliefs? What are the traps it might create?
Beliefs are sticky. Once acquired, they change how we perceive experiences, continually strengthening whatever you already believe.
Beliefs limit what we can perceive. For example, if you believe that automated testing is good and a bug escapes the tests, you will perceive it as an exception and a reason to write more tests. On the other hand, if you believe that testing is mostly a waste of time, you will see the same bug supporting your belief.
An exercise I propose is to make a strong case for both sides. Then, write it down. It requires you to question your belief at least for a while.
Here is my attempt:
- Testing is good vs. testing is not worth it
- Automated testing has the best ROI when it comes to avoiding bugs. It is a great tool to aid us in carefully considering the correctness of code.
- Automated testing is a distraction. It is better to spend time with informal reasoning because testing is not good enough to ensure correctness. You need manual testing if you genuinely care about quality.
- Static vs. dynamic typing
- We should use everything we can to ensure the correctness of our code, and static types are one of the best tools in that. They render entire classes of bugs impossible or almost impossible. They make for better tooling, like refactoring support in IDEs. They help achieve great performance.
- Static types muddy the clarity of code. Leave the type checking to the runtime; focus on what your code means; types are not adequate for that. They give a false sense of security. Some types of tasks (like metaprogramming) become unnecessarily hard.
- Estimating is very hard in the context of software, and it doesn’t bring that much value. It would be better to focus on estimating value instead.
- Estimating is possible when done correctly. Refer to How to Measure Anything for an example model (in short: estimate the range that you are confident 90% and use math tools to combine multiple estimates).
- Incremental methodologies like Agile, when done right, are the most reasonable ways of working in most cases.
- Incrementalism prevents serious progress. We need to take a deep look and carefully plan what we do.
- Focus on performance
- We ought to be careful about the performance of software. We can’t rely on surfing the Moore’s law’s wave forever. Most software nowadays is actually slower than it used to be 30 years ago!
- Make the system run correctly first, and only then consider tweaking performance if really needed. If something is automated, it’s usually orders of magnitude faster than a human anyway. “Premature optimization is the root of all evil.”
- Working for a big company vs. startup
- Big companies pay better. Many exciting problems require a scale that can only be found at big companies. See Dan Luu’s article on startup trade-offs
- Big companies are doomed to work in the old ways, and if you want something novel, you need to look to startups. At small companies, opportunities are not restricted with red-tape yet. Only in a startup do you get a good shot at having a significant impact on the company. See Paul Graham’s essays.
- Pair programming
- Working in pairs helps get better code quality and prevent mistakes. It aids knowledge transfer.
- Pair programming has low ROI because it halves productivity in some sense. It can prevent careful thought that is only possible in solo work. Pair programming is awkward and stressful for many people.
- OO vs. FP
- Object-oriented programming became dominant for a reason. There is an extensive body of practice and educational materials that teaches how to design OO systems well. OO is a big part of most popular programming languages, and we should take advantage of it.
- Functional programming is superior because of its simplicity. It is more natural to people. It’s not the 1950s, and we no longer have a reason to avoid FP because of performance. FP is like mathematics, pure and beautiful.
The third way
It might be that neither side of an argument is truly right or wrong. Nuance and context matter. Or maybe not! It might be that one side of the argument is actually right.
I argue that you have a better chance of finding the most useful belief if you put serious effort into seeing all possibilities instead of limiting yourself to whatever convinced you the first time. But it might also be worth the time to look for alternatives. Is there a false dichotomy in how a choice is stated? Can one side be more right in some contexts and the other one in different contexts? Is there a third way of any sort?
Here I propose arguments for “the third way” for the same beliefs I mentioned before.
- Automated testing is one of the tools that aid in making good software. You still need informal reasoning and manual testing for overall excellence.
- Static types
- Static or dynamic typing isn’t the most significant difference between programming languages anyway. Some problems can be more natural to model with either dynamic or static typing.
- Estimating is valuable sometimes. Figure out the value of estimating in your context before engaging in it.
- In practice, a mix of careful design and incrementalism is the best. Some projects might benefit from longer planning, while others are best done incrementally.
- The value of performance can be estimated, and it can vary from system to system how much investment is reasonable.
- Big company vs. startup
- Reject being an employee at all. Be a consultant and choose clients, not employers.
- Pair programming
- Pair programming should not be a must or a must not. Programmers need to be free to work in pairs when they judge it will be more effective, but never forced to pair. It should be normalized to say that you like pair programming or not without being seen as antisocial.
- OO vs. functional
- Different problems are better modeled with different paradigms. Often either OO or FP can be used to solve a problem well. You can also mix both – see imperative shell, functional core.
Did you find any other programming beliefs that you hold? Let me know!