KotlinConf 2018 - Representing State: the Kotlin Edition by Christina Lee

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

So many people praised this talk on Twitter. Can't wait to see it. Christina is honestly so good.

πŸ‘οΈŽ︎ 9 πŸ‘€οΈŽ︎ u/Odinuts πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

This is something Kotlin is definitely useful for. The talk reminded me of a Domain Driven Design talk from a couple of years ago. It discusses DDD in F#, but a lot of the concepts apply to Kotlin as well. If you liked Christina's talk, I recommend having a look at this one as well!

Bottom line: Make illegal states unrepresentable!

πŸ‘οΈŽ︎ 11 πŸ‘€οΈŽ︎ u/nhaarman πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

πŸ‘Nice talk with some good examples. Lots of problems tend to evaporate when you write good models.

Conversely, bad models amplify confusion and produce more bugs.

πŸ‘οΈŽ︎ 9 πŸ‘€οΈŽ︎ u/cdflynn πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

Great talk overall, however I find the solution to problem #4 (at 38:04) less than ideal, or maybe incomplete.

The problem is that enforcing the check at every access will inevitably lead to many redundant checks, in situations where the video data will always be loaded.

Of course, as mentioned in the talk, relying on such assumptions ("the video data will always be loaded here, because of some UI event sequence") that are not enforced by the compiler is bad, because they can change over time as the code gets refactored.

But having too many unnecessary checks is a problem of its own. They obscure the logic and make the code less readable - the reader now has to think "when will this situation occur? can it even occur?". And because the person writing the code still has the expectation that the failure branch will most likely never be executed (but they have to write it anyway), the code that's handling it may not be the best way to deal with the situation once other parts of the codebase change and the branch becomes reachable. It's defensive programming, with all of its tradeoffs.

A better solution would be to re-design the code in a way where the compiler can prove our assumptions, which is usually done by separating the part where the video data is possibly uninitialized, from the part where it will always exist, so that we can only initialize the second part once we have the data (i.e. the second part is a class or a closure that holds a non-nullable reference to the data itself). Basically splitting the code along state lines and initializing things at appropriate times. All the code that counts on the data existing should then only go into the second part, and all the checks that remain in the first part will be real, necessary checks, where we know exactly how the "data missing" branch can occur (and can reproduce it if we want).

Of course, Android being what it is, this may not always be feasible and we often have to make do with sub-optimal solutions. I just see the "just enforce checks everywhere" solution as kind of giving up.

But again, that's the only part I have a small issue with, the rest of the talk was great.

πŸ‘οΈŽ︎ 7 πŸ‘€οΈŽ︎ u/DoListening πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

Oh man I'll watch this when I can

EDIT: I've watched it. It's just as informative as I expected. In these previous few weeks I've actually been wondering about just how crazy it is that we have if( statements where just adding a single ! can make your code execute the exact opposite of what you wanted. Crazy room for error!

Naming state with sealed data class, even in these "simple-looking" cases, seems like a pretty cool way of enforcing the contract rather than messing up with an infinite combination of &&s and ||s, which may or may not do what you intended. Sure, boolean logic - but one character error and it's broken to bits.

And of course, this pretty much is only addressing scene 1 :D there are all the others

πŸ‘οΈŽ︎ 11 πŸ‘€οΈŽ︎ u/Zhuinden πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

I'm surprised she did not mention inline classes. I know this feature is only coming in Kotlin 1.3. But it is so relevant to the talk.

Edit: great talk btw

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/jamolkhon πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

Very solid concepts that apply regardless of language. I find myself applying these sorts of concepts to restrict the possibility of illegal states as a Java-only programmer all the time. I highly suggest anyone to watch this regardless of whether you use Kotlin or not.

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/Pzychotix πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

I'm going to watch this as soon as possible, thanks for sharing :)

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/Exallium πŸ“…οΈŽ︎ Oct 08 2018 πŸ—«︎ replies

Correct Horse Battery Stinger

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/Devirichu πŸ“…οΈŽ︎ Oct 09 2018 πŸ—«︎ replies
Captions
[Music] [Applause] [Music] hello and welcome my name is Christina Lee a I'm gonna start with a fun fact about this presentation which is that for the first time in my life my mom is actually here watching me she wanted to know yeah I know I know I know yeah she wanted to know that all that money for college actually paid off so if you recall the bribes that I promised four enthusiastic applause and audience participation yeah they're gonna be on the left side of the door when you leave so like I said my name is Christina Lee and thank you for coming to my talk which is about representing state the cotton version of course now if you wandered in here by mistake I'm sorry you're stuck now but hopefully you came here knowing what this talk was about and specifically there was the sentence in my abstract and it talks about how representing state might be difficult and the ways I'm gonna talk about how we can make it better but of course because people know me pretty well and I'm an open book they have a lot of ideas about things that I like mmm you know chief among them this one yeah so of course when I said I was gonna be talking about something related to state they immediately said I cannot wait to hear about UDF for your new state management machine but as fun as it would be to talk about those things that's not what this talk is actually about because those things those are the mountains of state management those are the huge architectural pieces the decisions that you make once and revisit at most every couple years unless something's going on in your company in which case there are bigger problems but there's a lot of content around this because making the decision is so important and it leads to us overlooking some of the more nuanced zoomed in details specifically sometimes we don't dive as deep into these tiny cross-sections and by seeing the mountains we miss the stones we miss all of those grains of dust the grains of sand that may got those mountain ranges so this talk this talk is about sand now the format of this talk is like an upside down pyramid it's gonna start really small it's gonna start with a single primitive an evaluation of it and from there we're gonna slowly widen out and write it out up until we get a bigger state representation so with that let's dive in now I need some audience participation which I know is your favorite thing to do so get excited it goes a little something like this true or false any other answers anybody going for false anybody thank you all right so y'all are brave and you don't write into that and so if I told you now that's the thing that I was talking about is the statement dogs are amazing all right so some people change their answers some people stayed ok so that was pretty easy well let's try this one on for size true or false so that level of gamesmanship that you just had that was actually my exact point there was a pause there where you were wondering if I was the type of person that would try to hot-swap something positive with something negative and of course I am that type of person so that was a very well founded belief however the point stands which is that when I asked the question the first time and immediately gave you the context on it it didn't matter that you had just receive that context when I asked it the second time because you still weren't sure in the second instance what I was talking about was it the same thing was it different you had no idea now I can do other mean things too I can ask you questions like this is the restaurant open or not and of course this is a binary question it should be answerable with a true or false with two possibilities but of course it's also really ambiguous it's not great grammar but people ask things like this all the time if you don't know whether you're responding to the first part of that clause or the second part and that leads to the second interesting observation which is that the way in which a question asks heavily influences the answer that you give most astonishing of all the same idea it can be encoded using both true and false now if we apply de Morgan's law you'll see this on the slide right now which is that we can have some value that says is yellow equals true we can apply that negation and we can have is not yellow equals false this is pretty wicked and so it gets us to this point where we start thinking what do I need to make sense of boolean so what is it and and here are some things you might need you might need to know where is it coming from is it always the same representation of a value like how is the question being asked and what all of these bits of data are pointing to is the provenance of the bool that you're using where it's coming from and you know both by nature they don't give us a lot of information the lowest signal form of a bull is something like this where we have bull equals true and there's very little actionable things that we can do with a statement like this so a lot of us instead we do things like this we add context to bulls in various ways either with comments or by pulling them into named fields or by using a really great IDE by I don't know jetbrains and you get these things in line for free but this is great and this is what most of us rely on but the issue with some of this is that the meaning of these fools in all three scenarios it's coming from something that's not at all tied to the type it's coming from documentation now we're all fortunate because we know that documentation is always correct it's a lucky turn of events I know but for real this is actually a problem that we have and I'm basing all the examples today on code that I've either written or reviewed or seen because I don't want this to be theoretical I want it to be infinitely practical and so I worked on a project once to add video streaming tune up and just one boolean in this app went through eight or nine iterations you can see it most simple form it starts with ru in the experiment group for adding this feature and then it goes through all of these different permutations are you on Wi-Fi do you have the setting checked is another video playing etc etc so you can imagine if in version 0 I added a comma or a comment by the end there's a good chance that that comment has drifted a little bit maybe it's still mostly accurate but give it time and it'll be completely gone now this is problematic because what we've just discussed is the fact that context is really necessary to understand primitives like Bulls but there's nothing about the type that enforces it it's not tied to that it's all optional and so this concept that I've been beating around the bush for it this is actually given a phrase called boolean blindness and a lot of people they have reactions to this phrase they feel like they know what it means and they're not exactly on board and so I wanted to spell some Mis which is that boolean blindness has nothing to do with bullying's being bad doesn't mean we hate them or that we shouldn't use them because of course anything can be stripped of context here I'm using a more expressive type I'm using a mode that I've described as read and write so yes we have some data we know that we read writing but of course I don't know if this is network I don't know if this is database so I'm still in a little bit of a lurch what boolean blindness is actually trying to get at is this idea that we should prefer to work with types that have more expressive value not the boolean czar bad but that we may want to use a different tool for the job and if we put this as a problem statement what we get is this that blind types are really prone to errors when we refactor and people refactor a lot I know this because I've made a Twitter poll and the internet never lies so it's a demonstrably true fact now I'm not going to offer problems in this presentation which without of course offering solutions so here's the first useful thing I'll do which is give you a solution to this problem I couldn't use words better than this so I'm directly quoting someone and I'm going to read it to you says when you have lots of faceless data types in your code consider painting them with their domain meetings make them distinct make them memorable and make them maintainable now that's all fine and dandy but how do we go about doing that well here's another sample from code that I pulled it's a class and at the top of the class it has some variable and that variable is called header added now lower down in this class that I was reading there was this function called update item count and inside that function there was quite a block of code but you could boil it down into two main parts the first of which was acting on the case when the header was already present if this was true we started checking the item count and we would update it or we would remove it if there was nothing to show the second block of code of course dealt with inverse which is when the header wasn't present and here we were checking if the header wasn't present and we had items and we would add it and update it so together this was the bulk of the logic now you can probably see why this is problematic which is that we had a value called header added you would assume that a boolean like this is being used to know whether header has been added and it's true that it was being used to know whether a header had been added but it was being used for that purpose specifically because the real piece of data that we wanted to capture was whether the header C matched the number of items that we had that's what we cared about and we were using this other boolean as a proxy for it so if we go back to that solution of painting types with their domain meaning we can take a stab at fixing this not saying this is the only right answer but it's one answer which is to say maybe you create some empty State it has some link to the type of view that you want to show in an empty State and then you can have your non empty State and in the non empty State you guarantee two things you guarantee that you have non null items that they're there and you also guarantee that you always have a header to show with them and here what we're doing is we're linking that issue that we actually care about which is that we maintain this initially between having a header and having nonzero items so awesome mic drop we did it but of course if you're looking at this code you might notice some other things and you might be judging us slightly and I don't quite blame you because I had one of these moments too yeah that's our code you're probably wondering how we got to this situation I mean we have some forced unwrap NOLA bulls we're acting on it with a optional later on it's a little bit frightening and my point about code like this and the very specific reason that I put this into a presentation instead of sanitizing the code and trying to appear perfect was that nobody sets out to write code like this code like this happens exactly because of things like this which is that developers they work in teams and teams change shape over time and so has everybody adds their piece it makes sense they're doing their best to make something that is logical and sound but unfortunately it's logical and sound within the universe that they're working and so when you add all these pieces from different developers sometimes the logic and the soundness of the system overall suffers and I like to picture this a little like this which is to say that the strength of your codebase and the complexity of your codebase it's only as simple as the simplest piece of code in your architecture chain so whatever diff you've committed that's the most complicated that's gonna set the tone for the rest of your code you could have a rock-solid piece of code that you're trying to commit to the codebase but if it's resting on something that's a little difficult to work with a little hacky a little complicated it's still gonna wobble it's gonna be difficult to really make that sound you can do it you can get it in balance but it's gonna be hard if you don't believe me about this wild accusation well you can think of the case of no ability the dull ability we have something that's pretty simple a type can either be capable of containing null or it can't there's two options like that's okay that's great look at this awesome thing that we have in Kotlin but of course if you work on something like say mobile apps you get into this situation where you can actually have classes be created and then also uncreated and what this means for you is that you now have a time spectrum of no ability so instead of saying something is capable of holding a null or it's not what you're really saying is at some point in time this becomes incapable of holding a null and that's a more complicated thing to say and again this is nothing against app life cycles they're necessary they're there for a reason but it is to point out that things like late init and delegates not not null they add complexity and they're doing that because they're building off of something that is inherently complex of course on the flip side of the coin if you start with something that's rock solid it becomes really easy to build other rock-solid concepts on top of it and that's what this talk is about today is how all of these million of little details will set the tone for an app makes you feel a lot more like this so let's dive into the second scene fortunately we're not gonna linger on billions anymore we're gonna go into types because they're useful for other things as well shocking I know so specifically what I want to call out is that types have the ability to store tests and they have the ability to store pieces and what I mean by that is you can use something like this knowable and you can test it by saying is it equal to null and you can get back two streams of information you can get back the branch that has always known and you can get back the branch that is never known so these are pieces of information and the tests that gets you to each and again quoting people that are far smarter than me in this area what we're getting at is the fact that parts have separate meanings and and they're kind of breaking the data up into them and so the types they're helping us express these different parts and if we revisit an example from earlier that one where I was giving the boolean fork an autoplay you can imagine a world that works something like this which is that instead of having a single boolean we now have interfaces something that your class can conform to to say that it is a high-end device or most importantly to say that it's a cat video because we know that nothing is where thought of playing unless it's also a cat video and so you can get into this situation where now that boolean turns into something like autoplay eligible and states can conform to that and they can be Auto playable if they conform to an interface now when you go to work with code like this you still have can auto play it's there all you have to do is ask if it's Auto playable so that information is exactly where we need it but now you also get all of the other bits of information that you calculated specifically you already tested against this concept of high-end device and now you can get that information back very easily if you compare that to this case where we have our you know non itemized boolean here and we have two bits of data that we're encoding into it you'll notice that it's a little bit harder to get data out of that so specifically here if we reach inside of a can auto play loop and we want to know whether something's a high-end device what can you do well of course you can just use it as a high-end device because what could possibly go wrong but of course this is a terrible idea because something that's true right now it's not going to stay true forever so where does that lead us well another thing you can do kind of the natural thing to do would be to test it again to ask once more despite the fact that you've already calculated once is this a high-end device and of course this works but it is doing redundant work so you hear this term in terms like it's so often things like composition over inheritance people love to talk about this and at the root of sayings like this is this idea of reusability of the way in which you can take data that you've calculated once and make it available to yourself over and over and over again so that you don't have to do it again this leads to the second problem statement which is that without these expressive types you can't capture the work that you're doing so what is the solution well when you break up chunks of work make sure to capture them in a way that you can recover specifically the TLDR is make use of your type system to be reusable so I use this interfaces as an example because it was easy but it's not the only way you can do this there's a whole class of problems under there like a memoization sort of arena where you can have proof of work or something else that you've calculated that you're building upon so you don't have to do every branch or every node in a tree something similar so while I use interfaces as an example it's by no means the only way to do this now I just touched on Tye Prius so let's touch on a different type of reuse I'm not sure how many of you browse the Internet in your spare time but around about a year ago there was a very good hashtag and it was called the internet names animals and what this hashtag did was it took common English phrases and applied them to animals so an animal that has a name that might not have much meaning got a much more descriptive definition so the porcupine became the stabbed rabbit the snake became the danger noodle kangaroos were hot pockets moose has become forest dwelling murder horses we have the American murder log and of course everyone's favorite the raccoon is really just a trash panda you heard it here first now we're all developers so I know that that goes without saying making accurate names is really beneficial to society this is something that we're bought into our community understands hashtags like this and so I want to be a good society member and I would like to propose my own but just to say that the type formerly known as strings probably could be better known as the alphabet iOS yeah now the reason for this or that strings are danger and of course danger is not always bad people spend exorbitant amounts of money to get thrown out of planes with a glorified bedsheet tied to their back so there's got to be something worthwhile in it but it doesn't change the fact that strings are dangerous and the reason for the danger well it's not them it's definitely us which is that we suck at typing and you know it's not entirely our fault because if you look at even the shortest simplest string say two characters and you do out all of the permutations of this string and in fact I'm taking a severe underestimate I'm saying the 26 lowercase letters of the English alphabet when I'm making this estimate you've been with an under estimate like that you have 676 options only one of which is the one that you actually intended to use if you go to any normal sized string at all you quickly get into a scenario where the number is so large that I can barely fit it on this 16 by 9 aspect ratio screen that's problematic now I know at least one person in the audience right now is really good at math probably majored in statistics and I saying that's not really accurate keyboard layouts and yes it is very unlikely that if I'm typing a string over here I magically like start typing strings over here I get that but infinity divided by a large number is still a heck of a lot of ways to screw up so why do we care well because we're often matching on content so when I make a typo in a string like this my data doesn't go where it needs to go my states don't transition in the way they need to transition it's problematic so how do you fix us well of course they're to try it in true solutions which is don't type strings and as part of don't typing strings especially don't type strings in places you don't actually really need them like state now again this is not a talk about strings being bad look at this perfectly great use case for a string but objectively speaking I think it's fair to say some use cases for Strings they are pretty bad yeah and of course you're feeling clever you might clean this up a little bit right because I said don't type strings more than once because the more you type strings the more you mess up so here we are typing the string only once but of course this is still terrible because if you had a user they could for instance set this variable string to the word Anarchy chaos doom you know just to name a few examples so this leads us to problem two point five which is that strings are easy to miss type and well what does the answer avoid typing them now this is near and dear to my heart and I want to make absolutely sure that people you know remember this and practice this so I've created this very handy meme for you strings are for data not States you can post it anywhere you want it's fine next big thing you saw it here first and of course a lot of you are probably looking at my diatribe on strings and you're saying okay old news we know strings can be dangerous we know not to type them more than we have to and of course I wouldn't bore you with something like that unless I had an alternative point which is that the way we treat strings and the knowledge that we've accumulated around strings and their use it's actually a far too narrow reading on the actual problem to understand it we get to do a bunch of math I know you're excited it's fine you can hold it in we'll start with boolean and basically all I want to know is how many things can a boolean hold here it's easy to true and false no I can go ahead and have a pair of boolean in which case I can put one of two values in the first slot one of two values of a second thought and get myself into a situation where I have four options and you can see the natural progression of this where now I go through and I have two pools and I have eight objects or eight different options and of course this is all using bools where I have two options for each slot I don't need to do that I can modify this and use unit which is an object and so there's only one possible solution here and so here I have two times two times one and I'm just getting back my four options and the point that I'm trying to get out here is specifically around how the types we use contribute to the combinatorial multiplication of possible States so we know that unit is one we know that bullion is complexity is two where does that leave us with strings well if we take that pair example again and we put the easiest possible thing in the first slot we put unit so it can only be one thing what is the number that we get in the second slot well I'm sure you've already made this leap which is that it's nearly infinite you can put in an empty string you can put in a string of one character you can put in a string with two etc etc etc you can have them in all their permutations we get to a situation that's roughly infinite now again the question is always why do I care about this fact the answer is that something that takes a string also takes almost infinite like possible input and it's really incredibly highly unlikely that whatever API or function we're designing will handle every single one of those cases gracefully which means that we're actually designing a function where it's possible to pass things that we don't have any idea of what to do with which more or less means that we're handing people the key to our own self-destruction now this is basically the programming programming equivalent of a trust fall and the only thing that I want to say on the topic is that YouTube has an entire genre of videos called trust fall fails so you can make of that what you may okay so that leads us to problem three which is that unbounded types make it difficult or nearly impossible to limit our state representations what's the solution it's too quickly as quickly as possible lift unbounded types into a bounded type to wrap them to kind of hide them away where they can be less danger to you and to the other programmers in your org so what does this look like well if we revisit the example we had earlier you can see here that we have our unbounded type that's string we've now lifted it into something that looks like this has exactly two options you can have your production or your testing endpoint when you go to use it you'll notice that there are no strings on this screen so awesome we've made an improvement it's not foolproof but it's a little bit safer now this is not a one-trick pony of course because strings are not the only types with this behavior you can also take a look at something like int where you get into this similar infinite possibility realm and of course I know someone is now thinking in their head that InSAR not infinite said yes you're right there is a limited number things that they can represent but it turns out when you do this multiplication it actually farms a number so large that I didn't know the name of it I had to google it it's quintillion by the way so if you want to test all cases that's the number you should be aiming for now of course we can do something about this in much the same way we did something about the string case which is you know constraining it to three valid options or say doing something to prefetch frequency where once again we constrain this to only the two options that we really care about if you take these two things in concert what you end up with is something that looks like this we've now taken in that same concept and encoded it in a way where it can only have six possible permutations this is great because six as a number is testable we can go through each one of those in a way that we couldn't that very large number that I couldn't even count to so I don't know about you but turning infinity into six feels a little bit like magic to me and it leads us to scene four which is probably my favorite of all of them illogical data structures now this may sound weird and scary or you may be wondering it's just a made-up term I don't know the answer to that question I think it might be but don't worry we'll go over it and so specifically what is the idea of an illogical data structure yeah you already know where I'm going with this I probably don't need to spell it out but I will anyways so here is the simplest most rudimentary illogical data structure you could possibly get which is that you have a lock and it has a field for being open and it has a field for being closed now this works out for you sometimes but it quickly goes awry when you get Schrodinger's lock and you can have it be both open and closed at the same time or neither up in door closed I don't know what to make of that it's above my paygrade I'm sure someone in philosophy has some ideas but the thing that we care about is that illogical data structures their data structures that allowed nonsensical values for instance a lock being both open and closed now a more subtle version of that may be something like a person model you'll notice everything here is a variable and some of them are knowable and we have sets and we can use this as a training ground for identifying some things that make up illogical data structures like probably the fact that some things can change that really shouldn't change last I checked science did not yet have the possibility to do ahead transplants so heads should probably not be variable you most likely have one and we'll have that one until the day you die so there's other stuff though which is that things can be missing that should not be missing I have not yet met a person who does not have a heart and is still attending talks so that's probably a thing that you need in some way shape or form and of course there's also this problem where you can have things more or less than you you need so for instance maybe having six arms it's not the most accurate way to represent a human so ways in which we can fix this well you can make things vows when they shouldn't be changing you can make them non knowable so for instance here heart stays variable because people have heart transplants all the time but head is a vowel and both of those are NOLA because you need them both to survive and you can see that we've defined our arms and legs such that we represent people who have no arms and legs we represent people who have all four but we're not yet capturing people who have six if you find one I would love to meet them and I will revise this slide now what does that look like in more realistic code well it looks something like this and it's quite a bit more subtle so what this code is doing is it has a model and then it has some field that was calculated on that model so specifically the way this field the imageless review field is calculated is if the model has a URL for an image then this balloon gets set now this is problematic in two really key ways which is that well first it relies on the model not being null and you can see that this is starting out as false actually it's lying to us right from the get-go if there is no model sets then this should not have a value we can't say that it is not an image list or that it is an image less review when there's no model there's no review to be imageless and so this is a lie this is incorrect and also of course it allows things to get out of state or out of sync so what you have is when the model gets set maybe you forget to update this boolean and so now you have a model that has an image URL but your boolean is reporting false and you have this illogical data structure where these things they're not in sync it's allowed to take on this nonsensical value so again we can take a stab at fixing some of these things when solution looks like this we redefine the image list version and then we define one that has an image and you can only be in the has image state of this review type if you guarantee an image URL now you can also add some helper functions to it which is not very important but kind of ports over the logic and together when you go ahead and use something like this it turns into this now it's not perfect but you'll see that at least we've addressed some of the illogical data structure flaws which is that now you don't ever have the chance to get States out of sync the model has a URL it's going to also report that it has image likewise it's an initial model this will always be correctly set what your initial model is is up to you but at least we know where the data is coming from so always always always the question is why do we care the answer for this one is if you've ever just like me gotten a bug report that you could only repro when you tap the button eight times quick switch the app or turn to the app jumped up and down twice and then force quit yeah that's why that's the reason because users are users and they do unpredictable things and you really can't make assumptions about how they're gonna use the code that you write because if the code is at all theoretically reachable it's going to be executed at some point really fun story about this that we just had a you know series of unfortunate events where in our app we have things behind death flag so only developers have opportunities to use them and through this series of terribly improbable one-off tiny mistakes it came out that our users had access to our dev options so even this thing that we were really really sure would never end up in the hands of users ended up in the hands of users and so when we encapsulate this into a problem statement we get something like this which is that assumptions aren't enforceable and they age really poorly over time and so the solution to something like this is well if you need something to be unreachable you have to do it at compile time so again what does this look like when you pull code from a real project it's more subtle than the the toy examples one example is we had a video song so if you are scrolling through a feed of objects and Android we would use something like a recycler view you want to show a video in one of those cells you have the situation where the cell continues to exist in some reuse pool even though the data is not bound to it yet and so the life cycles as they match up to the data I can get a little complicated and so us being you know forward thinkers said there is a tool for this job we can just say that the data is Lee in it because unbind it's gonna be called and the data will be there by the time we're actually using it so you know when the cell comes on-screen and it gets bound the data is gonna be there so this is a safe thing to do and of course you may not be surprised to hear that there were crashes for everyone and why well unsurprisingly the reason was because the codebase changed product requirements changed and assumptions were broken no when we took a stab at fixing this problem we started back with the requirements what did we actually mean well when this was loaded when we could verify that the data had fired off we needed it to be accessible and non null and then when it wasn't loaded we needed to know that the data couldn't be accessed so how did we represent something like this well again you've seen the structure so many times it's the easiest one to show on slide not the only one but the easiest we can have a state that says not loaded we're gonna have a state that says loaded and within the loaded state you can get exclusive access to the data that you've loaded when you go to use it this completely takes away the opportunity for anybody not in the loaded state to access your variable of course you may be wondering why would anybody not in the loaded state need access to this and the answer is always logging it's where good architecture dreams go to die so yes things like this that seems safe they can have these inherent flaws in them that only become evident over time but it is worth pointing out that there are other reasons that it's really tempting to use things like this specifically when you say that something's late in it you only have to do it once and then you can go off in this world and pretend that it's never null and it only actually matters when it crashes but you only have to do it once and the rest of your code is fine now something like this if you start to pull those states out well every time you reference that state you have to unfurl it and of course this is more work and it's not exactly fun now you know my stance on this which is to say that at least doing this explicitly gives you control because even with late in it you are doing you're just opting in to the default behavior which is that when I'm not in a loaded state I should crash and maybe that's not what you always want to do okay this brings us to our last scene in order to understand that point that I'm gonna make it's probably worth refreshing from where we've been which is you know I had this suggestion about painting pipes with their meanings and the answer was data classes or something like that and I had this suggestion about encoding information in reusable ways and it was interfaces and I'm for working with bounded types came up with classes and he Nunes and then you know the thing about nonsensical data and illogical data structures well you could go ahead and use mutability and knowability constructs but if you noticed in all the examples the TLDR of this talk really could have been summed up in three easy words which is sealed classes everywhere yeah and of course I use them because they are a bounded construct when I'm talking about the dangers of state being propagated in numerous ways using something that's founded is a really attractive solution to that but one problem that arises in this scenario is this elephant in the room now people who work on the little green robot like I do probably know exactly where I'm going but even if not perf always matters to the work that you do and you know that it matters because we do terrible awful things like this when we have really really nice-looking code like this and the reason we do that is because at the time it felt like a way that we could be more performant and this is something that we need to do often times now I would like to sum up our current state of affairs something like this which is that we have the most performant way we can write code we have the most readable way we can write code and then we have our expanse of anguish yeah now this is not always true but oftentimes it can feel like it is which is that when you want to performant code it doesn't always mesh with the type of code that's most easy to read or most easy to maintain and so again I have no intention of making the point that boolean czar bad that strings shouldn't be used or that classes are always the answer my point here is that with most things in life there are trade-offs and so yes it's our very performant but they also allow quasi infinite states and the question really becomes which is more dangerous to you if you have a stellar code review system if you take pride in it and you know you're gonna have six pairs of eyes on your code and they're gonna catch your mistakes or if you're working on perf critical code maybe graphics then it's make a lot of sense but if you are in a large diverse dynamic company or you're writing code we're making a mistake is catastrophic looking at you medical industry then having a strongly opinionated alternative might make a lot more sense so of course the decision is always your's and the only thing that I hope for you is that after attending this talk you have what you need to make it an informed one thank you [Applause]
Info
Channel: JetBrainsTV
Views: 22,061
Rating: 4.7196579 out of 5
Keywords: Kotlin, KotlinConf18, KotlinConf 2018, Java, JetBrains, Amsterdam, Pinterest
Id: -lVVfxsRjcY
Channel Id: undefined
Length: 42min 47sec (2567 seconds)
Published: Mon Oct 08 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.