Lessons learned building the Invoice Ninja Flutter app - Hillel Coren | Flutter Europe

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Thanks for posting the video!

You can try the Flutter Web demo here: https://invoiceninja.com/demo

👍︎︎ 3 👤︎︎ u/hillel369 📅︎︎ Mar 24 2020 🗫︎ replies

I was looking for more insight on state persistence.

👍︎︎ 1 👤︎︎ u/thepurpleproject 📅︎︎ Mar 26 2020 🗫︎ replies
Captions
[Music] good morning I'm really really really happy to be here it's kind of a bit of a surreal experience just to start it's kind of surreal for me speaking after Brian I think Brian's not here so I can talk of them in on the room Brian's an amazing human being and I think one story I'd like to share is that when I first started with flutter I was extremely lucky to find Brian's and resources videos articles and more than that he was just really helpful when I went to ask him questions he kind of always made time for me and made me feel like you know it was important to help me and that really had that massive impact on how I relate to flutter that's where we thank him for that and I just guess to kind of comment what Phillip talked about yesterday says that they are paying it forward right because he was so nice to me people come to me I try to do the same I'll share a very quick story with him voiced ninja when we first released it and I spent six months nights weekends coding it I'm so excited about it and I sent it to the founders of laravel which is a framework we used and the response I got was don't spam us and I was just crushed in tears almost really painful they named care I mean today I was just some guy even them bothering them I was like six months is what I built with your technology if they just didn't care and it had a lasting impact I still probably hold on to it today sore about it but it's a lesson learned rights idea that we have this amazing impact or opportunity to affect future flutter developers so you guys part of reasonably knowledgeable off letters as people ask you questions hopefully don't tell you tell them you're spamming you really nice to be here so let's just talk about my name is Ola corn I'm one of the cofounders of voice ninja also soon to be known as invoicing Co I'll talk a little bit later about why we change the name now just this talk is kind of half business story and half developer story try to combine the two and to share kind of lessons I've learned and the first lesson I learned was be careful choosing your company name I think looking back this was a mistake My partner chose the name it was a very good name a very clever name we had the domain with the dot-com which is important but it's silly right it's it's not serious and it doesn't fit the domain invoicing is serious business and it's really hurt us I think over the years we went so far to buy a second domain invoice that services and we ran the app on two domains so our pro users could have the option of having a better domain and that was an even worse mistake because running an app on two servers or two domains is incredibly complicated with sessions and that kind of thing big mistakes so we are lessons learned we are renaming our company through a slow process you'll still see them with ninja references but hopefully in the future it'll be Jesse Moy Cinco so just a little bit about us we're open source company we have a reasonable user base at this point one special aspect about our software is that we are completely open-source we don't have a community version we are just open source code we deployed a master from get right through our production service from git and I think that's been critical in key to our success and hopefully we'll keep growing I just want to highlight that I'm not it's not me I have two amazing partners Shalom and Dave Jones the CEO Dave the CTO and I am the other guy so I lead front-end development but I also lead customer support and this business story I think is wouldn't be one of the keys to our success in building great software is eliminating that disconnect or minimizing that disconnect and making sure that if developers are incentive to fix bugs because Lucky's keep getting annoyed but these emails about it they're gonna fix it and do a good job and I think what happens I've part of this talk is I'm a biased against corporate culture and kind of corporate bureaucracy and so my last company they used to measure support tickets by how quickly they were closed L ends up happening is there's an incentive to leave issues open right because if it's a known issue that's a very quick issue to close and it kind of was counter-intuitively incentive our support team to not report issues right because they didn't want them fixed because these issues they knew they knew the answer they can close it right away it's a known issue and that was a quick quick quick close and that would kind of average out the longer issues so at our company we try very very very hard to look for patterns in problems and make sure to fix them and so again as I mentioned we're a fully open source that gives us two separate communities we have both a hosted and a self host community and the key here is that there's this beautiful relationship between the two groups that hosted users all they want is time they want to save time and they're happy to give you money if that will say them even the slightest at a time and cellphones are complete opposite they're techies they're programmers they love to debug to figure out issues when I get a error report from a selfish user it's got logs screenshots details where can I look what can I do and from the hosted users it's like it's broken fix it right it's you know you're wasting my time fix assume you shouldn't have been broken how could you have a bug right this is a production app how can you possibly allow to bug through I also get I also allowed to this as we keep growing I find it harder and harder to do support for two reasons one is when we first started I was so excited when I got an email I was like can you use our app that's amazing right like it was just shocked that anyone would even consider using it and I felt I gave them the attention they really deserve and as we get bigger and bigger it's harder because you know you get a bit jaded I think that you're like well it's you know I do all this work and you're gonna benefit from it and the other problem is I think people are getting a bit meaner to us honestly but I think when we're a much smaller company people email us like human beings talking us like a person and as we get bigger what I'm finding is people email me as if you know I'm a support represents representative I know nothing about the code it'll ask me questions I'll say well speak to her manager speak to a developer actually know something and it's gonna be frustrating when I built most of it but but that combination is critical and I think what I'm struggling with myself and I guess just sharing personal growth is kind of retaining that same mentality when we started when each customer support request was this amazing event that we got an email dolar got a case but again I tried myself to bring myself back to that mindset so our app we're pretty good I think this talk isn't about our app really trying to learn more about a wrap you can google us and learn more this is a third-party site that does unbiased reviews and they gave us a perfect score which really thrilled about we're ahead of much larger companies and I think one of the best things about this is that it's not comparing open source companies or open source solutions it's comparing all solutions all companies I think this is a great point that listen you can build an open source app at the same level as closed source apps and I think the key is open source again I see open source as a force can be used for good or for bad and the kind of direct it and one of the quick thing I've had to learn as I get older is learning to say no it's been really hard for me so for example early on we've got a PR whatever it was it was going to be merged I was gonna work with him we had a merge PR I'm so appreciative of his changes and that's not always the best approach I think it's very important as you're building software like this devel to say no say listen that PR I really appreciate the work next time maybe speak to me beforehand but it's critical early automate some mistakes by merging Piazza shouldn't have merged so that's something everybody tried to try to improve on so this is not so good so our last scores are for the web app and this is for the mobile app so what went wrong this is something I asked myself a lot what I believe was the problem and just to be clear a three or four is a three is unacceptable I think life is too short for three star apps right there's so much selection and choice in the store these days but I see four point five about as kind of a minimum threshold beneath that you really are gonna have a hard time convincing people to use your app so what happened right how do we fail I believe subjectively that our core failure was a lack of developer resources so we are three people but only two of us developers and at this point we had three code bases and sir pretty much you know it's a sports metaphor we're out man right we were one man short and we just couldn't do good enough right we could get the app to kind of work but we couldn't make a great app and to really struggled and this happened about two years ago so you can guys imagine what happened I'm here at this conference around then again three code bases big problem and around then we started looking for other solutions and this is just when you see that inflection point early 2018 that's when the flutter beta was announced and you know my stars there that's when we decide as a company this seems like a good option let's try it and we did and it's worked out incredibly well so we actually just start from scratch we threw away our two native apps and we started clean slate flutter brand-new one code base two apps for mobile for iOS and for Android and this is the app we built our users have loved it you can look at it looks very fluttery it's very material design this just shows three different UI screens but our customers have really been happy with it and so the rest of this talk I'd like to kind of go into detail talk about some of the approaches we use lessons I've learned and go from here state management's all right this is the first question everyone comes across when you come in a flutter I'm not going to detail all these options but it's thought of might be health to kind of share my mindset how I approach it when we first started in which ninja there weren't that many options there's really just set state ARC's PMS I think existed in redux and that was kind of it and so we chose read it can seem the best of the chop shion's a big part of that actually for Brian Brian had a great video early on about the benefits of Redux I'd never used Redux before I'm a web developer and heard about a lot so this is my first chance to use it I find and I've actually changed this talk a bit this talk used to be a talk all about redux why Redux is great how we use it but I find in the flooded community readouts is just much less popular it's something I think about also I mean how many people just show of hands how many bill are coming from mobile developments so almost everybody and in web developers well let appear where developers also so I question whether people coming to flutter if you're coming from react for example there are comfortable Redux and just kind of make sense so they'll adopt that because they're coming to flutter but I think other developers reps come from mobile for example Redux is let's use maybe it won't use it just to go quickly down the list so you guys are familiar with all these options just the way I see it I think set state is great I mean if you can use that state and build your app then do that right if it works if it's scalable it makes sense to you that's the right approach for you I think provider everywhere degree right now is probably one a great good starting point for a medium complexity app but one thing I think really important keep in mind is provider isn't architecture it isn't I don't even see the necessary state management it's just sharing your data it's a place to store your state and send it to your tree where something like Redux is kind of a full app architecture which explains how every part of the option function how it all should come together which for me personally I am I'm a good architecture it's just not my strengths I like building you eyes and front-end development so using like Redux where it's very structured really I think fit well with with my mindset one point with block I think it's lost a lot is that block was first designed one of the reasons was to enable sharing dart code between flutter and angular Dart that's one of the main reasons it was designed and it's something isn't even used like these days I think most people use block aren't using angular Dart I also I myself haven't caught up to streams yet I took me years to catch up to Redux I imagine maybe in 10 years a lot of streams out but I'm you know it just doesn't again I thought brides that makes a lot of sense that use the right tool for the job but I think more than that it's also the right tool for your developer mindset we all think about code differently and we understand that our heads definitely model it differently and it's good to use a framework that kind of matches that of closely as hospital if I was going to start over today I might use mob X I really really like mob X to me it seems to solve the problems we've seen with Redux so I just gave it strong consideration and I think arcs the MS is also a great option and one thing nice compared to Redux is that it has eliminates all the boilerplate code that's really the big problem with Redux and something like go in detail about how we try to solve it but that has been a problem one thing I want to share is you know I don't consider myself an expert developer I can send myself a really exceptionally adequate developer but I think I have a secret weapon a secret power and that is I love coding right I just enjoy it right you have to pull me away from my computer I think that's what makes me enables me to be successful and I think with flutter it kind of doubles out up my flutter is just fun to use so if you code because you like it you start using flutter you'll be that much more productive and it's been been my experience whoa went too far there so how many people have used Redux so people over familiar with Redux are aware of it so most people so I won't go into much detail just very quickly the redux what's nice about Redux it has a very simple flow where you have your store which is your states which your view is bound to in your view users can dispatch actions which will use middleware to interact with your API the reducers then update your store and then repeat repeat repeat and what's nice to me is that I find bugs although they can occur are much easier to track down I just have to follow the pipeline right follow it around see where it's breaking and that's where the problem is I also immutability that really threw me off on a first order term it's like we're programmers writes all about variables and changing things and the immutability just didn't make sense to me at the time but I think one way to think about immutable immutability is that first off you are change things of course you but you're creating new objects they're different and in terms of streams and that's how Redux actually works it's a stream controller under the hood so what you're doing is you're seeing a stream of states so rather than changing a piece of the state you're just getting a whole new state each little chain creates an entire new state and again just keeps repeating so performance this has been one of the big challenges I think with Redux especially compared to some like block or mob X so with block or mob X just the piece that that updated changes worse with Redux if you change a small part of your store the entire UI that's bound to it will rebuild sounds horrible in practice I found it's not always a problem because the wave flutter works you guys familiar with a separate widgets and the render elements is that even though your app is rebuilding it's not necessary drawing so although it is rebuilding I'm going to say make your app slow but it's certainly not optimal and that's something we've had to kind of be conscious of and so in some ways we work around this or memoization memoization and the way memorization works is you pass a function parameters and the function essentially looks at the parameters the next time and says hey they're the same and then cache is the value internally so we found this really helpful in our views to memos data and that way when the build as an app keeps rebuilding it's not gonna keep recalculating the data it kind of uses the first value and this is a great dart package that supports this it is possible in redux to prevent parts of the tree from rebuilding you would use the distinct flag in practice I've struggled with this because use the distinct flag you have to make sure to always override your equals equals operators which I sometimes forget to do and that's kind of a source of bugs so the approach we've taken now is just not use this feature at all and then the last point is keeping number of layers to a minimum and this I need to confirm because I'm not certain about this but I believe what I've seen in our app is if we have layers of routes and the reefs and the redux state changes even layers not visible are being rebuilt I believe and which can cause performance problems obviously so Reax has challenges these things I accept as problems and has benefits also that I mentioned earlier and I think like all choices it's a trade-off if you are using Redux and using immutability I highly recommend using a package called built value when I first start with Redux I was kind of doing all by hand writing the copy of a copy of with immutable functions before was built value it'll essentially convert a class like this log and user name/password to all this code right this is stuff that you would have to do by hand if you weren't using built value so this also gives you things like JSON serialization so the key point here is if you decide to use Redux I think you kind of have to use build value I just don't see it being manageable without it so very quickly this is a quick gif and this is kind of one of the big problems of our first step in this is looking at persistence so I'm in this form I fill out a field I quit the app and the key now is that when you read the app right back where we were with the data in place and there's data back right so this is the key part and this is a failure we had in our last step that we didn't have good persistence so what happened is a user would be creating an invoice they would start the process switch their email app to copy and paste the customers and email address come back and the data was gone and as frustra died our users to no end so this is kind of the primary goal with this new app was to implement a great persistence implementation and this is one area where I think Redux really works well with Redux you have a single store one big big a nested object with all your data so civilization can become our persistence can become easy because just have to serialize a single object save it to local file and then load it when you restart the app some challenges we had and similar solutions we had is some of our users can have many thousands and thousand thousands of records so if we keep persisting the states on every change you have very poor performance and so the way we solve this is we separate our persistence into multiple layers where we have a separate for data separate for UI Sephiroth and the key parts are data and UI so data is a very large store that changes infrequently and UI is a very small store that changes constantly and so we broke down the app so essentially it understands what you're doing and when persist just what needs to be persisted and we do this using interfaces I'll show it on the next slide a bit of a sample code essentially we use interfaces on our actions and if the action implements the interface there are middlewares that handle that and although this is Redux Pacific I think this approach could be used in with other state management approaches a track loading I do the same thing with persistence or sorry on the next slide and this is a key point about persistence if you decide to use this approach to persistence it's really important when you use track the version of your store and that way a view as you have updates it's very possible that your changes in the app will make your last stored state invalid so the key there is that you compare the version of your store persisted servers to the version of the current app if they're different we throw away this the persisted state and we start from scratch so it's only through updates that the user kind of loses their store data and the key that what happens there they have to essentially reload their data from a server so this is some code so how this looks in dart code and again we have our top-level app state this is a massive Redux store that has everything all the state an hour and hour app and this is loading his saving flags are changed based on those based on actions and then again we have the separate states the off state the data state in the UI state and this is what the code looks like see at the top we have these kind of generic these can be abstract classes but start loading stop loading persist UI be sis data the start loading stop loading tells the UI that will trigger triple flags that are true and they will show a spinner in the app and then persist UI persist data tells the app hey you know something's change you have to save it and this is just an example for client actions so you see in this case we're sending a load client requested this implements start loading so automatically this is the app knows hey I see if implant start loading that will set he is loading to true which the UI binds to and the spinner will appear and then for example once it finishes loading it implements stop loading and persist data so by implanting those two classes it'll both stop the spinner because is loading gets set to false and in this case will also persist the data store because the data itself has changed and again so you think about it you know the data store is very big that's when you load list of clients where the UI UI store is for example if you're creating a new record and you're typing in it that's how we persist we keep on each key press we restore the state using a D bouncer to prevent you know constant saving we essentially do like maybe 300 second delay and that way it's almost in real time persistent so view models this comes down to I think separating the code is separation of concerns and the idea here is making sure your views as Brian talked about are as simple as possible and I should also mention that all of our architecture of this code is based on Brian's sample redux architecture we just took his architecture and multiplied it by a thousand right just took what he did and expanded it so if you models allow us to separate that where we have our view code which just defines how the UI looks and functions and the view model is bound to it which we're where we put the business logic that relates that to the UI so everything example yeah a complex UI logic we've got regard to the store we use nested view models and I'll show you on the next slide and example but essentially if you have a complex screen will have a top-level view model with a top-level view now underneath that will have a nested view model with massive views and it allows us to kind of break down the complexity of the app into separate separate widgets and separate classes and makes it easier to manage when if you do it again this is more Redux Pacific that can be abstracted that if you're passing data to your views with Redux a lot of the time is you under the hood it's using an inherited widget to look it up so it's you kind of think you would put it in an its state but you can't actually use inherited widgets in its state so you'd want to use the unchanged dependencies and then accessing the app state in the view using the context essentially there are three different ways of doing this you can either pass it in as part of the view model access it in the view and then also separate pass each field individually and the key point here is that we initially passed each field one by one thinking this was the kind of cleanest way to do it in practice it just caused a lot of boilerplate extra boilerplate code so now we just passed the whole state to the view and I found that's be a bit a bit simpler so in this example to show you just a classic screen in our UI in our app with three separate tabs and so what you're seeing here actually four view models and four views so there's one view model on one view feet for the larger kind of wrapper which is where you see the Save button in the top right and then the fab and then each of these tabs are then their own view with their each of their own view models and so again so this one screen is eight separate classes it sounds like a lot but it provides a really nice way of breaking down your application into smaller chunks that you can work on and then and then build it all together when you have your final commands so example each sub view model responsible it's view in the sub view model a factor up to the top level view model memorization just a quick example of what this looks like so if you have a function for example this case an active client selector and this is very simple this case is looping through the clients finding those that are active and to memorize it you would just wrap it in a memo eyes function you see memo two and the two is simply because this function has two parameters so when use memoization there's just like ten different memo functions memo one memo to mm3 etc and this is pretty simple to implement but has really good performance implications because again this way the in this case the loop through the client list only happens at one time so forms our app is really all built around forms it's kind of everything in our app and our app really I think is a relatively simple app Gretchen other apps it's really a crud app create replace update delete but all it's all about form this is some of the things we've learned built value that I showed you earlier where we had the login class and the username of the password with built value you can do deep nested comparison and that's really helpful in forms so my web background is that usual starts typing something we would flip a flag is changed to true but the problem with that is that way if they undo that change is changed never goes back to false so by using built value you can do analysis in the form and know is this object different than my object or the persisted object avoid nullable this is something that really hurt us early on is that when you first create a new object the fields are blank so the approach we took is to mark everything to allow nullable so you can easily create objects this caused a lot of problems and this broke the last point so if you start with null and then you present that in the form it appears changed instantly because what happens is when you show it to the form the null becomes an empty string because in the context of the form that's what it looks like it's an empty string so it comes back it's changed so the key point here particular with redux but I think other cases also until value is to avoid nullable if you can and only use it in case we actually have to one problem with build value is to say to create two client records and you compare them by default to blank client records we'll Val value 8 to equal to true because they look exactly the same and so the way we and that could be very difficult in the UI if you create two record to want edit one of them and the way we solve this is using a static negative counter and that way every object gets a negative ID the ink next one available and then when it's finally saved we then get a positive ID back from the server and that allows us to disambiguate between new instances of classes and the last piece has really been the key to our architecture work kind of comes together is completers this is native to Dart and the way this works is let's say our view has to do something it'll dispatch an action to the the redux I'll go to the middleware and the reducers will attach to the action a completer and it gives us loose coupling between the views and this in the middleware and what happens is the action gets dis fast with a completer and when the middleware is completed it completes the completer so this way the view and the view models don't need to be aware of the middleware they just know hey I requested things to happen and the view model can say completed and the view can then update based on that immediate change and this has been again really key to how we've kind of built an architect of the app and has worked really really well for us one point I'll mention here is for navigation we used to attach it felt really ugly and messy but we detached the context to the actions and would handle navigation in the middle where the reason is because in the Redux world kind of navigation is sort of like a side effect so I thought I made sense there and that turned out to be a big mistake the last time I gave this talk I talked about how well I was working for us it's kinda thing that works until it doesn't and the problem I found with this is that it worked until I want to add a feature where I wanted to warn the user about changes so I wanted to say when you change something and then navigate to different page to say hey you have pending changes do you want to you know dismiss your changes or keep edited or keep at it keep editing and so by dispatch by using the context in the state the context changed and then it failed essentially if you tried to reduce patch the action the next time context is no longer valid failure and it felt bad like sending the context in the actions never felt good but I finally found a case where it actually broke things so the approach we use now and think is working to the cleaners we passed the Navigator or referenced the Navigator instead of a reference of the context and it gives us really what we need at the middle of level where we have a reference the navigator which regardless of UI changes the Navigator still works right as a direct reference and if you need the context you can get the context from the navigator which has been a useful workaround where we actually if we pass a navigator they need the contacts for example for localization we can get that again through the navigator so we're seeing here's example of this just a short gif about how built value works so we see here as you make a change I can turn blue as you unchanged it turns white and it's just showing that the app is aware of what the original values were and this works at any level of depth so for invoices relative invoice items you can have nested deep nested trees we built value it just works automatically just get equals equals does it equal this or not and it's been really helpful so just some random things that kind of picked up along the way what has never scrollable scroll physics this is kind of some random widgets and before this talk I kind of tried to go to my art codebase and again as I mentioned the entire app is open-source it's all in github so feel for free I love it look at the code review it tell me where I'm doing things wrong help make it better so one of the things I found it never Scoble scroll physic this can be useful we use it on grids we want to use the grid it could be like the grid element we don't want to scroll and so by default even if it's not long enough not too long if you pull on it you'll see that blue kind of scrolling indicator so you can pass for the physics and never scroll the scroll physics it's nothing it's a way of easily disabling scrolling UI if you want to shrink things down you want to be cognizant of the kind of space on the screen and make small targets you can set the material tap target size to shrink wrap this is been really helpful for us when we have complex UI's we want to have a lot of interactions we can kind of just make that top target as small as possible the widget binding instance ad post frame callback whenever I use this it's another example where I feel this may be a bit of an anti-pattern this allows you to do something after the bill finishes and I literally this is a way I can check the problem is my code as I search for this but it's good to be aware of right if you do need cases where something happens after the bill this is how you can accomplish it but again the cases where uses it's most likely where I paid a different mistakes and this is how I kind of recover from the other mistake layers of mistakes that's a challenge right I mean I'm not up here saying I'm writing the perfect code I'm trying to deploy I'm trying to make a successful business right so I'm trying to be very pragmatic with my programming and I try to write the best to a code I can but I try to revisit and I think the key for me is that my code can't be the first draft right my first draft code is usually pretty bad and the question is how many drafts does it take to get good code and I'm lucky to have partners who give me that time I need to keep improving it will pop scope this is really helpful if you want to know if you should click back and we're using this currently I'll show us a bit little explain a bit later how we use this to solve a current problem and ignore pointer this enables you to kind of cancel any clicks and UI and we use this a lot in our forms and what we'll do is we'll want for example like a date picker we'll want to show a date picker in a form but a date picker doesn't really have a UI element so what we do is we take text fields we wrap them in both a gesture detector or I think an inkwell and then wrap that and then essentially so it's text field you can do a pointer and then a gesture detector and that gives us a way where from the UI perspective that looks like a text field you click on it you don't get the text field to get something else and then for example in that case we'll show a date picker and then once we get the value back from the date picker we'll use a text field controller to set the value on the text field and we can use the all kind of view a UI elements don't have their own Uys acerra li and it's a way of kind of lining them into your forms this is one problem that I had early on it's had to share this that you see that yellow border around the app I always thought this is an error I always thought like I got some error this is telling me this an error because I'm used to in flutter you know there's the red background with the failures in the yellow and black police tape so I thought this is another form of it it turns out it's not an error this is a focusing issue and the slides are all available it's if it's always just calm slash slides you can get these slides but this little line of code has been really helpful just add it and just fixes this problem so I kind of which one throws in here code generator so Redux I talked about a flutter makes me happy and coding makes me happy and Redux sometimes makes me happy sometimes it doesn't I literally each day I don't know if I like a reduction I'm really on the fence it's guys my first time using Redux I will say one thing you know I got like a lot of us a question the quality of my code and I have found with Redux I feel more like an engineer than I've ever felt before in the past that ways felt like I was thrown code in a wall and see what worked works at the redux I feel like an engineer an app I understand it I can follow it and I like that about it however you end up with a ton a ton a ton of boilerplate code I mean it's really it's kind of it's concerning in some ways and I think Bryan has a great example where he did one app in three and a few can state management examples and I think Redux was about 50% more code than block so if you're talking about a large app one hundred thousand lines of code that's next to fifty thousand lines of code that's serious and so we saw early on this is going to be a problem and so we created a code generator this is also open source and what enables you to do is kind of like mail merge you can create your first module and the package comes with a first Redux module you can then kind of copy and paste it to other modules and it'll merge in the specific name so we create these subclasses and then again merges in your specific name and then generates all of this boil pig code for you again this solves the problem because it auto generates the code the problems we have found is it's critical you get it right at the beginning code ends up happening is my cells first ten as I made small mistakes early on and those mistakes get multiplied because each time around the code generator you're getting another whole chunk of code it has the same mistake so Co trainers can be good if you have you know good code before generating bad code you've always got a problem I think also the key here in the mistake I'm which I need to abstract as much as possible I think the code Reina for code generators to be successful that to just be generating the glue like those little bits that are necessary and nothing unnecessary so what I should have done more Alvin I've done some of is abstracting the data or the the UI as much as possible to ten of sub widgets and the generator would just then generate these specific custom widgets that are needed to glue things together again this is a good example of how you use this package for example if you have a JSON data source and you want to convert into an application this package with about three lines of code will create an app that takes that JSON and gives you a working app that can interact you can view the list edit items add items etc I think if I could use again I like the concept of this generator construct I think Redux isn't so popular in the flutter world it might make sense to take this approach and use maybe a different management state management option but again it's all available it's on github again if you're considering using Redux for your app is so they're worth considering two caveats well what is again Redux may not be the right choice for you maybe it is I also I built this code generator at the very beginning of our app development and my plan I'm gonna get the time is I'd like to come back now that I've have a lot more experience and try to take the best code we have now from in Boise and in joy in Boise and ghako and bring it back into the generator but again if you have use for it please use it and please give me any feedback so just a few best practices that you know a lot of you guys may know this already this is some things I've learned through our project is one in particular is the analysis options yamo file when you create a new flutter project you get a very loose linting file and I think it's critical especially if you're new to dart that it's good to get the the analysis llamó file from analysis options file from the floor project they have much stricter rules and there many other other projects those pedantic you can use to do stricter linting but I find it's critical as you're learning dart okay this helps kind of guide you and hold your hand and make sure you make the right choices this is a clock common conversation in the reddit threads is custom widgets versus functions I think ever knows custom widgets are a little bit more performant I don't actually see that as the reason to use custom widgets what I find is it just makes it cleaner to to understand the code and to subdivided it also makes it more reusable so what I found is our development keeps accelerating so as we were building our app at building more and more custom widgets just for our domain and as I the next day I can then start reusing and leveraging and I found the first module took the most time each additional module I'm faster and faster because what I am developing is a custom flutter framework for my app right each widget I build is what I need to fill myself my use cases and even if there's tiny tiny widgets for example like a text next to an icon or icon next to a text I'll just create an icon text widget and I find these little widgets help you kind of shrink that nested tree they can sometimes get a bit too deep this is a cool trick flutter dart format lib it's really useful just at once format your entire code base which I find really helpful every once in a while you know most people have it set up so that their IDE will autosave but every once in a while I can do this in this way it prevents your git commit being kind of muddied by unrelated changes my background is web development where we automatically have server-side logging and when we first deployed our flutter app I was like wow no bugs no one's complaining all right but what happened was the truth is that flutter is so good that when it fails I use don't notice right or if they notice they don't care enough to complain right if they use an app and it crashes when something goes wrong they are gonna tell you about it they're gonna tell you it over and over again hey your app crashes but if they using the app and a small bit turns red with a bit of yellow or something they may be a bit cut off they won't miss a it's critical for us to have a back-end solution we use century IO ourselves which is great salsa open-source you can run it yourself hold a hosted on your own servers but right when that went live we instantly found whole slew of bucks we weren't even aware of because flutter did such a good job hiding it and then as I mentioned earlier if you are gonna use immutability I really recommend built value I started off not using it and was just doing everything by hand and it was a lot of extra unnecessary code this is very hard to read but what this is showing is if you're curious about flutter I really want to dive deep into it and see what's happening the future if you add flutter dev slash any of these lines so go templates ago it will be a short link directly to the Google Doc that the flirt team used to discuss the feature and stuff in progress this was hidden somewhere and the github source for the flutter site again it's in the slides but I really recommend if you're serious about flutter and you want understand where it's going this is where you can see it it's all in the open and I thought a talk yesterday we're talking about flutter to dodo and Mable to be massive breaking chain like Swift for example and my take is it's not what they want right they want breaking changes when necessary but they really are trying to minimize it because they appreciate how much code has been written and they're certainly not looking to break it all so again if you know one thing to take away from this slide if this talk is I cannot recommend that each one of these is a goldmine of really interesting flutter information and I highly recommend reading these Doc's also providing feedback if you have input so at this point our app is live we went from free code bases out the two code bases and we're very happy to show you again our scores were not good we were not happy with this even though 40 wasn't good enough but a3 was absurd and actually somewhat embarrassing to be honest I'm only showing this because this is where our old app and this was built with native technologies and then we then deprecated it released our new app and much better so again this to me shows that it's not about technology if we've it's critical or really changed here is the developer resources right we went from two code bases to one code base for a single developer and you just have more time that's it right you have more time especially if you need like me need the time to do multiple drafts of your code you have that time now right cuz you're writing half the code and so this is again why we're all here fundamentally right is this idea that of shared code between platforms so the dream though one code base is that possible can we do it so our back-end will always have a separate code base right we need it we don't use firebase we use have our own custom laravel PHP back-end and that's really critical for us for our open source community they would be very upset disappointed if we use firebase because I would incur cost them to run our software so by building a custom back-end it's free to run free to host themselves but can we achieve one code base and this is what we've been after so I've spent the past six months working on flutter web and so what we've done is we've taken from the screen before our mobile app and we're in the process of converting it to a web app and in the future I think this is the hard part once we get this we believe the desktop app will be much simpler and so with this this is enabling us to again have a single code base across not just you know mobile not just Android iOS but Android iOS desktop you know Mac OS you know this drill right this is flutter it's amazing and from our perspective we believe this will be a massive competitive advantage bless you against the other competitors we knew our large repairs they may have more developers they may have more money they may have more lots of things but what we have is left less code right and that's to me is just going to be an incredible strategic advantage and I say so what we're working on is available now that to be very clear this is this is not even alpha this is pre alpha this is like I'm like fixing there are tons of open bugs but I'm sharing this because I think it might be useful so you guys can see what I'm working on well our company is working on the progress we've had so far has been amazing it reminds me a lot of the early days of flutter right if you're doing flutter web serious flutter web now you kind of have to be on at least Deb if not master we should feel like the old days of flutter where you couldn't be unstable it just wasn't up-to-date enough but again this has been a really interesting process to share a couple of a couple of challenges we're having the big one obvious plugins it's kind of known thing we're waiting on plugins what's nice is as new plugins become available our rap just gets better right each new plugin so last week we implemented the shared preferences so now our web app has complete persistence so I showed you the persistence on the mobile app as you start typing change quit the app come back it's there now our web app has that same feature which our initial web app does even have right initial web app if your browser crashes you lose your unsaved data with flutter we've been able to build essentially a really powerful single page as application s.p.a with much better features than our older app has again through dart strict typing and just again a better a better framework just to end the talk if you guys don't know my background I was one of the people along with Thomas Burkhardt Simon Lightfoot and Scott stole the four of us worked together to create it so widgets comm if you guys build apps please submit them I want to credit Thomas for the great name is actually gonna be a podcast initially a pattern that's going to be another podcast of Thomas that idea for its own widgets and so again hopefully find it useful the one thing I suggest with this site is flip the open-source switch and then you have a great listing over 200 incredible open source apps and I myself use it as a resource for learning so again if you're making apps because you're submitting them and then just lastly invoicing can be a bit boring sometimes so I have a side project and want to share quickly it's nap called Moo do it sends for a music video so if anybody this is also completely open-source if anyone is a musician here this idea is that if it's like github for music so one person can start a song and some else can fork it and change and then add layers to it and change the song things like that it's doing okay it's how apps like this are hard it's hard to get attention I think one thing I'm really hopeful for is to port this the flutter web it's hard I can even get my friends sometimes they say download the app I just won't download it right is friction there but I'm pretty sure if I have a link I believe we're gonna have much easier way of sharing this application it's just hey you go to meu do app and you see the app we think that I'll you know potentially gives a better chance at improving the app and getting more users so if everybody here is a musician please feel free try the app jam with me virtually and that's it thank you very much so angry five minutes there any questions quick pass a quick question you talked about the persistence store and did you ever run into a case where you had an invalid state and the user was always forced to go to a particular screen and could not escape I was the users able to invalidate the state and very good question so we've definitely had issues like that one way to invalidate this the simplest way is just to reinstall the app which right that does it bit of a workaround and so good we also it when we hydrate the state we also make sure to check for errors we catch any errors then we throw it away in that case those are the two options in our web interface we're gonna have actual way of overriding the states right and we don't have a way of manual override a state in the app and maybe should consider that's a good suggestion any other questions cool all right thank you very much again [Music]
Info
Channel: Flutter Europe
Views: 8,582
Rating: undefined out of 5
Keywords: flutter
Id: G30K5wm7j_M
Channel Id: undefined
Length: 41min 35sec (2495 seconds)
Published: Mon Mar 23 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.