The Stack Overflow Podcast

Programming problems that seem easy, but aren't, featuring Jon Skeet

Episode Summary

Jon Skeet, the first Stack Overflow user with a million reputation, sits down with Ryan to share his wealth of knowledge on all things development: the deceptively simple but actually complicated problem of timezones, the importance of clear documentation for programmers, handling breaking changes and upgrading legacy systems, and the need for improved communication skills among developers.

Episode Notes

Jon Skeet, for those not in the know, is legendary here at Stack Overflow. He even got his own Chuck Norris Facts-style jokes

Jon has graced the podcast before in the early days on episodes 4, 72, and 123.

He’s so good at answering Stack Overflow questions that he appeared at Stack Overflow’s old NYC office and answered them in person

While he’s not the only million rep user, he was the first, so we ran the numbers on him

Have a question? Jon Skeet has probably answered it on Stack Overflow. You can also find him on Blue Sky.

Looking for C# 3.5? Spoiler alert: you won’t find it. Learn why from Jon’s very helpful question What are the correct version numbers for C#?

Episode Transcription

[Intro music]

RYAN DONOVAN: Hello everyone and welcome to the Stack Overflow Podcast, a place to talk all things software and technology. I am Ryan Donovan, and today joined by a very special guest, our very first million rep man, the inimitable John Skeet. How are you doing, John? 

JON SKEET: Hello, very well. Thank you. It's just coming up to the weekend. So that's always nice and it's a beautiful May evening in the U.K. just for a change. It's not cloudy or raining or anything, so, yeah. All good. 

RYAN DONOVAN: I can hear the birds, I can hear the birds in the background. 

JON SKEET: (laughs)

RYAN DONOVAN: So today we're gonna be talking about the things in programming that seem simple, but are actually very complicated.

JON SKEET: Yeah. 

RYAN DONOVAN: And I have a soft spot in my heart  for a lot of these. So I wanna start with time zones. That one, you know, I think people are like, just location, just figure it out whatever. But, I remember at my last job was a food delivery app and we had people stay up on daylight savings and– both daylight savings in the fall back just to make sure everything went fine. 

JON SKEET: Wow. And did you do it for February 29th as well for leap years, just in case?

RYAN DONOVAN: I'm not sure I was there for a leap year (laughs)

JON SKEET: (laughs) It's funny actually, just mentioning the topic being sort of simple stuff or–

RYAN DONOVAN: Yeah.

JON SKEET: –complicated stuff that sounds simple reminds me that it was, oh, many years ago now, what–17 years ago that I gave a talk at the Stack Overflow Conference on Humanity Epic Fail, which was very much about this kind of thing, like it was–

RYAN DONOVAN: Right. 

JON SKEET: –dates and times and numbers and text and how can we have made all these simple things so, so complicated. So yeah, it's, it's funny how things loop back. 

RYAN DONOVAN: Yeah, absolutely. So, tell me about why time zones are so complicated. 

JON SKEET: So they're one of those things where most people have a reasonably accurate idea of roughly what they are.

RYAN DONOVAN: Mm-hmm. 

JON SKEET: But then if Dunning-Kruger sets in, it can go either way. You either end up thinking, okay, I know that time zone's complicated, so I can't possibly get them right, therefore I will not bother thinking about them too hard. 

RYAN DONOVAN: Right.

JON SKEET: And just like leave it to someone else, which some of leaving it to someone else's is a good thing– 

RYAN DONOVAN: Right.

JON SKEET: –but not work through the steps and like, okay, no, I can understand this. I can then get it right. Or you assume, oh, it's fine. I know how to deal with time zones. I'll store everything in UTC and then just convert to local time at the client side and everything's

RYAN DONOVAN: Right. 

JON SKEET: And that is so dogmatic in the industry every time, if anyone ever says–

RYAN DONOVAN: It’s simple! (laughs)

JON SKEET: Yeah, and it's really simple to implement and that’s the worst kind of thing. And in fact, this happens in API design as well, where if you try to make something that is inherently complicated  seems simple–

RYAN DONOVAN:  Right.

JON SKEET: –then you lure people into a full sense of security. So,  date and time, almost all date and time APIs are terrible, or that was certainly the case like 20 years ago. So the initial Java 1.0. dtate and time API was absolutely awful. It got somewhat better in 1.1 in that they introduced calendar. So you've got this terrible type java.util date that doesn't represent a date. It represents a point in time and only a point in time. It doesn't know what date it was on 'cause it's got no time zone or calendar system.

RYAN DONOVAN: (laughs)

JON SKEET: So, you know, naming is hard to start with, right, but java.util calendar was also really hard to use well, but because it was hard to use at all, in fact–

RYAN DONOVAN: Sure

JON SKEET: –it didn't take long before smart folks came up with Joda-Time, which like, oh, that's easy to use and gets things right. Yay. You know, it reveals the complexity in the API doesn't try to do–in fact, Joda-Time did try to do a little bit too much defaulting in my view.

But Microsoft took a different approach with do net, so in .NET, the date time type from like well back in .NET one, sounds really simple. Hey, you know you can get the day, you can get the month of the year, and it's all fine, except that a system date and time is either UTC or local or an unspecified time zone, but you use one type for all of them. 

RYAN DONOVAN: Oh, no. 

JON SKEET: Which makes it really easy to use and really easy to get wrong. 

RYAN DONOVAN: Yeah.

JON SKEET: But because it was sort of so appealingly–well, it's almost, it's so usable compared with the Java stuff.

RYAN DONOVAN: Yeah. 

JON SKEET:The problems behind it sort of looked– 

RYAN DONOVAN: So how do you know what, what the time zone– the local time is, based on that?

JON SKEET: So local for date/time, kind of local means local to the system, which if you are doing anything server-side is completely irrelevant.

RYAN DONOVAN: Right.

JON SKEET: So almost no one should use date/time kind dot local. Like it's okay if you're doing an on-desktop app, but that's kind of all. But yeah, because it was so appealingly– and then we got DateTimeOffset, which people say, oh, that's a date/time, and it knows the time zone. Well, no, it knows what it says it knows which is the UTC offset, which is not a time zone.

RYAN DONOVAN: Right. 

JON SKEET: So that lure of almost right made it–, well, basically the world, if I say waited for me, the world didn't have a better date and time API until I basically copied Joda-Time, which comes back to that, that conference talk that I gave at the time I said, “If you are using Java, please use Joda-Time, and these days you'd use java.time, but this was before that came along. And I said, “In .NET, sorry, there isn't really a good library to use.” And I felt so bad about saying that I think it was on the train on the way home from that conference that I wrote a blog post saying, “Oh, I can see this is going to take so much of my time. I don't want to do this, but I feel morally obliged to come up with something better,” which is basically a copy of Joda-Time, but you know, nicely idiomatically .NET, remove some of what I viewed as the problems of like, I think, if I remember rightly in Joda-Time, if you create–I can't even remember what they called it, but something that knows about a time zone, ff you don't say a time zone, it will default to the system local time zone. Like, but that's almost never what you want. Like stop trying to do things for me. Don't default anything. Let me tell you, make me tell you. 

RYAN DONOVAN: Yeah. 

JON SKEET: And that was the mantra of Noda Time is very much dates and times is complicated. So the API is somewhat complicated. You don't just have System.DateTime, which is like, oh, one type can do everything for you. Instead, we have lots of types and people do, or at least did initially go, “Oh, Noda Time, it's so complicated. There are so many types.” It's like, yeah, because you've got to choose what you are trying to represent.

Are you trying to represent a date, but with no associated time zone, like the day I was born on? That's fine. I can represent that as a local date. That's different to a time of day. That's different to a duration of time wherein .NET you'd have time span and you'd use that for the time of day. But no, they're not the same thing. The current time of day. So at the moment here in London, it's 8:12 in the evening. So yes, today that is 20 hours and 12 minutes elapsed since midnight.

RYAN DONOVAN: Right.

JON SKEET: But that's not always going to be the case because if there's been a daylight saving transition, it might have been 19 hours or 21 hours and 12 minutes. 

RYAN DONOVAN: Sure.

JON SKEET: So yeah. Noda Time tries to make the API a little bit more complicated to expose the complexity and the idea is make the developer think and then make it as easy as possible to express that decision, express that thinking, and that approach, like I started it however many years ago and it seems to still be working.

And I  quite like taking that approach of work out where people ought to think, where you can't do the thinking for them. 

RYAN DONOVAN: Yeah, yeah. Reveal the assumptions. Right?

JON SKEET: Exactly. Exactly. Yeah. 

RYAN DONOVAN: So– and obviously storing date and time has been an issue. We have the Y2K problem. I read the other day that Epoch time in Unix is going to become a problem in 2038.

JON SKEET: Yes. Yes. Which is after I will have retired in general, but I guess if the consultancy rates are really high then, you know, it's gonna be great. 

RYAN DONOVAN: (laughs)

JON SKEET: Yeah, but I mean, that's only gonna be a problem for people who are still storing seconds since the Unix Epoch in a 32 bit. 

RYAN DONOVAN: Right, exactly. Yeah. I mean, you'd hope that people would upgrade, but I know there are still people storing things on COBOL and other things, which are…

JON SKEET: Yes. I think it will be the same, probably the same systems that needed treating for Y2K. 

RYAN DONOVAN: Yeah. 

JON SKEET: Are probably still a load of them still being used, and they will probably have the same kind of problem. 

RYAN DONOVAN: So, so the ones that were too important to take down for an upgrade.

JON SKEET: Right. 

RYAN DONOVAN: (laughs) Well that's good. Speaking of legacy code bases and the tech debt, this is one that I think, you know, I've been reading about this and thinking about this for a while where I'm like, why do people think this is simple? 

JON SKEET: Right. And in fact, linking with COBOL, you've got DOGE at the moment saying, oh, I'm sure I can rewrite, I can't remember what the acronyms are for the U.S., like the Social Security system, like how hard could it be? I'll just rewrite this million lines of COBOL. We'll give it to AI to do. What could possibly go wrong?

RYAN DONOVAN: Right. 

JON SKEET: It's not like anyone's depending on the money from Social Security or anything.

RYAN DONOVAN: Yeah. Wait. I mean, it's, you know, like it's this whole chain of dependencies and, you know,  I've talked to folks doing language upgrades and the difficulty from the language side is that you got to get everybody to get off this old version, but you also have to get all the libraries and dependencies off. So it's not just upgrading the one thing anymore. 

JON SKEET: And every single upgrade has the potential for, well, they just changed that one thing. How hard could that be? Well, it's when it's everything at the same time. Yeah. 

RYAN DONOVAN: Yeah. Do you think there's, like with the date/time, is there a way to sort of reveal the assumptions there?

JON SKEET: So, definitely you can have systems where all of your dependencies are, you have to explicitly say all of your dependencies, including transitive ones and say, this is what I'm assuming I'm getting, and yep, that's great in terms of having a manifest. It's terrible in terms of developer efficiency, but versioning as a general problem, there's partly is knowing what you depend on, for sure. 

RYAN DONOVAN: Right.

JON SKEET: But versioning in general is something that sounds simple. Like people say, “Oh, just use SemVer. Everything will be fine.” Will they though? It's sort of, yeah. And the .NET ecosystem, I've been banging on about this for a while, but haven't actually found the time to make an impact.

I have a blog post that I've written up for about a year, but haven't posted yet around how the ecosystem could get better if libraries could declare ranges of dependencies. So, yeah, I would like to depend on library Y version 5.0, but actually 4.0 is fine as well. Give me a range so that if I've got two dependencies that depend on the same library, I can afford for them not all to update at exactly the same time.

RYAN DONOVAN: Right, right. 

But yeah, versioning is very hard and I think we are kind of living in hope. So anyone in the .NET ecosystem will be aware of Json.NET. So Newtonsoft .Json, and despite the fact that that's set, I think still major version 13, I think it's had very, very few breaking changes. Now if James decided that version 14 was going to have a load of breaking changes, the .NET ecosystem would explode, right, less so than a few years ago because now most people are gonna be depending on System.Text.Json instead. But any really, really popular open-source software that decides to genuinely make breaking changes, what happens to all the things that depend on that? Do they need to make a breaking change as well, or do they need to split and have like this is my version of this that depends on Json.NET version 13 and I have a separate package that depends on Json.NET version 14, et cetera.

RYAN DONOVAN: In that case, you kinda have to upgrade everything at once, right? 

JON SKEET: With the way the ecosystem is now, kind of yes, and you have to hope about it. I think we could get a long way with actually the versioning systems that we have, but with tooling to check things.

 So at the moment, if you take a dependency in .NET and say, my application depends on libraries, X and Y, and I realize I'm drawing pretty diagrams for those listeners, please imagine that I'm drawing a diamond dependency.

Okay? So my application depends on libraries, X and Y, and both of those depend on library Zed or Z. Now if X depends on Z version 3.1 and Y depends on Z version 4.0, NuGet says, I'm sure it'll be fine. We'll just go with 4. What could go wrong? But no, surely the assumption if we're baking Samba in, we should say, “No, X has said it depends on 3.1. It can't assume that it can work with 4.0.” It should be able to declare, hey, actually I can work with anything below five.  And maybe that's the thing that you do as soon as 4.0 comes along, X should say, I depend on 3.1 or higher, but as far as 5.0 exclusively, so I know that it works with four. But nothing will give you any errors until something does.

RYAN DONOVAN: Right. 

JON SKEET: Which you know, Murphy's Law will say that the time that it gives an error is when you go down some corner case and you're actually trying to report a different error, so you can't find out what triggered this weird situation, et cetera. Now there are things we could do about that. 

RYAN DONOVAN: Sure.

JON SKEET: Partly like change the defaulting to say, “No, if I specify a version, I mean that version or higher within the major.”That would be itself a breaking change to the versioning ecosystem. But apart from anything else, we could definitely have tools that say, “I will look at everything.” It can be either conservative or quite liberal. So it could say, “I will look at the bits of X that I use in the application and see transitively what those bits use from Zed, Z, and see whether all of those still exist.”

Or it could just say, “I will look at everything that X uses from Z and see whether those still exist.” So that would be a bit more conservative. It wouldn't rely on the tree shaking as much, but we've got all this tree shaking stuff within the AOT side of things, ahead of time compilation to remove bits of libraries that it thinks you don't use.

Well, if you know which bits of libraries, like surely we can check the versioning stuff at the same time. it's possible that actually AOT gets this as a sort of side effect, but I want to have it even if I'm not using AOT. 

RYAN DONOVAN: Yeah. I was talking to the CTO of Polygraph QL the other day and talking about the sort of declarative versus procedural, and this looks like acase where we need to have some sort of declarative tool or process on the versioning, right? 

JON SKEET: So being more declarative could be useful on that, but I think brute force could actually get you a long way for saying, “Well, okay, I'm sure there is a breaking change in Z version 4,” and being declarative about how breaking changes happen, that would be fantastic– if we could have machine readable change logs, basically. So imagine you've got a method where, okay, the method still exists in V4 version compared with V3, but you know that it has changed in a breaking way.

 If you could declare that and the tooling could consume that and say, “What if X calls that method,” then it could acknowledge, “Hey, I know that this has changed in a breaking way, but it doesn't happen to break me.” So there can be this sort of protocol of negotiation between different libraries, but the trouble is this all takes quite a bit of thinking and maybe someone in Microsoft– and I'm talking just about the .NET ecosystem only because that's the one I'm familiar with.

RYAN DONOVAN: Right?

JON SKEET: I have heard various people say, “Oh, my ecosystem doesn't have versioning problems.” And then you delve in a bit deeper and it's like, well, it does, just not the ones that you were thinking of. I haven't found anywhere that really, really doesn't really, the technology is that sooner or later libraries do need to make a breaking change and how do you deal with that without taking the hit off? Oh, no, V1 and V2 can't talk to each other at all. They're effectively different libraries. That's one way of avoiding breakage.

RYAN DONOVAN: But it's not great user interface, right?

JON SKEET: Yeah. There, there's, there's all kinds of ways that you can solve half the problem, and that may be the half that you care about, but I think we can get better to at least being a bit more confident without actually solving all the problem. I'm hoping that maybe someone at– a whole team at Microsoft is really thinking deeply about this. 

I would like to spend some time– I've spent time thinking about versioning within my career at Google and client libraries and things. I would love to think about it more, but I don't have the time at the moment. This is one of my retirement plans is when I retire, I will offer some of my time to Microsoft and say, “Hey, how about we get in a room every so often. I will tell you what I've been thinking about in my cave for a while, and then you can tell me why I'm wrong and I'll go away and think a bit more, and eventually we'll get to some better stuff.” But that's a, a retirement plan. 

RYAN DONOVAN: Yeah. Yeah. So, when should Microsoft reach out to you? 

JON SKEET: Oh, I'm, I'm hoping to go down to like three or four days a week in basically when my kids have stopped sucking my money.

RYAN DONOVAN: (laughs)

JON SKEET: It's like I love them dearly. All of them. 

RYAN DONOVAN: Yeah. Yeah. 

JON SKEET: Love them dearly, but they're all at university and three kids at university is…yeah. But yeah, I have fun semi-retirement plans of, at the moment, I'm having a huge amount of fun planning for the next U.K. general election, and we had one just last year. So this is like nicely ahead of time, but I'm hoping that to be a sort of showcase for, hey, I'm quite good at taking data from different places and presenting it if you know where the data is, but you don't have the technical chops to get at it, please hire me to do so for a project. And ideally sort of small projects that when the project is done, you don't care about the code either afterwards, and so I don't need to do training of here's how you will maintain it forever, et cetera, et cetera. 

RYAN DONOVAN: Well that, that seems like a project that, uh, AI is suited for.

JON SKEET: Maybe, maybe, or it might be by then, who knows? Yeah, but I'm, I'm hoping there will be enough of a market for someone who can get some stuff done, without having to be full time. And ideally for these sort of not just short term projects, I would hate to work on a project short term and know that it was going to need to be maintained forever without leaving really copious comprehensive documentation, tests, like everything you would ever need.  And that sounds quite boring, writing all that documentation, whereas working with someone and say, right, what do you need for the next six months.

RYAN DONOVAN: Right. And then you throw it in the garbage and you're done. 

JON SKEET: Yeah. And there are plenty of projects where that's fine. That's absolutely fine.
 

So that's– maybe that's another secret. Thinks it's simple, but it's actually hard: the maintainability of projects in the long term. Why is that tough? 

JON SKEET: Ha! I would be really interested to think– to see whether there was anyone who'd been in the industry for more than three years that thought it was simple, to be honest. We are not good at predicting the future. 

RYAN DONOVAN: Right. It might be tied to the versioning issue we were talking about. Right? 

JON SKEET: Some of it is. I think a lot of it is tied to we are human and coding is fun. Documenting is not fun. But what makes most difference for maintainability? I think it's documentation. This code looks like it's doing something really weird. I wonder why. If someone had bothered to write the document, say, “Oh, it's 'cause at the moment we can't get to that end point, so we are having to do this weird thing.” Writing that documentation doesn't help you in the short term, definitely helps you in the long term, but yeah, it's just not that fun to write. 

RYAN DONOVAN: Well, that’s why you gotta get yourself a good technical writer. 

JON SKEET: Ah.

RYAN DONOVAN: Hey, as a former technical writer, you have to get yourself good technical writer. 

JON SKEET: I think technical writers have huge amounts of value and are undervalued in the industry, but they usually aren't involved in like documenting the code itself. And that's where. I think like developers just need to step up and that includes me. Don't get me wrong. I have this problem myself the whole time, but yeah, I think technical writers are great for talking to different constituencies. So where a developer needs to talk to an end user, absolutely, and to be honest, I would love for developers to put technical writers sort out of a job to some extent by saying, “Do you know what? Actually, communication is important for all aspects of my job. So maybe I'll put some more time into getting better at communicating and working out how to communicate differently with different people and build up those skills.” And then there would be a bit less need for technical writers, a bit less.

RYAN DONOVAN: A bit. A bit. 

JON SKEET: And every other aspect of your job would get better. You would get better at filing bug reports. 

RYAN DONOVAN: Sure. Sure. 

JON SKEET: Hopefully your colleagues would get better at filing bug reports for you. You would get better at writing Stack Overflow questions, and this has always been for me, this has been the biggest potential benefit of Stack Overflow is: it should be a way of people improving their communication skills because that is just so close to being a silver bullet. Obviously, no real silver bullets, but if you can identify, if you can communicate clearly that shows you are already thinking clearly, usually anyway. And so in order to build up your communication skills, you need to build up your logical thinking skills, which means you can diagnose problems, which means half the time you don't need to ask a question.

But by the time you do, you've got a minimal example. You are saying exactly what's necessary. You are not talking about things that are irrelevant. This is a big hobby horse of mine, as you can tell. 

RYAN DONOVAN: Well, I think this is a nice lead into another one of our simple, actually hard is  AI code reliability. And I think there's a lot of people who trust the code that is written and they shouldn't. But, I say this because we put out an article a while back that “Coding isn't the hard part. It's requirements, it's thinking through the problem, figuring out what you need.” 

JON SKEET: And that goes back to time zones as well, like to my mind, if you can get a really good product manager who knows their onions and will give their any time-based requirements to the nth degree and give you a load of effectively test cases saying, “Okay, so you say you are going to give a refund for one month. But is that from one month in the user's time zone from when they clicked purchase or when it was shipped in the shipping time zone or what? What does one month mean exactly? 

Like a good product manager will be awesome on that. And yeah, the same is true for reliability. It's one thing to say this code must be reliable. Well. Yeah. What does that mean? That doesn't help at all. It's like how much effort do you want me to put in to avoiding what failure modes? If I can see a way that my computer will catch fire, please put a lot of effort into that.

If it's going to turn itself off unexpectedly, that's probably really bad as well. So anything that you are doing that might have that. Think about as many things as you, you can. If it's just gonna put an extra dash on the screen somewhere, somewhere that won't be treated as a minus sign, then yeah don't worry too much.

RYAN DONOVAN: Yeah.

JON SKEET: It's all prioritization, which is where, yeah, like the, when everything's P1 or P0, then nothing is. If you are not differentiating, then it doesn't help. So, yeah. Absolutely. Requirements and requirements that are specific, but you don't wanna be so specific that it doesn't cover a whole class of problems, but equally, you can't be so general saying it must be reliable. That it's meaningless. 

RYAN DONOVAN: Well, that's, that's interesting. What's, what is the middle ground between, you know, specifying every single sort of failure mode and sort of just covering the possibility of failure?

JON SKEET: I mean, it's gonna be very application specific, but I guess, if you are writing files, I wouldn't want to have a requirements document that says– or say I'm reading a file, “If the file doesn't exist, do X. If the directory doesn't exist, do Y.” Okay, I'm done. Well, hang on. What happens if I don't have permission to read the file or I have permission but it fails to read halfway through because maybe it's, it's on a USB drive and someone's pulled out the USB drive halfway through, just saying, “If I fail to read the file, probably I should do the same thing in all cases.”

Maybe check does the file exist, and I don't need to differentiate between directory and file, but if the file doesn't exist and it's been user specified, prompt the user. If the file does exist, but something went wrong while reading it, that's probably a whole different class of, I guess is this an inherent system? There's something badly wrong, or is it, hey, this is probably a user error that I can fix by asking them more questions. Right?

 That broad classification is probably where it's interesting, but I should say that this is all very top of my head and I am not a requirements expert by any means.

I can just hear people sighing, say, “Oh, I'm a professional product manager. I know how to do this.” I apologize. If anything I'm saying is completely boneheaded, then yeah. 

RYAN DONOVAN: Yeah, I mean, I think the ultimate lesson is assume complexity. You know, think through all of your problems 

JON SKEET: and if someone tells you something is complex, believe them the first time. I've had this a few times and date and time is one of those cases where, as I said here, the mantra of, oh, just store everything in UTC, everything will be fine and for a whole class of problems. That is correct. But if someone says, no, I know a case in which it's not going to work, which is a future time in a known location kind of thing, believe them. 

I had a product manager who, when I would explain why our product was quite complex because some things worked on, they had to expire globally at the same instant in time, and some things were 5:00 PM wherever you were physically. But explaining these are different things need to be represented and handled differently, and people need to specify them differently, say, “No, no, no, no. You are making it too complex.” No, I'm not making it complex. It is inherently complex, right? If you think it's simple, you don't understand the problem.

RYAN DONOVAN: (laughs) Yeah. Well this is the time of the show where we shout out somebody who came on to Stack Overflow, shared a little curiosity and dropped a little knowledge. Today we're doing something a little different. We're gonna shout out one of Jon Skeet’s first non-closed questions, “What are the correct version numbers for C#?” Something you've been thinking about for a long time, I assume. 

JON SKEET: The reason for asking that was because people kept on asking questions using either the tag or saying in the question, “I'm using C# 3.5. There's never been such a thing. So I thought, well, if I create the right question for the right answers to be there, then it's fine.

RYAN DONOVAN: Right (laughs). And did they, did it work? 

JON SKEET: Yeah, I believe so. 

RYAN DONOVAN: Nice. 

JON SKEET: I haven't seen– well, I mean, C# 3.5 is a very long time ago now. 

RYAN DONOVAN: Sure.

JON SKEET: But things seem to die down roughly correlated with having created that question, so I think it at least helped. 

RYAN DONOVAN: All right. Well, you can, uh, you can change the world little by little.

JON SKEET: Absolutely. 

RYAN DONOVAN: I am Ryan Donovan. I edit the blog, host the podcast here at Stack Overflow. If you wanna reach out to us with comments, concerns, topics or otherwise, you can email me at podcast@stackoverflow.com and if you wanna reach out to me directly, you can find me on LinkedIn. 

JON SKEET: I'm John Skeet. You can find me on Stack Overflow, ask a question there if it's a dev question. My email address is on my Stack Overflow profile or you can find me on Blue Sky. I do still have an X account, but I hardly ever check it. So if you @ me there, please don't expect a response soon. Go to Blue Sky instead. 

RYAN DONOVAN: We won't put it in the show notes. All right. Thank you everyone, and we'll talk to you next time.

[Outro music]