Ruby Conf 12 - Boundaries by Gary Bernhardt

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
the title of this talk is boundaries this is the only one word talk title at this conference which I'm very proud of the next shortest is three words thank you this is some of the stuff in this talk is going to be very familiar to anyone who comes from certain functional programming backgrounds but this is a story of me approaching some ideas that they have from a very different direction and from a very different history so I am Gary Bernhardt so I would look like this on the internet where sometimes I get mad and my Bluetooth is not working very well I might have to forego it I own a company called destroy all software that produces screencasts on various advanced software development topics and to start us off in this talk we're going to start with test doubles there are a couple talks about test doubles mocking and stubbing at this conference this is not a talk about test doubles but they are going to be part of my motivation just to make sure everyone's on the same page let's go through a quick example of what an isolated unit test might look like I have a sweeper class this is in some kind of recurring billing situation and if I have a user who is subscribed but has not paid in the last month I want to tell him that something's wrong and disable his access so when his subscription when a subscription is expired we will make a user Bob he's going to be a stub he's an active user and he last paid two months ago we will have an array of users that's just Bob for convenience and before every test we're going to stub out the user doll method to return that array of Bob so this is one of the ways in which we're isolating ourselves from third parties from other classes like user we want to email the user when the subscription is expired so we will invoke the sweeper and we expect it to call user mailer billing problem to send an email to this user telling him things are bad so this is an isolated unit test it's isolated because it moves its dependencies like a user and like the user mailer hopefully my phone is back now awesome okay the implementation of this is very simple we will pull out all the users from the database we will select only the ones who are active users but have not paid recently enough and then for each of those we will send the email right so very straightforward stuff what we have here is a three class system these three classes integrate in production but in tests where we're moving two of the dependencies replacing them with stubs and mocks giving us this as our testing world so everything is nice and isolated there are several good reasons to do this several very big benefits that come out of it but there's also one really terrible thing that happens when you do this so let's go through those this allows you to do real test-driven design looking at your tests seeing that you have mocked six things and two of them are mocked three method calls deep this tells you that your design is not so good for this class so it gives you a form of feedback that you can't get without isolated tests at least I don't know how to it allows you to do outside in TDD where you actually build the higher-level pieces before the low-level pieces exist so we could TDD the sweeper using the user using the user mailer before those classes exist because we're just stubbing them out anyway then when we want to write the user class for real we can look at what we stubbed and that tells us the interfaces it needs and finally this gives you very fast tests this is one of the main things in the whole fast rails tests me more I don't want to call it a movement but people getting excited about fast tests in the rails world and we're talking about the difference between a 200 millisecond time from hitting return to seeing the prompt back versus a 30-second time to run a very small test it's a very big difference when you're when you're really isolating so these are all very good things that you want but they are balanced out by a very bad thing and that bad thing is that in tests you're running against a mock and a stub and in production you're running against real classes and if you don't stub the boundary correctly your tests will pass and your production system will be wrong and this is this is such a big problem that for most people I think it overshadows all those benefits even if you explain them to them they're going to look at this problem and say it's not worth it now there have been attempts to fix this various various approaches to try to solve this problem in one way or another one of which is to solve it with more testing contract and collaboration tests this is an idea sort of most closely associated with JB rains Berger who is one of the people who is most influential on my understanding of isolated unit testing I've not actually done this and something about it doesn't resonate well with me but it is one attempt to fix this there's also the tools approach our speck fire is a tool and Ruby that tries to solve this problem if you mock a class in art with r-spec fire it will make sure that you only mock methods it actually exists so and make sure that you don't cause these boundary problems or at least you don't cause simple boundary problems and finally you can solve this with static typing like so many things in life it comes with all the same costs you pay to solve anything with a powerful static type system but if you think about your mocks as being subclasses of the real class they just remove all the actual implementations that gives you an idea of how static typing can solve this boundary problem all of these only solve simple kinesins mismatches between objects they solve things like I called the method with the wrong name like passed the wrong number of arguments they don't solve deeper things like my two algorithms that need to cooperate don't actually cooperate correctly the way that you can solve that and the most common way people try to fix this problem is by just not doing isolated unit testing by just integrating right the problem with solving the isolation problem with integration is that integration tests are a scam I can't try take credit for the sentence this is once again JB rains burger there's a talk called integration tests or a scam which you should all watch it's a really good talk that really lays out the argument for why integration testing doesn't work on a long enough time scale and he nowadays uses a terminology integrated test I mean any test that's integrating multiple pieces I'll give you the really quick and dirty argument for why integration tests don't work the number of paths through your program goes like 2 to the n where n is the number of branches or conditionals and that includes try/except that includes a short-circuiting boolean expression that includes a loop every time a branch is happening if you have n of those you have 2 to the N paths and if you're trying to test the whole thing you have a space of 2 to the N to decide to choose from if you have 500 conditionals in your program this is a number with about 150 digits in it it's a very large space it's very difficult to effectively choose which which paths matter because they're effectively uncountable to you the other problem is that suite runtime and an integration suite is super linear whenever you add a unit test or whatever kind of test you're writing you're also adding a little bit of code so your number of tests goes up by one and you make the system a little bit bigger which means all your existing integration tests get a little bit slower so every time you add a test there are two sources of slowness one of which is linear and one of which is something else I'm not sure of but together it's definitely a super linear runtime and anyone who has a three-hour rales test suite will be able to tell you that this is in fact the case and they will probably not like their lives very much either so that's all background this is this is how I came to the ideas of this that I'm going to talk about for the rest of this talk this was this has been a large focus in my software development career for the last five five years is isolated testing and figuring out how to do it well so now it's shift gears entirely talk about values values meaning the the pieces of data inside of a program if you want to test the plus method and let's just think about + on machine integers and for whatever reason you decide you want to test it in isolation so you don't want any other dependencies involved in the testing what do you have to do to isolate plus nothing it isolates for free plus doesn't have any dependencies there's nothing to mock out there's nothing to stub it's totally local and why is that the case it's not just because + whoops it's not just because plus is simple it's it's tempting to say oh plus is simple so of course it isolates for free that is not what's happening it has two properties that are necessary to be naturally isolated with no stubs or mocks the first is that it takes values arguments and it returns new values and it doesn't mutate those values it just gives you a new value right it takes an integer in an integer and it gives you an integer the second property is that it doesn't have any dependencies there's nothing to mock it doesn't it doesn't need anything else it's a local computation that just produces a new value so how could we apply that to more complex code that we work with all the time stuff like the sweeper well let's go through this and just impose both of these constraints and see what happens starting with the Bob stub we can't use a stub because we're not faking out any boundaries so let's replace that with a user object but not like an active record object but like just a struct some kind of a piece of data even a hash I wouldn't use a hash but you could just use a hash we can't do the the user dot all stub because we're not allowed to so we'll just delete that and then the actual body of the test instead of doing a mock expectation we can just call the method and get back the array of users who are expired now this does less than the original code we're going to get to that later the the implementation changes we basically lose the second half we now have a method that goes through all the users and returns only the expired ones this difference is huge the difference between the original code and us is huge the the nature of the communication between the components has changed instead of having synchronous method calls as the boundaries between things we now have values as boundaries the value returned or taken by the method is the boundary between it and another object now just as a quick digression when I talk about values I often mean things like this may be a class that is a struct it has two fields title and body and it has a slug computed from the title but behaviorally this is equivalent to a class that has a title body and slug and computes the slug at creation time they're basically the same thing right the only way to tell the difference from the outside is timing properties on the method calls so I'm going to use these two ideas interchangeably but really they're basically the same so we've seen isolated testing as a bit of background the idea of converting the code in the system to communicate via values at the boundaries instead of via message sends or method calls at boundaries and now I want to look at how this fits into the three dominant programming paradigms putting aside logic programming but how does this relate to procedural low and functional programming here's a small piece of procedural code we want to feed some walruses so for each of the walruses we shovel some food into its stomach we shovel some cheese into walruses stomach there are two properties of this code that make it very obvious that it's procedural the first is the each whenever you see each and Ruby there's something destructive going on each each with it with a non destructive body is a no op so there's something destructive happening and we know the structure of the walrus and the structure of its stomach we know it has a stomach we know the stomach can have things shoveled into it we have knowledge of the internals contrast this with the oo solution where you still have in each it's still destructive in most oo code but now we tell the walrus to eat something he knows how to eat instead of us knowing about his stomach and then the eat method will shovel things into the stomach same code as before just encapsulated and my Bluetooth is dying again so we have two two paradigms here both of them involve mutation one of them separates data and code that's procedural one of them combines them into units called objects if we add functional to this instead of doing in each we do a map we're going to take all the walruses and produce new walruses that are slightly different so for each of them we're going to call eat on the walrus and some food some cheese and I'm going to use a hash for the walrus and array for the stomach and strings for the food so in the eat function it's kind of weird but we build a new stomach that's the old stomach plus the new food and then we build we build a new wall wrist that's the old walrus with the new stomach you can see why oh oh models real-world things a little better than functional programming does okay so that's that's functional nothing is being mutated right so we have no mutation but data and code are separate they are not combined into single things now if you look at this table obviously I've left a row there's one more row to go but even just looking at the variables we have two variables does it mutate or not does it bind data and code together or not they clearly vary independently which means we have four possibilities so what is the fourth possibility it's not logic programming by the way here's what the four spot fourth possibility looks like we map like in functional programming so we're producing new walrus's but we're telling the walrus to eat something and that's not a destructive eat instead they eat method constructs a new walrus that is the old walrus with a new stomach that contains the new food so it combines the immutability of the functional code but it combines the merging of data and code together like oh oh does and that is the fourth entry and I call it lovingly pho because it's not real low now there's a problem with programming this way and that problem is that you lose the ability to do anything destructive to talk to network to talk to disk to do any kind of i/o you lose the ability to maintain state over time so to to reintroduce the idea of state we have to add imperative programming back into this sort of photo style of programming we have to figure out how to compose the user database the expired users class and the mailer together even though the expired users class is functional in nature so we have our expired users it returns an array of users who we need to notify and what we need to do is reintroduce the imperative layer around it an imperative shell which surrounds the functional core it talks to the database it uses expired users to filter those users and then it emailed each of the ones that comes out so the imperative shell is a layer that surrounds the functional core the functional core is the bulk of the application it has all the intelligence and the imperative shell is sort of a glue layer between the functional pieces of the system and the nasty external world of disks and networks and other things that fail and are slow if we if we look at what's actually happening in these two things it's not an arbitrary distinction even though all I did was cut the original method in half this division runs very deep if you look at what these things do the expired users class makes all the decisions and the sweeper class has all the dependencies so if we look at the way that that relates to testing the functional core is heavy on paths heavy on decisions light on dependencies which is exactly what unit testing is good at especially isolated unit testing when you take away the need to stub out the dependencies you can just focus on the logic and the tests become very simple and exactly the same thing is true for the shell lots of dependencies few paths is exactly what an integration test is good at it because it makes sure all the boundaries are lining up all the pieces are communicating correctly but you don't have a lot of test cases which means you don't end up with a 30 minute or a 3 hour test suite just to get a sense of what that integration test might look like since we already saw the unit test maybe I create two users in the database actually create them in an actual database I invoke the sweeper I pull out all the mails that were delivered by action mailer and I make sure that only Alice was mailed she's the only one who's expired he or she paid two months ago Bob paid yesterday but I only have to write one of these whereas I'm going to have to write a bunch of the isolated tests on the functional core so now we have a a solution to the isolation problem in for most code in system because we can build it all as functional pieces in this sort of flow style where there are still objects but they're not mutating and they're just taking values in and out and we have a way to reintroduce the imperative part around it so we can actually talk to the outside world and it turns out that this leads to all kinds of amazing benefits not just the testing benefit not just the fact that functional code is easier to reason about over time but it even makes certain types of concurrency much easier if we think about the actor model of concurrency which is the one that I have the most faith in as something sort of approaching a general-purpose concurrency style or currency programming method let me quickly explain it to you just in case everyone's not familiar I'm going to do it with just threads and queues so we have a queue and this is going to be the communication mechanism between two processes it is the inbox of process to process one is going to send to it for process one I'm just going to fork off the thread that is going to infinitely loop reading from standard in and pushing into the cue process to is going to infinitely loop reading from the cue and writing to standard out so this is an echo program that's communicating through a cue where the cue is the inbox for process 2 if I just run this at the shell and start typing things into it it's just going to print out whatever I sent in this is the the simplest way I know to explain the actor model you have independent processes each of them has an inbox it is only readable by that process and they communicate by sending messages to each other into each other's inboxes the reason the way that this relates back to functional core imperative shell 2 fo o 2 the idea of having lots of values is that every value in your system is a potential message a possible message between two processes every value that is struct like and can be easily serialized can also be easily sent over the wire and this is a special case of the value is the boundary between the components so if we rewrite our sweeper in a slightly different way so we have a sweep method it calls expired users on user dot also pulls everything out of the data out of the database finds only the expired ones and then for each of those emails this is the imperative shell that you're looking at right now the functional core is the expired user's class it's going to do what it did before or the expired users method excuse me it's just going to filter out expired users and then we have this very trivial notify a billing problem thing that just delegates to the mailer let's translate this into the actor model for the first one I'm going to make an actor that pulls everything out of the database and just sends them one by one into the expired users actor and then dies if I didn't do die then this would loop infinitely the expired user's actor is just going to pop a user off of its Inbox it's going to decide whether that user is late and if it is late it's going to forward that user on to the mailer process and the mailer process is just going to invoke the mailer so the imperative shell is sort of a bigger process it takes a little while to run it fires off all these messages to the smaller processes and what we've just done is converted a program that could only use one core into a program that can use three cores not on MRI but on other VMs we'vewe've parallelized this by doing very little work because we had the values available to send over the wire oh I forgot to actually translate that there's the new version it's the same thing as the old basically values in your system afford shifting process boundaries but really in general values in your system afford shifting boundaries between anything between a class arrangement between subsystem arrangement between the wave you're building your program whether it's serial or parallel so this has programming in this style has surprisingly deep effects on the things you can do in the way that you can do them that was a lot of stuff so now I'm going to try to reset it in like three minutes to make it all tie together in this style you design your program as a core of independent functional pieces that take values and return values the imperative shell orchestrates the relationships between those interfaces them to the network the disk other nasty systems like that and maintain state for example I wrote a Twitter client in this style it's sort of a it's a terminal program but it's interactive like vim would be so you hit J to go down to the next tweet the imperative shell sees the J calls into the functional core to generate a new cursor position the new cursor is generated and returned and then the imperative shell updates the instance variable holding the cursor to be the new cursor the functional core built the new cursor and it was a purely functional operation the imperative shell just updates references to these new objects as they're constructed what you get from this is easy testing especially isolated you also get easy integration testing and the distinction between which one happens where is a lot more obvious than it is if you just start throwing things against the wall and try to figure out what gets tested how later you get fast tests you don't have to do any weird stuff to get fast tests so just inherently fast because they're functional and working on small pieces of code you have no call boundary risks you don't have to Stuber mock you have easier concurrency at least in the actor model and you have more fluid transition between concurrent and serial computation and that's all just a special case of having higher code mobility in general moving code between components moving code between processes so that is the end of the actual talk once again I am Gary Bernhardt I run destroy all software which produces screencasts and if you are a subscriber or want to become one it is not free but there is a screencast on destroy all software called functional core imperative shell which is the first time I ever talked about this in public and the one that's coming out two weeks from now is also about this topic expanded a little more and in that screencast I give a much larger example that I can't really give here but I show you the Twitter client and how its arranged and how how the different parts of the system are segregated in this way so with that thank you guys very much for listening to me for half an hour that actually went way faster than I expected so I would be happy to to take comments or questions or yeah do you think there's any useful distinctions besides the functional bit between like a ports and adapters architecture right that's a wonderful question the question is about port the relationship to ports an adapter is writer or hexagonal architecture or these kinds of things yeah so if you're building a large system that's going to be 30,000 lines of code you don't want to have one functional core and one imperative shell if you ask a haskell programmer about doing this they will tell you that that it just becomes a nightmare I think that the the ideal large system is actually many smaller systems built out of this in a sort of way you you have the functional pieces you wrap them in a layer of scar tissue to interface them to the nasty outside world and then you build a bunch of those that communicate in destructive ways is it does that answer the question sure there's no adapter in that explanation but it's sort of the adapters are the stars exactly that's true I guess yeah does some extent the the the imperative shell is just an adapter fair observation yeah over on the side the question is how if I have how if I find sound success in using actors with Ruby the answer is no I have so this this Twitter client that I that I wrote to as I was figuring this out does use the actor model but it's just threads and cues I just built a little actor library it's like 35 lines of code a simple actor library is easy a more complex one I see diminishing returns if your VM isn't built for it you can't spawn half a million processes in Ruby your machines just going to go up explode into smoke so use our lang yeah paradise bringing in other gems of libraries the same time like let's see a traditional right so the question is how suited with a rails app be to this style development the answer once again is no it's not going to work very well you could I mean it depends on how large your rails app is the thing about a rails app is if your rails app is a hundred thousand lines you don't have a rails app you have ninety five thousand lines of your application and you have five thousand lines of rails glue code and probably what you've done is dumped those ninety five thousand lines into models controllers and helpers and fail to actually design your system if you have designed a system and treated rails as a small component of it that you want to mostly protect yourself from then you might be able to do this but to be honest I've I've never even thought hard about how you would do that I guarantee it's possible but but you're not going to transition your large rails app into this easily by would be like we do letters a lot written software and you if with the imperative shell wrapped around the functional core you can do whatever you want out there right so you can use I mean like my Twitter my Twitter client uses all tons of ghent well not tons it uses like six or eight gems normal gems that are just you know work like anything else and they're they're imperative in nature as oo programs and Ruby programs tend to be and I just put them out in the scar tissue layer and I let that be as big as it needs to be to reasonably allow me to use it and then in the functional core it doesn't it doesn't have to see any of that stuff it is this is exactly this is the difference between just thinking about that sort of photo style programming the functional oo style and then actually adding the imperative shell the imperative shell is what allows you to build real software that actually does work in this way so when you give the functional example you create Larson and sort of a true functional standpoint right just returned data sure you feel about the next level like you know there's nothing special on Wohlers that's stomach return data and so you know like how do you feel like going next level so I missed the last sentence going even more functional I guess well I wouldn't consider changing from returning wall or sister returning stomachs as more fun no unless ain't dancing right well if you look at the code I used the word walrus but really there's nothing especially while we're see about the code you could replace that with animal and it wouldn't know the difference right it just knows that there is a stomach key and there is inside of the stomach is an array of various foods so it's not tied to the to the walrus nature of the walrus the the user has lost right the class of the boys it's not well no I never mentioned a walrus class I could have used the word animal it would have been the same thing right as long as it as long as it has a stomach that code will work on it I just used walrus to make it more concrete give it like whether it's how you build up the wing just for 30 days eg if values are the neighbors then like different values or boundaries objects are data if they're if all if all the methods on an object are pure functions then the object is data and it's indistinguishable from an object that's struct that has everything early bound right late binding only matters in a in a system with mutation in it this is why for example Haskell is lazy well Haskell is weird yeah I don't know how else to say that I feel like I'm failing to understand some part of your question okay yeah yeah so well if you go if we go back to the place where I actually did that where I merged way back here there it is this was actually the functional example right if you look at the the functional oo example I just did Wallace knew which is a little more natural there's not an easy way to say I want a new object with only this field changed because Ruby's not designed for that but that is easier to build in than it would be to build in to replace all your core types the nice thing about the Ruby core types is that the the really scary things have bangs on them usually the mutation it's not true for like delete but but the names are usually very obvious that they're mutating or they have a bang on them I've actually not found a problem maintaining maintaining functional data structure manipulation code in Ruby your mileage may vary yeah in the back despite your cultural important there's a whole bunch of these exactly what they're doing it certainly could you have to spend what I've found is that the the choice of which classes you have in the core is extremely important the names of them and the way that the responsibilities are divided up so actually I could pull up part of the Twitter client and show you guys a larger example let's see wait where am i yep so for example the cursor cursor this is one of this is a piece of the functional core it has state that includes the tweets in a list of tweets and then selection is the currently selected tweet all right so this encapsulate all the behavior of the cursor actually why is my keyboard not working part of some of this is gross like it's actually quite a large class this is one of the largest classes I've written since I started programming Ruby it's almost a hundred lines but that's because it's really like a very small module dude laughs it's like a very small module of functional code it's just sort of self-contained and then if we look at the actual imperative shell this is the entire shell it's 153 lines that what that says you guys read that there sorry about that so let's see where cursor dot something with tweets no starting at index the shell is sometimes a little bit awkward here we go so here is the cursor actually being manipulated when you hit J it just reassigns the current cursor in the shell to the result of doing cursor down and if we look at cursor dot down all it does is construct a new cursor so the fact that I chose cursor to be one of the boundaries in the functional core is very important if I had had if I had a tweet list and then was maintaining a selection separate from that this would have been awful it's very important to find those boundaries that make very small cohesive functional components but not too small I mean I showed you like three line examples in the talk but that's because it's a talk really you want pieces larger than that but smaller than a whole subsystem does that answer your question at all I was Chuck right yeah I can't see but I can hear hidey-ho yeah that's the hard part I mean that's always the hard part right but separating separating things that do mutation from things that don't gives you a starting point and I it's the best starting point I've found it's not an absolute rule but if you start there as opposed to some other arbitrary rule I found much better results or design other questions there is no library the Twitter client is not online because I stopped working on it because it turned out that Twitter Twitter's evilness is growing much like test run time of an integration suite and I lost confidence that I should build software that interacts with it sorry Twitter employees I assume there's something here yeah so nothing oh if it's not sorry fair enough fair enough at least it scales okay pretty much new objects while you see because you like to start as well yeah I mean the the Twitter clients doesn't really have many performance concerns I mean it does when it comes up it's sorting through thousands of tweets it remembers everything all the way back and so it has to do a merge of like what it has versus what it sees from the API but it's not doing anything really big in an MRI your life may not be especially good if you're doing tons and tons of allocation if you're in the JVM it's much better right and if you're in a VM that's designed to have constant object creation and destruction it's going to be even better than that a VM design for functional programming I would guess that the Erlang VM would would handle this very well for example because in Erlang you're constantly making small objects and letting them be freed so yes doing doing this on MRI if you have performance concerns is probably going to be a little difficult but you can do certain types of caching right if everything is a value in immutable you can always cache things because they don't change so there's there are ways there ways to work around the the unfortunate nature of your VM I saw a hand back there yeah what's the what's the biggest thing you've built using this style and do you have any concerns that as it gets big the ability to organize those both good questions what's the biggest thing I built and do I have concerns about scaling this into larger projects the biggest thing I built is the Twitter client it's not that big it's about 600 lines and I would not be up here talking about this if that were why I thought this is good the reason I think that this is good is that it it has it has shades of both the actor model built into it the idea of functional pieces that are communicating by passing values back and forth and it also is a lot like the Haskell idea of using the i/o monad to encapsulate state which is a wonderful idea that scales wonderfully up to about 500 lines of code and then everything falls apart right you look at a 20,000 line Haskell program that does a lot of i/o and you're not going to like life that this is why I say I think that the larger program is is smaller ones built in this way communicating via via channels external to the process but what I'm really trying to do is merge merge this idea of actors merge this idea of the i/o a monad and bring them into the oo world using our terminology right I didn't talk about monads I only talked about actors at the end as an example I'm trying to rephrase that stuff in terminology that we use so that it seems more directly accessible but to get back to your question about about larger systems some of the largest most well some of the most reliable large systems in the world are written in Erlang and probably probably most of the reliable large systems in the world are written in Erlang lots of lots and lots of nines not not like Twitter's three 9s we're talking about like eight nines right and the fact that they can build large systems that are that reliable using the actor model even not even knowing what those words mean tells you that there's something there right so that was a long-winded answer to a very simple question yeah very uh if there's an approach that you might recommend one we're creating new rails app and let's say they were hitting a user model that was sub classing active record base they're an approach that one might take try to expand it with the techniques you're talking about an isolate right what sorry if you're building a new rails application and you're doing things like you have a user the subclasses active record base how do you how do you go about doing this I haven't gotten that far yet I have opinions about how you should be building that application but they don't involve this that's a different talk called deconstructing the framework but yeah it's not clear to me yeah give me give me a year or two others yeah deal with the case where the extraction starts exactly be in the sweeper capacity featured at all but they turned out the database is really fast that yep one of the reasons that my talks tend to take half as long as when I practice is I forget to give all the qualifications like for example you don't want to actually do that right you don't want to call use it all then filter in in Ruby the most of the complexity of your application is not database clearing right I mean there's plenty of querying in a complex app but but it is not the 50% of your application it's a fairly small percentage and I think that probably if you're using a using Postgres or my sequel or sequel light that goes in the shell if you're using something like de Tomic which is a database where everything is immutable that can go in the functional core it's just data structures data economic is just data structures so it depends on the nature of your database and the more your components are designed to work in this way the more can move into the core but it doesn't mean that pieces it doesn't mean you can't do this if you have Postgres it just means Postgres has to be relegated to the scar tissue which i think is fine 80% functional is a heck of a lot better than 0% you don't have to get to 99% yeah front row keeps you what keeps me in Ruby inertia to a small extent also I just don't like any of those languages I have this this problem where I can't I can't not care about syntax I really like syntax and I've written I wrote a lot of Lisp in college and I just never really enjoyed it that much Python and Ruby or what I like syntactically this is why I want to go live on a cruise ship and write a new language how are we doing on time is 3:10 we can do a couple more guess yeah ways to fix these problems contribute to Rubinius for about a year until you know how it works and then for Karoubi language i'll tell you how to do it i mean you want persistent core types all right you want to you want core types that are designed to be used in this way and from that most of this will fall out pretty pretty naturally you probably want actors and lightweight processes and you're going to have to build a user land scheduler but it's not that hard that's what our lang has and if you have a user land scheduler with lightweight processes if you can fork ten thousand hundred thousand processes easily and you have immutable core types you're most of the way towards doing this ninety-nine percent of the time or ninety-five percent of the time yeah back right RT sort of ask the question before is someone who's ah very well acquainted with Eagles Twitter guys I would still encourage you to go execute this is an example this style yeah the question is why won't you answer my question no that's legitimate I do I do plan on putting this up eventually even though I kind of am NOT happy about Twitter I just I struggle with the idea of encouraging people to write software that interacts with something I don't like versus demonstrating something that I think is good so yeah also it's a little bit embarrassing like the shell is not actually tested at all there are zero tests around it even though 250 lines long which I think will give people the wrong idea I mean I have reasons that I did that but but they're very hard to articulate in like a readme to anyone will actually read so I'm a little torn about encouraging bad things metal right I think that this is a little bit more of a minute but since I'm interested in a lot of your ideas here I just wonder if you look at array languages and their approaches to concurrency right versus thinking about these are thread levels and I'm wondering because I have a thinkable idea working for the long part from future concurrency just wondering what your needs are right so the question is have I looked at array languages and and dude believes that thinking explicitly about threads or I assume you mean processes as well like any kind of explicit yeah thread of control think about those explicitly isn't is not the the right long-term thing the first the first answer is no so that's easy I mean I'm familiar with like J and all those languages I don't actually know any of them I've seen small snippets but I don't understand them the to the second part about threads and arrays or threads and processes not being the right primitive I guess would be the word right then right primitive to build on I'm not convinced that that's actually true I'm not I'm not convinced that they're the wrong thing I assume the alternative you're thinking of is things like a parallel map right like like implicit parallelism that if you're still writing sequential programs to just have parallel pockets whereas in the actor model everything is inherently parallel I mean if it's even remotely reasonably decomposed right as long as you don't have one process that's doing a ton of work so I'm not totally not convinced that that the threads and processes are wrong well I'm convinced that threads are wrong if you're sharing the state but I'm not convinced that independent threads of control independent processes of control are the wrong thing yeah we thought about writing your twitter application using a more open protocol like writing the Twitter app against a more open protocol like Oh status I guess I could doesn't sound very interesting that's the problem I I already wrote it once I don't want to write again maybe I'll put it on github and I'll accept pull requests that put it on a more open protocol I think yeah that it is time thank you guys very much you
Info
Channel: Confreaks
Views: 40,729
Rating: 4.9353681 out of 5
Keywords:
Id: yTkzNHF6rMs
Channel Id: undefined
Length: 45min 55sec (2755 seconds)
Published: Sun Nov 25 2012
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.