scala.bythebay.io: Bill Venners, Finding Simple in Scala
Recording: scala.bythebay.io: Bill Venners, Finding Simple in Scala
you hello everybody I I was going to walk around and be more exciting to watch but this this new design of the Macintosh has a beautiful curved edge that slides right over the lip that would cause my laptop the fall so I'm just going to stand here to prevent that so today I am going to talk about simplicity about what I wanted to do let's try and capture well what what you know why you should care about simplicity of what it means what it is and how to achieve it in Scala so I want to start by talking about the why and what I if I had to come up with one word to describe what we should try to do as programmers that would be the word right so I mean it's not easy to come up with one word but that would be my word so anyway there's a couple different reasons I think we should care and one is that it simplicity baguettes prog productivity that's the begets operator essentially we are paid to program usually and if you know the more value we can create for the less value that comes in and that part of that is less time the more productive we are to society right so I think that what it really achieves you know one thing that it achieves is is economic that and it does it by the if you make something simpler if you spend time which is money today to make something simpler then tomorrow people who are using your code or your library can spend less time because they don't have to spend more time to figure it out right so that's how it's a way to to make people more productive so that's one way to think about it and one of the things I wanted to say was that even though I think that that's what I would describe it you know if I had to put in one word what we should try to achieve as programmers I don't think we should always do it because it really is an investment decision how much time to spend to make code better because it is actually a bet that if I spend this money now or this time now to make this code better or make this this design simpler then in the future there'll be a payback and if if you spend two days to make something really beautiful and then no one ever uses it or no one ever needs to go and look at that again then you actually made a bad bet and it would have been better just leave it complicated right so it's not a slam dunk that you should actually make code better or as good as you can it's sort of like you have to figure out what it's like investing money if you have you have a limited resource and you have to figure out where to put it to get the best return and you don't know because it requires information about what's going to happen in the future you don't what's going to have in the future so I think part of becoming a good programmer is getting good at that sort of figuring out where to spend your time and what's the best way to do it okay so even though I think it's a good thing it's not always the right thing to do and another thing is that the way i think about design is that it's for people even though it's you'd think it's like for the computer to run stuff it's really about the design is like more about helping people use it so if you're designing a library then you want to make it simple so that the users can actually save time and that's a way to be nice to them so I think it's actually worth doing because it's a way to sort of be kind to others right that's one of the that's what you're doing is you're actually doing it for people and it's your co-workers you got to look at your code or your users if it's a library right and so that's that's one justification or one not justification but motivation for doing it and then another one is that and this is really a you know I think in the heat of battle when we are you know we just got to get stuff done it's usually don't have time to make things really elegant but when when you see something that's quite elegant it's there's just something nice about it just in its own sake and I think I wanted to say that you know one of the things that well for me anyway I spent a lot of time programming in Scotland it's sort of my form of expression when I was younger I wanted to be an artist and that sort of ended up you know I'm a scholar programmer but I try to make things aesthetically pleasing because it makes it I think that that's worth doing just in its own sake just like art people don't usually do art for economic reasons right and if they were to try that it wouldn't work out very long right so I just want to mention that one and then the other the last thing I want to say about sort of the why is I was interviewing Anders Hiles Berg who designed c-sharp up in i went to Microsoft years ago when I was a java guy and he'd mentioned this word simplexity is like what simplexity and and what it what he meant by that is you can make things too simple and actually make your users lives more complicated and so what I think the goal when you're when you're trying to achieve simplicity in a design it's not actually the to make design simple but to simplify the users lives or the people who are going to be working in it that's what you want to simplify because you can make the design so simple like if he keeps getting smaller and smaller and more beautiful it could actually disappear there's nothing there that's really simple but then it doesn't really solve your problem right and then in in any project or task there's some inherent complexity of that task and over time because computers get more powerful there you know they they more memory and they're cheaper than the requirements of our of the things we're asked to do get have gotten grow more and more more complex and you really can't get past that I mean that's real complexity that you have to actually have in your solution so what what you want to have is is make it the minimum amount of complexity in in the software that actually does the job it needs to do and get rid of accidental complexity or extra complexity that isn't really necessary but i wanted to say about complexity to that people actually want it if it solves their problem I mean it what simplexity really means is that you can make things simple and if it doesn't solve the problem that's people actually want more complexity than that actually want it if it's useful and so part of the art of design is figuring out in between these two things you know where's the sweet spot where things are as simple as they can be but they actually solve people's problems okay so that's a my you know what I have to say about simplicity and so where Scylla comes into play is that I think what we do in just programming in general to deal with complicated requirements is make api's we actually separate out we try to put the details the complication complex details behind the scenes in front of a simpler API that's employed interface so its application program interfaces it's open for people alright so that's the trick that which we should do that all over and over and that's abstraction so that the reason that interface is simpler than the implementation is because it's more abstract so we abstract away detail to abstract away complexity and I think the reason is just because it's for people again human brains can we can only keep track of so much in our heads at once so the less I have to think about the more I can work with it right so Scala is really designed to do this I think that like if you look at there's a talk that's really great to watch it's a great video bye guys steal called growing a language and he starts to talk by just having one syllable words only in the talk and he doesn't allow himself to use two syllable words unless he's defined them in terms of one syllable words and you can use to civil words and he's the whole talk goes like that but his idea was was kind of like the cathedral and bazaar of programming languages there's there's the cathedral way where you design a programming language and you put in solutions to things people want to do so like there's NC sharp going back to C sharp there's link right that kind of addresses data access in c-sharp so there's a like nice way to do it and so they just said well c sharps for this domain in this domain of this domain so let's add these features to help make people's lives simpler that's a cathedral right you actually put the specific things in the language what I think Scala is is like a domain-specific language for library design so the features that are in Scala are to enable people to make libraries and to solve problems there so that's more like the bazaar so anyway what we do then is we just we make these things or we grab them and then we just write application code and the application code should just be real simple because we're just using the simple interfaces in it and we try to keep that simple so yeah so then what the scala as a global language is it really is I just think that's sort of the point of it or is that it's like it's designed to make library design simpler so that you can do this separating out of the detail and help allow people to manage complexity and complex requirements okay so i have ten guideline specific guidelines i just wanted to go over and one of them is there's a lot of features in scala that are intended for library design and so one guideline is just don't use that it when you're writing application code and it can be kind of tempting because it's fun to use all these things they're like knobs to twist I mean and none of these things are like that you should never never I'm not saying you should never do it but just in general I think that that application code in the middle should just be really straightforward and where you use all those fancy features are in these things when you designing the libraries so an example I've seen for example would be a in application code you use a implicit class to add a method to something because you like a name better I mean it just adds complexity that the person reading the code has to go like where'd that come from and I think it'd be better just call the method you don't like is it's already named that right now there are giggles because my sure if that means that I shouldn't have done that but anyway so that's one and another thing I think is that when you're designing you need to think about the people you're designing for a busy and they are busy and they don't care about your library because they just want to get their job done the metaphor that I like for this idea is is when I rent a car I have rented cars lots of times I have never read the owners manual I mean tenant was in the glove compartment I've never gone in there and read it I just get in the car and I takes me a second to kind of figure out where things are all wait you know this is this and then I can drive off and go to the where I'm going right when I bought a car occasionally I haven't bought many but occasionally we have bought cars I did always read the owners manual when I bought the car right but what when people use libraries when they're doing this thing they don't want to read the manual I don't want to become an expert in it they just want to get their job then they want to just get in and use it and that's how they're going to be using it so you have to remember that that's the casual and designed for casual use and then the other thing about inheres teams people don't usually um interesting software is not usually written by individuals it's written by team so what you're designing is not for people but for collaborations of people right people working together so yeah so that's designed for busy teams and an example of this from Scala test was that in the old days when I like I don't know what version was version 10 this was in version of what I do the top thing would do what you think the second one would not and I actually documented this in the manual which people parent I didn't read because they would keep recording this as a bug but I thought that equal should just always mean call double equals and that B is the one that has these special things but if you look at it you think it would work just by looking at it you would think it would work so like if you look at the pedal and you think it's the gas but it's actually the brake or you know that's gonna you're going to screw it up right so I actually changed that and made that mean what the people thought it meant and then you know it was technically user error but was really a fault of the design because it you know people are too busy to read the documentation okay so that's one and then I think the way to make people work together well to collaborate is just to make it obvious if if drop dead stupid obvious what it means when you look at the code then that saves people time so that's hard to do sometimes so if you can't get that then make it guessable and that guessable is like you look at the code or they look at the code and they think sure what that means but I think it means X and it does mean that right that's guessable and if you can't get it the guessable didn't make it easier remember what that means is are going to have to look it up so they won't know what it means they won't be able to figger it out but they'll look it up but if it's easy to remember then they won't have to look it up once so that's I think for example one thing that's hard to remember is symbols if you have a lot of symbols symbolic names in your your library people can use it they can look it up but it's hard for them to remember symbols it's easier for them to rember names right if there's too many of them so so here I actually this plus or minus I don't know if anybody remembers that but in early Scala test that's what I that's how you did it and the reason is is like I just wasn't sure that us that a simple was obvious enough and then over time I I just didn't like it it was too verbose and so I I went around with some you know informal surveys and people could guess it they weren't sure but they said does that mean plus or minus on is like yeah I mean sponsor mightest so i changed it to that so again i think that that making things obvious is the way you get people to work together they can just read the code in the save some time right okay and then there's two roles people play when they're working with code one is there reading code and one is there writing code and if you're designing a library you really want to try to make them equally ecstatic right you want to make them happy and it's just that sometimes that these two things are in tension so what I do when that when I can't get them to be you know equally nice for reading and writing as I favor the reader because I have heard people say and it seems to be true but I've actually no evidence that people read code more than they write it and so so i think you should favor the reader and an example of that from scala test was this in polk private thing when i had to come up with a name for that i had the problem with of naming which this room was named after I'm kind of curious how hard it was to name the room it seems like it would be easy but I had to side with the name this thing and what it does is it causes it it allows you to invoke a private method which is a no-no and even in testing philosophy people tend to and I agree that most of times you don't want to test private methods you want to avoid that but occasionally it's useful so i made this thing it uses reflection and i just had to come up with a name for it and one of the names i considered was this this little lightning bolt operator which I thought looked pretty kind of cool right and it's like lightning strikes the object and private method gets invoked in that kind of you know you might be able to figure it out but it just I didn't think it was obvious I didn't think it was guessable and I didn't think it would be easy to remember because I didn't want people to use this that often i didn't expect people would and I didn't really want to encourage it so I picked a that's what i use and the other reason I use that it's just like it says what it does but it's kind of a boast to write out so I sort of favor the reader over the writer here and if it had been something that I thought would be used a lot I would have probably come up with a shorter name but probably still made it a word but because it it I didn't expect to be used a lot and I kind of wanted to discourage it i made it spelled out so that's a no private so another one which i think is very central to scala is [Music] you know all i want to do is see there we go how much time I have left so one of the other things that I think is very central to ask Allah is use the type system to make errors in not compile right so it saves p because it saves people time right it's not just it also makes things makes it impossible to get things wrong but it also saves people time because boom they get a compiler when they try to do it the wrong way and so one of the things I did in Scala test early on was I had to think about what should be the default for parallelization of of tests when you run tests should they run in parallel or not and [Music] tests are usually embarrassingly parallel I zabal so it seems like a real simple thing that you usually want to run them in parallel but if they run in parallel by default then you have to think about concurrent access to shared mutable state and so people do put that in tests and it's not the end of the world if you got a concurrency bug in a test but still I wanted to make it harder to have that kind of problem so the default in Scala test is actually all sequential there's no parallel by default it's not an svt that defaulting SBT is parallel and that actually I think does make sense for tests but when you just ask Allah tests like a fun sweet to run in parallel what it does is it it doesn't it runs all its test sequentially but if you've got 100 sweets then then those will can run in parallel so that's its parallel at the class level by default not at the test level because usually in tests these things are pretty isolated from each other usually you know there's a lot of times there's data inside a test class and multiple tests share that data and it could be mutable but there is not it's usually not the case for like multiple ones right so that was what the the default was and to actually run tests in parallel you have to mix in a trait and that was why it's just because now you have to have to worry about concurrency you have to worry about shared axis yeah that's kind of concerning a loud boom when I walked out at the bar today the protest was just going down the street but hopefully that's okay but anyway parallel test execution is also there's in Scala test 30 there's an async fun sweet and I that was tricky because it would it would in an async fun sweet there is a each test returns a future and so it can quickly come up with a bunch of features that can complete later so I had to figure out what should be the default execution context in an async testing style and it wasn't obvious at first I thought well I mean if you're doing things with futures you'd expect it to run in parallel and that's what I did it to begin with and then I realized well now this by default there's the possibility of getting the concurrency bugs again and then a test you would in a test your lot sloppier you know you're not as careful you put stuff in there so I felt it was not unlikely people would have that problem so what I ended up doing in na in the async style is by default the there is a default execution context but it's one that we invented which just remembers the things to do so it doesn't actually do them when you like when you map a future there's no execution context that goes in there just sort of puts that job on a queue and so when a test excuse to just you know there could be all these jobs being built up and then it returns a future that thread is then used to execute those jobs so it's it means that within a test one thread is doing everything so you don't actually have to worry about synchronization by default and then we actually register execution of the second test as a side effect of or like a something that happens when the first test completes when the future of the first tests completes and the third test is registered to start when the future for the second Test complete so they actually all run in sequentially with one thread just like in in in sort of regular styles and then if you really want them to run in parallel you you can mix in parallel test execution and then the test will run in parallel but if you don't change the excuse me context they'll still within one test everything will happen on one thread so it's the same the same basically the same thing you get with synchronous tiles okay so and the other thing I wanted to mention is is like the type system like that that wasn't that stuff was not really about the type system that was just trying to make it difficult to screw up there's a J unit sweet that is the kind of kind of sweet if you if you're using j unit it actually is AJ unit test class and it's a scala test suite so you can run it with either tool that you parallel test execution wouldn't work as j unit has its own way of doing parallel test execution so I just if you try to mix it into a J unit sweet it won't compile and the way I did that was I just final override a lifecycle method and and you just get kind of an odd error saying you can't you can't mix this in because parallel test execution tries over light a lifecycle method that's this final anjana sweet okay so one of the things that I think is is a it's a human factors thing is the people the people you are designing for they actually know something I mean they are used to something and usually when you're designing something new you want to actually change their behavior in some way so what this trick is is to to choose your battles so so actually to sort of pool them into doing things the new way that you think is better by making them feel comfortable so an example of app that I've I've heard before was it the way what james gosling had in mind when he designed Java what what he thought the industry was doing wrong was they were spending too much time chasing down memory bugs in C and he thought they should use a garbage collector but C programmers and I was one of them didn't think it would be fast enough right so that was what he went he want to change people's behavior that way so what he what he did is he said Java was a will orchestrate he said this at one talk I heard him give Java is a well-orchestrated fraud because he fooled people into using C program wasn't using a garbage collector by making the the rest of Java looked like see right i mean the curly braces are the same and the while loop looks the same if looks the same the four looks the same but yet there's no way to free memory so i think you know he was exploiting the famille the familiar e of C programmers with the C programming language to trick them into using a garbage collector and i think scala you know he also martin or dare ski was trying to like encourage people to be more functional right so he picked his battles and and some of the things he left the same just because that wasn't important to him to change even though it could be arguably better like using colon equals instead of equals for assignment right maybe he liked that better but it wasn't like that's one more hurdle that if that isn't really important what he was trying to achieve he just leaves that the same right so so in in scala test one place i think i did that was this is what when I design you know when I first was creating Scala test this is what people were used to they were using j unit or testing g in java and running test methods and this was the way that I learned anyway when I first learned about unit testing was that you make one test method / method under test right so if I have a size method I call my test test size method and if I have a ahead method I call a test head method right and he just and I have these really long test because the method did a lot sometimes right and I would do a bunch of different things on that that's how we sort of thought and then what I thought I mean what I learned and came to believe is a better approach is to have each test focused on a bit of behavior so for one method there may be 20 different behaviors of that method you want to test you'd actually make 20 different tests and the using a method name for for you know the the tests name is camel case and it's painful so what I did is in all the styles in Scala tests I made it really easy to write focus test with descriptive names but this one was supposed to make people who are used to X unit comfortable because it's test test test it's flat it's just like j unit but it has that one change which is it encourages focused tests focus on one bit of behavior with a descriptive name so anyway that's a exploiting familiarity minimizing redundancy is a I think another way to keep things simple is is to not give people too much choice I really like this this thing from the Zen of Python you know we have the sip processing scholar rate or and the slip process sip is for like improvements to the language slip is for improvements the library that's called pep in in Python the pep is like a sip and they have one that's just philosophy so I think that's kind of a neat idea I don't know that we would ever be able to agree on a philosophy for Scotland our committee but there's one thing in there that I think is really nice it's there should be one and preferably only one obvious way to do that and that's how they hyphenated it so I copy dead I think that's a good thing right and I'm the guy that has like 50 to style traits right so what I would like to ask you to try this see if you believe me is this is a picture of my screwdrivers and the reason there so few is that we had some work done on our house a few years ago I think was well was 56 years ago and our my toolbox disappeared I had no tools 0 tools I'm sure was an accident but someone thought they were their tools and they took them so i decided i would just buy a tool i wouldn't go like you know we love doing this by big thing of tools you know i'm just going to buy a tool when i need it and just grow a toolbox over time with things that i actually need and at the time i took this picture which is a few years ago this is how many this is the entire this is all I screwdrivers I had fought five them one two three four five six of them so far that's all I needed so would my toolbox be simpler if I just have one screwdriver I no way it would because would make it easier to choose which screwdriver right it would make that simpler but then if it was the wrong size it makes my life more complicated right so I think that kind of complexity or redundancy when the each one is focused on a different task is is actually makes users live simpler what you want to avoid is this kind we're really you just have a bunch of different things and it's like well whatever you feel like you know and so I have tried to keep that out of Scala test and I it has snuck in and I've tried to deprecate it out sometimes I for example felt that should and must were you know in retrospect me if I just picked one so i did deprecated that one time and we had I user revolt it turned out that some people really want a purple handle and so you got to leave it in there so so so once you you have to be careful another guideline should be be careful what you put in because it can be really hard to take it out but anyway what with the style traits I I did feel like I come came to feel there was maybe just one or two too many I wish I could take some out and I was talking to us panera hidaka guy got his own acha one time and I was telling about this like I and I which kind of like to take one out or something and I see and I said he asked me which one I said well probably Platts back and the reason is because all the other ones were modeled after something like fun sweet was like xunit fun spec is like our spec right words Beck is like specs too so they were sort of everyone was kind of inspired by something there's cucumber is very popular tool and we have features back right but flat spec I'm invented it was not like anything else so I said you know that was probably the one I should have just left it out you know and he goes oh flats packet but that's so nice that's my favorite one and I was like a great i can't get respect so whereas stuck with them all but I'm trying really hard not to add any more and what and I did think they were you know focused on specific things if you're coming from here I want you to be comfortable to come with me or what you be comfortable but what what I found was that you know when you look at screwdrivers people can figure out what they're for by looking at them when you look at like fun sweet fun spec people have no idea what those differences are so what I what I realized is I needed to add guidance of like this one's for this use case this one's for that use case so that's what I what I did eventually so this one is fun sweet is people coming from xunit feel comfortable familiar right but you can write descriptive test names and focus tests so okay so that's a minimize redundancy maximize consistency is just another kind of simplicity because it's one less thing for people to like inconsistency is another thing for you to keep in your head in the example i give here is this one which i think mr. Bader and still here but i think they're going to get rid of in 213 which is that by default when you just say set in a scholar program it means immutable set when you just say map the scholar program it means immutable map which you say seek it means general seek that could be either mutable immutable so i have release code thinking i was like an immutable index seek and it actually wasn't general which is not the end of the world but it's just a very easy mistake to make because because it looks like it would be immutable Zeke right so that's consistency and then there's this one this I'm not sure why put this near the end but I think that this is one of the really tempting knobs to twist is to make symbols and the guideline i think is good to keep in mind for like deciding whether or not to use a symbol is if your users are already experts in that symbol then you should use a symbol but otherwise maybe you should pick a word and the reason is because they're none if they're just kind of it's hard to come up with but if they're not an expert they're going to have to learn if they have to look it up and learn it and it's just hard to keep those things in your head for some reason keep any of them in your head and the example that I would like to show here is these are both valid Scala code using biginteger but the top one is using java.lang begin ature and the bottom one is using Scala something math biginteger java math beginners you're in Scala math beginner so I think you know this symbol one is a lot easier to read and especially get a large expression it looks like math to me but I think the reason that it's better than using words is because I'm already an expert in star n plus i know it means star and me plus i know what the you know what it means so if you are doing a library for internally for for scientists who are always in some domain where the papers that they're reading have all these little squiggly things if you use symbols they like oh yeah and what that means it actually will make it better for them so you should use symbols if they're experts in them but otherwise I think it's better to use a word and and just just use a word what sometimes people will say is that well you know what the best thing to do is give people a choice you know if if my symbol is not obvious like frowny face here I'll just give you another option which is fold left which means the same thing an alias and I am one of the few people i've met who so I'm kind of swimming upstream here but I don't agree with that because it gives the writer a choice doesn't get the reader a choice so I think really you should pick one or the other either it's also a kind of redundancy right there's two ways to do it so just pick one way and the way you decide is is it you know is that symbol obvious to their users and they're already experts in it and it's not obvious is it guessable like plus minus okay and easy to remember is another one I mean it's basically it's not like you should never use them but just decide if it's if it's the right thing to do then just use that otherwise just use a word okay so that's symbols and then lastly this kind of goes back to number one which is try not to use library features for applique just keep that just silly simple create objects invoke methods on them look at the answer right in general there's there's all these features in Scala that are really allow library designers do amazing things and just make really great libraries for people to use but you want to achieve that with a minimum amount of those features because like like what I think the trade-off is is that this client code is really clear for the domain that it is whatever the domain is but how it works is not necessarily always so simple and sometimes people need to know how it works so I think that keeping the magic down is is very important and Dick wall tells a story of when he was a kid he would went to the garage one time and his dad was using a new power tool it's back to tools again it's like a you know one of these drills that elect our drill and dick of course wanted to use this new toy and his dad said well here I want to use his hand drill first it's like what I want to use that thing and what his dad said is that remember what tools are for their for solving problems not finding problems to solve so I think that's you know a good way to think about scala's feature set is don't just use them because they're fun even though it is fun try to avoid that temptation and just use the minimum set of features necessary to solve the problem ok that is all I have to say about simplicity and I'm sorry it was a little more complicated than I'd hoped but anybody have any comments or questions yes huh that's interesting so he I don't know I'll repeat it since he didn't get the the microphone is there's another Python mantra that explicit in place I think it's in that same pep yeah I don't think so i think we actually I think we have a different philosophy which is so that the trade-off with implicit is what implicit implicit since kala can do is it can simplify it can drop boilerplate it just falls away like rose petals and all that's left is the essence of the meaning and it's beautiful when that happens right but then what can also happen is an example of this was using my first time using spray this guy sitting next to me in the cubicle that I was working with he said can you explain how this is happening and I couldn't I'm you know I couldn't figure it out because it was a magnet pattern and there was implicit and I couldn't find it right so when it's when it's not explicit it can be very obscure so you know we have to balance balance that but I don't in Python they did have a different philosophy what you always makes it explicit somehow he kept it simple anybody else and I like Python but I like school better but I think it's nicely done okay that's cool let's hope those booms were a good thing celebration right thank you [Applause]