SF Scala: Haoyi Li, Open-Source Library Design
Recording: SF Scala: Haoyi Li, Open-Source Library Design
hi so my name is Howie and this presentation is I'm going to talk about four facets of what I think make good open-source libraries so these are ideas that are not specific to any particular library or any particular field or any particular language but I think that if I'm going to use up open source libraries what I would want to see in that library and someone who writes an open source library what I try to provide to users of that library so that they can use it and be happy using it so a bit about myself I was previously at Dropbox I'm currently I'm a small software how shop in Singapore called bright we do a bunch of their science gal consulting and we've made it cool tool called the fluent code Explorer which I'm going to picture just at the start of the presentation which is basically online it's an online online code search tool kind of in the vein of if you use Holland or if you use like grape or similar things it's like that but better and faster so if any of you wants online code search tool you can come talk to me later now that's over with so I've done a bunch of workforce college AAS and I've made a bunch of libraries so that's why I'm talking about writing open source library today so here are some of the libraries I've written so then does anyone here use any of these libraries in their day to day work you know chart out which ones every night and use anything else other than Yemenite scala tags okay so I assume if you're using a lively you probably like it because there are other options and if you didn't like it you'd probably not be using it so this presentation will talk about what I did to try and make these library is nice enough that people like you would like to like to use them so what what are the goals of an open source library by my relatively narrow definition the goals an open source library is to make something you use that your friends and your colleagues will use and that random strangers values so someone in China someone in someone in Romania who you've never met before can pick up your library and be happy using it if you only want to hit the first two points you do not need most of the things that we'll talk about in this presentation but if you want to hit the third point and make something that strangers will use that's somewhat more difficult than making something that someone sitting next to you is when they can just ask you questions whenever they of the 31 students they don't understand it so non goals of the open source library again as I defined it relatively narrowly is to go around answering questions to talk to lots of people or in general to build a community all these are perfectly fine things you can do but I don't think that they are code to an open source library so you can have a library without the community you can be library with the community like I've used plenty of both you can have communities without a library you can community about raising chickens in your backyard there's quite a popular one online so it's to kind of separate whether you're on the community and reserve the library and I think that for my perspective alive really something like the thing on your left which is you want it to be dumb and not very interactive but solid enough that you can take and build something more interesting out of it so library itself is not meant to be challenging or difficult or impressive divert itself is just one block in a sea of many many blocks that you want to use to build your house in contrast the community tends to be much more engaging and you can't really maintain more than five to ten communities in your personal and professional life just because of all the time that you spend to maintain to engage with them but you can easily use five 50 100 different libraries when you're making a reasonably large application so what does it use the one from an open source library and what do I want from an open source libraries I want to be able to use your library without reading a documentation if the documentation that's great but I want to be able to just pick it up and start using it because I'm lazy I want to learn about your library without talking to you as the author because maybe on different time zone maybe you take a few hours to respond to emails if the informations I can find in five minutes I want to wait three hours for email response I want to live Rita cater to me when I'm both a total newbie as well as I say me with a total weight when I'm expert both of which are totally different totally different personas new be me one something that's really easy and quick to get started with while expert me wants something that's really powerful and sexy both and those are kind of at odds and I want your library to fix my problem despite you not knowing who I am and you not doing my project I'm going to use it in so those are somewhat unreasonable record requests I would want from the open source library and presumably most of you it wants similar things they may seem unreasonable but as a programmer who is lazy and greedy you want all of it in order to be happy so how do you get to all those accomplish those goals so the four facets I'm going to talk about are intuitiveness which is how you gets on to use your library without reading Doc's or in to use your library with reading doctors little as possible layering which is well educated to both newbies and experts documentation which is what lets people learn about a library without ever talking to you or seeing your face and considering how about the shape of your library which is how you can make it fit into other people's projects despite you not knowing what their project is or who this person is so all of these are things that people talk about very hand wavy high level terms but I'll try to cover it in a lot more detail to see how can you actually reach these goals so the first point is intuitiveness so I think that being intuitive means you can use the library without looking at dogs so any library can be used after you look up Docs no matter how you implement it but it's a matter of how much you have to look up the docs and if you have to look up lots of Doc's before making a simple application or using a using a single feature that tend to be very frustrating especially for newbies so imagine if you are like doing a whiteboard interview and you want to do say inability to implement enterprise fizzbuzz as part of the interview process and if you want to use enterprise fizzbuzz that of course that needs the HTTP server because it's enterprise so the interview will then ask you to say well you need to you need to HTTP server but for now just make up your own library to make HTTP request to the server but just assume the server exists and come up with a magic API to to talk to HTTP server and we'll just move on from this is you're not in the business of implementing HTTP so this is something that's very common and in these interviews and if you totally on the spot make up an arbitrary HTTP client API in any language you probably end up with something that looks something like this so you import your client package thing you call get on the URL and you call get get some result object thing that you can pull the JSON out of and if this is actually Python the Python request library the output looks something like that so the fact that someone who doesn't who knows about what he wants to do but doesn't know about your particular library would note would come up with something similar is what mix is what makes intuitive and the fact that you can see if you show this to anyone whether they are Ruby programmer or a Java programmer or Python or Scala programmer they'd probably be able to guess that you're putting some JSON from HTTP endpoint even if you don't tell them what this library is without reading any documentation so that's intuitive and people really like the request library in Python which is interesting because it isn't that it's not a powerful library it doesn't give you any new capabilities these are high performance is our asynchronous and unlocking lot web scale distributed none none of that stuff it doesn't let you do anything that the normal Python standard library doesn't already let you do in maybe two or three lines more code but people liked it so much because it lets them do it without needing to read the documentation because it's intuitive so if you dig deeper to that what does it mean to be intuitive doesn't mean that Kenneth reaches has a magical talent that lets you write intuitive code lets him write intuitive code I think that the reason why a line like this is so intuitive to people is it matches what the person who's using this library has used before so one thing that they've used before is other Python libraries in this case for Python package so in many other Python libraries standard library or non-standard library you import the package and you just call methods on it to get what you want that's how things work in Python lands and you can configure it more later if you want to but the basic API always almost always look like this and with requests if you've used a JSON library then this will look totally familiar to you you import requests you may go get maybe there's some optional arguments can pass in and you're done the other thing that the this line of code is consistent with is other parts of the same library so if you've used request to make post requests then using using the same library can make a get request would feel totally familiar to you and if the question then is how do you make a put request or option request then it's also more or less obvious if you've used these to API it's already the last thing that requests if they request API is similar to is underlying data model of HTTP that it is dealing with so in this case the mapping from request I'll get with the URL is pretty close to the actual get request that goes over the wire with the past with a horse than all the other stuff that the all other stuff there will be optional arguments on the request in your request method will go into optional headers and other things in your actual HTTP request so that means that because it's so close even if you don't know anything about Python and don't know anything about this library you kind of guess that there's going to be some get method and it's good you're going to passing the host and path somehow and turns out that is how you use this library so that's what I think makes requests intuitive it's not some special talents or magic in the fingers of the programmer but the fact that it looks similar to what you expect the users who have used before and the users have used these particular things before so if you monkey those things and make something similar they will be able to pick up your library much more easier so y'all I breathe mapping to the other libraries in the space mapping to itself and mapping to the underlying model their library is dealing with all of which help make things intuitive so another library that I like to think is intuitive is my own Fastpass library so it is lets you define a parser using distant text so either parser is P like a dot repeat B or C or D for the end of the parse and you call the thing dot parse and you get a result object I think this is intuitive because it Maps closely to other libraries in the same space that you may have used before so if you've used the scholar parser combinator library it looks about the same here you have the wrap in a P here is dot rep instead of rapid currents but other than that is more or less the same API so all the people that come in Scala and who learn parts of Combinator's in the scala book would be more less familiar with how this works it's similar to other parts of itself so whether you want to repeat or whether going to repeat with the separator or we're going to make something have a string optional not optional it looks more or less like the same library and can probably guess for example if I want to repeat with a minimum number of repeat with a minimum number of repetitions then you probably guess we put in an optional argument in the wrap lastly it's more or less maps to the underlying model that sounds thinking about when you are using this library so most people have looked at grammar definitions in some form in the past and a grammar definition for example a DNF grammar for would look something like this and it's not quite the same we use the reference set of star we use tilde instead of space but it looks more or less close enough that if you are familiar with the grammar definition you can relatively quickly figure out how to translate it into a Fastpass parser without needing to go to a bunch of intermediate steps so not everything is intuitive and even unintuitive things that were looking at to say why are they onion to ative um that's very unintuitive right we are back okay so here is one part one portion of SVT that I think is particularly unintuitive so as we see overall some people like you some people doing but this person is this portion is particularly confusing at least to me and that's when you define if you want to try sneaky to generate a file like for example a files will have generated source code from your ion or from a proto buff or whatever then you have a source generating compile plus equals desktop task with the block of what the employer can generate and a task value at the end so I think this is unintuitive and if you look into what someone coming into this problem would know before you would see that like they know how to generate files in Scala like that and it doesn't look like how you do it in SBT so you may have to put this in the middle of the SBT block but you never had to do this deft asking before it's not how I generate files is gather they know how to set you know how to set set settings and set tasks in Scala in SBT so in for example you can set a name like that you can add library dependencies like that everyone knows how to do that and none of those did you have to do this via desktop tasks thing and actually the underlying model is I want a file to appear at this path in the file system with this blob of source code inside and if you're thinking about that you may probably Majan like I went this path this source code and that has no relation to the desktop task being in SBT so this just desktop task thing is consistently SBT its own internal implementation of this feature but as someone who's coming in to use SBT they're not likely to be familiar with SPG's internal implementation so the fact that consistent with that thing doesn't help make this intuitive to someone coming to use SBT so you're not always consistent or in front of everything so one interesting one example I found is with the akka HTTP server API where you can put a block with a get order get routes inside and put a post with all your post-ops inside can extract things and have multiple routes and sites for example Dex action um the heads on here Yutaka HTP before on the server did you know we can put pre-signed in or out to debug them that which route is going to yeah or not no we could put print lines in your routes okay I guess I'm the only one well so if you want to see like for example what routes is trying and put print lines anywhere in these docks and you'll get run and executed when the request comes in and I think that is surprising to me because it's very different from how most other routing libraries work most other routing libraries for example play routes or jangle routes or Ruby on Rails routes the route code doesn't run every time your your request comes in the route code runs once and generates like a data structure that then gets used every time the request comes in so putting in a example putting in a pretty line your play route doesn't make any sense I even if you could it be when you get run once but on the other hand HTTP is very self consistent with all the other directives that are in the libraries they all behave the same way and once you learn that this small change from the other routing libraries may be familiar with the rest of the directives all behaved more or less the same and similarly the underlying model which is I want to figure out you some logic to figure out which endpoint on the run that makes perfect sense like if you want usual things you could use if statements or match switch statements and you'll work just as well another example of partial consistency one that saves the library rather than makes it confusing is the Python operating system library so if you come to if you look at this library you see things like OS coxa dear or get quiz or chowon and if you come from a point of view of other Python libraries no one else writes API to look like this and similarly different parts of the same OS live we are all totally inconsistent for example why is it list 0 well mcdeere instead of mcdeere like this arbitrary and inconsistent but the fact that it is consistent with underlying POSIX API is is what makes turns this into something usable because anyone who's used bash or user C or Linux API directly would be familiar all of these terms so if these weird short abbreviations who are not consistent with the capi will be totally inscrutable to anyone and yet people using with people using with send all these open documentation but because everyone's was using it on many people who are using it have seen it have seen the capi before they know that tone obviously means change ownership obviously and so this becomes something that then can be used without too much without too much documentation that makes it somewhat intuitive so like me I think intuition is about being intuitive is about being consistent with what your user has seen before and what your user has seen before will change depending on who your target user is for example your Python average Python programmer will know different things from average Scala programmer who know different things from average Java programmer and having for example a huge builder initializer for it would be intuitive to a Java programmer but not intuitive to a Python or Scala programmer but in any case this is I think how you make something intuitive you try and figure out what you've seen before and you make your thing look as much as the other things you've seen before such a when you look at your thing you can know oh I know how this works like I've seen this and they can get started right away without having to look up documentation for every step of the way the next class that I'm going to talk about is about layering so layering is how you can provide a simple API for newbies we're also providing a powerful complex API for the more advanced users so if you have a library with multiple layers it would mean look something like this you have the API the first level where the most important thing is discoverability and lack of configuration because the last thing anyone wants to do when you get started with a new project is start fiddling with XML files or JSON config or whatever they just want to use your thing and see a result come back second level is configuration sunny becomes important because to actually integrate into whatever enterprise project they're using or in whatever VPN they're going to need to configure or something and then you should and that needs to be possible next level Kumiko the configurability accessibility matters the most and discoverability totally doesn't matter at all so if someone's been using for example your library for a last six months and all sorts of ways then they are you know most of the things that there are to know and what matters to them is can I do the thing I want or do I need to use a different library or do I need to your librarian at my own feature and as and after that of course there could be more advanced layers for more advanced users so what does it look like in practice in the case of request the beginner level is two lines of code HTTP request and get batch of JSON about the github events that events happen on the whole of github so easy to get started with no config just make the request and go next level you start configuring it sending up special headers sending up more data making post requests next level maybe you need to maintain session so then you start having this session objecting to pass around and deal with that next level you need to you start to talk about streaming and canceling that on and using iterators to read the response or send up the send up the request but what's important about this kind of layering is you only need to bump into each feature when you need to use it so if I don't need to maintain multiple sessions I do not need to use care about the session object in fact I don't even need to know it exists I just use requests not without it and it works fine if I don't need streaming I don't need to care about streaming I don't have a single word stream in my whole program I can just use it without streaming and get to have a simpler API and when I need streaming later I can then go and figure out how to use it but when I don´t need streaming which perhaps maybe the majority of people if they most of people are newbies then I find it easier for me to get started with without having to deal with it um I think example of a insufficiently layered API would be sometimes akka HTTP client api which has a lot of stuff in it to get started so this is not necessarily a bad layer but I think it is insufficiently layer a insufficiently layered api in that for example the active system will materialise I think that people do want to configure and do configure so you can't just not let people configured actors actresses and materializer but you also have a lot of people who don't like to configure the access the Exorcism materializer and even if they want to configure it later they mean on to configure it now and you just have to get started so perhaps in that case you could like a possible solution would be to have a simple version where you can just make a request with some hard-coded actor and whatever and later on if you want to configure it you don't have a second level API said ok now you can configure it and what you want to come how you want to configure it another I think example the well layer API is the flask API there's a Python web server that's very popular by our mean by our main monitor and what is what's interesting is you can write the application in seven lines of code that's of the HTTP server and later on you're going to need to make it more complex so later on you're going to need cookies you request session session state's argument posts posts bodies URL parameters file uploads all that stuff later but when you're first getting started with it you don't care about all those things and you don't even need to see any of those things you don't need to think about them you can get started and later on when the time comes to add conquer multi-process concurrency using unicorn or whatever you can deal with that later and for now we're getting started is that all that stuff isn't in the front to confuse you and intimidate you while you're just trying to get something working the converse is something like the octo old HTTP API which is actions change slightly which also is similar to client in that there's a lot of stuff that is useful to somebody but perhaps shouldn't be quite the first sitting that someone sees when they are looking at your library this probably maybe this maybe should be the second or third layer of the library when people actually configure it and perhaps there should be a simpler first layer where they activate with just to get started with so they have since added such a first layer and turns out that apart from a slightly messy imports your scholar your scholar web server and you just as easy to get started with a tail Python web server so it's not nothing intrinsic to I mean relative being really good at ap is and programming and being a beautiful API everyone can get started with really easily it's just a matter of properly layering application such that you have the easy mode you have the intermediate mode any of the hard modes and people can choose which one they want to use and everyone from the most newbies put in newbies to the most advanced users will all have be able to use your library effectively so that's what's learnings about you have a simple code for newbies you have intermediate code of more advanced layers and there's no one API that will satisfy everyone and the solution to offer more than one API so this is a headache to maintain more than one API like maintained agility of treat two or three different API s but if you want a bunch of newbies in the country you've never been before who have never met you to start using your open source library then this is how you get make it easier for them to get started and still let continue using your library to get more advanced the next thing I'm going to talk about is documentation so the first thing to know is that documentation is a future just like any other live feature in your library so if you have a beautiful API to let you write code in a really nice way but no one knows how to use it in that very nice way and y'all use these in a very awkward verbose way then it's just as good as having a really awkward more post API to begin with so just like any other thing you implement whether it's improving performance where the scalability whether it's most thread safety the one thing that you should implement is documentation just as important so your users don't want to talk to you as I mentioned earlier because talking to you is slow and awkward especially for those INTJ programmer introvert types and you probably go on to talk to other users either because they may not speak the same language as you and if there are thousand of them asking you questions you'll probably run out of time that's the scale so the first thing that I think about documentation is because of the feature the amount of effort you put into it should be proportional to the rest of graphic if you spend three months writing a really cool library that does something really beautiful already awesome in a really beautiful way you should spend more than two hours writing documentation for it if you think if you want someone you actually start using it so for example fast Paris which I think people say it has nice documentation has about as much documentation as main code and test code which turned out to be a lot of documentation so this is something like 30 pages of documentation but if you're going to be writing 30 pages of really intricate Scala library code writing a bunch of English is usually not too difficult and pays off when someone tries to use the library they can get started very easily we don't have to ask you lots of questions and similarly for many other libraries so it varies but it's within a factor of five or two to five that's not how much documentation you have and how much application code you have so obviously this doesn't apply like uniformly to everything fossils have a really complex application which is really simple to use complex libraries that's really simple to use externally but for many libraries it's more or less there's the amount of times we spend writing our API all that needs to be documented somehow and so you should just go and document it the apart from having enough documentation just as important is having layer when I call layer documentation with a similar stepping on the API where you want something for everyone and whether that everyone means some who has no clue what your project is and doesn't know why he should care for someone who's been using a project for six months giving you lots of feedback and wants to be able to customize every way he wants so what does this look like in practice so in practice this looks like for fast pars intro fast passes are faster company to library for Scala you thought also Python is not if you thought it was a JSON library it's not it's a faster Combinator library the newbie topics once you've already decide how to use that that person wants to use fast parse is this is how you use it don't ask questions about why it works but just this is how you use it and try it out the next level is things like you are using it you bump into problems you bump with me the performance isn't great maybe you don't know how to debug your power something is broken or maybe like your users don't know how to debug their input when the input your parts is broken so all that stuff is things that people will care about but maybe that's at the first step so that put later on and lastly like talking about fast parsers internal implementation like blah blah immutable interpreters grammar transformations something that maybe 99% of your users don't care about but quite possibly the 1% it does care the point percent that's going to be contributing fixes to a library other 1% is going to give you the most valuable feedback about your library but again some 99% don't care so it can get chucked cracked at the end and the people who need it can find it anyway similarly for my Scala tag HTML generation library first step what is the same why should you care second step you know how to use it example example example example third step more more advanced things that you may or may not care about but most people probably need one or two of them after you've started using the library last step all the weird implementation stuff that most people won't care but the people who are contributing fixes would need to deal with what does incorrectly layered documentation look like so the old svt getting started which tip since improved upon what is a good example so this is what a newbie would used to see when you go look at SVG is getting started so it is after examining a project SVG you have a mutable map build definitions do not affect a CTS map the build definition creates a huge list of objects of type setting and the type T is the value in the Met type of value in the map the setting describe the transformation and in new transformation attends it returns new map cuts functional programming that the old map in place and the setting transforms the map by adding and the transform that becomes a new map so all this is correct and all of this is useful documentation for somebody who is contributing to SVG or someone who's trying to implement competitive the SBT or someone who's trying to deal with basically X Keys internals but so it's not what was it is documentation for a newbie so it should still exist but it probably should put somewhere at the bottom where the advance people can find it and newbies will get confused so luckily they've improved upon it so this is a new at viikii getting started documentation so a build definition is defined in tilde SBT that's something that newbie may not know because they just are teaching Scala and scholar users SBT and you don't know what everything is projects are often called sub projects in build SVT which is looking located in a current directory not a very important particular newbie look something like this the sub project has key value pairs and the key is the name and in this case one key is name and that's that the string value is the thing that is bound to the name so no explanation about how it works marination about what the colon equals how it implements the how it's a map or not a map or immutable immutable it just is here is something and here's how you use it to begin with and this is I think very what very good introductory documentation so that's the second power portion of this other point about documentation in that the quantity is not the only thing less importance so just to take SBT as an example again SVT I traditionally had a tremendous quantity of documentation like 5200 pages worth of documentation he printed out is basically a book on SVG website but people found it confusing especially the introductory introductory pages because it was properly endeared and so they had the really advanced stuff about it fut internals so things are many at the top where the newbies who bump into the main get confused so the structure of documentation making sure is properly properly layered from easiest to hardest it's important to make sure that if a new becomes a project you can quickly find what they want even though you don't know who they are and it and they've never talked to you so the last facet of a good one sauce library about is thinking how think about the library is shaped so if so libraries solve different problems sometimes it's overlap some have more corner cases than others but generally each like we can be thought of as something that fixes a problem with the disease in the design spaces the thing that you're trying to build and you kind of piece them together ad-hoc pile them on top of each other and silly arrested glue code in order get something itself or branch a bunch of money or try to sell for a bunch of money and if you have if you have other projects to work on that's when the library becomes useful because you can put the light put library together in different ways and also satisfy more than one project and in the end you don't need to write that much code only this small bit of orange in each of the project bodies so what are the failure modes for thinking about about our life for about the shape of your library so one failure mode I think is when your library is so perfect that there are it's totally self insistence and there are no corner cases that's like the circle haha and in that case your life if my final library doesn't really fit in and do what you'd want it to do in your real project which actually is full of corner cases some of them are really pointy and you're not having to write a bunch of blue code not to stitch your perfect library together a really nasty real-world problem the other pillar mode is if you have a library that is just the glue code extracted out into something called like misc utils or helpers slash health resort Scala or like like Scala extensions to or something and it did everything that needed to be done in the original project but now you're this awkwardly shaped things where does it really fit in any new project it does a bunch of things you don't need it to do doesn't do a bunch of things you would need it to do and generally doesn't play nice use all the other libraries are trying to use in that project so that's how that's something that's worth thinking about when you think about your library like where does it fit in not just your particular project but in the rest of the world so you don't want something that's too self consistent but you also go on something that's two problem specific that only works in your particular project you want something in between that solve some people's corner cases but is regular enough that you can stack it again the Kleenexes other libraries and and thing I see with itself and understandable so you can use this to build your application so just to sum up so these are things or user ones from an open source library these are things that I would want from an open source ID I'm using in that I want to build a user library without reading documentation I want to learn about library without talking to the author if I can talk to author it's great but I don't have to talk to the author I want to live with a cater to me when I'm newbie and don't know anything but after six months of using libraries I'm no longer a newbie I want to just feel cater to medium and I know everything and want to customize in all sorts of ways and I want your library to fix my problem despite you and ever having met me and me not giving you any money so that's what I was from an open source library and that's something that actually you can provide without too much difficulty just with a bit of effort so we can work on gimmick library intuitive by making sure it matches what what do you expect the user will have seen before whether in other libraries previous experience or the underlying model that the library is dealing with you can layer the library to make sure it works well for newbies and experts and you can make sure you have enough layer documentation such a people can learn about the library without having to come and ask you and get the channel or email and lastly you can think about the shape of the library and where it fits such that you don't end up with a weird miss utils library that doesn't fit in any else's project or perfect utopia library doesn't do anything anyone really wants so all of all of these things are things that people anyone can do and don't require any special talent especially things that intuitive nuts which are often thought of as something magical that really smart people have actually just takes a bit of work to think about what your user has seen before and this is a user is a programmer and try to line up as close as you can to that search that way the person can use a prior experience in order pick up how your libraries need to be used so that's four facets of good open source libraries hope you enjoy the talk and I guess I'll take any questions [Applause] anyone going once going twice I think fast parse is really nice yeah many of the others are kind of messy and sketchy and not that well organized but that one I think is quite nice a good counter example my personal verse would probably be probably be puppet have you used puppet before the configuration management library all of you are laughing already like that's a total hellhole to start using yeah and the documentation is using our Gigi came in the form of a PDF you to sign up for so I'm not not a great onboarding experience yeah how do I cite is the need for everyone to write it basically it comes down to having a whole it having a particularly in your house that you're trying to build and you fill the hole in your own project and then you decide well this is something that's really specific cuz it something we generalize to other projects so most of my good libraries are written by written with some motivation in mind and it fills the original goal fine and I took the extra 10% effort to extract there and make intro library other people can use so for example fast power source because I wanted to write a parser and other parts of Combinator libraries or either two-syllable to to sketchy and M&I I needed ipython like Sheldon scallops I built it and you're kind of useful in that own project and so I kept a cool I work without a net and publish it separately yeah so if you don't have a if you don't have a target sheet for live real probably end up being terrible and that's just the way it is because you need some motivation to make the lively the way these advisors just become ad-hoc exploration of all the things you can do which are infinite any other questions yeah I think that in terms of intuitiveness the Python people actually do it very well out of necessity so compared to the Scala world I feel that is Gollum any API is a kind of janky and you can kind of work with them because of all the types the idea will help you a compiler tell you and get wrong whatever whereas in Python world because everything so dangerous people put a lot of effort to try make things as inclusive as possible because there's no one to help you and you're there with your intuition trying to figure out the user library and simple things like documentation which are often much more verbose in that's a Python land and then in Scala in terms of JavaScript like I can't really say is a javascript is like ten different ecosystems in one language so each of the each of them has their own like ups and downs my I don't really think having that head of the library is that greater idea for example yeah any other questions yeah yeah I don't like that either I think that for that particular point which is asynchrony I think that that violates layering in that the dumbest version should probably be synchronous and then you could use asynchronous version later in terms of rewriting a whole code I think that's unavoidable in some cases because the like the equivalence is the person the person's disobey the library works on a new thing and it's more less the same for the end-user like at some point the interests are going to change on SSD is going to change or something's gonna be unfixable and you can have to fix it so something to be unfixable without breaking some practically listing they're going to need to fix or want to fix and then oh well yeah you can't ensure you cover the most common use cases but you can try which is basically all your all your API is should be documented every method call you expect someone to use should be either visible in your documentation somewhere with Nick that in an example or should be trivially guessable from another API that they are already using for example if you have like foo a foo be Fuji and you don't document with the Fuji maybe that's fine but generally if you I think if you have examples that contain area complicated every API in your code base that you expect end-users to use then that already goes a long way to getting clipping people using it so you have those things so a bit a bit more structurally than either way I approach it is you have the hello world example which is like a one to five line thing that people can see and immediately understand hopefully you have the unit's documentation it's just documentation for every individual API this is how use it I use it how is this some people use Khaled up for that some people put it in a separate web page mine are in a separate web page that's already matter and then you have a few more like integration Doc's which is to say like here's a 50 hundred line example of something that you can build with this and using all these API is and then that will cover quite a good range of total newbie to someone who is using it for wheels and want to see what how another person we have written the same application using our library and then if you are really proud of you're really clever internals can write about that later and that covers I think the whole range yeah any other questions cool I guess we're done then thank you [Applause] [Music]