 Hey, OpenJS world. My name is Linda Nichols and today I'm going to talk about writing great code even in the Cloud. So I'm going to start out by going through some slides and talking about maybe some bad process, some good process, and then having a little hands-on demo at the end. So let's get started. So again, this is me, Linda Nichols. I work for Microsoft. I am a Cloud-Native Global Black Belt, and I like to focus really in serverless and development and really like developer process is something I'm really passionate about. I'm from Virginia and I live in Norfolk, Virginia where I organize a couple developer events. Norfolk.js is our JavaScript user group, and Revolution Comp is our very own conference here in Virginia Beach and I am a co-founder and organizer of both of these. So the first thing that you have to start with, anytime you're talking about code that's in the Cloud, or serverless functions of the service, no matter what Cloud platform you're talking about, you always have to have this what is a serverless slide. I like to acknowledge when I do this, that serverless is completely made up. It's just like a really catchy marketing term, like Cloud. But when we talk about serverless, what do we mean? So serverless really means fully managed services, event-driven architectures, different internal and external triggers that then execute perhaps functions as a service that is part of a greater event-driven architecture. But also serverless tends to be very inexpensive. So it's very cheap, essentially, because you're only paying for what you use. You don't have servers sitting out there forever idle, holding your code that you pay for. If you have thousands of APIs, you're only paying when those APIs are actually executed. Also, serverless is a focus on applications. So it's more about your code making it to the Cloud, that code being executed, and not so much about what's happening behind the scenes, which is why we get to serverless, which is essentially just fewer servers and not really no servers. And it's essentially fewer wasted resources because, like I said, you don't have servers just sitting out there idle. So serverless is for developers. Because we, as developers, don't really want to have to worry about infrastructure in most cases. We really wanna focus on development and our code and making our applications really be as streamlined and as fast as possible. So really also within serverless or just code that's executed within a Cloud platform, you have so many services that are out there at your disposal. And a lot of these services really replace instances where we might have written a lot of code before. JavaScript developers are kind of used to using something like Happy or Express for an HTTP server. I don't tend to use those anymore because I'm using something like API management and Azure, API Gateway and AWS, Apigee, all kinds of various API management platforms and services instead of writing that code. And also there's not a lot of redundant code. It's just naturally microservices or even like nano services because functions as a service tend to be so small. And it's a faster time to production because you're not worrying about that infrastructure. It's so easy to just deploy these functions, have your architecture ready to go. But there are actually servers. So this is a little joke, but apparently in Alaska, they're very concerned whether or not they're servers and serverless. So for the purpose of this talk, I'm going to talk about serverless. I'm gonna talk about programming in the Cloud, so to speak in general. But mainly this is a talk about developers. We as developers, we as JavaScript developers and how our behavior might be the same or different when we're now focused on pushing our code to the Cloud. So we as JavaScript developers, we have a lot of opinions and we love process and best practices. If you know developers in general or especially JavaScript developers, we love to discuss what's our favorite everything and how to make everything faster and look better and be easier to use. So we really, we like to use our favorite editor, our favorite languages, our favorite formatting tools, we want our code to be a certain amount of pretty, we want static code analysis rules and formatting. No one will ever deny that they don't want these things. There'll be arguments about when to execute these tools or which tool to use, but it almost never is anyone saying, yeah, I don't want to do any of this. Unless you're talking about a situation where you're just trying to push code to production quickly. And in those cases, no one's arguing for that, it's just situations that sometimes happen. And so these are like some examples maybe of all the various things that we love and may discuss. And in this perfect world where we're executing everything the way that we want, we're testing the code, we've written the code with all of our perfect tools that we love, testing the code. Oh wait, like we tested the code, but should we have written them before? Do we do TDD? Maybe not, that's another developer discussion. And then we commit the code. So now we commit the code to a revision control system. And maybe that system is local, maybe it's on a server somewhere within your building, maybe it's in the cloud. And then now to get that code through development and testing and production, we've got various branching strategies. Do we squash commits we don't like? Do we not squash them? Do we want to rebase our commit messages? Is it okay to just, looks good to me, here's my code, or do we need to include some sort of issue number for another system, the branch names have to be some sort of specific format. These are all things that developers care about and we focus on. And again, all kinds of choices here, there's nothing that anybody has to know or shouldn't use, it's all just very opinionated and most products are just doing the job for us. You know, we're merging our code then into master, into production. Do we use pre-commit hooks? Do we push to a dev branch and then the dev branch goes to master? Do we have our individual dev branches? We issue a pull request. Once we issue a pull request, then what happens there? Our code analysis, does it happen in our editor? Does it happen in the cloud? You know, we ensure that if we've written all these unit tests, we want them to pass. And then, you know, we request a code review because we're working on a team with other developers and we care about their opinions. And sometimes these are their opinions, you know? And sometimes those reviewers can be tough, but it's good because it makes us better to kind of understand what people within our team and external to our team might think about the code we just wrote. Okay, so it looks good. The code is now merged. And to our CI CD tool. Again, another very opinionated list of tools. And there's all kinds of choices here of different tools that can, you know, run lots of smaller tools like code analysis and tests, et cetera. And, you know, what kind of CI you want to use, where you want it to run, where you want it to be hosted, again, all your choice as long as you are choosing at least one. So now here's the topic of our talk because we're gonna talk about what about code that's written for the cloud? What about serverless code? What about code that's gonna go to a function as a service as opposed to maybe just application code that we're used to writing before where it gets packaged up and maybe containerized or something. And it's, you know, maybe used on-prem or it's used in, you know, maybe some other cloud service, but it's not quite functions as a service. So I'm gonna show a prerecorded demo of kind of what I have seen as far as developers who are new to the cloud pushing their code to production. And so this is our dramatic reenactment here. We've got our programmer, he's in the AWS console. This is AWS Lambda, there's an editor. The editor, you know, does have like a little bit of interesting features here as far as, you know, autocomplete and, you know, preventing bugs. But as you can tell, he made some choices there. He made some changes and then he pushed to production. So that seems a little dramatic. However, I have seen this happen before. That editor is available. It looks like your ID that you're used to and there is a button to deploy there. But it's a little scary, right? Because what if we think back to all we know, we just went through all these tools that we love and we use in processes and linting and, you know, testing and where was all that? No unit tests were run, nothing was linted. It just went to production. And then basically testing then happens in production. So let's kind of zoom in again and look at this code. Well, already we're seeing that there's some kind of bugs in this code. There's, even this editor here is flagging some errors, but our developer is essentially ignoring those and hitting publish because we said it was fast to get code to production using serverless and he's going to do that. Yeah, but it doesn't make sense, right? Like why would you push your code to production when we've talked about how developers have all these opinions? And unfortunately, no matter how fully managed a serverless or cloud service is, it's not fully managed enough to format and debug and test your messy code, garbage in, garbage out. So as developers, we hold these processes so close to our heart and then we're willing to throw them away. And you may say, well, that's not me. I would never do that, but I've seen it a lot because while the cloud is new and it's a little scary and you're given all these tools and it seems like a new way of doing things. And so it's easy to kind of forget that it's still development, that you still want to go through your software development life cycle, that the things we've been doing for years, the things we fight about on the internet, these tools that we disagree with, the reason they exist is because they're important because all of these checks and balances are how we create good software. And we can still capitalize on the fact that serverless or cloud development platforms are fast to production without sort of losing our soul. So I'm gonna talk about now how all of the development practices that we love still apply in this environment that even though it's scary, even though it's weird, even though it's different, it's still the same. So you don't have to sacrifice all that you love. Like maybe some of the services that you love, we will now get rid of because we don't need that code anymore. We don't need those frameworks. But as far as running through testing your code, making sure that it's quality, all of those things are super important. And I just always want to keep stressing that. So here's my very highly opinionated tool set. And anyone could sort of say that any of these tools, they would prefer something else and that's fine. But this is what I'm gonna kind of demonstrate today. So first of all, ESLint. This is very important to me. I love ESLint. I have ESLint in my editor. Sometimes I'll use ESLint as a pre-commit hook. I always have it as some sort of like CI CD process no matter what tool I'm using to run a linter because I've seen code that wasn't linted make it into a code base. And sometimes it's just ugly. Sometimes it's just inconsistent. But lint can also find errors. So if you're not familiar with ESLint, essentially it is a list of rules that you define. And then if you have it, so it is automatic in your editor, then it will tell you as you're typing that you're going against one of the rules. And I really also like ESLint as a team tool because you can create ESLint configurations for your team. If you all have the same highly opinionated opinion or your manager has a certain opinion, then you can define that in the rules. And then you're not always kind of arguing amongst each other whether or not those braces need to be at the end of the line or the next line. And so there's also configurations out there that sort of bigger companies have made like Airbnb or Spotify or even the ESLint recommended that you can import and then you can kind of use their rules and then you can kind of overwrite the ones you don't agree with, like as necessary. Editor config is a file that you can put in your code base that will also enforce style like tabs versus spaces for a code base. So if you have maybe like open source software that a lot of people are contributing to, this is really helpful so that when you're looking at the code later, the spacing isn't really off. Prettier is sort of similar. Prettier just sort of builds upon ESLint and I tend to use this as a pre-commit hook because then it allows me to sort of code the way I'm comfortable coding, but then Prettier runs right before I commit and it formats everything in the way that the code base wants, even if it's different from my personal development style, because that's something you might not want to enforce as a team. You might not, if your developers can code faster using their methodology and then just have it automatically conformed to what you want as let's say a manager or a team lead before it's committed, then that makes things a lot easier. For testing, I like Mocha, I've also used Jest. There's lots of testing tools out there. This is unit testing I'm talking about here more so. For CI, I like GitHub Actions. I also like Azure DevOps. I've used Travis CI quite a bit also in the past and today I'm gonna show GitHub Actions. And for an editor, I really like VS Code and off language, of course, JavaScript, no JS. And for cloud, well, I prefer Azure because I work for Microsoft. But I have a little asterisk there because today I'm going to show in my CI CD process how I would deploy to both Azure and AWS Lambda. Just as sort of proof that this is really kind of a cloud agnostic way of thinking. Even though some of my tools here with GitHub and VS Code seem to be very Microsoft specific, it's actually the idea of using a tool set to ensure that your code is bug free and looks really great and is gonna cause you no issues in production. That's really a very agnostic idea. So now I'm gonna go, switch over to my editor and I'm going to work on this demo. Essentially it's an algorithm. We'll put an asterisk there to determine who is the best Ghostbuster. Perhaps you've noticed that theme throughout this talk. There's my GitHub repo there on no day, not only Zool. And we're gonna go through just a very simple process. I mean, this is not production code by any means, but just demonstrating how if I'm developing services for a serverless system using a function as a service, whether it's Azure Functions or AWS Lambda, what does my development process look like? All right, so now I'm in VS Code. And I wanna talk about just a couple of things now with my workflows. So I have three workflows. One is pull request and then I have two here that are essentially my production workflows. My pull request workflow, the idea for this is that this just runs my build, my unit tests and it does some linting. And really this runs on both of my services. So I have four services overall, two are not implemented yet. I've implemented Spangler and Venkman. And this runs those two services. And essentially what I want to do with this is I wanna say when a user issues a pull request on my main branch, that the linting and the tests have to pass before that pull request can ever be pulled in. And admin can do it if they want to, but at least that barrier is there that these initial checks have to run. Then also for each one of these services, Spangler is Azure Functions, it deploys to Azure Functions after it also runs some additional tests even. And then Venkman deploys to AWS Lambda. If you're not familiar with GitHub Actions, this is sort of the format here, this YAML format. And then at the top here, it will talk about the trigger. So here it's whenever you push anything to the main branch, it deploys. And then I have some checks that people can't push directly to main without first issuing a pull request. All right, now I want to look at my ESLint file. So these are the rules I have. My base configuration is the ESLint recommended. And then I override that a little bit and say like I want my attention to be for spaces. I want my quotes to be single and I always want to have semi-colons and that's very opinionated here. And I also have my editor config file that indicates that I prefer spaces to tabs and automatically trimming the white space. That's really nice too. So let's go into one of my services here. Now it might look like there's some really bad HTML in here but just push the I believe button because this is a very complicated algorithm to determine the best ghostbuster. So you can see here in my editor that if I remove the semi-colon, I immediately get an indicator there. So I know what I have done. So let's say, let's make a couple little changes. So that was in Spangler. Now let's go to Venkman, which is very similar. Now I'm down in my terminal here. I have modified two files. You might notice too that I am on a different branch that's called OpenJSWorld. This is my development branch and it's a branch off of main. Oh, I don't want to send it to main. I want to send it to OpenJSWorld. If I tried to send it to main, it would be very confused that it's on the wrong branch. So that's just a nice little check using git here. So now my code has been pushed. Let's go back to GitHub. So now GitHub, this is my GitHub repo. GitHub has seen that I've now pushed to this branch. So now I'm going to do a pull request. And I'm going to say this message is okay. I would normally leave some better comments. I don't care at the moment. I could set some reviewers on my team and I'm not going to worry about that either, but in then also some labels. But for the sake of time, we're just going to open a pull request. And now we're going to see here that it's running these two checks essentially that is running my lint, my unit test, all of this sort of static code analysis here to make sure that this pull request really makes sense to pull into the code base. While this is running, I can also go here and look at all of my workflows, not just past, I have two jobs. And then I can see what happened inside of each job. So if something fails, I can go in here and look and see what happened with my unit tests. I have some very, very simple unit tests that are meant for passing currently. Okay, so my pull request is now ready to be pulled in. So I'm going to pull it in and it's automatically going to deploy my brand new algorithms for finding the best Ghostbuster. There's a couple of settings that I have here. I have the setting so that it's a, actually a setting on the main branch that allows pull request to not be pulled into main unless they pass those certain CI checks. That's an option within this repo. Also, I automatically delete branches after I pull in a pull request. So it's just a little bit of housekeeping that I prefer. So now we'll go up to our actions and they're both working on deploying. All right, so this one has already kind of gone through the environment. So right now I'm sort of banking everything on Node 14. You can also specify other versions of Node and you can run through all of them. There's similar capabilities in Azure DevOps and Travis CI and Jenkins and other tools. But I like the way the matrix works here where it just runs them all as separate jobs. And here's my Lambda deploy option and then my post checkout. So it looks like that is still running here. Okay, and it looks like this one has now passed also. Little job completed. And you can see here it gives me this deployment address. Okay, so now we can look at our algorithms. So you'll notice this URL matches this URL which has determined that the, I'm gonna refresh because this is old. Okay, great. It received my change and it still believes that the best Ghostbuster is Spangler. Thank you, Giffy, for our GIF. Now this is the Azure Functions service. Now let's go to the AWS Lambda service. I'm going to refresh. So we receive our latest change for OpenJS world and AWS prefers Venkman and says that Venkman is in fact the best Ghostbuster. But like a lot of developer opinions, there's also a lot of opinions about who the best Ghostbuster is. So in conclusion, just a couple of things that I wanna drive home here. No ops, as in not worrying about infrastructure, worrying more about code, doesn't mean no DevOps. That doesn't mean that you don't think about your development process. You don't think about how you move through your stages. It doesn't mean no DevOps, no CI CD tool. All those things still apply. All those things you still care about. Almost everything you cared about before as far as process still exists. Online editors are a lot better than they have been in the past and they're getting better and better, but it's not the same as a true revision control system. Whether that's GitHub that I prefer or SVN or whatever. It's just not the same. And even saving revisions of software in the cloud isn't quite the same as a robust revision control tool. So love your linter. I love my linter. You should always love your linter. Even if you have to run it multiple times at multiple stages, it's really important. It will save you from making bugs. There's a rule for not allowing variables that aren't being used. That has saved me so many times from times where I've just misspelled something. Put your editor to work. Make your editor do the formatting. Make your editor run prettier. Make your editor do the linting. And that really saves you a lot of work and it saves a lot of failures once your code makes it into the cloud. Testing in Prod is not testing. We saw our yellow developer video where our developer wrote some code and then pushed it to production. And then, of course, that code was going to fail and then tested it. That's not actual testing. We need unit tests. We need integration tests. We need load tests. And it's all important. I didn't go through all the testing options here. In fact, in this particular algorithm, the testing is light, but it's to give you the idea. Abstraction is not CI CD. Once you abstract away all of the infrastructure concerns, it's not the same as having a true CI CD system where your code is pushed through many layers. If you're writing code in the cloud, you're not just gonna have necessarily one subscription or resource group or however your services are kind of logically organized within your cloud. You're not just gonna have one that's production. You're going to have development testing production, different layers and different ways to move your code across those platforms. So it can be properly tested. You don't have bugs in production. And like most importantly, don't abandon what's important. If you're doing something, if you're writing code, no matter where you're writing it, if you feel a little dirty, if you feel bad, if it's scary, then think about it. Okay, why did I lose that process? Why did I think it was okay to push directly to production? Why did I think it was okay to not really check through my code? Why did I expect things to magically become better once they went to the cloud? And thank you. Thanks for coming to my talk. And I hope that you will continue to hold what's dear and fight for all the tools that are important to you on the internet. Thanks.