The SemVer Talk 1.0

Opening title So next up, someone who many of you will know of. Ben Buchanan. And in fact, Ben has come onto virtually every web version events over the years. And even prior to that, to events that were called Web Essentials, that a very small number of people in the room might have heard of, or have come to back in 2004, 2005. He exemplifies someone who has been in our industry since he was quite young, and he got more and more involved. He speaks and he writes. He's just started a new course that you check out online, what's the URL for that one?, so if you wanna kinda really get your head around bash, please check that out. But he's gonna talk about something that perhaps we should be doing, and maybe we're not doing, which is how we name things. Basically, everything's validation, and about naming things, right? So, even when you number things, you're really naming things. So, to talk all about how to number things, please welcome, Ben Buchanan. (audience applause) - Ladies and gentlemen, understanding versions will make your life better. I know it's a big claim. Modern web development has become a huge challenge around the way that we have lots and lots of dependencies. We don't just have our own code anymore, we have code from all over place. And we deal with files like this, where we've got a range of dependencies. And there's numbers, and squiggles, and there's all sorts of stuff going on here. And what I found is, even though it's extremely important, a lot of people don't truly understand what's going on. They know roughly and they use this everyday. So, they know enough to get in trouble. But when you actually ask people, "Well, look at that set, what's that version zero mean?" "Oh yeah mate, yeah no, no, I know what that means, yeah." "What about the tildes, what's that gonna do?" "I don't know, is it time for coffee?" Yeah, you find that people don't really, really know. And it's kind of shocking in a way because devs need to know, but what you could find is, a lot of devs could swap semantic versioning over here, which is what I'll talk about today, with Drone-Ver or basically a random number for all they care, they just kinda shove a number in and hope for the best, or see if it breaks and they're really shocked or surprised when things work or don't work, or whatever. So, obviously SemVer is not the only version scheme out there. Most of them are out there that are sequential, or date-based, which is just sequential, or they're trying to describe degrees of change of compatibility. But of this smorgasbord of options we've got right here, random crap still seems to be the most popular. At least, that's what most people seem to be using. As a quick aside, I'm sure there are a bunch of people in this room going, "I already know this." And that's great, that's really fantastic. But please please please, don't assume that everyone you work with knows this. Because when you actually ask them, you'll find out they don't and it's a chance to then unravel the mysteries and help them out. 'Cause if you don't actually follow something which is expressive, if your version numbers are essentially random, or it's internally consistent, but no one else understands your system, what you've done is given everyone, "Read my blogver." ReadMyBlogVer, that's the one where the version means absolutely nothing, and I have to go and read your blog. Thanks because ReadMyBlogVer doesn't scale. Now, this slide deck uses reveal.js, and it's a fantastic product. I'm really enjoying using it. It's not an unusual product either, but it does have, when you go through the full tree, 484 packages. Now, let's assume that I'm an absolute machine, I don't need to stop, I've got a lot of coffee, I've got nothing else to do, and it only takes me two minutes to read each blog. That's 16 hours. ReadMyBlogVer does not scale. And the other thing is, you have to accept in the end, is that people don't read your blog, with respect to Veen - your API is a tiny piece of a much larger experience. And your blog, look, your blog is absolutely lovely, but I don't have time. And this is where Semantic Versioning comes in, where it's trying to communicate something in a very, very short string, it's actually a string in the end, a very, very short amount of information to give you a lot of information based on that. It's a code, it's a compression. And it's all about a public API. And whether we think of it this way or not, you can always think about the first version you want to support as your public API. And it is the most popular version control system. I did a quick survey on hash, the 91% of people who used it. And it is actually preferred by most stacks. And let's just go with another unscientific survey for a second, so put your hand up, and I'll get you to keep it up for a second. Put your hand up if you use Node.js. Excellent! Keep your hands up for a second. Who else is using something like say, Python, Java, no one wants to admit it? Alright, most of you did put your hand up, which is cool. Whether you care, know, like it, or other, you are using semantic versioning because the package management is in there doing these things for you. Semantic, okay, we all know the word semantic, relating to meaning. So, semantic versioning is about the meaning of versions. And it is a degree-of-compatibility scheme. It describes changes to itself. That's the compatibility it's concerned with. It's not compatible with everything else in the world, or magically reading your mind. It is anchored to version 1.0.0, that is the first one that you actually put out there and say I can support this. Version zero is great. You can break everything all the time. This is also why it was terrible, that Node sat on version zero, for years and years, as we were all putting our livelihoods in its way. Version zero is something you shouldn't stay on forever. It's like the old permanent beta. We all thought that was stupid when people did that. And then when you put that out there, you say, "Okay, everyone use this." That's 1.0, and then when you break it, pop the champagne, that's version two, that's your first breaking change. But it's not based on the size, or the number, or the count of changes, the general vibe of the thing. And it's not trying to guess if your code works. And it's not trying to estimate how much work is gonna be required for you to upgrade. It is not trying to do any of these things. Some people wish it did, and this leads to a lot of extremely passionate and extremely wrong rants on the internet about semantic versioning. Because it's not actually trying to do any of that. It's just trying to say, "I've changed, and I'm gonna alert you to that." This is the core of SemVer. So you've got three numbers, there are three numbers. The first one talks about your major version. The second one talks about your minor version. And the third one talks about the patch. This is all about this one release relative to the previous versions. Keep that in mind, if you don't get this, the rest is not gonna make much sense. One major, two minor, three patch. I've got a nice way of thinking about it later on probably. Keep you in suspense. You can do pure release versions because we often do that. We wanna put out an alpha or a beta or something, we need to deploy it to get into our package management system. That's cool, SemVer's got your back. You just put in a dash and then nothing that extreme. The best format that's read by the most plug-ins out there is to do a string and a dot and a number. Don't ever assume you're only doing one beta. Frankly assume you're gonna do a 100. It's much easier to assume that you're gonna break something and have to release another one, to actually put it out. You see this all the time. People put out RC, this is a release candidate. And then they have to put out RC2. Never assume. Builds can be added with a plus. It's actually referred to as build meta data because it's not really intended to go out to the public. If you're using builds, you cancel the releases and can still go through your package management. Something to understand about precedence is that the build versions are entirely ignored. And anything which is a modified version from that trio is actually of lower precedence. So, if you see 1.2.3, and 1.2.3-beta, you can just automatically assume that 1.2.3-beta is the earlier version and you should go there. Very simple, but it does trip people up. The other thing that trips people up all the time is to think of this as one number instead of three. 'Cause each number can increment as far as it needs to go. It goes sequentially but forever. So when you hit 1.9, as I once thought, I thought, "Oh 1.9, crap, okay, next one's going to be 2." No, no, no, no, no. 1.9 can go to 2.0, it can, but it can also go to 1.10 and it can also go to 1.9.1. All of these are valid depending on what your release has done. Because it's really talking about whether they are breaking changes, new features, or bug fixes, and that determines the number. There's no guessing, there's no opinion because this is something you know. If something used to not work and does now, that's fixed. If it didn't exist at all, it's a new feature. And if you break everything, that's a breaking change. Because breaking change just means that whatever was there, no longer works. If you were calling it the way you used to, it no longer works, breaking change. But let's go through an example because I used to hear that all the time, breaking change, done, good, no. So, you're coffee-obsessed in your office and you build an app to order your coffee because you must save 0.3 of a second a day by spending a week writing this. And because GitHub's tiles don't go green on their own, you decide you're gonna open-source this thing 'cause maybe someone will use it, that's great. So, you put out this thing, Coffee Gimme Large, and it brings you back a small black, hang on. Great, 1.0 didn't work, actually it's a bit wrong. Everyone's just getting small coffees and the people who need more caffeine are very upset. So, you do another release with Coffee Gimme Large, actually gives you a large coffee, fantastic. That's a patch, 1.0.1, nice and easy. But then the latte drinkers are on your case and so you add in another argument saying, "alright ok cool, we'll do lattes now." Release a new version, didn't exist before, it's a minor, 1.1. Notice that the bug fix doesn't come through. The lower digits are reset. When you go to the next one up, everything else goes down to zero, it's nice and simple. But then you release that there are a lot of coffee types out there and you're gonna have to order orange mocha frappuccinos, and all that kind of stuff. And you saw that this argument system is gonna be ugly, had a brainstorm, I'm a genius! We're gonna take an object, but you also mean that all those old arguments systems, they don't work anymore. The argument version that used to work, no longer works. You have to use objects, otherwise, if you don't use an object, no coffee, no caffeine, sadness, pain, headaches. That's a breaking change, 2.0. So basically, SemVer is compressing information. And the reason it does that is we make decisions every single day about risk. This is actually literally copy and paste of something that happened to me while I was doing this presentation. My command lines said, "Hey you wanna do this upgrade?" I'm like, "Sure, that's a bug fix release, "that would be great." Now, the story doesn't end where everything broke. That actually followed SemVer, it was good. Nothing happened, which is great because I don't have time to go and read the blog. But I do know I can look at that and say, "How risky is this upgrade? "How big is the chance that something bad is going to happen here? "Am I going to have a good evening from here on out or am I going to be rolling things back?" 'Cause a major upgrade, you know that that's dangerous. You need to go and do some research for that. But if you're just getting new features, well look maybe, you don't have time to go and read about it. But you do know, because of the scheme that minor releases can also include bug fixes. You can actually go up this scale, right? So, maybe this is a bug fix, I'll take it anyway. There's no risk, it's fine, but maybe I'll go and look and see if I got some new toys to play with. And if it's just a bug fix, you're not gonna worry about that, you're just gonna do it. 'Cause you really need to know, is this something where things are gonna break? Do I need to do work? Do I need to go and actually find out how this thing works now? Compared with the old one. 'Cause in the end, having said I don't have time, what time I do have, I'm gonna read the things that I really to read. And if you are doing a major version release, you probably wanna do an upgrade guide saying, "Hey, you're on version one, you're going to version two, these are the things that are gonna really be painful, watch out for these, this is the upgrade guide. Do this, your users will love you. The rest of the time, you're probably gonna go, "I'm probably not gonna read that." Now, it's worth noting that, it's not just code. You can actually use SemVer for anything. Design and copy you can all have the notion of being broken and being fixed. And I do know that this is familiar. I was gonna ask, does this look familiar? I know this looks familiar, we've all had this. And we decided to get really clever and we went from network drives to the Cloud, so now we've put this in Dropbox 'cause we've put our mess in the Cloud. Wouldn't it be really, really nice if this was happening? Because if you completely re-brand from say, red to blue, anyone that designs something complementary to red, that doesn't work now, it doesn't fit with blue, that's a breaking change, your design API has changed. So, this is perfectly valid. I don't know how many people get their designers to follow this, but I've got my chief design officer putting stuff in Git, on the command line, so that's the challenge. So, we've solved everything, excellent! Pub!, alright, you knew that was too good. It couldn't possibly be that good. A lot of people don't follow SemVer and you will have seen these breaches occurring. If you're really unlucky, you've had them break things in your day. And you see stuff like a breaking change coming out in a minor version or a patch version. New features chucked into a patch. Is there an upgrade guide where it's like, "Here's our bug fix version and these are the new features." Oh I'm very proud, that's good! But, oh no, people aren't reading your blog to know that they're there. Skipping versions probably not the worst thing you can do, although it does break completionists' day. Modifying a deployed app, now this is our friend LeftPad. Because deletion is a very severe form of modification, but modification, nonetheless. It's taking something that used to be there and changing what it does now, that's really sneaky. Permanent zero, like I already said. So, what can you do? Protect yourself, that's what you can do. If you know that there's a dependency in your stack and it doesn't follow semantic versioning, and some people are very proud of not following semantic versioning, lock 'em down. Do not let those things auto-upgrade, or even better, don't use them at all. I read one fantastic rant about how SemVer was silly and I never used that library again. There's a better one, it did what it needed, they followed SemVer. And if you are using NPM, avoid that confusing tildes, and carets, and stars. There's a better way and use shrink wrap. Auto-upgrade is probably the biggest cause of complaint about this whole situation because people aren't totally sure how it works, but the default does actually say when you add a dependency in NPM, it does have one of these in place. I think it's, I can't remember, it's the caret, I always take it out, so it doesn't matter. But star is basically what you call the YOLO upgrade plan. That is, whenever something comes out, it just automatically puts it in your project, that's great, that's gonna be really fun. I'm not doing that. If you put the caret, it's gonna take any minor. You should get new things, you should get bug fixes. Everything's fine, but you're not gonna get any breaking changes. And then the tilde is just the patches. Now, it's great if you've got this slide in front of you, but if you're just looking at one of these, try and to remember when you're pre-coffee because your API is broken for your coffee machine, and you're looking at the tilde and you're like, which one was that, I can't remember which one that was. There is another syntax which is oddly not used very much, which is the x syntax and if you just put version x, again still yolo! But 1.X, that's much easier to understand. I understand which part of the version I'm being loose with because I put the x right there. Everyone can read this, no one has to look anything up, so just use that. Shrink wrap, probably could do a whole presentation on this. The idea of shrink wrap is that you can get a resolved dependency tree. Everything all the way down, and your dependencies have dependencies and so on and infinitum. And the shrink wrap feature in MPM just generates a JSON file that gives you an exact record of what works. So, if you ever need to run up that tag, like in a year's time for some reason, you can actually work out what works and not have to sit there and try get these ranges of things working again. So, include that when you tag your project. So, let's take this by the horns. Why don't people use SemVer? And there's lots of reasons. But most of them really, I could be harsh and say boil it down to ego. But really what they boil down to is that it's either too hard to make changes, or because lots of people don't do it neither should I. 'Cause that's kind of how everything works, right? Too hard to make changes - you really need to just put the user first. There are ways to make changes that are nice and easy that don't really cause you any great trouble and they will give your users a lot of benefit. And the other simpler thing you can do is plan your API. Don't just make it up as you go along. Like, if this is actually your business API, you should be able to do that and make use of deprecation. So, keeping things backward compatible as much as possible and using deprecation, it really is all about any pain that you can take on yourself, so that your user doesn't have to feel it. That's the way to go, put your ego to the side. That's what I really mean by that. It's basically saying that if I could do a little bit more work so a hundred other people do less work, I will do that little bit of extra work. I've put this API out in the first place, right? And what does that mean? So, let's think back to the coffee app, sorry, API. I don't know why I'm calling it an app. Let's say it's a web service, possibly an installed one. When we decided to make that new format, that's great. That's actually a much better format. But we didn't have to break the old one right away. We could have just kept accepting arguments and shim them through. You don't even have to maintain the two separate code bases, you can just maintain a piece that passes it through and it will keep going. It's really not very much maintenance. Then you didn't need to do a 2.0, 'cause you could just make that 1.2 and you can mark things as deprecated and say, "Hey guys, stop using this." Throw warnings in your debugging tools or anything like that. Put it in the docs, give some people some time. It also means that they can choose, rather than having to do it today because they're trying to upgrade they can say, "I need to plan for this, I'll put in the next sprint." So, you're not messing everyone's stuff up. Or you can just design around it, you had Coffee Gimme, maybe the new one's gonna be called Coffee Give Me. Do users really care? Not really, 'cause they're not using either one, not using the new one yet either way. They have to make a change either way. So, you can give them a new function name. That's actually much easier to find than a code base too 'cause you just have to search for Gimme and then you can just change all the instances. Deprecation, I know a lot of people out there don't know how to use this because you see it marked up sometimes in documentations and we've depreciated it. Close, but not quite. Deprecation is really just a way of saying, "Look, this thing, it's not broken yet, "but it's gonna be broken, it's gonna go, "it's gonna be gone, stop using it." jQuery have gotten better at this over the years. And it gives you freedom to release something cool, earlier. And it just gives your users time to update and plan around it. A really common pattern, if you can wear the time is to actually let things deprecate for a longer time. The most generous I would say is, deprecate a feature on 1.2... take it out of your docs, that 2.0, so it's still there quietly feeding along if anyone's calling it, and actually kill it in three. That's if it's not causing you much harm. Otherwise, the convention is you can remove it at the next major version because it is a breaking change. But if you wanna be really nice, give people longer. Most people are pretty happy if you give them longer to get something done. And the other thing you can do is, is pre-releases. The scheme allows this, there's a reason for it. So, if we had gone out there and said, "Okay, we're gonna do our first version beta one." That's the one that got everything wrong and sent you small coffees for large. You fixed that, that's okay. No one cares, this is all part of version zero, really. You can tag it according to the version you're gonna land in. That's one of the big things that people get confused about that beta one of V one, you don't release that under 0.90. A certain fruity software company did that with a browser recently, I was very upset. But if you went through this pre-release phase, by the time you hit one zero, your very first version could have had the right format. You'd never even have had the breaking change. It's a much better way to go. And the other thing is, this is intentionally too small to see this, there's a lot of coffee out there, a lot of types of coffee, a lot of ways to make it. If you're setting out to make an API around coffee, you should know that. You should not design something so brittle, so narrowly focused that it can't handle the situation. And if it's your own business domain, well, you should be the expert. So plan ahead, think about what you're probably going to add to your API. And you don't have to build it today, but you need to build something that's not going to break when you do. But if we bump the version numbers, people think it's unstable, oh dear, this is just-- Okay, I have to look at my notes for this one. Haup-versions-nummer-hohung-sangst. That's probably terribly, terribly wrong. Fear of increasing the major version number. Free yourself of this, do not be afraid of versions. They are free, you are going to release the same number of packages regardless. So, just put the right numbers on them. Don't sit there worrying what people think of you. We've got so many things to worry about. Worrying about what people think of your version number? come on. Do be judicious, in a short period of time, 50 major releases is probably a bit weird. Over time, that's perfectly fine. Some of the browsers are finding this fast release channels. 50 minors, that's great. You're giving me new toys all the time, I love you. That's awesome, you're never breaking my stuff. 50 bug fix releases, do you need a chat, are you okay? (audience laughing) Not followed, why bother? Look, lack of compliance does not invalidate a standard. It doesn't make it a bad idea or make the alternatives a better idea. It's just something that is a phase in standards. So, sometimes you need to actually be an advocate. You need to get out there and push an idea. You can't just sit there and say, "Oh it's too hard." Because this is not just a job. I know because you're here, that you care a bit more than the average person that's doing this job. This is a craft. And if we're gonna have titles, like "engineer", we need to earn that. We need to have a little of engineering rigor, we need to follow some of these rules. Software has been around for a really long time, like decades. They did learn some stuff, we could maybe learn some. That's cool, but this is part of professionalism. And the call to professionalism in web development is definitely not new. This is a term that I've actually had in my head since 2005 and Molly Holzschlag talked about this, and she quoted various industry experts, and it was about at the time, moving from tables and font tags to CSS. And people were pointing out that if you don't actually move to standards-based development, you shouldn't be calling yourself a web professional. It's just that blunt. Professionalism is all about putting out stable APIs because the web is where business is done now. It's not a toy, it's not something we do in our spare time. Everyone is running a business through this. They should be able to expect from us a stable API, something predictable, something of high quality. This is what we should be doing if we are professionals. And obviously semantic versioning is just a very, very small part. It's not the whole, it's not gonna give you the professional status tomorrow. But we should use it for our own code. We should demand it from the code that we use. So, remember this cheat sheet, I'll leave you this one. You made your version, one, you broke it, two, you improved it, three, you fixed it. Just remember that, broken, improved, fixed. That's pretty much it. has the full details, do have a read. It is a little dry, but it is worth reading up. Thank you very much. (audience applause) - Thank you so much Ben! Right, any questions for Ben while we get Hadi set up? So, you all have had a quiet-- So, Ben Yoav had a question-- I don't think, is Yoav here at the moment? Yeah, I'll ask it though, it's like up in Sydney, we're moving up to a model of evergreen updates for various things, and I was talking with Yoav, specifically around this particular technology now, coming out of the W3, though I can't remember exactly. The problem with Picturefill was that people aren't familiar with Picturefill, what was polyfill for the picture element, that Responsive Images Community Group had. And it was referencing in JavaScripts to demonstrate this would work and people wanted it. And so you browse and people should implement it. Basically, they supported that and they had multiple versions, but actually what happened was, it wasn't perfect. And so, when the browser starts supporting Pictr natively, you had actually very large websites dependent on Pictr, this Picturefill and versions of it. And so, the thinking was, "Okay we're going to do something like this again." Maybe what we do is have something evergreen and require people to link to the evergreen version without any version numbering at all. I'm very long-winded. But I guess I'm wondering whether are we moving, in what's seen in browsers as well, to model with things that are evergreen. Does versioning make as much sense in that world? - I think it does, yeah my man Tommy! We've known each other 20 years, but that's incredible. ... I think it does more than ever. If you're going to release more often, I think you need to be expressing what's going on in those releases. As I was saying before, you can increment these numbers as far as you need to go and it's still a set of rules that applies, regardless. But if you're breaking things, if things that work before are gonna break now, you should be incrementing the number. I think it is difficult because browsers are such huge applications, so it could be that maybe modules of browsers need the versions, just to give people a bit of a chance. 'Cause otherwise, you're recreating read my blogver. There are so many dependencies inside that browser. But the principle is the same. If you break the API, if you break that contract, you should still increment the number. We're not gonna run out of numbers, at least not in any practical sense. - Well I guess we could have 64-bit numbers for version. - I am thinking about a presentation last year about how we could actually run out of numbers, but anyway. - Well we ran out of IPv4. Alright once again, thanks Ben Buchanan for that fantastic presentation, cheers Ben.