Global CSS droidcon News droidcon NYC 2019 Share Tweet Flutter at scale By Jorge Coca droidcon New York City 2019 Flutter has been out of beta for less than a year. It is an amazing framework UI that lets you run your code pretty much anywhere. There's a lot of expectations around it, incredible apps running at 60fps, but... is it ready to be adopted at scale? At BMW, we faced that question a while ago, and the answer was YES! We tried it, we loved it, and we collected all the necessary information to prove that Flutter was the right choice for us. In this talk, let me show you our process to make Flutter our preferred tool for developing applications, and how we enable multiple teams around the world to deliver incredible experiences fast and safely. Transcript en-us 00:00 [Music] 00:12 thank you all for coming to this talk 00:14 that it's called Fred flattered at scale 00:16 my name is Jorge and I worked for 00:19 Vietnam of you and in this talk I'm 00:21 going to explain how we used to platter 00:22 at vnw because yes we've been using 00:25 flattered for a little bit more than a 00:27 year but before we get started if you 00:30 want to know why we're using flatter I 00:32 would recommend to check out the 00:34 conference talk that I gave two weeks 00:36 ago at Android Sam I'd call our journey 00:38 to flatter so with that said what do you 00:41 exactly mean by flattered at scale like 00:44 that at scale sounds pretty cool but 00:46 what does it truly mean and depending on 00:49 who you ask you might have different 00:51 answers to me and to my team it means 00:54 that every time you're facing a complex 00:56 problem and let's be honest we're 00:58 working we're engineers right like 00:59 that's our job we're trying to solve 01:01 complex problems but if we don't provide 01:03 an easy solution a simple solution that 01:05 can be replicated and scaled to many 01:08 other people as well they were not 01:09 solving the problem properly so that to 01:11 me is what I mean by flattered at scale 01:14 an example of that would be a vehicle 01:16 right these machines are very very 01:19 complex and powerful a lot of years of 01:22 development a lot of different people 01:24 working on just brakes and the engine 01:27 and the windshields and all the stuff 01:28 but you as a driver you only have to do 01:31 two things put your hands on the 01:33 steering wheel press the gas press the 01:35 brake pedal that's pretty much it right 01:37 so that's an example of how to solve a 01:39 very complex problem how to take you 01:41 from point A to point B in a safe way in 01:44 a way that everyone around the world can 01:46 do it right so how do you start thinking 01:51 about these simple solutions to complex 01:53 problems well to me it starts by 01:56 stirring up goals before writing any 01:58 single line of code whiteboards they 02:00 were invented to design code not to do 02:03 software engineering interviews at least 02:06 that's the like I would like it to be so 02:08 what were our goals when we decided to 02:11 start a flatter project well we start 02:13 down with the business team and we start 02:15 down also with our design team are two 02:17 main stakeholders 02:18 and after a few centuries of working 02:20 together we try to come up with a 02:22 sentence that describes the goal for 02:24 this project the philosophy of how 02:26 should we what it's this platter project 02:30 accomplishing right and this is the 02:32 sentence that they gave us back they 02:34 want to be able to regularly release all 02:37 the products that we have across all the 02:39 brands in all the platforms iOS Android 02:42 with in all the regions around the world 02:45 right like being W operate a global 02:47 scale its present in pretty much every 02:49 single country right so as our digital 02:52 products we have to be available there 02:53 as well and we also want to have the 02:55 same feature capabilities that doesn't 02:56 mean that all the capabilities are going 02:58 to be turned on at the same time but if 03:00 we need to we have to be able to just 03:02 flip a suite and get done with it right 03:05 to complement this business and design 03:08 goals we also have our own engineering 03:09 goals right like at the end of the day 03:11 engineers are working on the platform so 03:13 what is the respect Asian of the final 03:16 project and as you can see I'm not even 03:17 mentioning flattered here yet this is 03:20 just like normal stuff where development 03:23 goes right so our goal with this project 03:25 was to create a platform that is 03:27 developer friendly developer scalable 03:29 and performant which provides safe 03:31 experimentation and continuous 03:33 deployment and you might be asking like 03:35 yeah those are very cool words it's all 03:37 the buzzwords that we have in the 03:38 industry but how do you get to that 03:40 point well that's why I'm highlighting 03:42 and I'm gonna focus on each one of these 03:44 points to tell you how we solve this 03:46 problem but before we do that I want to 03:49 explain what the infrastructure or like 03:52 the team setup that we have at vnw right 03:54 I sit in that box in the middle in the 03:57 core mobile team so that means that I 03:59 have an infrastructure team that are 04:00 dictating me how do you use my 04:02 infrastructure and I have teams in this 04:05 case feature and market teams what I can 04:07 tell you like hey these are the tools 04:09 that the core teams are providing if you 04:11 wanna be part of the project if you 04:13 wanna include your feature in this 04:15 market or whatever you have to play with 04:18 the rules that we provide you right so 04:20 with that said let's think about one of 04:23 the each of and one of the goals that we 04:25 listed before right so how do we achieve 04:28 release in regularly 04:30 very simple we start down with business 04:32 and we said if you wanna release 04:34 regularly just give us a new schedule 04:36 and schedule that no one can actually 04:39 skip there's no like wild cards or 04:41 anything we know two years in advance 04:44 the days that we're going to push our 04:46 application to production that means the 04:48 trend releases this is something that 04:50 many companies do as well right and that 04:52 means that every two three weeks 04:54 whatever you dictate we're releasing 04:57 whatever it's in there right if it's not 04:59 ready it's gonna be turn on turn off if 05:01 it's ready it's gonna be turned on that 05:04 means that also we follow trunk vice 05:06 development that means that every single 05:08 commit goes directly into master we 05:10 don't have develop branches or featured 05:12 branches or hot fixes or anything like 05:14 that you create something you put it in 05:17 immediately to master when we talk about 05:21 all the brands three years and platforms 05:23 I talk about having in a single codebase 05:25 B and W be in Wi the electric version of 05:29 vnw meaning Rolls Royce and if we have 05:32 morphia brands in the future we will 05:34 accomplish that as well right and we 05:36 also have a global presence but the 05:38 different markets they have different 05:40 legal requirements GDP are for example 05:42 that's the best example but also like 05:44 the integrations that you have in China 05:46 with Alibaba with ten same they're not 05:49 the same integrations that we have here 05:50 in the US that we may be working with 05:52 Google or Amazon right so within the 05:54 same codebase we need to facilitate all 05:56 those integrations but in a way that if 05:59 I'm reducing something I want to turn it 06:01 off and not bring that functionality - 06:04 for example North American customers so 06:07 that means that under one single flutter 06:08 code-based we're not only doing an ios 06:10 and android application we're doing like 06:12 four brands with multiple like flavors 06:15 around the world different stages and 06:17 all the stuff and we do that by also 06:18 providing different design libraries or 06:21 UI libraries that they collect the UI 06:24 sentiment of each brand right when we 06:28 talk about same feature capabilities 06:29 we're talking about simple feature flags 06:31 for this market this is turn on or this 06:34 is turn off or we provide a different 06:35 configuration right and that's how we 06:37 can have a dynamic bundle depending on 06:40 where we're planning to deploy this 06:42 version of our application 06:44 at the same time we took a cloud centric 06:46 approach meaning that we're trying to 06:47 reduce the amount of decisions that we 06:49 make in our mobile clients our mobile 06:51 clients they're just presentation 06:53 rendering devices whatever so we decided 06:58 that our clients they need to be really 07:00 stupid relief in and all the processing 07:03 all the decision points they need to be 07:05 made in the backend so we have more 07:07 control over the deployments and things 07:08 like that and we're not tied to the 07:09 releases of the Play Store or the or the 07:13 Apple Store right and now we go back and 07:16 transition to you developer friendly so 07:18 we're talking about the engineering 07:20 goals what do we mean about developer 07:22 friendly well as an engineer the first 07:24 thing that I look at a code base is the 07:26 amount of tests how many tests do we 07:28 have is this tested the more test is 07:30 that you have the more freely you're 07:32 going to be to new engineers or to 07:34 existing engineers right that's your 07:36 kind of like safety net at the same time 07:38 we want to provide a consistent coding 07:40 style I wouldn't be able to navigate 07:43 between different modules different 07:44 projects and feel like it was written by 07:47 the same person even though that's not 07:49 true because we have teams all around 07:51 the world right and finally this is a 07:53 negotiation with our product teams tech 07:56 dev must be addressed 07:57 soon the sooner the better right 07:59 sometimes you made assumptions from day 08:00 number one and you keep growing that 08:02 feature making changes or just changing 08:05 the scope or the requirements change and 08:07 when what's ballot on day number one is 08:09 not valid anymore on day 25 so that's a 08:12 negotiation with your product team to 08:14 address the tech Dave right and that's 08:16 something that yes it's a case-by-case 08:17 but if we want to be developer friendly 08:19 both business and engineers we need to 08:22 understand that this is a priority what 08:26 do we mean by developer scalable well we 08:29 assume that at any point in time in our 08:31 code base we're gonna have either a 08:33 single developer or n developers and 08:36 that n is totally variable it depends on 08:38 like what's the market that were 08:40 planning to release or like what's the 08:42 level of integrations that we have the 08:43 partnerships right I know that in our 08:45 existing native clients at some point in 08:47 Android and iOS we had like more than 08:49 200 developers which is a lot right and 08:51 we need to accommodate all those 08:53 requirements so for that we created an 08:57 natural onboarding 08:58 this where we explained our techniques 09:00 before you write any line of code 09:02 nothing not before writing a light of 09:04 code you're gonna be assisted to writing 09:06 code but once you feel like you're ready 09:09 that you've been on boarded it's gonna 09:10 be very natural to join the code base 09:12 because all these test samples that 09:15 you've been doing they're gonna be the 09:16 same ones that you're gonna find in the 09:18 final code base and finally we are 09:22 guided by a rule that is just keep it 09:24 simple like if a developer goes to an 09:26 article and it's like in flattered you 09:28 do things this way we should not try to 09:31 reinvent the wheel and create a 09:33 different framework in which these rules 09:35 don't apply anymore right so we want to 09:37 be consistent we want to be simple we 09:39 want to be predictable by performant and 09:44 this is just a list of technicalities 09:46 and requirements that we have I'll show 09:47 you later how we get to achieve all 09:50 these metrics right but flooded promises 09:53 60 frames per second right that's great 09:55 that's how you have like beautiful 09:57 animations you don't see any lag when 09:59 scrolling or doing anything so we want 10:02 to be able to make sure that every 10:04 single offer features dran and renders 10:06 at 60 frames per second we also captured 10:09 like our crust matrix of course and our 10:12 KPI is like before we put something in 10:14 the market we need to make sure that is 10:16 99.9 crash free and we collect data 10:19 around that right so our philosophy is 10:22 like keep measuring keep analyzing your 10:23 application and with that data keep 10:25 improving right and again this goes back 10:27 to the idea of address in tech tip it's 10:30 not just engineer said okay we need to 10:32 refactor this module we have data to 10:33 prove that a module is not performing 10:36 the way we want it we need to address it 10:38 as soon as possible and again how do you 10:41 achieve this by having taste not only 10:43 one or two or three no we're talking 10:45 about thousands of tests right and with 10:48 all this in place it's gonna be easier 10:50 to pinpoint what are the problems if 10:51 you're having problems on the rendering 10:53 layer you can pinpoint - it's happening 10:56 in the UI if you're having like latency 10:58 Network layers you can pinpoint to your 11:00 network layer or to your backing layer 11:02 right so that's the goal in here is to 11:03 be able to identify where do you have 11:05 those performance bottlenecks what do we 11:09 mean by safe experimentation those are 11:11 two words that 11:12 they shootin kinda like or they don't go 11:14 together because if you want to 11:16 experiment it's like well I want to try 11:17 these this and that and then gather the 11:19 results but at the same time I don't 11:22 want the customers to beat it to pay the 11:23 price of our experimentation failures I 11:26 want them to only see the success right 11:27 so we do that by having again feature 11:29 flags a be testing test all the 11:32 different varieties and different like 11:36 versions of the app that we generate 11:38 right so by doing that we move the 11:40 complexity out of the clients and we put 11:42 it in our back ends and the back into 11:43 that one dictated like that feature that 11:45 area that screen should be turned on for 11:48 these percentage of people's or in these 11:50 markets things like that and for the 11:52 rest of the world whatever they need to 11:54 be turned off and we have something that 11:57 will run integration tests a lot of 11:60 integration tests so we can render the 12:02 UI 12:02 take a screen shot and things like that 12:03 and we are testing those variations in 12:07 our integration test readwrite we have a 12:09 long long learning digression test with 12:11 where we can validate with the signers 12:13 that hey if this is turned on that's the 12:16 way you're expecting it to see that's 12:17 the entry point but if it's turned off 12:19 you also need to validate that case 12:21 right 12:21 and finally continuous deployment that 12:24 was the last of our engineering goals we 12:26 said that we merged every single commit 12:28 direct link to master that means that 12:30 everything you merge is gonna make it to 12:32 production in less than two weeks that 12:36 is in the client in the back end we're 12:37 talking the review merge to commit to 12:39 master that goes to production 12:41 immediately so that creates at the 12:43 beginning like a lot of pressure by the 12:45 same time it gives you a lot of 12:46 flexibility because something goes wrong 12:47 you have all those metrics to analyze 12:50 that something went wrong 12:51 digit roll back fix it whatever but we 12:53 wanted to reduce the complexity of going 12:55 to production am i having the same 12:58 merger strategy in the client and in the 13:01 back end developers don't have to think 13:03 about like oh is this gonna be roll out 13:05 in production in two weeks or when it's 13:07 gonna be no no do you have it 13:08 immediately in production that's the 13:09 assumption enjoy it right like it's 13:12 tough freedom it's a flexibility that 13:13 it's great you don't have to think about 13:15 it scheduling and like like 13:18 cherry-picking comments that go to 13:19 production and all that that's gone 13:21 right but if you wanna play safe you can 13:23 have a percentage roll out and that's 13:25 pretty much what we do 13:26 when we released our clients like we go 13:28 to production but the first day we might 13:30 try like a 10% then we increase it to a 13:32 2050 and then we're allowed to 100% so 13:35 that is very important to have the 13:37 proper monitoring alert and like remote 13:40 debugging and we have all that in also 13:42 unit second how to do that but if you're 13:45 thinking that so far I'm crazy well I 13:48 might be a little bit who knows but this 13:51 can be achieved and this is what I'm 13:53 gonna be focusing right now how do we 13:55 achieve all these metrics 13:57 I'm flattered right like this is what's 13:58 enabling all the teams that we have 14:01 working on the mobile platforms at vnw 14:04 to be able to deliver fast saved and 14:08 actually be happy while doing all these 14:10 things so first of all the first step is 14:14 not like oh let's introduce this tool 14:15 let's get flooded or all this no no no 14:17 the first step is learning from your 14:19 past we are here not an Android 14:21 conference right I was leading the 14:23 Android teams before and we had a lot or 14:25 we gathered a lot of knowledge good 14:27 ideas things that they were working for 14:29 us things that they were not working for 14:30 us and we now have the opportunity to 14:33 put all those lessons learned into 14:35 practice and to apply that into in this 14:37 case I'll further project but this also 14:40 applies to our micro services to the 14:42 machine learning teams right like keep 14:44 learning try to analyze always what's 14:46 working for you with that said I'm gonna 14:51 list the tools that we actually have 14:53 open source these tools either by my 14:55 teammate Felix and galuf as you can see 14:58 for flatter blog or all mothers that are 14:60 open source under the vnw take a space 15:02 I'm gonna explain how these tools are 15:04 helping all of our teams to develop 15:07 flatter enough efficient way and just 15:09 think about what's the problem and not 15:12 having to worry about like automation or 15:13 scalability right so we're gonna talk 15:16 about like the high level architecture 15:17 of our product and how do we validate 15:19 this architecture we're gonna talk about 15:21 the state management solution that we 15:23 have that it's called flatter block and 15:25 it's developed by one of my teammates 15:26 that sits next to me we're gonna talk 15:29 about how we collect data from our 15:31 clients using Lambor - then we're gonna 15:33 talk about how we do and how we set up 15:36 our pipeline to do unit area tests and 15:38 integration tests 15:40 and finally as part of this integration 15:41 test suite we have a tool called Asti 15:43 that is helping us to test this variance 15:45 and measure performance so for the rest 15:48 of the talk I'm going to be using an 15:49 example a very simple example it's just 15:52 a boring counter but this is going to 15:54 help me to validate all the cases but in 15:57 case you're interested in more complex 15:58 examples if you go to phalangeal that 16:01 get have that idea that block you're 16:03 gonna see that there's many projects in 16:05 there like trying to solve how to do 16:08 authentication how to do what to do 16:09 application this counter example many 16:12 other complex examples so with the blog 16:14 state management solution so what are 16:18 high level architecture 16:19 well we divide our project into what we 16:22 call vertical modules that means like 16:24 data layers repository layers or our UI 16:27 layer right and this is pretty much what 16:30 we've seen in all these talks about 16:32 modularization in android we're not 16:34 reinventing the wheel is just applied to 16:35 a different technology but we separate 16:37 our it typically in our databases or 16:39 secure storage or like if we need to 16:41 access the Bluetooth or the GPS into 16:43 smaller modules to smaller libraries 16:45 that they just can be reduced into some 16:47 other layers right and they can be 16:49 reused in this case into what we call 16:51 the domain layer the domain layer 16:53 answers the how is this information 16:56 being used the data layers they respond 16:59 to the question of what data do you need 17:01 to use and where is it coming from right 17:04 strangers the domain layer you can 17:05 compose multiple different data sources 17:07 in this case you could have your network 17:10 layer and your GPS to get points of 17:13 interest about around a single place 17:15 right and then this information that is 17:18 composed from these data layers is 17:21 provided to the UI layer the UI layer 17:23 just responds to the question of how am 17:26 i presenting this response right so very 17:29 simple and as you can see this is this 17:31 could be like a simple unit and then we 17:34 could have different units like 17:36 different nodes having like access to 17:39 all these modules so flattered by nature 17:42 is composable 17:43 you've heard all about the widget tree 17:44 and how the widget tree it's gonna you 17:46 have this note in here this note in 17:48 there and I can compose it I can remove 17:50 branches or notes or whatever right so 17:53 we are 17:53 my design philosophy and it's one of our 17:55 features can be incorporated into a tree 17:58 structure and if we need to turn off 17:60 feature a and has two children those two 18:03 those children are going off as well 18:06 right so that could be the high level 18:09 architecture to our project flutter 18:12 block what's the philosophy or like the 18:15 main goal of flutter block it's just 18:18 very simple we want to be predictable we 18:20 want developers to be consistent in the 18:22 way they present data to the UI layer 18:24 right when you're dealing with data 18:26 layers those might require more thinking 18:28 process but like rendering data on the 18:30 screen should be a problem self already 18:32 so in this case we created this library 18:36 using our experience that we have with 18:37 reactive programming right like a tricky 18:40 rx weaved but at the same time 18:43 understanding what were their pain 18:45 points when drawing this code vases and 18:46 it was like nor having unidirectional 18:49 data flows or like having a lot of 18:51 memory leaks because we forgot to 18:52 dispose descriptions or things like that 18:54 so what we do with blog is very simple 18:56 still acknowledges that idea that every 18:60 application that we have at vnw is 19:02 reactive in a way that if you have 19:04 changes in the vehicle those changes 19:06 might affect other screens as well right 19:08 but we want to simplify this idea of 19:10 like subscribe in a like playing with 19:14 Erics operators and things like that so 19:15 it's very simple from the UI the user or 19:18 the system will generate events we 19:20 process those events in the block and we 19:23 just have a single output where we 19:24 publish States very simple we're gonna 19:28 see how that works before we do that we 19:31 need to understand that UI is as simple 19:33 as a function of the state of your 19:35 application it's a screen of your 19:37 application is something that is 19:39 happening at a certain point in time and 19:40 your function your business logic is 19:43 what determines what do you do with that 19:45 data how do you present it right very 19:48 very simple in this case the UI is our 19:50 flutter widget our function is the build 19:52 method of every single flutter widget 19:55 and the state is just a piece of 19:57 information at a given point in time 19:59 with this idea that is very simple but 20:01 powerful it's when you can start 20:03 providing different state management 20:04 solutions so for us what 20:07 an estate is something as simple as 20:11 what's the data model what's the class 20:13 or in this case just a field that 20:15 describes what's being painted on the 20:16 screen in the case that like or in this 20:19 case the information that changes on 20:20 that screen so in the case of our 20:22 counter it's just gonna be the contour 20:23 value right we see that it goes from 0 1 20:26 2 3 to 0 1 so that's our state that's 20:29 the piece of information that changes 20:31 and it's as simple as a pure dart class 20:33 if we were talking about Java this could 20:35 be a POJO or anything like that the same 20:38 concept applies to UI events we need to 20:40 capture what the user or what the sister 20:42 is telling us that is happening at that 20:43 time in this case we can capture that 20:46 information with an enum our content 20:48 event is just like okay every time you 20:49 play you tap on the plus button 20:51 do you incrementing the counter when you 20:53 tap on the minus button do you think 20:55 remain the accountant this could be 20:57 captured as an enum but it could be also 20:58 like a single like pure there class and 21:01 that's how it would work and with this 21:03 idea our block is just I receive events 21:06 and I'm gonna push the states back to 21:08 the UI it's as simple as that and 21:10 because it has no flower dependencies 21:12 you have any other dart project like you 21:14 could be a command-line interface 21:16 application or angular dart or anything 21:18 like that you could use block as well 21:20 and it works right and it only has two 21:24 API is that we need to provide an 21:25 initial state what's the information at 21:28 the very first frame of that widget and 21:30 how to map these events to states that 21:33 you're gonna push to the UI and then 21:36 flutter block provides also a collection 21:39 of widgets to actually listen to these 21:41 states or to provide blocks to children 21:46 nodes so it's kind of like a dependency 21:47 injection version for that right so 21:50 let's take a look to how a block looks 21:52 we extend from the block class we get 21:55 our event and our state in this in this 21:58 case the status and end right so first 22:00 of all we provide an initial state for 22:02 this counter very simple what's the 22:04 initial state 0 what do we do the end 22:07 with our event well very simple if I 22:10 receive the event decrement I just want 22:13 to grab the state that I have in that 22:14 screen and remove one from that state 22:17 right same thing for the increment type 22:20 if I receive 22:21 from the UI that hey you are processing 22:23 the increment event is as simple as just 22:26 increment in my current state to one and 22:28 yielding back to the UI how does it look 22:33 on the flatter side very simple we have 22:35 in this case our content application 22:37 right this is the entry root node of the 22:40 application and we do something in here 22:42 we say that the home widget is gonna be 22:45 a block provider that is gonna create 22:47 your content block the class that we saw 22:49 before 22:50 and it's gonna render at children widget 22:52 that is the counter page why are we 22:54 providing this block in here well 22:56 because then in our counter page that is 22:59 again a stateless widget because we 23:01 don't need to this post in this case the 23:03 block the first thing that we're gonna 23:05 do right is to well in this we 23:08 understand list widget the first thing 23:09 that we're gonna do is to retrieve that 23:11 block from my widget tree this is kind 23:13 of like without noticing dependency 23:15 injection being executed but in a very 23:17 simple way right like compared to 23:18 Android we're not talking about dagger 23:20 or coin it's just like oh I can just 23:22 retrieve it from my tree and that's very 23:24 powerful where am i retrieving the block 23:26 from the previous children well it's 23:30 because first of all in my block builder 23:32 I'm gonna be used in the state of the 23:34 content block to render the account as 23:37 you can see we have a text widget that 23:38 is rendering the value of the count but 23:41 also I have buttons that they need to 23:43 send some information back to the UI in 23:46 this case on the impress of the add 23:49 button we're calling the content block 23:51 that this pad with the event that I 23:53 wanna process right that's why we need 23:55 to get access to the block from from the 23:57 previous parent and we do we do the same 24:01 thing for the decrement button we want 24:03 to this button event that is the 24:04 decrement and we use it like that so so 24:08 far it's very simple every screen whose 24:11 information changes over time has a 24:14 block associated with a single entry 24:16 point where we passed events from the UI 24:19 to the block and from the block to the 24:22 UI there's also a single exit point 24:24 where we send States to be render in the 24:26 UI by doing this as you can see there's 24:30 something in there sitting between the 24:32 phone and the block that says like 24:33 analytics low 24:35 debugging that's very powerful because 24:37 now every single block follows the same 24:40 pattern it looks the same it's just 24:41 processing events rendering states and I 24:44 can put a middleman in between those 24:47 transitions sorry about that 24:49 and these transitions are gonna help me 24:52 to capture actually analytics or to do 24:54 remote debugging of my application if 24:56 needed right and we get all these for 24:58 free I don't need anyone to be writing 25:01 analytics or putting log statements it's 25:03 all done by the framework that's the 25:05 beauty of this solution in my opinion 25:07 how do we do that well this is where we 25:10 use number that's another library that 25:11 we develop and I think we have the 25:13 cutest logo ever I don't know that's my 25:16 personal opinion but what we do with 25:18 Lambrettas is very simple we just want 25:21 to collect logs so first of all we put 25:24 Lambert us to work with what with a 25:26 client and this is the magic we can have 25:29 many different clients right in this 25:31 case we'll put in Lambert has to work 25:32 with a simple client and then it's as 25:35 simple as you log a warning you log a 25:37 fatal message or like just a simple 25:39 message or a log error that's all you 25:42 have to do as a developer you can just 25:43 set up Lambert us to work with a client 25:46 at the root of your application and 25:48 that's it you don't need to change the 25:50 client so we've open-sourced many 25:52 different clients depending on our needs 25:53 some of those they could be like if 25:56 you're in a debug build you don't want 25:58 to be published in changes or like logs 25:60 to your cloud systems but in some other 26:02 cases for example we have a century 26:04 client and a firebase client that's 26:07 because in China for example you are not 26:09 allowed to use firebase so we could use 26:11 sentry instead and it's very simple as 26:15 you can see if you're running on your 26:17 debug flavor you could select okay pull 26:19 Lambert has to work with a simple client 26:21 my friend running on something that is 26:22 not a debug flavor like your release 26:24 flavor I want to use the fibrous client 26:27 but if I'm running on China or if I'm 26:30 running on North America integration 26:33 staging whatever you could be using a 26:36 different client that accommodates your 26:37 needs right 26:39 so with that what flooded block provides 26:42 is this idea of delegates and this 26:45 delegate is what sits between your UI 26:47 and your block 26:48 that middleman that is listening to 26:50 everything that is happening so every 26:52 time we get a transition I can just log 26:55 it with lumber - and every time we have 26:57 an error I can just log it again with 26:59 lumber does so with all these lines of 27:02 codes that they will only set up once in 27:04 my project we collect analytics we can 27:07 remote debug what's happening because we 27:09 Lambert us I can publish those logs to 27:12 different environments to different 27:13 systems and then it's as simple as in 27:16 the entry point of my application in my 27:18 main method I just said my blog 27:21 supervisor that delegate to be the 27:23 counter block delegate in this case and 27:25 working with my lumber that's client 27:26 that we generated before and just run 27:29 the app so with all these that looks 27:34 very simple right think about all the 27:37 things that we've done we've done a 27:38 counter application that could be 27:40 testable that could be actually like the 27:43 block pattern can be reproduced in every 27:45 single part of your application and 27:47 you're getting analytics and remote 27:49 debug for free so that means that our 27:52 feature teams those teams that are like 27:55 spread around the world and they don't 27:57 have to worry about the problems that I 27:59 have at the core team they actually 28:00 don't need to think about those problems 28:01 they don't need to think about analytics 28:04 they don't need to think about 28:05 performance or anything like that it's 28:07 gonna be all measured and provided by my 28:09 team by giving them the right tools 28:11 that's I think how you scale these teams 28:14 to be so big and so performant I asked 28:17 him actually to send me like hey I want 28:19 to put any money about or I give about 28:21 the how you feel about the code and this 28:23 one was the most boring so I I would say 28:26 that we're in the right direction but at 28:29 the same time like my job is not done 28:31 just with this tool right how can we 28:33 measure or how can we ensure that what 28:35 we're putting in the market is up to the 28:37 level of quality that we expect well 28:40 again we need to provide automation 28:43 automation testing and we need to do 28:46 this in a transparent way but that can 28:48 be enforced by every single team so what 28:51 we have is we have dr. eyes or CIC the 28:54 Empire environment and we have a lot of 28:56 scripts in there to analyze our 28:58 architecture graph and our dependency 29:00 graph to validate the test cover 29:02 we needed to find a number it wasn't a 29:04 greenfield project so we like 100 better 29:07 than 99 so our code tastes like our code 29:11 race is tested with a 100% of coverage 29:14 and this doesn't mean that we don't have 29:15 any bugs I understand that part these 29:17 for us it just means that at least every 29:19 single line of code needs to be executed 29:21 if that code was written by humans 29:23 that's the other part also we had 29:26 integration tests we'll see how we can 29:28 measure that we run at 60 frames per 29:30 second every single time we have a 29:31 visual dependency graph right like this 29:34 idea of like the widget tree and how we 29:36 compose our application being a tree is 29:38 that something that we can validate and 29:40 make sure that we don't have modules in 29:42 the wrong places we have a consistent 29:44 Linton informatn in every module and 29:46 again if you want to create a new 29:48 feature project we provide project 29:50 generators that will do all this setup 29:51 for you so you don't have to do it 29:52 manually so this is an example of how 29:55 one of our pipelines in one of our 29:57 modules looks like we have a 29:59 verification stage where we run like our 30:02 for water our translations to make sure 30:04 that they're validated we run around 30:05 eliezer and if everything is going great 30:07 we have another node as you can see in 30:10 the bottom left that says visual 30:12 architecture this is what we used to 30:13 validate that our dependency graph 30:15 doesn't have like for example UI modules 30:19 talking directly to data modules right 30:20 that's what we put that repository 30:22 modules in between or to ensure that 30:24 like it's composed in a way that makes 30:27 sense we can validate that in the 30:28 pipeline then every single node that you 30:30 see on the test is testing different or 30:32 smaller modules of this project with 30:34 100% of coverage and finally we 30:37 distribute this feature module or this 30:40 application to many different channels 30:42 that we use for distribution so as part 30:45 of the testing phase that you've seen in 30:46 there we used a tool called Aussie it's 30:49 just something that we add during 30:50 integration test and it's going to allow 30:52 us to capture screenshots of the 30:54 application and measure also the 30:56 performance of how its frame is being 30:57 rendered I think it's very if I present 30:60 a gif of how it works so in this case we 31:02 create a generate like an HTML report 31:04 that captures all these dates of this 31:06 counter application unto 20 so you can 31:10 see the screenshots in there and then 31:11 when we tap on the performance it's one 31:14 of these screenshots or feature tests 31:16 performance rating associated right so 31:18 in this case we're dropping frames it's 31:20 not smooth enough I can actually break 31:22 the build or if everything is green and 31:24 it is our threshold parameters we're 31:27 happy with it we can learn that that PR 31:29 so how does this look in code right 31:31 because if this is a pain for developers 31:33 to what they're not gonna do it and I 31:35 don't want that so it's as simple as 31:37 this in your setup method of your test 31:39 you get an instance of the flutter 31:41 driver that is going to enter your test 31:44 and then you create the instance of the 31:47 OC will you pass the driver so we can 31:50 take the screenshots and you're just 31:51 gonna give it a group name so we can 31:53 create a nicer HTML report when you're 31:56 finish your test and your tear down all 31:57 you close the driver so you don't have 31:60 memory leaks and we ask OC to generate 32:02 the web report and then on it test 32:04 it's as simple as OC profile the 32:07 performance for all these actions and 32:09 while taking these actions take a 32:11 screenshots as well right so it's two 32:13 lines of code and with that you can 32:15 measure performance and get a screenshot 32:17 for your marketing department for 32:19 testing your variations whatever you 32:21 want we can also provide a configuration 32:25 to us T to be more like conservative or 32:28 more aggressive in the amount of things 32:31 that we'd or or how we want to fail or 32:33 succeed our bills right so first of all 32:35 you can pass the configuration of like 32:37 hey OC has the ability to give you 32:40 coordinates in case you're getting close 32:42 to a number that it's dangerous but if 32:44 you want to fail your build on warnings 32:45 set it to true of course if you want to 32:48 build a field lab fail the build on 32:50 errors which is recommended set it to 32:52 true as well but if you just wanted to 32:53 get performance reports and let the bill 32:56 pass set it to false and that's it right 32:58 and then you can press that I've like 33:00 performance metrics like see a KPIs that 33:02 you wanna measure against so in this 33:05 case you can set up a threshold for your 33:06 missed frames so if 5% of your frames 33:11 are being missed 33:12 you can raise no warning and if 10% of 33:14 your frames are being missed then you 33:16 can fail the warning right same thing 33:19 same idea for the frame build rate and 33:21 from the frame rasterizer rate very 33:25 simple just put the configuration in a 33:27 yellow file two lines of code in your 33:29 integration test and you 33:30 get an HTML report with the screens 33:32 fields performance profiling like very 33:35 powerful very visual very easy to 33:37 understand so we see to understand that 33:40 someone that I haven't made before 33:42 yesterday while I was preparing part of 33:45 the talk send me these tweet and it made 33:48 my day 33:48 Wow it's the first time that someone 33:49 complements me and Twitter about an 33:51 open-source project 33:52 so thank you Lucas so yeah these are the 33:58 main tools that we use to guarantee that 34:00 our fluttered code risk can scale to 34:03 multiple teams all around the world 34:04 right at the end of the day my goal is 34:06 to facilitate feature teams to do just 34:10 feature work and think about the pro 34:11 another solving like how to integrate 34:13 with this market how to do integrations 34:15 with different platforms and if in my 34:18 case I need to put the the heart of a 34:20 feature developer I can also dogfood my 34:23 own solutions and provide feedback and 34:25 understand like hey this is very very 34:27 complex to do no one's gonna use it or 34:29 like actually this is very simple so 34:30 simple that I don't mind doing it or 34:32 like it's just part of my day-to-day 34:34 process right so I wanna do a recap 34:36 before we kind of like open a session 34:39 for Q&A about the things that we talked 34:42 and this had not tied to flutter 34:44 I think they applied to every single 34:45 technology regardless of what it is it 34:48 just happens to be that we apply this in 34:50 our case for for flatter right so 34:52 complex problems they require simple 34:55 solutions this is easy to say I 34:56 understand by yourself in a complex 34:59 program with a complex solution then 35:02 sorry you're not providing the right 35:04 solution make sure that you capture 35:07 first your business goals at the end of 35:09 the day they are the people that they 35:11 make the money and compliment those 35:13 business goals with your engineering 35:14 goals right and for us the rule is like 35:17 if you don't test it you don't shape it 35:19 there's no argument about it it's 35:21 actually all out I made it so I'm not 35:23 the one failing your business the 35:26 requirements that we put in there and 35:27 because of that if you don't know domain 35:29 it it's gonna be a pain so 35:32 automate all the things and finally for 35:35 us we learned that developer experience 35:36 is key to success not only to make sure 35:39 that we're providing us like actually a 35:41 good codebase but that also 35:43 your own happiness as a developer and 35:45 that's had another topic that I could 35:47 have for a different day but if you're 35:49 not happy being a developer because of 35:50 the technology choices then that's a bad 35:53 sign that the developer experience is 35:55 not really good right with that said you 35:58 can follow me at Jake Coker Ramos on 36:01 Twitter I also run the Chicano flutter 36:03 Meetup 36:03 we're located in Chicago by the way I'm 36:06 writing a book it's gonna be called dart 36:08 to you in action 36:09 hopefully it's gonna be in the market 36:11 soon but it's not there yet 36:13 and if you have questions about 36:15 flattered you don't need to be actually 36:17 located in Chicago to talk to me you 36:18 shoot me a message on Twitter or like on 36:20 my website I have a something called 36:23 Friday's and coffees where like before 36:25 going to work I like to meet up with 36:28 people from the Chicago community or 36:29 like people remotely they just like hey 36:32 let's do a Skype session and we talk 36:34 about Friday or whatever it is right 36:36 it's kind of like a mentoring 36:37 opportunity where both you and myself we 36:40 can learn how to grow together and 36:42 finally if you like this presentation 36:44 like share it on Twitter thank you and 36:47 it's gonna be published on speaker dick 36:49 and they're like okay very at scale 36:52 before I finish there's a flutter booth 36:55 right behind the stage organized by the 36:58 fried New York community awesome 36:59 community hi Maureen I'm gonna be 37:02 hanging out in there for hours if you 37:03 have any questions or anything or like 37:06 do you like the t-shirts or you like - 37:07 actually stop bad you can get one so 37:11 with all that said thank you so much and 37:13 happy coding everyone droidcon News Tech Showcases, Developer Resources & Partners /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader EmployerBrandingHeader https://jobs.droidcon.com/ /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com jobs.droidcon.com Latest Android Jobs http://www.kotlinweekly.net/ /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly Kotlin Weekly Your weekly dose of Kotlin https://proandroiddev.com/ /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev ProAndroidDev Android Tech Blogs, Case Studies and Step-by-Step Coding /detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando Zalando Meet one of Berlin's top employers /detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success /portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success Academy for App Success Google Play resources tailored for the global droidcon community