Dart: Productive, Fast, Multi-Platform - Pick 3 (Google I/O'19)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

I downloaded the Flutter Gallery again to see if it is actually fast yet, and I think they can say that now.

However users won't think it is fast until they fix the touch slop issue - when you start a drag it always "jumps" a bit at the start. It isn't technically a performance bug but it feels like one. In a way it is worse because it always happens.

👍︎︎ 2 👤︎︎ u/IshKebab 📅︎︎ May 10 2019 🗫︎ replies

This was a really interesting presentation and I am looking forward to some of the up-coming language features.

👍︎︎ 1 👤︎︎ u/amugofjava 📅︎︎ May 10 2019 🗫︎ replies
Captions
[MUSIC PLAYING] BOB NYSTROM: Are you guys ready? [APPLAUSE] Yes? Yes? KEVIN MOORE: That it? All right. My name is Kevin Moore. I'm a product manager on the Dart team. BOB NYSTROM: I'm Bob Nystrom. I'm a software engineer on the Dart team. KEVIN MOORE: And today. We've got lot of to go through. We'll try not to go too fast. Here's the rundown. We're going to talk about the three things in the title. What we love about Dart. Why we think Dart is cool. We'll talk about the language. We'll talk about the platform. And we'll talk about some of the future directions we're going with Dart. Sound good? So Dart-- BOB NYSTROM: If you don't like it, we can do something different. KEVIN MOORE: Anything else? No, that sounds good? OK, we'll stick with that. That's what we practiced. It's probably a good idea. So Dart's a programming language. It has a platform, a runtime, compilers, all those things, right. We're all on the same page there. If you've heard of Dart, you've probably heard about it in the context of Flutter. Right? Some people here. Occasionally, we get the question. Why did Flutter choose Dart? Sometimes it's done very politely and just with genuine curiosity. BOB NYSTROM: Always. KEVIN MOORE: I don't know always. There was that one Perl guy once like, why not. So, as a way to jump in, I think that's a good way to talk about, why did Flutter choose Dart. What's cool about Dart. So if you don't know already, Flutter is a framework for building beautiful applications. They run across mobile devices and other things. We'll talk about that in a bit. Here's some examples. If you look at the Flutter architecture, on the lowest level is a C++ engine. Flutter doesn't use the native UI stack or widget library on IOS or Android. It has its own. And it runs on its own runtime. Skia is part of that. That's the engine that drives Chrome as well. The Dart VM is buried in there as well. As long as some tech support. And then the whole Flutter framework is all written in Dart. So everything from the lowest level foundation bits, the core animation things, routing, the widgets, theming, rendering. That's all written in Dart. Then of course, the bulk of the Flutter application you write is also in Dart code. So you have your app, the framework, and then even in the C++ engine, you have Dart. So clearly Flutter has made a big investment in Dart. It's not just a scripting layer on top. So we want to talk about these three things that we think are important to Flutter and important to Dart. Productivity. We want you to be able to be productive and happy as a developer and get things done quickly. We want you to be fast, and this means two things. We want your productivity to be fast to be able to get things done quickly. And then you ship your app, we want it to be amazing-- 60 FPS, high quality, fast. And then we want to run on many platforms. Now, this is a hard set of three things. It's pretty audacious to try to do this. We think we have a pretty good story, and so that's what we're going to talk about. BOB NYSTROM: Oh, I get the clicker now. So, we're going to start talking about productivity. So, the primary domain, the application style that we're aiming for with Dart, is building user interfaces. So client application development. And for that domain in particular, developer productivity matters a ton because a lot of what you're doing is very small scale subjective changes-- tweaking UI, layout, color stuff. So you want that really fast loop so that you can get to a good user experience. Productivity starts with the language that you're programming in, which, spoiler alert, is Dart. I'm assuming that you haven't seen Dart, so I will run through things. But I obviously don't have time to do a deep dive or a full intro with the language. So I'm going to kind of skim stuff. If stuff doesn't sink in, that's OK. I just want to paint a picture in your mind. I think of Dart as being a modern, multi-paradigm language. And it's been designed to be familiar to people coming from other mainstream languages, JavaScript, Java C#, things like that. Curly Braces, that kind of stuff. It's in the same family, the same ballpark as Kotlin and Swift. So by modern, what I mean is that it's kind of lightweight, it feels a little scripty. So here's a slightly more elaborate Hello, World program. We've got collection literals. There's string interpolation. You don't have to define a class to make a new file, things like that. But it's not just a scripting language. It is also an object-oriented language. So we have classes, objects, methods, fields, interfaces, all that good stuff. We have some interesting object-oriented features like mix-ins. I don't have time to talk about. Object-oriented programming, people have strong feelings about it, some of which are positive, some of which are negative. I'm sympathetic to both of those. My personal experience-- I've been doing UI programming for a long time-- is that for UI stuff in general, in particular, OOP is just a really nice fit for it, works really well. So this is the domain we care about. So we have these features, and I find it as my program gets larger, these features help me organize the larger structure of it. But Dart is not dogmatic about object-oriented programming. Because we are a modern language, we also support a functional style. So we have lambdas. Here are the little arrows making a function here. We have closures. If you see, the bang is declared outside of it. We have higher order methods. So here, we're passing a closure to the map function to transform it. All this stuff is familiar to you now. If I was giving this talk 10 years ago, people would be like, I've never seen any of this, unless you're a scheme programmer. And the neat thing is, this is deeply baked into the language in the core library. So I'm calling map right on the built-in list type. So all this stuff, the functional style that you like is all baked in. But a language is more than just its runtime semantics. So we take that behavior and we wrap all that up in a nice static type system. So, you can do the typical things that you expect. You can put type arguments on [? your-- ?] type annotations on your parameters, return types. And then the type checker will tell you if you made mistakes, because we are human, and we do that. This is another thing where people have strong feelings about it. My personal experience is that when my code is small, when my programs are small, types-- sometimes they get in the way. Sometimes they're net-neutral. But as my program grows, or as I work on larger teams, I really appreciate having the structure and the kind of defenses that static types give me between the different regions of my code. We have this idea that we want users to never outgrow Dart. Your program should never get so large that you feel like, well, Dart can't handle it, and I need to port it to another language. And static types are a big part of that. When I say that we have a modern static type system, what I mean is things like this. So we have generic classes. So here, this is declaring a box of T that has a field of type T. So a box of int and a box of string are different types. I'm using a weird, contrived example here. I know you're looking at this, and you're like, this is not adding any value to my life. Hopefully it will be. I'll walk you through why I picked this example, and hopefully it will make a little more sense. KEVIN MOORE: It's a tuple of one. It makes total sense. BOB NYSTROM: Yeah, exactly. Thank you. KEVIN MOORE: There you go. BOB NYSTROM: We also have generic methods. So here, this method rebox has its own type argument R, which is different from the surrounding classes type argument. And it takes a function, takes a first class function as a callback, and invokes that callback on its own contents. Gets a new object back, wraps it up in a new box. So this will turn a box of T into a box of R. Obviously, super useful. This is something you want to do every day. Here's why I'm actually talking about this. So, static types are nice. The safety you get from them is nice, but having to write code like this is slightly less nice, right. It's cool that it's typed, but it's pretty verbose. So we also have a rich type inference system on top of this. So I'll walk you through what you can do. So, when you're constructing a box of string here, well, we can tell you're passing it as string. So it must be a box of strings. You don't have to write that. Inference will fill that in. When you're declaring this string box variable, we can see that you're initializing it with a box of string, so we can infer that, obviously. You see here when you call rebox, you're passing num.parse. That's a core library function that returns a num, so we know that that's rebox of num. And then we know the return type of that method, so we know what the variables type is going to be. And then we know that's a box of num, so we know its contents type. So, actually, we can infer that, too. So this is what idiomatic Dart looks like. And the nice thing is that this is fully, statically typed, just like the previous code. You get all the safety that you had before. You get all the code navigation, all that good stuff. KEVIN MOORE: So, that means if I go and I said, print string box, that runtime type, I would see, box of string. BOB NYSTROM: Yes. Yeah, the actual type it constructs at runtime is correct, too. Our goal here is to give you basically the brevity of the scripting language, but then the safety of a statically typed language. So this is my super science summary of the language I'll run through. So, we try to be lightweight and feel modern scripty. We give you, when you're organizing your code, the structure you like from object-oriented programming. And then inside your methods and stuff, we give you that nice declarative style that you get from functional programming. And then we kind of wrap that up in a nice, rich static type system that can understand both of those paradigms. So this is a foundation of a general purpose language. And Dart is a good general purpose language. But we want it to be particularly good for writing client application, for writing UI code. So over the past year, we've been working on this initiative called UI is code, where we've tried to add a few features to the language to make it even better for that-- that use case and other stuff. So I'll walk through it a little bit. I'll show you an example of what you would do now. And then we'll go back and see how the new features work. So if you haven't seen it before, this is what a little contrived bit of Flutter code looks like. So anytime you build your new UI framework, you have to figure out how the users are going to author their UI. Sometimes they say that you do it in a separate template file. Sometimes you embed the templates in the code. For Flutter, you just do it using vanilla Dart code. So your UI code is Dart code. What's nice about that is, you don't have mental context switching when you're moving between the code and the UI. There's only one language to learn. All of the features from the Dart language that you like, you can use in your UI. So this is kind of a simple, trivial example. And it looks pretty nice, right. Like the body of that method is just a single expression, which is why we can use a little arrow. And it's just a nice little widget tree that just builds a column with a series of text elements. You can imagine we're building maybe the navigation for a book reader or something. This is the goal. This is what we want your code to look like, and this is hopefully what you feel-- you feel good about your code when it looks like this. So let's start making it a little more interesting. So let's say that when you're on the last page of the book, we don't want to show the next link. So, what do you need to do to get to that? So first of all, we're going to have to do a little bit of imperative logic. So now it's not going to have an expression body. We're going to need a block. And actually, we need to do something like this. So we pull that list literal out, we hoist that up to a local variable, then we need an if statement to imperatively add the next link. And we even need to imperatively add the index link to the end of that, even though that's not doing any interesting logic, just because it happens to appear later. So we had a sort of small conceptual change, but it required a very large code change. So let's keep going. So let's say, also what we want to do, is we want to add links for every section. So that's another little bit of imperative code. Here we're using add all, because we want to take that sections list and unpack it into the list that we're building here for the column. This is OK. Again, this is an imperative code, so it's not the end of the world. We'll keep going a little bit more. So let's say actually what we want to do is, for every section, we want to include all of its chapters. So we flatten out the sections and include each of the chapters. And this is what you get. So I think most people can read this code. It's not the end of the world. KEVIN MOORE: But I have to run the compiler in my brain. BOB NYSTROM: Right, but yeah. To think about what is the UI structure this generates, you basically have to execute it in your head. The textual structure the code doesn't reflect your UI structure anymore. So, let's go ahead and rewind it. I did a little rewind transition there. I'm very excited about that. KEVIN MOORE: So the return method's gone. We're back to a nice arrow, which is-- BOB NYSTROM: We're starting back at the very beginnings. So, the first thing we wanted to do, and this is with the new features that we're adding now. The first thing we wanted to do was omit the Next button when you're on the last page. So for that, we just let you stick an if right inside the list literal. It does, hopefully, what you can infer. So if that condition is true, the body gets inserted in that element in the list, condition's false, doesn't insert anything. So notice the body, that it's not saying add text. There's nothing imperative here. It is just the expression for the thing that goes in the list. OK, so what do we want to do next? The section links. So for that, this little dot dot dot here is called a spread operator. It's something we borrowed from JavaScript. So when you use this inside a collection literal, it takes the sequence following it and it unpacks it in place in the surrounding list. The last thing we did was we walked [? through the ?] sections and then did the chapters. So for that, we also let you do for directly inside a collection literal. So what this will do is, just like a for-loop, it will execute that body multiple times. And that body can produce as many elements as it wants each time, and all of those will then get flattened out into the resulting collection. So the super science summary, this is kind of the before and after here. So these features. These are three relatively small features. They're kind of incremental additions to the language. I didn't show examples here, but all of these work with all of the collection types in Dart. So we have map literals and set literals, too. And you can use these and those. They can also be freely composed. Here you can see we're using a spread inside a for. But these are not amazing rocket science features, right. But what I like about this is it gets the code 30% smaller. What I really like is that the code stays more declarative. And at every step of this when we needed to introduce a little logic, we never had to go back and rewrite our code in an entirely different style. So any small conceptual change we made was a small textual change. That almost rhymes. That's great. So-- KEVIN MOORE: I'm tweeting that later. BOB NYSTROM: So this is the new stuff we have. This came out in Dart 2.3, which was released-- KEVIN MOORE: Today. BOB NYSTROM: Like right now. KEVIN MOORE: Yeah. BOB NYSTROM: And in Flutter 1.5-- KEVIN MOORE: Yes. [APPLAUSE] It's cool stuff, right. Yeah, that's pretty cool. Bob did a big part in implementing this stuff. So good job, Bob. BOB NYSTROM: These are my babies-- my three strange little syntactic babies. So this is the language, but this is kind of the language spec. A language is more than just a paper specification. KEVIN MOORE: I've heard. You're right on time. That was amazing. Wow. So that's the language. Now languages are great, and they're great to discuss, but at some point you want to run the code, right? I guess there probably are people who put in a text file and just share it. BOB NYSTROM: I just read specs. KEVIN MOORE: Yeah, exactly. Then I write, so it's perfect. So how do we run code in Dart? So we start. Anyone who's taking the compiler class, which I never did. I've learned it all on the Dart team. BOB NYSTROM: It's never too late. KEVIN MOORE: I know, you help me a lot. So you start with a text file, Dart source code, and you Lexer + Parser it, and you get an AST. Yes. BOB NYSTROM: Yes, I got that right. KEVIN MOORE: Stands for Abstract Symbol Tree? BOB NYSTROM: So close. KEVIN MOORE: Arbitrary Sync? BOB NYSTROM: You're getting farther. Colder, colder. KEVIN MOORE: Abstract. BOB NYSTROM: No. Yes. KEVIN MOORE: Symbol. BOB NYSTROM: Syntax. KEVIN MOORE: Syntax tree. There we go. BOB NYSTROM: Ladies and gentlemen, Kevin Moore. [APPLAUSE] KEVIN MOORE: Understood continue. So on top of that, when we're thinking about running Dart code, we have this amazing little compiler. And it does things that compilers do. So Bob showed the type inference stuff, does all that logic. Type checking. We make sure things are accurate. Evaluating constants, optimizations, collapsing constants. So if you define 15 strings, const, const, const, and then you have some 16 string that's like, I want all these, plus, plus, plus, plus, when we compile, we'll just generate one string for you. We can do all that kind of logic. And then we have back-ends that run your code. And we'll talk about that in a little bit. On the side here, we have a separate stack, and these are the bits that actually enable a dev experience. So we have a package called Analyzer. And the idea is, you want to stack a code on the left, the yellow bits, that can take correct code and deal with it really quickly. Go as fast as you can from Dart source to something we call kernel. Talk about that more later. On the right side, you want a separate set of stuff that's really good at incomplete code. Because I don't know about you, but at some point I'm typing, and my expressions not complete, and I want to hit Tab and get completion. And so, those are the analyzer bits, and so all the things you think about a dev experience are handled there. This is also a package, which is super exciting. So if you want to write code that looks at Dart code and generates Dart code, something I'm very fond of, you can use that. On top of that, we build a server that runs in your local machine, that basically knows how to take those bits and expose it to clients-- so your IDs. So when you think of the green bits, this is it. So if you're-- go to definitions, refactor, find using, all those things, the red squiggles. That's the stuff in green. That's the analysis bits. But the yellow bits, we talk about running code. And so we think about fast, and I actually think of fast in two contexts. One is your dev cycle. So this is how quickly you can go from changing a line of code, changing a bit of code, and seeing it running, seeing if it works or not. So that's enabled by the Dart VM. So all those yellow bits are there in the yellow box, the CFE, and then we have all these things on top. And so the CFE basically takes your source code and gives you kernel files, or kernel blobs, I guess. BOB NYSTROM: You don't necessarily put them on disk. KEVIN MOORE: And then the VM runs that. So the purpose of the VM is to go as fast as possible from source files, so uncompiled raw source files, to something running as fast as possible. And so that's what the runtime does. We have just-in-time compiler, so we can get it running really fast. And then if you're running for a while, we can optimize and generate machine code as we're going. And then we have some really powerful debug services that I'll to talk about in a second. So we're going to start filling out a table here. And right now, this is kind of like the box thing, one column, one row. It's not exciting, but we'll build more. So when you think of development, native development in Dart, that's the JIT and the VM. So if you're doing Flutter development, that's what you're using, not only on your test device, but the analyzer and the footer command line tool, and the formatter, and the doc generator. And that's all running the DART VM. BOB NYSTROM: All of our tools are written in Dart as well, so. KEVIN MOORE: So, what does that give us in terms of speed? So, fast-- first, the VM itself is really fast. We can get your code running really quickly. But that's not good enough. Anyone who's done rebuilds on native devices and waited to get the screen loaded again, it's a really painful thing. It's really slow. It was painful for me trying native development after doing a bunch of web stuff where the web is just so quick. So we have two cool features. The first is hot reload. And again, for those that aren't familiar, those that know Flutter know this really well. You'll see I have an app running on my little Android emulator on the right. I'm changing the plus buttons. You see the number increases. And then I'm changing the color and source code. And I just hit Save. The color changes, but my count is preserved until my animation loops back to zero. So this is amazing. I can change state in my app, change something as fundamental as color, which is actually propagated down to a bunch of different widgets, and my state is preserved. What's really exciting is, even things like if I'm down 15 levels in my app and I've gone through 15 dialog boxes-- I'm somewhere deep-- I can still do this trick. And I don't have to relaunch the whole app and re-navigate to where I was to see how it worked. So how do we do this? BOB NYSTROM: How do we do it? KEVIN MOORE: I'll tell you. So you had your IDE running, coding along, you hit Save, and the IDE sends a hot reload event to the Flutter command line, kind of the Flutter engine running. That's talking to the front end server, a Dart front end server. Now already, you're seeing this interesting thing where, again, because we maintain the whole stack, we can split these things apart. So we have the front end running on your dev machine. And it takes that event and it figures out, what are the set of deltas that are affected by that change? And I'll only recompile the Dart code in the kernel files that map to that change. And then I'll only send that delta to the device. So I'm not sending a whole big app. I'm just sending the delta. And then when the emulator running on your phone-- actually could be your emulator or a hardware device-- gets that diff, there's actually coordination with the framework, and it figures out, is this the type of change I can do safely with a hot reload? So obviously if you're adding and removing classes, changing methods, removing methods, you can't do that safely. But things like variables and colors, you can do safely. And we can get that really fast hot reload. So that's super exciting and already saves people an amazing amount time. People love hot reload in Flutter. But that's not all. We also have deep introspection services. So again, you see emulator here. And on the left, we have a web UI, that's actually also written in Dart, that lets you inspect the running application. So you can click on widgets on the right, and have it show up on the left in terms of your UI, and see what you're looking at. You can click around the UI on the left. It highlights it on the right. You can show things like your layout boundaries. And this is enabled by these debug services I talked about. So not only does Dart have debugging services built in so you can get memory allocation, object allocation, hot paths, code coverage, all the things you want, it's also extensible. So Flutter was able to build on top of those things and use data in something like the kernel file to map back from the running code, back to the source file, and give you this kind of rich introspection. So that's the lightning bolt. We build on top of an already fast VM for dev cycle. And then we add really powerful tools to make your dev experience that much more productive and that much faster. But that's just half the story. BOB NYSTROM: Am I next? So if all that works great, then you have this wonderful application that you've enjoyed developing, and you've had a good experience. But all of that is sort of all for naught if when you run it on end user's device, which may not be top of the line, it's slow and janky. So, end user performance is also critical. It's easy to get into this mental trap of thinking about performance as just how fast does my stuff go. But we think about it in a sort of more multifaceted way. So part of the performance story is how big is the generated code. The smaller your code is, the shorter your download time is, which matters especially in places where you don't have great internet. It affects startup time. Startup time, in general, is an important piece of the performance story. How much initialization, code, other stuff has to run before you can start getting to the interactive part of your application and users can start doing stuff they care about? And then actually, what you normally think about with performance is, how much code can you execute per unit of time? How fast can you make stuff go? And that matters, because that's really the upper limit on how rich of an interactive experience you can give people. But it's not enough to have a good peak performance some of the time. You need to be sure that your performance is consistently solid. Especially for interactive apps on client devices, they want it to be buttery smooth. It's not acceptable for the garbage collector to wander off and lock everything for two seconds while he's sweeping, right. So to have-- from a user's perspective, to have good performance, you need to do all four of these, which is difficult for a high level language. So if you look at what a JIT does, a JIT's job is to take a bit of text that you just wrote and get it to machine code that's running as quickly as possible. So it doesn't have a lot of time to parse it, analyze it, optimize it. It just doesn't get to do a lot of the classic textbook compiler optimizations. And that's the right trade-off when you're in your developer loop because you just want to see some results. But that doesn't benefit users. So in addition to the JIT, we have AOT. We have an Ahead-of-Time compiler. So what this does is, when you're ready to ship your application, takes all of your Dart code, including all the transitive dependencies, all the libraries you use, compiles the whole thing down to machine code ahead of time exactly like you would do C or C++. The end result is you get a native executable that contains your application and the Dart runtimes, so the garbage collector or runtime representation. And you get the performance experience that you expect from an actual natively compiled application. It starts up fast, runs fast, runs consistently, there's no JIT warm-up, that kind of stuff. KEVIN MOORE: So that's the data side. Clear, so far? Good. BOB NYSTROM: So we've already talked about Android. We've talked about x86 and ARM. KEVIN MOORE: Right. That's it right? BOB NYSTROM: What other platforms are there? KEVIN MOORE: Funny you should ask. Who is a fan of the web? I love the internet. BOB NYSTROM: It's all right. KEVIN MOORE: Actually, one of my favorite things about Google, before I even joined thinking about it, was it brought experiences that usually you thought of, you had to buy and install a big application, and made it available on the web-- Sheets, Google Maps. The first time I saw Google Earth on the browser, I was just blown away. The web is super powerful. There's no app store. App stores are nice. I don't, you know-- they have a place, but URLs are just so easy, right? And so an important thing to keep in mind, especially if your only knowledge of Dart is Flutter, is that we've been doing web a long time. Dart has been in web before there was ever a Flutter. In fact, one of our internal apps, Google Ads-- you might be aware that Google does a little bit of ads business, right? The thing we use to let people buy and sell ads on Google Search-- and as you can imagine, that's not a small business-- that's all written in Dart and has been for a couple years. This is millions of lines of code, and it drives one of our most important businesses. So Google has been betting on Dart compiling and running on the web in JavaScript for years. So we have a story here, and the matrix continues to expand. We have a dev experience with JavaScript and Dart that's great. We do analogous things to what we do on native. In this case, what we do is we take your individual libraries or modules. We compile those individually. Again, we can do that really quickly. We compile them into JavaScript that is meant to be looked at and read, generally. And source maps work well, too, if you're on the web, for debugging. And we have some tools that build on top of this. The idea is, again, if you make a small change, we can be smart, understand the impact of that change, only recompile a JavaScript that was affected, and push only those deltas to the browser. And we have some clever hooks to the browser so that we can reload the app. We're not quite at the hot reload stage yet. You do lose state. But actually we're working, and we have a plan for how we can implement that as well. So you actually get the stateful hot reload where your counter, your dialogue, is where you left it off. So that's the dev side. So that's the lightning bolt, sorry. Now you can have it. BOB NYSTROM: So, you think of DDC as a separate compiler. It compiles each Dart module to a separate JavaScript file. That's great for incremental compilation, only rebuilding the pieces of your application that change. The downside of that is, when it's recompiling a module, it has no way of knowing which functions in there are used by other modules, right. So it gives you everything. So the end result of this is, it compiles your code quickly, but you get a large amount of JavaScript. KEVIN MOORE: In fact, people on the internet have been asking. It's like, the code is huge. No that's the dev compiler, yes. BOB NYSTROM: So if you've done web development, you understand that code size is king. So when you're ready to ship your web application, we have a separate compiler called Dart to JS. So this is-- I'll fill in the other box there. So this is a whole program optimizing compiler. So it takes-- again, just like the OT compiler, it takes all of your Dart code, all of your libraries, runs a bunch of whole program optimizations on it, including a bunch of pretty advanced dead code elimination. So it figures out which pieces of libraries you're using you don't actually use. Discards all of that. Does a bunch of other even performance optimizations. And then it gives you this one monolithic ball of-- small ball, as much as possible, of not very easy to read JavaScript but very, very highly minified. What's interesting is, the Dart language itself was designed for this because we've always compiled to JavaScript. So because execution starts with main, the top level of a file is not imperative code. Our static fields are lazy initializers. All these sort of language features that seem somewhat arbitrary, and many of those were chosen in service of being able to generate smaller JavaScript for deployed applications. KEVIN MOORE: And they help our AOT story as well, right? BOB NYSTROM: Mm-hmm. So if you look at this from a project management perspective, having a language with four independent back ends, this is a lot of work to maintain. And especially when we want to move the language forward, we don't want to have to implement everything four times. What's cool about this is that all four of these are built on now, in terms of the same front end technology. So for example, the UIS code features that we just shipped, those are mostly syntax features that we can kind of compile down to the existing kernel representation, which means in a perfect world-- it doesn't always work out this well-- we can advertise that work across the four implementations, and then not have to do too much back end work for these changes. KEVIN MOORE: So that's great. So we talked about the native story and kind of in the context of Flutter. We talked about web. Some here at I/O might have heard we're announcing the preview of the Flutter for web work. So we're super excited about this. It combines the best of both stories. So how did we pull it off? So remember we had a stack of Dart code, you have your app code in Dart, you have the framework in Dart, and you had this blue box. How do you implement it for the web? It was that easy. Just like that. That was it. No, it took some time. Although, you'd be by be surprised, relatively speaking, how little time. Because basically what we did was-- again, if you know Flutter, there's this kind of Dart UI library that is the bridge between the Dart bits and the native bits. And effectively, we replaced that and instead of mapping to native C++ bits, we mapped to browser APIs, Canvas, and DOM. And so then we take that library, that Dart UI library, all that Flutter framework, and then all your app on top. And we send it through our production amazing JavaScript compilers. And we give your JavaScript that runs on the web. And so you end up with a scenario like this. We have, actually, folks from Reflectly here today, and they jumped on this really quickly. The quiz. Which one of these is web and which one of these is native? I'll give you a hint. BOB NYSTROM: I know. I know the answer. KEVIN MOORE: You've seen this talk a few times. You see the mouse maybe moving on the right one. That's the web. So I asked our friends, I was like, how long did it take? And I didn't specify units. I probably should have. And they give me units of beers. It was four beers to migrate from native to web. And he said he actually hadn't finished the fourth beer yet. So somewhere south of four beers. BOB NYSTROM: We don't know the size of the beers though, so it's hard to tell exactly how much. KEVIN MOORE: They're Australian, so we don't. They were big. So check out Reflectly, they're a great user of Dart and Flutter. So this is available now. We want you to take a look and try it. Again, this is a preview, a technical preview. There are a few caveats. Read those. But we'd love you to take a look and try it out. We're super excited about it. [APPLAUSE] Thank you. It is cool stuff. And in other iterations of this talk, I had all these other things, because we run on Chrome OS. Now there's discussion about running on Home Hub, Raspberry Pi, obviously command line apps. They write a bunch of those in Dart. We run on the cloud, Cloud Run. Our package sites all run in Dart. People have compiled Dart using Node, and they run it for Cloud Functions. The SAS package that's on NPM right now is actually sourced in Dart, and then compiled to JavaScript, and published on NPM. BOB NYSTROM: You can't talk about all the things. KEVIN MOORE: We run on all the-- I'll stop. But we run in a lot of places. And we try to do all that following these three check boxes. So, we want you to pick three. And we're not so arrogant as to say we've nailed this. It's always-- it's aspirational for us. Let me know, I'm going to stand back here. It's aspirational for us and for the Flutter team. But we think we have a really good story now around productivity, fast experience as a developer, and at runtime, and multi-platform. And we aspire to get better. And actually you have some thoughts on that, right? BOB NYSTROM: I do have some thoughts. So I think what we've shown you is part of the answer for why Flutter chose Dart. They looked at the design of the language and the implementation, the maturity of the tools we had. But also I think they were looking at where Dart is going because this is a long term commitment for them. So I thought would be cool to talk about some language features that we're working on now that will be the sort of next stuff that we ship. The first feature, this is one that I have wanted for a incredibly long time. This is very close to my heart. The team right now is working on adding non-nullable types to Dart. [APPLAUSE] The guy who's designing it is a genius. Well, I guess the guy-- I guess Leaf and Lasse are both working on it. They're geniuses. They're a joy to work with. So if you're not familiar with this concept, I'll walk you through it really quickly. So Dart has this core library method tryParse. You give it a string, it tries to parse it to an integer. If the string is not a valid integer, it's defined a return null. The string not int is not an int, so that's going to return null. And then if you try to call .isEven on null, you're going to get a runtime error. That's going to crash your application. If it's in a shift application, you're going to have a sad user, and you will transitively feel sad. So non-nullable types, the idea is finding these errors at compile time-- so being able to discover them in your IDE before you run your code. The way it works is the type system treats variables that can contain null as having a different type from variables that cannot. So this would be an error because tryParse returns a nullable int, so we can't assign it to int because int doesn't contain nulls. You have to change it to int question, which is how you say nullable int. And the other half of this is the type system says, you're not allowed to call methods on anything that has a nullable type. So then this becomes a compile error that you need to fix. KEVIN MOORE: The compiler will scream at you if you try to compile, and the analyzer will red squiggles. BOB NYSTROM: It will kindly tell you. KEVIN MOORE: Kindly, yes. No screaming. In red. BOB NYSTROM: So this is part of it. But it's not enough to just jam some stuff into the type system, because null is still a useful value in your code. So you also need a set of usability features to let you get in and out of the nullable world so one of them, for example, is-- so in this case, you can see that I've dynamically checked that number is not null. So we're not going to get into the body here if it is null. So that type system is smart enough to know that, OK, in the context of that if statement, now we will treat that as having a non-nullable integer type. And then it will allow me to call methods on it, and that's fine. There's a bunch of other usability language features we're working on for this. So we'll be doing something kind of the union of lateinit in Kotlin and lazy in Swift. It will kind of cover both of those cases. Doing definite assignment analysis for an initialized local variables. That's a sentence that gets a lot of people excited at parties, let me tell you. KEVIN MOORE: It is cool, trust me. BOB NYSTROM: Anyway, the goal of this, if you kind of look at it. So this will be correct code in Dart. KEVIN MOORE: And really quick, too. And you don't have to type whatever question mark all over. I could just put var there, and all the stuff still works. BOB NYSTROM: Inference. It'll flow through inference. So the goal here is that we're trying to give you the safety of non-nullable types, but let you write code and more or less the style you do today without worrying about it too much. So that's great. The hard part is we don't have non-nullable types today. So how do we get there? So there's a couple of pieces to this. So first of all, the system is designed to allow an incremental migration. So you will be able to take your Dart program, and in any order you want, pick and choose different files and migrate them. You can migrate your application before the libraries you use have migrated. Or those libraries can go before you. The system can handle that. Even so, it can still be a chore. So we are planning to ship tooling that will automate most of this migration for you. So because we have this open source front end that's written in Dart that does static analysis, we can extend that to do refactoring tools. So for the most of the grunge work, it will try to do this for you automatically. You do have to do some of it yourself, because a big part of this feature is you being thoughtful about where you want to allow null to flow through your API. So that's a thing where you're adding value to your code by writing that down. But for the stuff that's not adding value, you shouldn't have to do it. The cool thing about this is the system is designed such that once your program and all of the libraries you use have been migrated, it is fully sound. You will get zero null reference errors at runtime. KEVIN MOORE: Provably. BOB NYSTROM: Provably. There's like, math. There's a meta-theory theorem. I'm not exactly sure how it works. KEVIN MOORE: There's a lambda calculus or something. BOB NYSTROM: Something. So let's say, imagine you decide to make a new language, and you want your new language to be successful. This is a thing that sometimes people do. The easiest path to success is you take an existing language in an ecosystem, and you build on top of that. So you make a language that runs on top of the JVM or on top of the JavaScript ecosystem, and that's great. You get to leverage all of that by having really seamless inter-op, right? KEVIN MOORE: And all the code that's there just comes along. That's great. BOB NYSTROM: Right. The downside about that is that means values are flowing into your language from other languages whose type system you don't control. So in most other languages that have added non-nullable types, they've done it in unsound ways because of inter-op. So Dart, for better or worse, has its own separate ecosystem. So this lets us design a system that is fully sound. And what's really cool about that is it means once we've finished fully implementing this, we can actually take advantage of this for optimization purposes. So when we're compiling the native code, we don't need to generate machine code for doing null checks. We can compile the smaller JavaScript code because we know certain things aren't going to have null. We can do unboxed representations. So I'm super excited about all of this stuff. It's not the only thing we're doing. We've got some other things in the pipeline. We're working on extension methods at the same time. [APPLAUSE] It's so fun to have fun features to talk about. KEVIN MOORE: I'm excited, yes. BOB NYSTROM: The plan for this is, we're going to do basically extension members. So anything you can define inside a class, you can define as an extension. So we'll do methods, getters, setters, operators. If you want to do operator overloading extension methods, go to town. Actually, that is useful. Then you can do symmetric vector operations. Great. KEVIN MOORE: Yes. BOB NYSTROM: We are investigating some new concurrency primitives. I don't know a lot of details, so I can't give them to you. But I'm sure they are interesting. We're working on a new foreign function interface. This should help you reuse existing C and C++ code, which is important for some critical stuff. And just generally, other things. What I'm particularly excited about-- this is one of the reasons I'm on the Dart team is that we are a fully open source language, and we do this in the open. So we have a separate repository, the language repo, where all of the design work for this stuff is happening. And I would love to have you show up, participate, help us do the design, help us make Dart into the language that you all want it to be. KEVIN MOORE: And that's Dart. So we have a new website, dart.dev. [? We want ?] you want to check it out-- we just launched this today as well-- to learn more about the language, do some code exercises, learn, dig in the community, ask us questions, create packages. We're excited for you to join us on this adventure and this ecosystem we built together. Thank you. BOB NYSTROM: Thank you. [APPLAUSE] [MUSIC PLAYING]
Info
Channel: Flutter
Views: 61,289
Rating: 4.9516826 out of 5
Keywords: type: Conference Talk (Full production);, purpose: Educate, pr_pr: Google I/O
Id: J5DQRPRBiFI
Channel Id: undefined
Length: 40min 1sec (2401 seconds)
Published: Thu May 09 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.