Armin Ronacher has become a prolific contributor to the Python software ecosystem, having created such widely used projects as Flask and Jinja2. Over the last 10 years, he had worked on various Open Source and commercial projects, and we were extremely excited to speak with him about his life and career. In this interview, Armin talks about his work at Sentry, shares his thoughts on handling errors in the backend, speaks about the differences between Rust and Python, the "gradual typing" approach, and, of course, the secrets of his work-life balance.
- Your job title is Director of Engineering. What does your everyday work look like at Sentry?
Armin: From a scheduling point of view my day is typically split into two parts. I work from 9 to around 3 pm/4 pm when I pick up the kids from daycare. Then I have a second slot late in the evening/night for meetings across timezones. That segmentation works well for me because that way I have time with the kids when it's light outside. In terms of what I do in many ways, my role is to make sure that all the people that work with me are aligned on the things that matter. This is particularly important because Sentry is a company with multiple locations across timezones. Really it's a mix of hiring, solving people problems, assisting in system architecture, shaping or communicating product vision to the actual projects and then a lot of assisting with odd engineering issues.
- The popular "full-stack" approach promotes developers to write both frontend and backend code. As a developer who knows lots of programming languages and technology stacks, do you approve such a practice?
Armin: It's a complex question because what's full stack on a complex project really? Sure for a trivial application it only really consists of a CRUD backend and some React frontend, and you can comprehend the entire thing. But that process does not at all work for us, because Sentry is a much more complex endeavour. The simplified description of what Sentry is is a service to take crash and performance reports and show them to the user. However, from a technical perspective Sentry is a very complex processing pipeline with multiple databases, multiple services to process the reports before they are persisted. The idea that a single individual could be tasked with working on all these components to ship a feature is not just unrealistic, it's also very inefficient. So my answer to if I approve on this practice would very much depend on the type of project.
- Recent Mozilla restructuring hit lots of Rust language developers. How do you think that will affect language development?
Armin: For me personally it hurts to see the developments at Mozilla. Like Mozilla, we're an Open Source project made into a commercial enterprise and our paths crossed a few times. We're sometimes leveraging Mozilla technologies in the same way Mozilla uses ours. I think for Rust as a whole the changes at Mozilla will surely affect the language, but I don't think Rust will take any damage from it. But no longer having the Servo project will definitely have an impact on how the language and community evolve.
- What do you think is the main reason why Python packaging is still so complicated?
Armin: It's a very complex story but I believe it comes down to technical challenges and lack of focus. For instance, to contrast this with the Rust community packaging was recognized as an important thing and a community project (cargo) for packaging was made part of the language development. In the Python world, these efforts are always separate. The packaging infrastructure (pip, setup tools, virtualenv) are largely developed independently from the language. From the technical side, there are many shortcomings in Python that stand in the way of a better user experience. For instance, you can only load a single version of a library at the same time, limiting how "wild" you can go with dependencies.
- Comparing Python, Rust, TypeScript, and other languages you work with: what do you think is the best strategy for an average developer to handle errors in their backend code?
Armin: Since I work for a company specialized in crash reporting I am exposed to a large number of backend errors :) My learning from that is that you should spend the same amount of time designing the error types as the return values. You cannot have enough contextual information on errors. There is a shocking amount of code that just writes error messages into an exception and calls it a day. Then eventually someone will want to respond to those errors and starts parsing the error messages. This type of "stringly typed error handling" is a source of a lot of frustration. I remember some database handling code that checked for a certain type of connection error by parsing the error message and handling multiple languages (German, French etc.) since the database on the other side would localize error messages.
- Are there any Python language or ecosystem features that you really miss while working with Rust?
Armin: For sure. Python is a very mature and grown-up language so whenever you switch somewhere else, there is a wealth of stuff that's just not there. It will take a lot of time for other ecosystems to become as wealthy as Python's. One of the first things I noticed when writing more Rust is that the ecosystem was quick to adapt to typical "2020" things but less so to older technologies. The first time I had to interface with XML instead of JSON I noticed how weak Rust's XML support is for instance. Another thing is just that Python as a rather "slow" language doesn't punish you much with adding more debugging features into a production build. In Rust. you can't really do that without throwing one of the best features (the performance) out of the window. That causes you to program very differently.
- What do you think is the best way to evaluate software developer expertise?
Armin: A hard question for me. I feel like the right way to hire or assess people does not exist, a lot comes down to how good you are at assessing people in general. There is a whole community of people that do nothing but grinding interview questions from FAANG companies and that has for sure changed things quite a bit. We're also in the situation that my teams are often working on issues which are pretty unique, so it's more important to find out if developers are interested in solving unique and sometimes frustrating problems and how they work in a team on tricky things.
- Do you think Python is still the best general-purpose programming language we should teach first to new developers? Do we have any alternatives in 2020?
Armin: I'm not sure if I thought Python was ever the best general-purpose programming language, but I always thought it strikes a pretty good balance. Despite all of its shortcomings and frustrations it causes, it's quite good for solving problems quickly and in that sense, it's as good in 2020 as it was 15 years ago. I thought for a while that JavaScript would replace it but somehow the community has embraced such a complexity that even the simplest things become complex. I'm still faster making a throw-away project in Python than JavaScript just by the fact that I only need a handful of libraries. If I were to teach someone programming in 2020 I would probably pick C, Rust and Python as languages and Python to a large degree because you can also show them the interpreter source code and they will be able to understand how it works behind the scenes. That's not true for many other popular languages.
- With so many programming languages to work with, what operating system and IDE do you prefer?
Armin: Computers are terrible. I have a love/hate relationship with macOS. Still using it and every time I try to use something else, I'm back in a few weeks. I deploy to Linux machines though and there is plenty of Windows around in my life. IDE wise I use Visual Studio Code with Vim bindings and I still use Vim independently a lot.
- The new "async/await" syntax and concepts were recently introduced into Python, Rust, TypeScript: all the languages you work with. What is your opinion on this approach to handling concurrency in our code?
Armin: I'm torn. I think it has a lot of benefits when used the right way but it hides the challenges of concurrency too much. It also makes lack of backpressure management more apparent and I would guess that most async/await code in existence would fall over if I try to bring it to the tipping point. This is something that traditional multi-threading code (which mostly uses a pool) does not suffer from out of the box. It's also important to understand that just because multiple languages have async/await how they actually approach it is very different. Rust's and JavaScript's async/await designs couldn't be more different.
- Python seems to be eating the world. Can you name any real competitors to it as a general-purpose programming language?
Armin: Python seems to be eating the world largely because of data science. I think while it loses popularity in the web world it's quickly making up these losses in the data world. Because JavaScript isn't good at numbers (to put it bluntly) it has less of a footing there. That said, I think JavaScript is just out of necessity becoming more and more popular.
- With all your Flask and open-source background strengthened up with Sentry work you are an expert on programming languages. What do you think about the future of Python?
Armin: I think it will become more and more specialized into some ecosystems and completely give up on others. This is somewhat consistent with how it has worked in the past too. For instance, Python gave up on becoming a language for embedding (Game or application scripting etc.) or mobile development. It's also not something you would use as the preferred language for Desktop apps, particularly if you want to get into app stores. It is however probably going to become more popular for serverless, data science and scripting infrastructure. I noticed a shift in the users of my template engine from classical web applications to more and more infrastructure scripting (Ansible, salt) for instance.
- What do you think about the new "gradual typing" approach introduced into Python, JavaScript (via TypeScript), Ruby, PHP, and other dynamic languages?
Armin: I think it's great. I absolutely love TypeScript and I think if more languages want to learn from somewhere, that project is what should be copied.
- As both a father of three children and a software development lead, how do you organize your work-life balance and avoid burnouts?
Armin: At the time of writing still two kids though days away (fingers crossed). The first and most important thing is that I'm not parenting alone. With my wife, I have a wonderful partner and we are taking care of our kids together. To help us with that, the next most important thing is to find good daycare. You can't be a good parent 24/7 but you can make sure that the time you spend with them you give them the right attention. Particularly during the early pandemic days, we had the kids at home all the time and I noticed how that was not good for us or them. They spent more time on TV and iPad as we had to juggle work meetings with taking care of them.
For me personally, since we live in Vienna and the head office is in San Francisco I adopted a bicameral model of working twice with a break in between. For me this is ideal, but I don't think it would work for everybody. I started doing a list where I write down when and why something emotionally upset or stressed me in a week to try to optimize away from that. Eventually, you start understanding yourself a bit better. Out of that, some patterns emerge.
Once I identify a situation that has the chance to upset me I now no longer try to prevent or avoid it. Instead, I try to recognize early that it's going to evoke some emotional response in me. Doesn't always work, but overall has helped me a lot. For instance, Slack notifications no longer disrupt me as much as they used to do even without turning on do not disturb.
We had a great time speaking with Armin and learning more about his approach to life & writing code.