Home Bookclub Episodes Software Mistake...

Software Mistakes and Tradeoffs

Tomasz Lelek • Mark Rendle | Gotopia Bookclub Episode • April 2024

You need to be signed in to add a collection

Mark Rendle and Tomasz Lelek explore the tradeoffs that can prevent software teams to make the wrong choices. Code performance versus simplicity. Delivery speed versus duplication. Flexibility versus maintainability—every decision you make in software engineering involves balancing tradeoffs. In Software Mistakes and Tradeoffs, you’ll learn from costly mistakes that Tomasz Lelek and Jon Skeet have encountered over their impressive careers. You’ll explore real-world scenarios where poor understanding of tradeoffs lead to major problems down the road, so you can pre-empt your own mistakes with a more thoughtful approach to decision-making. Learn how code duplication impacts the coupling and evolution speed of your systems, and how simple-sounding requirements can have hidden nuances with respect to date and time information. Discover how to efficiently narrow your optimization scope according to 80/20 Pareto principles, and ensure consistency in your distributed systems. You’ll soon have built up the kind of knowledge base that only comes from years of experience.

Share on:
linkedin facebook
Copied!

Transcript

Introduction

Mark Rendle: Hello and welcome to another episode of the GOTO Book Club. I am Mark Rendle. I'm joined today by Tomasz Lelek. I will let Tomasz Lelek introduce himself, and say a little bit about himself.

Tomasz Lelek: Hi. Welcome, everyone. So I'm Tomasz Lelek,  I am the author of this "Software Mistakes and Tradeoffs" book, and we'll be talking about the book today. I am a software engineer, and I've been working more than 10 years in the industry. I'm currently working at Dremio, and previously I was working on Datastax, building Cassandra, and products around the Cassandra database. In my book, I was trying to share the experiences from DataStax and previous, because I wasn't working at Dremio when the book was finished, but I was also working at Allegro Group. That's the e-commerce in Poland, and I mean the biggest, biggest company. For example, Amazon and eBay wanted to get this market, but it was too hard because Allegro is like, well-known here, everyone uses it, so there is like, 15 million active users. So I was involved in streaming processing, and other interesting stuff there. Also, I've covered part of it in the book.

So that's me.

Mark Rendle: Okay. And just to introduce me, Mark Rendle, software engineer, 34 years now. So when I started, we were dumb terminals attached to SCO Xenix machines, and C, and Informix, and...yeah. And over the course of those 34 years, I have seen a lot of software mistakes and tradeoffs, and I think I got roped into this because of my Programming's Greatest Mistakes talk, which is, you know, NASA exploding things on the way to Mars, and proper big mistakes, not just choosing the wrong front-end library or something like that.

Recommended talk: Programming's Greatest Mistakes • Mark Rendle • GOTO 2023

I am very interested in the kind of higher level aspects of software development and engineering, and yeah, this book I found extremely interesting, and I think it's an interesting angle. It's not one that I've seen before.

Was there a moment when you thought, I should write a book about this?

Tomasz Lelek: So the stories that I was, like, trying to document, all the decisions and mistakes everyone did with their team. For example when we were working on some problems, and there was some decision involved, and almost always there is some decision involved, so if you want to be able to another path in the code or architecture or the library that you are choosing, then I was like, trying to document what was the main factors that backed up this decision, and why we go and pick, like, option one or two, and etc?

When I had a list of such decisions and mistakes, then I was like, after a year or two, when the system was like and n production, I was trying to do some introspective and see if it was the best decision we can make. And often it was not the best one, but because there are tradeoffs, right? So then I was trying to understand the tradeoffs, and to see if you would pick a different solution, would it be better? I was, like, trying to document the biggest things that also were repeating in the ecosystem that I was working in. So I had the list, and it was like, 10 items or even more at some time, and at this moment, I started to think that maybe I can document that in a better way for other people to benefit from it.

So like, the one option would be to just have a blog post, right, with not related topics.

Mark Rendle: Yeah.

Tomasz Lelek: More like an end-to-end approach that could be distributed better is to write a book, so that was the idea.

Mark Rendle: Like I say, it is a very good book, and there's a lot of interesting stuff in there. It's not... One of the things I like about it, is you've got some code samples, and you know, they could be Java, they could be C#, but it's applicable no matter what language you're programming in. Whether you're front-end, back-end, DevOps, you know, wherever you are, a lot of the ideas and concepts in the book, they're broadly applicable.

Tomasz Lelek: I was trying to, like, back up every chapter with actual code, and tests as well.

Mark Rendle: Yes.

Tomasz Lelek: So, I think you will, if you... I mean, GitHub repository is public, so you can check it out. It's on my GitHub. Or you can just type the title of the book in GitHub and in Google, each code example is paired with tests. So you need tests, integration tests and so on so you can also experiment and break stuff.

Decoding Software Complexity: Exploring Date-Time Dilemmas and Data Compatibility

Mark Rendle: So now, that book title again, just in case anybody missed it, is "Software Mistakes and Tradeoffs," by Tomasz Lelek Lelek and Jon Skeet. What was it like working with Jon on the book?

Tomasz Lelek: He was involved in the book at the early stage. So when I sent the idea for the book to the Manning publisher, Manning is sending this to top authors, best-selling authors of this publisher, and Jon was one of them. So he liked the idea of the book a lot, and he was like, interested... He proposed that he could contribute to a couple of chapters that he has the most experience in.

Tomasz Lelek: So there is the chapter about...

Mark Rendle: Working effectively with date and time data was the one that jumped out at me, when I knew Jon was working on it. Because obviously, he maintains the Noda Time library for .NET, which is essentially a .NET port of Joda-time from Java. And I have watched a one-hour talk by Jon on why dates and times are difficult, and yeah, it's an insanely complicated...

Tomasz Lelek: Yes. So here he is able to elaborate more about this topic, in this chapter. So you'll find really interesting stuff there. When I was reading it as well, it was a very entertaining read as well.

Mark Rendle: Yes.

Tomasz Lelek: Because like, he's trying to consider, like, time zones between planets, for example.

Mark Rendle: Yes.

Tomasz Lelek: So what will happen if we need to communicate between, like, Mars and Earth.

Mark Rendle: Yes.

Tomasz Lelek: So the second chapter that he was also volunteering to help was about compatibility of data, so like in versioning and so on. Because he's also, like, deeply involved in Protobuf format on Google.

Mark Rendle: Yes.

Tomasz Lelek: So when you have, you know, in the industry of storing data you have Avro format, Apache Avro that also allows you to keep consistent...like, keep compatibility of your data, evolve it, and so on. And you have also Parquet that is more like, optimized for fast queries and columnar storage. So you have Protobuf that is more like generic format, that allows you to... Like, gRPC is backed by Porto, so it allows you to define APIs of your application in a very strict schema way.

That's why he volunteered, and also he authored this chapter. My first idea was to use Avro as the format for, like, explaining concepts there, because I have more experience in Avro. I was working a lot with Apache Kafka. It treats Avro as the main format, for some good reasons. But of course, Jon's knowledge about this topic was even wider. So we really, like, we changed to Protobuf, and this is also only for demonstrating the concepts, because concepts are the same, compatibility, forward compatibility, avoiding your API, and allowing your API to, like, not break when you change stuff, like automation and so on.

Recommended talk: Nullable Reference Types in C# 8 • Jon Skeet • GOTO 2019

Mark Rendle: The people who designed Protobuf, this was one of their kind of key considerations in the original design, was that you can add new fields to objects without breaking the existing contract. And with gRPC, which is the RPC framework that runs on top of Protobuf, and uses Protobuf as its wire format, and...

Tomasz Lelek: It's also interesting for me... Because this gRPC adoption is trending a lot right now. When this book was completed, gRPC was, like, not yet at, like, the recommended way to use and create APIs between services.

Mark Rendle: Yes.

Tomasz Lelek: Because it's mostly used in the microservices world. When you have a lot of services, you need the contracts and so on. So previously, like, people tended to use REST, right, for example GraphQL, but now I see that gRPC is trending a lot, so I think this chapter is even more relevant now than it was when it was, like, finished.

Mark Rendle: Which is always nice. When I learned about gRPC, it was one of those things I was kind of aware that it existed, but Microsoft...  I'm a .NET guy mainly, and I've been working with Microsoft's tech for 25 years, and they deprecated WCF, which was their RPC framework from, like, 2005, and then recommended gRPC as the alternative. And they've invested very heavily in making sure that .NET's gRPC implementation is absolutely...it's one of the fastest out there, and it's very easy to work with.

Tomasz Lelek: Also, those formats must be, like, technology agnostic, right, so you can... And also, those patterns for compatibility.

You can use it from C#, as you said, from Java, or any other language

Mark Rendle: And with gRPC, it is almost every other language. I don't think the Zig supports gRPC yet, but you can certainly do it in Rust and Go, so...yeah.

Tomasz Lelek: I mean, there was always, like in our industry, I think there was always, like...there was always endeavors to try to create a format, or the way to... So like, communicate within services. There were some, like, high-level frameworks that were hiding remote calls, that I think is not a good idea, because we need to be aware that remote calls involve, like, potential failures, and sometimes you need to retry...

Mark Rendle: That's it.

Tomasz Lelek: ...and impotency and so on. I think that's a good middle ground between those two things.

Mark Rendle: Yes, there is a tendency with RPC frameworks to pretend that they're not RPC frameworks, and to try and make it look like everything's happening in one place. You do need to remember that you could have network partitions, or services could be in the middle of a rolling upgrade, or you know, all sorts of things to be going on.

Tomasz Lelek: This chapter is related also to other chapters in my book, like delivery semantics. So if you have some good formats like RPC and gRPC also, then you can build on top of it, like build a system that works, for example, like these ones deliver your messages. In that case, you need to consider a lot of things like side effects, like this idempotency of our API. So also in this chapter, I'm like, trying to consider a situation when you...how to design APIs that are idempotent, that may not be idempotent at the first site. For example, if have an event-based system, you can send only modifications. Like for example, if you have an entity with a lot of fields, and in the event you can set only the notification with one field that changed, but that's problematic because if you retry that, you don't know if this modification was done twice or not, right? So the better approach is, like, to go send the whole entity, and it allows you to retry with some, like, unique identifier, right?

Mark Rendle: Yes. Yeah, e-tags, and things of that nature.

Code Duplication

Mark Rendle: So yes, looking at some of the other chapters in the book, and Chapter 2 was one of my favorites, Code duplication is not always bad. And I've actually seen discussion of this over the last sort of week or so, particularly concerning React, and React components, and actually that whole component-based way of building front ends and user interfaces. And there is a tendency, you know, this concept of DRY, don't repeat yourself, which I think came from "The Pragmatic Programmer." And it's a good kind of idea. It's a good notion to bear in mind. But you do see people saying, oh, I've written essentially the same four lines of code twice, I should pull that out into a helper method, and put it in a helper project, and that sort of thing, and there is that tendency to try and abstract and extract functionality when it doesn't necessarily need to be extracted.

And then, particularly, you get to this point where you then start trying to build flexibility into your new abstraction layer with configuration points, because actually, it's not doing the same thing over and over again, it's doing similar things over and over again. And it was very refreshing to read a book that said, you know what, sometimes it's okay just to have very similar looking code in multiple places in your application. So…

Recommended talk: Anniversary Edition of The Pragmatic Programmer • Dave Thomas & Andy Hunt • GOTO 2020

Tomasz Lelek: When I was discussing this idea with Jon, this chapter with Jon, he said a very, like, a very nice quote, like when you have the code that is similar at the beginning, it doesn't mean that they have the same functionalities. There may be some functionalities that may evolve differently. And if you have this abstraction, then you will not be able to evolve this in different ways. Or you can, but you will need to build some complex patterns, you know, template patterns, abstractions, and so on.

Mark Rendle: Yes.

Tomasz Lelek: And so it's like in the context of, like, the hierarchy of your organization as well, so if you have, like, two independent services handling two different business entities, and you have this common code refactored to a common component, so then you have this, like, point of, like, contention between those two or more teams. So if you want to change something, you cannot change or evolve so fast. I mean, that can be important in the startup context.

Mark Rendle: Yes.

Tomasz Lelek: So if you want to deliver something quickly, then you have this... Like, if you are in the static languages world, when you need to compile things, then you need to have maybe some kind of a library that needs to be distributed, and you need to upgrade your services. I mean, there's a lot of aspects around that.

And I agree also that this principle is, like, accurate in most of the cases. Because when you start, like, programming, or you have, like, first project, or you know, like a second project, then it's better to, like, have some guidelines around you to write better code.

Mark Rendle: Yes.

Tomasz Lelek: Then you can start noticing that it's not always accurate.

Microservices & Protobuf: Overcoming Challenges

Mark Rendle: One thing I've seen a lot, as teams are told, oh, we need to do microservices and break things down into smaller services, and you have two services that are talking to each other, maybe using an HTTP JSON API, and so they both need the data transfer objects, they need the classes that are being passed backward and forwards. And then people can create a NuGet package, or a Gradle package or something with those object classes in them, which are then shared between the two or three services that are using them, which I think is an anti-pattern. If your release process involves pushing a new microservice into production that is then live, and also publishing a NuGet package that then people have to update specifically and say I'm now going to version 2.1 of this NuGet package or whatever, versus just very simply handwriting an object with maybe a dozen properties, and having that in both places.

I do a gRPC workshop, a two-day workshop on gRPC, and one of the things I point out there is that with gRPC, and with other RPC frameworks as well, and actually with HTTP APIs, if you're using Swagger, you have this kind of text document, so a proto file or an open API.json or a swagger.json file, which you can distribute, or you can just make it part of your wiki, or part of your GitHub repo, and then people generate code using that. When I'm teaching the workshop, one of the things I point out is that if you're using a proto file and it's got 8 RPC methods in it and 60 message-type objects in there, if you're building a service that only needs to call one of them, and only needs five of those objects, you can delete the rest, and you can only generate the code for... Even down to removing specific fields, and then your code will just ignore those fields, and it doesn't matter if they're there or not.

And so...and this comes back to versioning as well, is if they take away a property that you weren't using, then you don't need to change your code at all. You just go, yep, no, we're not using that. We don't care about it, it's not referenced anywhere. But yeah, it's...

Tomasz Lelek: Because when you're consuming your data, you don't need to consume everything.

Mark Rendle: Exactly. This is one of the nice things about GraphQL, because with gRPC and Protobuf, and with REST and JSON APIs, even if you're not consuming all the properties, it still sends them all over the network because it doesn't know which ones you're reading. Whereas GraphQL, you can actually say, I only want these three fields, and it will throw those back.

There’s no One-Size-Fits-All Solution

Mark Rendle: One of the sort of general things that I liked about this book is a lot of the time you'll buy a book on a new pattern, or a new framework, or a new paradigm in software engineering, and it's sold as a magic bullet. It's like this can solve all your problems. Your book makes it very clear that there's not a one-size-fits-all solution, that it's not if you just do this and this and this, and then everything will be smooth. Whereas you're looking at you could do this, and here are the pros and cons of doing it this way, and you can do it this way, and the factors that go into deciding which are the right choices for your particular. And it's more about teaching people how to think how to analyze the problem, and what factors to bear in mind, rather than saying here is the solution to your problem.

Was that something that you were aiming for?

Tomasz Lelek: My goal was to write a book that will not go outdated quickly, right? So like, my idea was... The scenario was that this book could be relevant in 10 years, that some of the things would be still... That's why, also, I didn't use a lot of frameworks when showing the code examples and those patterns. I just tried to, like, use the additional framework. Of course, sometimes it was easier to explain things based on some well-known solution that is used in a lot of places. Like for example, I was talking a bit about dependency injection. You can do it yourself. You don't always need a framework that does that for you.

Mark Rendle: Yes.

Tomasz Lelek: So you choose one of the frameworks from there but having it in the context of the actual reward example, but still proposing a solution that is like, framework agnostic, yeah? So that was my goal for most of the chapters.

And I think, like, the book was published two years ago, and it's still very relevant. So currently, I think none of the chapters are outdated, or the examples.

Mark Rendle: No. Certainly, when I was reading it, it all seemed very current, and as I say, some of it is relevant to conversations I've heard in the last couple of weeks.

Is there anything that you would add to the book now, after another couple of years of, you know, being in the trenches, working on actual software projects, anything else you've come across in that time?

Tomasz Lelek: I had an idea that maybe in the future, I would create a second part of it. But of course, I think I would focus more on the open source, how the open source code evolves, and how it impacts the community. Because when I was working on DataStax, I was part of the Java-driven team, so we were, like, working on this Java driver for Cassandra, this open-source framework. And also, I was contributing to a couple of frameworks that were firstly private and then transferred to be open source. So this is, like, wrote from taking the project that was, you know, proprietary for example a Kafka connector from DataStax, and that allows you to integrate Kafka with Cassandra. It started as a private project, but then we were transforming it to open source, and like, this process was quite interesting, what abstract way, and how to, like, make it more common, more generic so the community can use it. So that will be one topic that I would focus more on.

Mark Rendle: Yeah. And I've worked on a couple of projects where we had parts of it that were made open source for different reasons, and that process of prepping what has been a closed source in-house, maybe a team of three or four people working on it, and turning that into something that you can publish on GitHub or GitLab. I mean, in a lot of cases, it's going through and taking out sort of slightly salty comments, and function names, and variable names and things, but also just getting code into a state where a potential contributor can come along and be able to understand the code, and what it's doing, and how it's doing it, and be able to contribute is a challenge. It's a difficult process, I think. I would be very interested to read your thoughts on that.

Tomasz Lelek: This making the product open source is more about subtracting, not adding new stuff, like removing some of the code.

And increasing the potential use cases. Also, it's about, like, providing more extension points to your code.

Mark Rendle: Yes.

Tomasz Lelek: I briefly touched on this, in my book about that, and how to make it easier for your customers to extend your code. And it's even more tricky in the context of, like, multi-threaded or asynchronous code, because you may have some functions that the code is non-blocking, so when you provide books to your API for customers, they may not be aware of that, so they may block APIs. For example, if you are using some kind of non-blocking or Node.js, Node.js processing when you have one thread, and even look if you have customer code that plugs into your stuff and blocks things, that can be problematic.

But fortunately, I mean that there is a way to detect those problems, and after I completed the book, we worked on such a solution in DataStax, I remember. So additional, like, analysis, detecting potential blocking code, deadlocks. That was quite interesting.

Mark Rendle: Yes.

Tomasz Lelek: ...extend this idea here.

Recommended talk: Navigating Through Programming's Greatest Mistakes • Mark Rendle & Hannes Lowette • GOTO 2023

Navigating Third-Party Dependencies: Balancing Open Source, Abstraction, and Telemetry

Mark Rendle: Yes. And another thing, so you have a chapter on third-party libraries, and how when you adopt a third-party library, you essentially become responsible for supporting it within the context of your application. With open-source libraries in particular obviously...it becomes even more complicated. Because, I mean, obviously there's the licensing issue. You've got to make sure that the third-party library that you're taking a dependency on fits with your open-source license, whether that be GPL Apache or MIT. But also, and this is something that I've run into with the sort of libraries and packages that I've created over the years if you take a dependency on a library, say a logging library, then you're forcing anyone who takes a dependency on your library to take a dependency on that logging library as well.

I found that people were kind of creating a logging abstraction within their library that the consumer could then hook up their logging instance to, whether that's, you know, in .NET it's Nlog and Serilog and log4net and those sorts of things. That's a constant battle, of trying to avoid taking dependencies on libraries where possible, if there is a choice within that, like dependency injection, like logging, like... You know, it's one of these things that we're hoping to solve with open telemetry, and that's...

So if I can say one thing I would like to see in a future edition of the book, a chapter on telemetry, and the sort of choice between traces, metrics, and logs, which are the kind of three data types of open telemetry at the moment. I've been told not to call them pillars.

Tomasz Lelek: Also in the context of, like, managed services that are connecting, and trying to provide business value, many services connecting, and having a chain of, you know, commands.

Mark Rendle: Yes.

Tomasz Lelek: Logging can be tricky because you cannot relate stuff. But tracing allows you to do that. There are even some people who have really strict views and think that tracing is enough, right, so you don't need logging at all in some places in your code, and that's the direction in which we are going. But I think that's all, as you said, it's a very new approach, I would say. I mean, tracing was always there, but using it at this scale for...

Mark Rendle: The ideal would be that we use tracing everywhere, and we have it always on, so every sample, every span gets written to some kind of back-end store. But I know that there are people out there who were generating petabytes of trace data...

Sometimes logging is the more affordable approach. And you keep logs, you know? Logs you can keep around for years and years. Traces tend to be shorter-lived. So yeah, that's...

Tomasz Lelek: For the tracing, you can also... Like, I've seen an approach of, like, sampling for normal scenarios, right? If everything is going smoothly in your application, you can sample one out of 10,000 events. And in the case of any of the, like, potential problems, you can try to, like, save the trace for it.

Mark Rendle: Yes.

Tomasz Lelek: There is a big tradeoff between costs there, costs and feasibility, right, of your application.

Mark Rendle: Yes

Tomasz Lelek: And the two more topics that I would add for now is like, the first is multi-tenancy on all the cloud products are going to limit costs  for multi-tenant 

Mark Rendle: Yes.

Tomasz Lelek: ...like DataStax, Astra database, it's like Cassandra on cloud went in that direction. Also, the Dremio cloud solution uses multi-tenancy, and there are a lot of tricky things there, like how to isolate your customers that are using the same environment, and propagate information about which customer executed what, the authorizations is hard. Yeah, there is a lot of interest.

Recommended talk: When To Use Microservices (And When Not To!) • Sam Newman & Martin Fowler • GOTO 2020

It's a topic for a whole book, I think, the multi-tenancy, and supporting it in the cloud solution.

From Microservices to Maintenance

Mark Rendle: Actually, you don't sort of have a chapter about microservices, and micro service architecture specifically, but you do have a lot of things in there about distributed systems, and some of the sort of potential mistakes and tradeoffs in distributed systems as well, which is very helpful. So yes, edit point.

Yes, and this is something that two years ago, when you were writing the book, was sort of on the rise. It's become kind of the de facto way of building systems now. Nobody's starting with a monolith, and separating it, and they're sort of up front trying to identify microservices. And I think you've got a lot of useful information in there on things like distributed transactions, and sort of delivery of messages between microservices and so forth.

Tomasz Lelek: Yeah, I was trying to structure this book in, like, two parts. The first one was more, like, low-level, or for code, and the second part was about distributed systems.

So I tried to touch on, like, most of these important things, like consistency, those delivery semantics. 

Mark Rendle: There's a lot of useful information in there.

Tthen there's your last chapter, which made me chuckle, Keeping up to date with trends, versus the cost of maintenance of your code. So in my Programming's Greatest Mistakes talk, which is one of those strange talks, it's kind of informative but mainly entertaining, it's one of those that goes very well in the last slot at a conference, and I talk about a couple of my mistakes in there as well. One of them is when I was working on migrating a desktop application from Gupta SQLWindows to .NET, way back in, like, 2004 I think I started on it. And yeah, so I was building this application using Windows Forms, which was the desktop application framework, and then in 2005 or 2006, sort of in the middle of this project, Microsoft released Windows Presentation Foundation, which was all new and shiny.

And so my thought was this is a brand new sort of project, and we've been supporting the last one for 20 years, and we're going to be supporting this one for the next 20 years so I should switch to the newer framework. And then attempting to do that quite frankly almost killed me, and I ended up completely burning out, having to take an extended break from work. And so yeah, that chapter hit home for me. It's a very fine line that you have to walk, making sure that you don't have outdated things in your code base, but at the same time, you can't chase every single new thing that comes along.

Tomasz Lelek: Because you said that, about the project that was already there, to migrate new stuff, it also applies to, like, green field projects. So you shouldn't try to use all, you know, the new stuff, like event-driven and microservices, using GraphQL and so on, because maybe you don't need everything, and what you get, you get complexity. You don't need to be like, you know, on the actual edge, but a bit, like maybe use something from a year ago, or that has proven on production and has good documentation, and you know, good discussions.

Mark Rendle: Yes.

Tomasz Lelek: On stackOverflow, or somewhere else. In this chapter, I'm focusing on, as I said before the dependency injection, also reactive programming, that solves specific problems [inaudible 00:42:07] complex. Also, functional programming, uses languages that are not fit for that. Because functional programming [inaudible 00:42:16] and so on, but sometimes you have a language that doesn't, like, support it very well, and you need to kind of emulate that, and what you get is like, a hybrid approach, without the benefits of it, but with all the drawbacks.

Mark Rendle: Yes.

Tomasz Lelek: There like, a lot of examples, I think, as you mentioned, of this migrating to a new library to maybe imagine if it was so hard to migrate. So that could be a list of tens of examples, I think.

Mark Rendle: I very much enjoyed reading the book. It's very well written. I find it difficult, personally, to read badly written prose, but this one, was very, very easy to read, and I enjoyed it, and it made a lot of sense. There's a lot of very good advice in there. There's a lot to think about. And like I say, I very much like the fact that it's not offering a magic bullet can solve all problems. It talks about how to think about these problems, and what factors to consider when weighing these things up.

So the book is "Software Mistakes and Tradeoffs" by Tomasz Lelek Lelec and Jon Skeet. It is available from all good booksellers. It's published by Manning, sou can also buy it as an e-book, and live book, and so forth through manning.com.

Tomasz Lelek: And audiobook.

Mark Rendle: Yes, and audiobook. This one actually would work as an audiobook.

So having sort of got this one out there, you know, writing a book, I've written a short one myself, and it's a lot of work, and particularly at the end, where you're working with editors, and knocking it into shape, and having the reviews done by other authors and so forth, so are you up for writing another one? Have you got any other books inside you? Or are you happy to let this one sit there for a while?

Tomasz Lelek: No, not yet. Not yet it's a lot of work

Mark Rendle: Yes

Tomasz Lelek:  Maybe I will try collecting some ideas for the future, but I don't think it will happen very soon.

Mark Rendle: And you've just started a family, so I'm guessing you're going to have a little bit less free time over the coming years, so you got this out just in time.

Tomasz Lelek: Yes, that's some good advice for writing a book before you start a family.

Well, thank you very much for talking to me about this, and thank you for the book. It is... Yeah, I recommend it to anybody who is building software, to be honest. It is applicable across all languages, all frameworks, and all types of software. There is, there is something in there for everybody. 

Tomasz Lelek: Yes, yes, thanks for the invite. Bye.

About the speakers

Tomasz Lelek

Tomasz Lelek ( author )

Senior Staff Software Engineer at Dremio & Author of “Software Mistakes and Tradeoffs”

Mark Rendle

Mark Rendle ( interviewer )

Creator of Visual ReCode with 7 Microsoft MVP awards and 30+ years of experience building software