Sessions is temporarily moving to YouTube, check out all our new videos here.

Building Consumable JavaScript APIs

Patrick Kunka speaking at Front-End London in May, 2017
729Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

JavaScript APIs are the interfaces with which we interact with our day-to-day front-end tools. What makes a good API and what can we learn from the APIs of today's popular libraries and frameworks? This talk will cover a variety of techniques we can use to create robust and predictable runtime code which is both easy to work with and easy to debug.


Transcript


- A good API is really critical to the front-end developer experience. So, a good API can expedite your workflow, it can promote clean code in terms of your integration. And if it's great, it can actually make working with that tool really fun and make you kind of wanna come back to that tool project after project. So you probably hear people saying things like, "Oh yeah, I really love that library. "It's got a really nice API." So maybe we don't realise it, but we're actually all kinda thinking about this stuff. So bad APIs, on the other hands, at least for me, usually mean one thing, which is a quick visit to the command line for one of these. Just get that off my machine ASAP. Then you go off and look for something better, right? But I wanna talk about good APIs today. So, over the past 10 years or so, I've kind of used a lot of JavaScript tools. The really great ones that stood out to me, they all kind of have certain traits in common when we think about their APIs. So I'm gonna go through a few of those. So, first of all, we've got flexible and robust. So, a good API considers all the many different ways that developers might interact with it, and it's flexible enough to accept kind of different kinds of inputs, and robust enough to do it without breaking. Helpful. So, good APIs should anticipate common mistakes that developers might make. And instead of just breaking, actually, provide something helpful, some actual human readable feedback to the developer. Consistent and well-named. Good APIs establish patterns and implement those patterns across the software, across all the entry points. Configurable. So, good API is highly configurable and that allows us for high reuse, so you can start using the same tool in lots of different situations and scenarios, because you can customise it to your need. And finally, established standards. So, good APIs build on top of best practises and well-known patterns. They don't expect their users to learn something really obscure or some proprietary syntax that you'll never gonna use again. And all these things kind of add together to make a great developer experience when we're working with JavaScript tools. You might be thinking, "So, I don't really have any intention of "ever writing an open source tool, "or I'm never gonna put something out there "and give it to the community and see how people use it." But I really think these traits are things that we can apply to all of our code. So, probably a lot of us work as part of a team. Maybe you've been tasked to build some kind of service or utility library or something like that, that other people in your team are gonna have to integrate with and use on their projects. So, it's really important to actually think about the experience of those people that are integrating with it, and make it really nice for them to use, and re-scalable, and something that's gonna have a long life time in your company. And even if you don't work in a team, even if you're just a freelancer and you work on your own, you probably have sort of helper functions and things that you've written on projects, and you come back to it six months later, and you can dig it out and use it again. So, even though in that scenario, just having those clean entry points, well-named stuff, is really gonna make your own life easier. Actually, Sam was talking empathy in his first talk. I think we talk about empathy a lot when we talk about UX, UI design. I don't know if we talked about it a lot in terms of software design. But when we're designing APIs, that's exactly the kind of word that we should have in our heads is we need to be empathising with the developers and engineers that are gonna be using these tools and integrating them. Just try and get inside their heads and imagine what it's gonna be like, not knowing what this thing, having to learn it and pick up. I think that would really help. I'm gonna get into some kind of examples now. Some sort of tips and things that I've picked up over the past few years of building a lot of tools that either I've sort of open sourced or things that are used by other team members in company, and things that I found are really helpful and sort of hitting these points and just improving the experience. So for all the example I'm gonna show now, I'm gonna use a date picker as a sort of generic example of some sort of JavaScript tool that we might integrate. So, just to give you a quick visual reference, I've got a little example here. So you can imagine you've got some kind of text input in your application, and the user clicks on it, and they got a little calender, and they can sort of pick a date, and then you've got a value in your input. So that's just... I'm not really gonna get into the details of how we build something like that, but it's just a kind of great model for kind of hitting all these points that I want talk about. But it's an example of something we might call a UI widget, so sort of little pieces of JavaScript functionality that we use to kind of progressively enhance our application. You sort of instantiate that date picker, you pass in maybe a reference to that, DOM element the input, and you've got kind of a self-contained instance of the date picker. Maybe you have several date pickers going on in your website or your web app, and they all kind of self-contained, and you can configure them different and interact with them independently of each other. So, how do we go about implementing that kind of pattern? Well, I guess as Sarah was talking about earlier, we've got this kind of object-oriented approach that is kind of perfect for that kind of thing where we need self-contained stateful instances of some code. So the typical way to do that is sort of class instantiation. So we've got a date picker class that represents and sort holds all our functionality, and we're gonna create an instance of it with the new keyword. Also, people call that kind of newing up the class, instantiating it, and we're passing through a reference to a DOM element, in this case, probably a text input. And we get back a reference to this newly instantiated object, and we can save that as a variable and kind come back to it later and perform sort of other API methods on it and stuff. But this is kind of like, essentially the primary entry pint of our JavaScript API. This is the thing you have to do before anything else. And that's great. That's definitely the best way to implement this kind of thing. But if we look at some of the APIs of sort of the tools we all know and love, you don't really see this kind of naked class instantiation syntax very often. So, here's a few example. First of all we've got good old jQuery. So, in this case, a similar kind of thing. I'm passing in a reference to an element, in this case, using a selective string. I'm building a jQuery object, and this goes like a little date picker plug on it, and I get back a reference to that jQuery object, and then I can call more methods on it later on. Next up is some reacts, so some JSX, very nice and clean, and then underneath I've kind of what that desugars to, so you've got this create component function. You're passing in a reference to your component class. It instantiates it and gives you back a reference to that instance to be rendered or whatever. And then some other examples. They're not really related to UI, but just to show how JavaScript API is much more than just UI. So here's one from Handlebars. This is a nice little kind of static method that you can use to create discrete instances of it. And then for people that maybe have experience in doing server-side JavaScript, you've probably worked with Express. This is a super clean API. You just import the Express function in your module, and just call it, and you get an instance, a self-contained instance of an Express app. So these are actually all doing the same thing. They're all basically creating an instance of something and return it back to us, so basically doing the same thing as in the previous example, but it's kind of very nicely abstracted now. So these are actually all example of what we might call factory functions. So that's kind of a term that, it does have some very specific meanings in certain circles. But in this talk, I'm just using very broadly to describe a function that you call, and it creates something, and it gives it back to you. So, not only is that syntax a lot cleaner, a lot more robust, there's less room for error. For example, if the developer left out the new keyword, and sort of maybe doesn't really have a good grasp on object-oriented kind of patters, there's very little than can go wrong when you're using these kind APIs. I can think of loads of other tools that kind of have similar entry points as these ones. So let's look at our date picker again, and sort of see if we can refactor it. So now we've got a factory function, instead of class instantiation. Much more simple again, much robust. Again, we get back the reference to the date picker, and we're passing in our input element as before, and then just kind of a very, very simplified way of how you would implement that. So, I basically just wrap the class instantiation in a factory function, and just kind of hidden that away from our API consumer so they don't really need to worry about that. And not only is this, as I said, a lot cleaner, a lot more robust, there's actually numerous other benefits that using this kind of factory function entry point is gonna give us, in addition to just a cleaner syntax, and here are a few of them. So, I'll go through these. So first of all, caching. This is actually a really great one when you are dealing with UI widgets and stuff like this. If you can imagine, we don't really every want our user to be able to instantiate multiple date pickers on the same input. You can imagine that's sort of something you might do by mistake if you ran your factory function in a loop or something. Suddenly, the user clicks on it and six date pickers open, overlapped over one another. It's just a nightmare. With factory functions, there's things we can do to prevent that. So when you're using just direct class instantiation, the only thing you're ever gonna get back is a new instance of that class. That's just what the syntax is doing. That's what it's designed to do. But if we abstract that with a factory function, we can kinda implement lots of clever things inside it to kind of suit our needs. So, in this case, we can implement a cache inside our factory function. So when somebody calls it, we can look through the cache and say, "Is there a date picker instance already in the cache "that was instantiated on this input element? And if there is, we're like, "Oh, the user already instantiated a date picker here." So we return them that instance instead. And if there isn't anything in the cache, then we create a new instance, add it to the cache, and then finally return it to the user. So the user really doesn't know anything has happened from the consumer point of view. But internally, we've done some sort of optimizations and hopefully prevented some misunderstanding of the API or kind of common errors like that. And that kind of leads onto the second point here which is dynamic return type. So again, the idea that with the factory function, we're not limited to just returning one thing. We can return different things in different situations. So imagine if you have, on your page, maybe six date inputs, and you wanna just kind of create all your date pickers in one go, in one line of code or something. So instead of actually calling the factory function six times, we can actually query the DOM for all six input elements and just pass them into the factory function. So then you could say inside your factory function "Well, if there was one input that was passed in, "then I'm going to new up one date picker and return that." But if there's an array of input, what you might call a DOM collect, passed in, then we're gonna new up as many inputs, as many date pickers as we need, and return back an array of date pickers. So you can kind of start to see the flexibility afforded by factory functions. But it's worth noting that when you are building these kind of APIs, you probably don't want your factory function to be that unpredictable in terms of returning different things and different scenarios. So it's great to be flexible with what the user is putting into the function, but it's probably better to be a little bit more predictable in terms of what's coming out. So, I'm actually gonna link to some gists after this talk where I've kind of taken that example and sort of refactored it into separated factory functions. But I won't kind of go into that now. And then finally, asynchronicity. So this one is actually really... There's a great example to illustrate this. So this is the XHR API from the good people that brought us IE7. I don't know if every of you have used it hands-on, but there's a good reason why it's always abstracted from us, with things like jQuery AJAX. It's easy to laugh at it. This is an API that kind of also changed the history of the web in a way. This is AJAX and Web 2.0 as people used to call. But looking at it now, it's very hands-on, it's very low-level, so you've got to new up an instance of your XML HTTP request. And I like that they used upper case for XML, but then mix case HTTP. I don't know what's going on there. So you new it up, you open the request, you have to specify what method you want. You have to tell it that you want it to be asynchronous, You have to attach your own handler function, and then you finally send the request. And then when your handle function gets called, you kind of interrogate the request and see if there's something inside. So, it's very hands-on. And I'm sure we've all heard about Fetch, right? Here's Fetch. It's kind of like the new kid on the block. It's gonna replace XHR, and it's basically doing exactly the same thing as the top example, but in one line. People have used it. Probably now there's a little bit more in terms of reading out streams of JSON and stuff but, essentially, those two things are doing the same thing. So this is actually a really cool example, because it's sort of like an asynchronous factory function. Each time you call Fetch, you are newing up a new instance of request and a response internally, and you get that back that response eventually. It's just that it's returning a promise, instead of the response, and that promise will resolve that response back to you. I really like that example, because you can just so clearly see the benefits of just kinda wrapping all of that stuff. And the other aspect I've talked about, looking that XHR example, is you have to kind of specify that you want it to be a get request. With Fetch, it's kind of they've chosen these very sensible default values to just mean that the most number of users have to specify the least amount of configuration. So it kinda makes certain assumptions about the way that people are most likely to interact with it, and that's why you end up with this extremely clean, kind of calling syntax. So that's instantiation. The next part of any API is kind of configuration. Imagine we've built a date picker, and we've got people on our team that are using it. And then two weeks later somebody says, "You know what, I need the ability that "someone selects a date on a calender, "and I don't want that calender to just close. "I want it to stay open for whatever reason." And you're like, "Okay, that's great. "We can just pass a Boolean into the factory function, "and you can use that "to kinda toggle on and off that behaviour." And that's cool and it works. And then maybe two weeks later, somebody else says to you, "Is it possible if we can make the animation "a little bit faster when the date picker opens." And you're like, "Sure. "Let's just pass through a number, "and we can use that to dictate "the number of milliseconds that we want "the animation to last for." And before you know it, you've kind of come from your nice clean factory function into something like this. And I'm sure we've all got code that looks a bit like this in our own projects, but this is kind of a hallmark of an API that sort of just organically evolved over time, and just had stuff hacked onto it. And there's, obviously, so many problems with it. Firstly, it's really not clear. If somebody comes on and looks at this integration, they're not familiar with the software, what that's doing. Who knows what that false is referring to and what that 300 is referring to? It's also very hard to deal with kind of optional configuration options. So what happens if I just wanna specify the animation duration, but I don't care about that first Boolean. Do we know if it's gonna be flexible enough to kind of intelligently pass out our parameters. Who knows? But a common way to refactor that in something better is something like this. Basically, passing out what we call a configuration object. So we split up the sort of required parts of our API from the optional parts, and we've got two parameters now, And the second one is this completely optional object that we could pass in with as many or as few configuration options as we like, and each one of those options will overwrite a default value internally. So going back to kind of Fetch again, we're gonna ake some assumptions internally about the most common sort of setup that most of our users are gonna need. So again, the most amount of people require the least configuration, and then you just add in kind of property configuration options as needed, and set it up the way you need it to work. So how do we implement something like this? Well, there's many different approaches. A lot of the stuff I'm gonna sort of show is sort of based on my personal experience and ways that I like to write code, but this is one way that I think is really great. So let's just define a class to hold a configuration. And this sort of becomes, in a way, like a schema, and it's nice reference point in our code. We can say, "This is the configuration class "and these are all the default options." and you can see we've, again, sort of carefully chosen what the default values for each of these properties should be. And you'd sort of take care to make sure that you're very careful about your typing again. So closeOnSelect, that's always gonna be a Boolean. AnimationDuration is always a number, and animationEasing, that's a new one, that's always gonna be a string. So as soon as the user overwrites that value with that sort of consumer-provided value, you can sort of instantly validate that. And so is there still a Boolean? If not, then let's throw a type error, and let them know that they've done something wrong. And we also got this object.seal call at the bottom there. I'm gonna come back to that in a second. But then now moving back to the date picker implementation itself. So we've got another class here that we've sort of seen externally in previous examples, but now we're looking at the actually implementation. So inside of date picker class, we've got a property called config, and we're gonna initialise it with an instance of the config class. So every time you create a new date picker, you're gonna create a new instance, a new discreet instance of that configuration class that you can kind of override as needed, from instance to instance. And then underneath that, we've got this object design call. So what we're doing is we're taking the user-provided config object. You might see we've got an ES6 default value there, in case the user passes nothing. So that just makes this code a lot easier to reason with. We're always gonna merge in something. So object.assign is just a way of taking the values of one object and merging them onto the top of another object. So we're taking our user-provide config and we're merging it on the top of this new instance of the config class, and that's just a very easy way to sort of implement that kind of overriding defaults pattern. And then at the bottom, we've got our factory function again in which we're actually exporting. So going back to the object.seal. So this is actually something from ES5 JavaScript. We've had it since IE9 in other words. It is really quite an underused piece of functionality. And something I really like to add, it makes for really robust runtime code. And what it essentially does is it locks down an object. So we're saying, we're saying, basically, once you've created this instance of the config class, you cannot add any more properties to this class. So you're locking it down. You're not making it unmutable. You can still change the values of the properties, but you cannot add any more properties. So you can imagine how that sort of works when you're taking user provide input and merging it over the top. So let's imagine that a user actually misspelt one of our properties or they use dash case instead of camel case, or they added a plural, or they copied and pasted some configuration from a previous version of the API docks and something. We can instantly sort of catch any of those errors with object.seal. As soon as the user tries to add a property that isn't defined, you're gonna get a type error. So I'm gonna just go into the code editor for a second, and so you can see how that works. So here I've got another example of a config class just with some code of imaginary options and I've sealed the instance. And then next up, I've got a little experiment here which is I'm gonna create an instance of the config and I've got this myOptions object literal with just one option in it. So I'm gonna overwrite the value of option1, which is false, with true, and we're gonna do that by using objects assigned to merge the values into it. So let's run that and see what happens. Just give me a second. So, I ran the code, everything worked fine. We got to that little console over at the bottom there. So now I'm gonna mistype this option. I'm gonna say options1 instead of option1, and let's run it again and see what happens. So we've got some stack trace here, so something has gone wrong. So I scroll up. We can see we got a type error, "Can't add property options1, object is not extensible." So, that's actually really great. We've just kind of achieved all this super easy validation just with one line code of code using object seal. And what that means in the context of an API like this is that if we ever to just let the user just add erroneous configuration options without doing anything about it, what they end up with is kinda fiddling around with their code and it's not really behaving as expected, and what to do then? Where do you start debugging? Who knows? By doing this, we're actually just preventing them immediately from getting to that point and giving them some information back about what went wrong. They can just fix that and just move straight on. Having said that, going back to the early points about providing sort of helpful human readable feedback. This error message here is obviously designed for developers. It's designed for people with a certain expertise, maybe people that understand the concept of objects and extensibility. It's not gonna be very helpful to the average sort of, let's say, as a designer that's just downloaded your date picker plug-in and try to instal that, and they get this back. And maybe it's not particularly helpful. So let's see. I've got this call to handleMergeError. So this is a little error handle function that I've written, and we're passing into that a reference to the error that was thrown and we're also passing a reference to the target object, which is the object we're trying to merge into, and you'll see why we do that in a second. And again, I've got my erroneous option here, options1. I'm gonna run this code and see what happens. So we've got another stack trace here, and we've got a much more helpful error message. So this time it says, "Invalid configuration options1. "Did you mean option1?" So you may be wondering how it's doing its magic. So let's take a look at the error handler. So I'm just gonna close the terminal there. So it's actually a really simple function that is just doing a huge amount in terms of improving your developer experience. So I won't go into it in too much detail. Again, I'm gonna link to a version of this with full-on commenting at the end of the talk. Essentially what it's doing, we have a regular expression at the top, it's matching the structure of that error message thrown from the browser. I should note that different JavaScript runtimes throw slightly different error messages here, but they mostly follow this structure of this property is not allowed in this object. And I put a little capture group in that to extract the name of the offending property. And then what we do is we basically iterate through all the keys in the target object. And for each one, we compare it with the offending property, and try and find the one with the most number of characters that matches. And that builds... We get back this best match value. So if we get a best match, we can add on this little helpful suggestion saying, "Did you mean this?" If we didn't get anything, then we still throw something a lot more helpful in the form of invalid configuration option. So, hopefully that... It's just a kind of example of little things we can do to just make the experience a little bit better. So we'll go back to the slides now. So, another thing we can with configuration options is as our API scale over time, you might end up with just huge objects, and they can become a little bit intimidating and unwieldy. So one thing I like to do to make them easier to work with is break down the configuration options into these kind of domains basically. So instead of just everything flat and one object, I'll have an animation to make, and all the properties related to animation go in there, and another one for behaviour, and that's sort of everything to do with how the software behaves. These are kind of just made up terms, but you can organise it however you see fit. And we implement that in much the same way as the previous one. So instead of one config glass, I've got a config root class which has properties that instances of other config classes. And it's just kind of a nested version of what we have before. Each one is sort of self-sealing and self-validating, and it sort of works in exactly the same way. The only crucial point of difference here is that we can't really use object to sign anymore, to merge in our values, because that only does a shallow merge, so it's only gonna merge at the very top level. We wanna actually merge recursively. We wanna treat each object as its own kind of merge process. So there's lots of libraries that do this kind of thing. So jQuery extend, Lodash merge, or we can write our own. In fact, if you do wanna kinda integrate the sort of error handling as I showed you, you would write your own recursive merge function to do that. I've got an example that I'll link to later. But that's basically configuration. So the last aspect I wanna talk about is kind of the secondary entry point. So the primary entry point is the factory function. The secondary entry point is what you get back from that factory function. So a date picker, you can imagine, it probably has some methods on it. So it might have an open method and a close method. So for example, a way that we can open and close the calendar as an alternative to just sort of relying on user click events or something like that. So this is what we might call the public API of our date picker. But you can imagine inside our date picker implementation, we probably got loads of other methods as well that we don't really concern the person that's doing integration. So you can imagine you might have a bunch of event handlers, you might have a render function, and all sorts of other stuff that is just only for internal use. So that distinction between stuff that's for internal use only and stuff that we actually make available to the API consumer, that's what's known as public and private. So that's actually a concept that exist natively in a lot of more strictly typed languages. But in JavaScript, we don't have public and private native yet anyway. But over the history of JavaScript there's been sort of lots of creative approaches about how we implement that. And the reason people have tried to do this is because they really shouldn't be underestimated how much of an improvement that is in terms of hiding your implementation. It's not necessarily a case that you're trying to hide something because it's sensitive data, like a password hasher or something like that, or it's dealing with user credentials. You're hiding it just to make people's lives easier. So for example, we know a common thing you might do if you're trying to debug something is console log it. And you open your date picker instance in the console, and maybe you've got a hundred private methods there, and you're trying to find one thing specifically, and none of the other stuff concerns you. By sort of making certain things private and hiding them from the consumer, it just makes the debugging experience a lot easier. And you're probably thinking as well that we have things like TypeScript and IntelliSense now in our IDE that sort of when we're writing integrations, we can just kind of, you've got a list of all the public methods. So that's great, but when you're writing APIs that are gonna be used by who knows, you really wanna keep the barrier to entry as low as possible. So we should make any assumptions that our developers have IntelliSense, or that they even sort of would know what the difference between a public and private method is. We just wanted to just make it easy for everyone, and we wanna write code that is... People are gonna be debugging it at runtime as well, not just in the IDE or in our editor. So as I said, there's been sort various approaches at implementing private members in JavaScript. So the first one, I'm sure we've all seen this. So just kind of underscored member name. So this is just the idea of prefixing our member names with an underscore just to kind of mark them as private. So it's really nothing more than naming convention. It's still very widespread. It just kind of helps you as a developer, more than anyone I guess, to sort of differentiate between public and private. It doesn't really help the API consumer very much, because they're still gonna see everything. The other important thing to mention is if you are exposing your private methods and properties, there's nothing to stop somebody writing an integration around those properties, even if they're not supposed to. And what that means is when you refactor your implementation between version, you might get a bunch of people that have a broken integration, because they didn't realised that that method was private. So that's the great thing about having a very lean public API, is that you're essentially entering a contract with the people that are using your software, and you're saying, "This is the public API. "It's not gonna change between versions. "You can kinda trust us that "you write your integration around this, "and you can upgrade and stuff is not gonna break." So underscored member names doesn't really help in that regard. The user still gets everything, and there's nothing to stop them from sort of tampering around with it. The next method is closure. So, this is actually a really clever solutions. I think it was Doug Crockford that first started kinda making noise about this a long time ago. And it basically takes advantage of what's called closures, which are the sort of private name spaces that are created every time a function is invoked. So by defining variable inside a function, in this case our constructor, wee basically prevent them from being accessed outside of the class. So it's really clever, as I said, and it really does give you private members. You can define variable inside your constructor, you can define functions, and nothing outside of that constructor can see them or interact with them. But the problem with it in my opinion is that it kind of leads to this weird mixture of syntaxes and sort of a little bit... It breaks the standard pattern. So we've lost a very nice constructor prototype differentiation. It's even nicer now that we have ES6 classes, which is, to my mind, a very nice separation of concerns in terms of breaking up sort of instance properties versus prototype methods. So we've lost that. We're basically, we're defining a bunch of stuff inside our constructor just to keep it private. And we've got som properties which are variable, and we've got other properties that are actual property assignments. And actually, there's a problem with this example is that the public method is just I've defined as a typical class method. It doesn't have access to the private variable at the top there. So if I wanted to make that public method still public and give it access, I'd have to put that in the constructor as well and just do that as a property assignment, and initialise as a function. So basically, you follow this approach to its natural conclusion, and you start asking the question, "Well, why are we using classes at all?" And that's actually the sort of thing that Crockford has been saying, and it makes a lot of sense. He's come up with all kind of creative solutions using object create and composition and stuff to kind of reinvent how we can use the stuff in a more consistent pattern. But personally, I like using classes. And I think now that we have them for real in ES6, it's a great way of writing code that's very, with a nice separation of concerns, and very easy to see what it's doing when you look at it. So, for me, this approach, it's really great, but it wasn't kind of what I was looking for. I kind of been grappling with this problem over the last couple of years, and the solution that I've arrived at is something I'm calling facades. So, a facade is a term that exists in a lot of other programming languages already. But in this context, I'm essentially meaning it, using it means something that sits between the consumer and the implementation. The facade is gonna have the responsibility of exporting the public API. So the really nice thing about this approach, I think, is that we can write our implementation as we normally would. So here's an example of my date picker, and I've got some public properties and some private properties. I've got a public method and a private method. And this all just looks very standard. It's jut typical kind of properties on the constructor, methods on the prototype, nothing funny going on. And I guess what you'll notice is that everything is actually public. So, I've used these little js.comments to kind of denote which are public and which are private. You can just ignore what I've named the actual members that's just kind of the illustration. I like to use js.comments just so for my own kind of reference, so I know what's public and what's private. And it also means if I do auto generate documentation, that only the public stuff is gonna make it out there, which is really great. So that's the implementation, again, very clean. There's nothing weird going on there. Its just like a pretty normal class. So here's the facade. So basically, it's another class. And using the concept of closures, we're basically creating an instance of the date picker implementation inside the constructor function of the facade. So only the facade has access to the implementation now. And now what we can do is just go through our implementation and cherry pick which properties and which members we wanna export. And this doesn't have anything to do with implementation. Implementation is untouched. We could use the facade or we could not use the facade, and nothing would break or nothing would change. So just going through this line by line, we're newing up the date picker implementation. I'm just saving it as this underscore variable again, just kind of keeping in theme with this underscore mean something private naming convention, but you can call it whatever you want. And then first step, we've got a method. So my public method, what I'm doing is I'm just creating a property on the facade and then assigning that to a reference of the method of the same name on implementation. And just worth nothing that little function.bind thing, that just make sure that the lexical scoping is kept correct so that this keyword is referring to the date picker implementation, and not the facade when it gets called, especially if you're calling it implicitly. So you could add as many public methods as you like, using that syntax just one by one there. And then the second part there, we're actually dealing with the public properties now. So I'm using this ES5 define property call, which basically allows us to add properties to an object. In this case, I'm adding them to the instance of the facade. I'm saying I want a property called my public property, and it's gonna have a get function that basically retrieves the value of the underlying function, and this kind of ties into what Sarah was talking about. By emitting that set of function here, I'm actually making that property read-only. So that's something that is, again, probably gonna be pretty helpful in terms of exporting a public API. If this is just a property that is just for the user to kind of find some information about the state of the date picker and not really in terms of putting input into it, then making it read-only just gives us that extra level of robustness. And then finally, I've got an object freeze call at the end. So, that's just kind of... I'm sure we've all kind of seen this working with sort of a mutable JavaScript and stuff in Redox or whatever. But because the facade is basically stateless, we can freeze it. We could have used object. Seal at this point, but we can got a step further and actually freeze it. And that means that none of these public members and properties can actually be reassigned by the consumer. So you've got something extremely robust at this point. And then, finally, here's the factory function again. So going back at the very beginning of the talk, the factory function newed up an instance of the date picker and returned that. And now we're newing up an instance of the facade and returning. So, very much the same thing, the user doesn't really know that anything different has happened within the factory function, but this time there are only getting back this very nice clean lean public API with only the methods and properties that concern them. So that's facades. I know these are kind of the three main sort of areas that I wanted to talk about. And I think they sort of hit those points that I talked about in the beginning, in terms of just really improving the developer experience. So these are kind of three ways that we can improve our code with these kind of patterns. I guess these are a little bit idiosyncratic to the way I like to work, and there's actually different ways you can do any of these. If you don't like using classes, if you like kind of a more Crockford object create approach, you could kind of swap that in for any of these but, as I said, I love using classes. But yeah, that's everything I wanted to cover. I have made a little GitHub Repo with links to the slide deck and the blog post that I wrote that this talk is based on. And I've also, as I mentioned before, I've got a bunch of GitHub gists which kind of go into each of the examples I've shown in a much higher level of detail with commenting that you can check out. And I will tweet that link in a few minutes. So if you follow me on Twitter, you can find it there. I hope that was insightful and thank you very much. - [Facilitator] Thank you very much, Patrick. We already have a question. That was quick. - [Audience Member] Good talk. The facade thing is something that... I have this for myself. But I'm concerned that the object of freeze will stop people... - Can you just explain that in a little bit more detail? - [Audience Member] So if you're in Express, you might override the rest of the render method in the middleware. If you've frozen the API and you kind of write those methods, you can't-- - Oh, so in terms of preventing people from--- - [Audience] Yes, you might want to. - You might want to, yes, I understand. - [Audience Member] Yes, is very important part of Express itself because-- - Yeah, that's a very good point. I guess I just did that to kind of show that it's a stateless part of the architecture and you can freeze it, and that makes it more robust. But I guess if you are writing something that you really expected people to interact in that way, then you can do whatever you want with it really. As I said, these are just kind of little examples and things that I found helpful. But I think you would make a call on whether that's the right thing to do. I'm not suggesting you freeze every facade, but yeah - [Audience Member] As a developer, how you put your projects into-- - No, no, you can never really project that. - [Audience Member] Maybe it's error free. - Yeah, perhaps. Yeah. Put it in a configuration object, you know. Do you wanna freeze this or not? Let the consumer decide. - [Facilitator] Please put your hands together one more time for Patrick.