In our First Line of Code series, Commit co-founder Beier Cai talks to prominent tech founders and tech leads building the next generation of companies, to hear about their experiences and lessons learned.
Dieter Shirley worked as Chief Software Architect at Axiom Zen before becoming CTO of Dapper Labs, the breakout blockchain company behind CryptoKitties (which he co-created), NBA Top Shot, and the Flow blockchain.
Commit co-founder Beier Cai sat down with Dieter to talk about his journey in tech and all he has learned along the way.
This is part one of this interview. See part two here.
Beier: Let’s start with a simple question: how did you get into software?
Dieter: I got into software as a kid. I found computers absolutely fascinating. I was fortunate that both of my parents were teachers, and in the eighties Apple had incredible discounts for educators. I got to program on an Apple IIe, learn BASIC and just did silly little things.
I don’t know whether it was a blessing or a curse that I didn’t have access to the internet in those days, because it would’ve distracted me from programming. But it would’ve also been a resource to learn. It was really clear to me even at about age eight that this was something I wanted to do my whole life.
I have a copy of a book I had as a kid where every year you’d enter in what you want to be when you grow up, and of course in the early years it was fireman and policeman and stuff like that. I think I was in grade five when I decided I wanted to be a computer research scientist. In my twenties I would’ve told you that that job doesn’t exist. I wouldn’t call myself a scientist, but I think I’m closer now than I might have ever guessed.
Beier: What was the first piece of software or technology that you built?
Dieter: I built a lot of silly little programs when I was a kid. One of the things I liked to do was experiment with simple line drawings and mathematical functions, like building a sine wave or doing interesting spiral circles.
College is when I really broke out as a professional developer, where I really understood my purpose in life. I had a co-op job working for a company called Metrowerks, which was a developer tools company, and they were the number one developer tools company for Mac computers at that time.
I realized how rewarding it was to make other developers more productive. That set the trajectory for my career. The most satisfying projects I worked on–I had worked on a ton of direct consumer-facing stuff, and I do enjoy that—was finding ways to build systems, whether it’s libraries or tools or processes for other people to be more productive.
Later in my career it was a natural move into management, coaching engineers and teaching them how to make themselves more productive and choosing tools for the team. It was a real natural through-line from my first paid jobs to where I am right now, building a development platform for Web3.
Beier: When you started at Axiom and then Dapper, how did you choose between new technology versus tried and tested ones?
Dieter: That’s a tough one because I can think of examples where we very intentionally said, “We’re going to use brand new technology.” We were building an iOS application and we decided to build it in Swift even though Swift was very early in those days. Part of the motivation there was, if I’m being honest, that the product wasn’t that interesting to the engineers. So making the project interesting to them was part of it.
It was a way of exploring history. So that was one aspect of it. Another example is Flow. We had a team that had a lot of grounding in Golang but the received wisdom was that something like Rust is much more robust and performant than Go, and the question that came up was: should we build the Flow blockchain in Go or Rust?
We ended up going with Go. The way I decided it was that if Rust was the wrong choice, we would learn before we launched. Because Rust is very complex, it’s something new to use, there are all these static checks. The mistake of using Rust would be that it would be too complex; it wouldn’t be flexible enough for us to recode aspects of our program because it’s a very structured language.
Whereas if Go was the wrong choice it was going to be a run-time program. It was going to be garbage collection; it was going to be potential performance issues. If Go was the wrong choice we would find out after we launched.
If Rust got in the way and prevented us from launching–and it’s not that it would’ve, we would’ve never figured it out, but when you’re a startup you’re always fighting against the risk of not getting something into the market and proving the traction before the investors and community lose faith in us. Knowing that we were already taking a big risk in terms of actually building a blockchain, we wanted to go with the thing that was more comfortable for the team.
In both of those cases it was about balancing risk. It was saying in one case it was a very standard straightforward application, and the biggest risk was that the engineers would get bored with it because, from the standpoint of technological development, the application itself wasn’t the interesting part. The interesting part was what was happening on the backend. Bringing in Swift was to a certain extent addressing the risk that the engineers might not be really invested in the project, whereas with Flow the whole project is a huge technical risk.
I think with a lot of startups, you look at your project and one risk is that no one cares or wants this product. The other risk is that so many people want this product that you’re going to have performance problems. Many engineers get caught up in that second one, “If we build it this way it’s not going to scale,” or, “If we do this, we’re going to have problems, we’ve got to build it in a nice robust way.”
You’re taking on the risk that you build something that either takes you too long to build or you build the wrong thing and it’s not exactly what the market wants. You end up having to make major changes to it and you end up with this robust system that’s wrong. It’s the wrong robust system for what you end up building. It’s always that balance of: what is the riskiest assumption and how am I going to test that? Technology can be a part of that.
Beier: Many engineers are curious about how to manage technical debt in the early days and how that evolves over time as the team gets bigger and the product gets more mature.
While you were building the early stage product with the team at Dapper and Axiom, what did the technical debt management process look like, how did that evolve over time and what does that look like today?
Dieter: I don’t want to sound like a broken record but it’s kind of the same answer. It’s about where the risks are. One analogy that has really struck me this year with our team is that building a product is like pushing a boulder. You spend all this time pushing the boulder uphill and it’s so hard and it’s so much work. But when you catch on in the market, suddenly you’re running downhill after the boulder, running as fast as you can to keep up.
And if you aren’t in one of those modes, that’s scary to me because it implies that you’re not successful. You’re not being pulled forward by the market because people are using your stuff and you’re not being overwhelmed with desire for people to have more of your thing and you’re not pushing forward hard enough to find that inflection point.
The reality is that the most successful teams are the ones that have the most technical debt because it’s not that technical debt causes success, it’s that success causes technical debt. If you find yourself thinking a lot about proactively fixing some technical debt, maybe you’re in a mature market and that’s fine, by all means address it.
But if you’re not successful, if you’re an early-stage startup, you probably have a bigger problem with your company and you should be thinking about markets and product and whether you’re even building the right thing.
When technical debt is not something you’re thinking about proactively but it’s something that you’re tearing your hair out over because the technical debt is getting in the way, then yes, by all means, fix it.
The goal with technical debt is to address it only insofar as it’s a daily annoyance. As soon as it’s not a daily annoyance or a massive issue every single sprint, then you’re probably better off putting your energy into something else. Again, this is different for mature companies.
If you’re somebody with an existing user base and you’re no longer in that high-speed growth phase or trying to find it, I think the calculus is very different. But in that early stage, I think that it really is something that is always going to be there. You’re always going to have made a mistake in the past, and you’re going to have to live with that mistake, and you only really address it when it’s bad enough to be a constant frustration.
Beier: So the way to look at technical debt especially in the early days is: pay a lot of attention to the impact of that technical debt. Is it just a question of frustration, or is this actually having a large impact on the team performance or speed? If that’s the case, that’s the signal you try to pick up and actively stay on top of.
Dieter: I would go so far as to say that if you have to ask the question, “How bad is our technical debt,” then you probably shouldn’t even be asking the question. When you can’t ignore it anymore, that’s when you need to pay attention to it. If you look back on the last three sprints and think, “If that subsystem had been more cleanly architected, that would’ve gone a lot better,” then maybe you fix it, but you probably have better ways to use your time.
When you’re in the middle of a sprint and you think, “Oh my God, this is the third sprint in a row where we built something and then we had to tear it down again because of that stupid limitation of that subsystem,” that’s when you have to finally buckle down and deal with it.
Beier: So it’s when it’s in your face all the time, that’s when you know OK, time to tackle this.
Dieter: Engineering best practices suggest that being messy can’t be the right solution. But my experience is that if you have time to be tidy, it’s probably because no one wants the thing that you’re building.
Beier: Is there a particular technical debt management framework you use or that your team adopts, or is this more like an internal established system that you just use now?
Dieter: I don’t want this to apply to established companies. I think established companies should have a metric. If we’re talking specifically about startups, again, if it’s not a constant pain, you probably shouldn’t be thinking about it. And if it is a constant pain, you don’t need a framework—you’ll know.
Beier: What are some of the major technical milestones at Axiom and Dapper? I know behind the scenes there are some major technical milestones that are less known to the world. Are there any particular moments that you remember from a technical accomplishment perspective that you want to share with us?
Dieter: The big ones we had were getting Flow up and running—having a functioning blockchain, being able to submit a transaction to it and have it come out the other end, executed and finalized in the blockchain—and having the first usable version of NBA Top Shot.
Everything has been a constant evolution since then. You can pick out some specific inflection points in that evolution. We have a performance improvement rolling out in Flow right now that’s probably going to unlock up to 10X performance improvements on certain kinds of transactions. That’s a big one.
Again, if we’re talking mostly about startups, I think that constant iteration is important. That’s the mindset to get into, rather than big plateaus. The most important thing that happened to us this year was when Top Shot caught the imagination of the end-users and we had a flood of them coming in.
On the engineering side, that was about dealing with all of our systems being overwhelmed. But it wasn’t like we shipped one feature and unlocked that. It was about critical mass, about people being interested in it, understanding the product and having faith in it.
In practice, it’s a million little things and it’s getting that critical mass together that finally gets you the ability to be successful.
Beier: You’d rather have continuous constant iterations, make small improvements, and aggregate until it’s a big thing at some point.
Dieter: An analogy would be something like the Grand Canyon. If you could go back in time to the first day the Grand Canyon existed, what would that even mean? Because every year it gets a little bit deeper. When is the first year of the Grand Canyon? That’s an underappreciated aspect of building a product. You just have to keep working at it and it’s a million little changes that make something great.