Flutter Firebase & DDD Course [13] - Note Entities

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what should we do with the value objects we created in the previous part let's group them together into entities representing a note and a to-do item [Music] hello welcome to riso coder where you are getting prepared for real app development so that you will get freelance clients or a job and be confident about the apps you built so subscribe and hit the bell to join our quest for becoming in-demand flutter developers in this tutorial we are going to take all of these value objects which are note body to-do name note color and list of three items and put them into entities entities are basically a group of value objects which has an identity which is going to be given by the unique identifier which we have created a while back the unique identifier is actually here in core unique id value object every single entity will be identified by its value which is of course unique as it says in the name of the value object itself and in the case of firestore database we are going to use this unique id as also the document id inside firestore but that's going to come later on in this tutorial series for now let's focus on the domain layer by creating entities so let us first create the note entity and then we are also going to have the to do item entity so we are going to create a new file under notes domain let's call it note dot dart and this is where the entity is going to be present it's going to be very similar to the user entity so basically it's a freezed class it's going to be a data class and there are going to be a few more fancy things added on top of that so let's get started we are going to create f data class using the code snippet and you can by the way also get this code from the link in the video description let's call this note and import freeze and rotation and while we are at it let's also open up the terminal and run our favorite build command flutter pop run build runner watch delete conflicting outputs and this command is also available from the video description once we have this watch command running we can go ahead and actually start putting all of the needed value objects into the note data class so the first one is the unique id by which each individual instance of the note class will be identified so it will be required parameter unique id let's call it id and of course it wouldn't hurt if we actually provided a freezed part statement so note that freeze.dart is the part and let's actually make this into a named parameter with the curly braces now we are talking so this is not something specific to the note feature of the app unique id is just always present no matter which entity we are currently creating what's important about the note is that it should hold a note body and note body will be nothing else than our beloved note body value object which we have created in the previous part so let's call it body then similarly we should have add required note color let's call it color and let's check out the value objects which are still left out so we have node body we don't have to do name we have node color and we don't have this list of uh three items so we are still not using two of the value objects which we should use those are list of three items and then also to do name well we know that each and every note should have a list of at most three to-do's so can we do something like add required then list three and to do name to this well we can do something like this but then the problem arises that these to do's cannot be completed because this list 3 of to-do name has no concept of done or undone to do it just holds basically what is a validated string of a to do name but we need to provide a way to complete or uncomplete the given to do that's why we are going to create yet another entity and this one is going to be called to do item so let's go ahead new file to do item dart and over here it's again going to be a freeze the data class so we're going to create a part statement for the freeze package and then also f data class to do item let's import freeze and now we need to provide the fields even to this data class and it's going to be precisely over here where we should include the to-do name as one of the fields of the to-do item so add required to do name name let's import the value objects.dart of course even a to-do item is an entity so it should be identified separately in this case theoretically we can leave out the unique id because to do item is really just a part of a note so technically those uh to-do's could be just identified by the note id as a whole but let's just include the unique id even inside the to-do item it's not going to hurt for sure and then also what we came here for is the ability to mark our to-do's as done so complete them in other words so again required and this is going to be just a simple bool done so unlike all of the other fields which are held inside an entity which are value objects like node body node color list three and so on the done field is just a simple bull and the reason for that is also very simple how can you actually validate a boolean sure for now you can make the boolean to be null in just a little while when the non-nullable types arrive into dart even that thing will be not possible so one less thing to worry about but if we discard the possibility to set done as null like this of course in pseudo code if we discard this then there is nothing else we can practically validate when it comes to a simple true or false boolean so that's why we are not wrapping this inside any sort of a value object now that we have the to-do item we can go ahead into the note and store it inside the list of three items so let's say to-do item and just like this we have basically a nested entity inside the list if we wanted to build just a bare bones data holder class we would call it a day right now because everything that's needed to hold these value objects inside a data class is already here but we want to make our lives easier in the future and that's why we are going to provide some helper factories and also getters or other properties which are going to allow us to write code more quickly in the future in the future parts that is so the first thing we are going to add to our entities are empty factories because think about it when you open up a new screen that you want to create a new note you need to have an empty note body a certain default note color will be selected and you are going to have zero to do items added to the note so that's going to be sort of the empty state let's say of a note empty body predefined color will be selected and the list of to-do's will be empty by default so let's create a factory note dot empty and let's just say that it is going to return a note and it's going to simply populate the id with a new unique id then body will be node body and we are going to pass in an empty string with 0 characters then color this is where things get interesting will be note color and note color value object takes in a color and we are going to select it from the predefined colors which we have created in the previous part right here and we are going to select the first so that is the canvas color so we're going to say note color dot predefined colors zero so the first one and lastly to do's this is a list three and this takes in nothing else than a kt list so the immutable kotlin fake list or fake cotton list the list is not fake only the kotlin is sort of fake so we want to do something like this an empty list but the way you do this with the kt dart package is by saying empty list simple as that so we have just imported kt dart over here of course without a semicolon at the end and this is what's needed in order to produce the default empty note which will be present when we open up the note form for the first time similar to this we also want to have an empty factory for whenever we add a new to-do item inside the note creation form in the ui so in order to simplify the process of creating a new empty to-do again we are going to have factory to do item dot empty and we're just going to instantiate a to do item and we're going to again provide the id to be a new unique id which is going to be generated from the uuid package then name will be to do name and empty string will be passed in there and lastly done will be false by default all right so we have the empty factories done so what is next when i open up the app and open up the note creation form like this and i hit this check mark to basically add the note to the database we are going to get an error message under the note body saying that it cannot be empty and the same would go also for the to-do's and we cannot add more than three to-do's and so on so that's all nice but the thing is that these error messages are coming from the individual value objects for example from the note body value object from the list 3 value object and also from the to do name value object but how can we validate the whole entity at once currently we can validate value objects just fine and that's awesome but we have no way of validating the whole entity that means combining the validation results of all of its value objects and if all are valid then the whole entity is valid if just one value object is invalid that means that the whole entity is also invalid so how can we do that and actually i will show you why we are going to validate the whole entity at once it surely is a bit of an overkill but again we are building the most awesome secure application that has ever been built so uh yeah that's why we need to have this sort of a validation in place the easiest way for me to demonstrate what we want to happen whenever an invalid data somehow manages to get into our entities is by modifying the firestore database and although i know that uh the online or remote database should in fact be the single source of truth and client code should not even really worry about validating the data that comes from the database again we are pretending that we are building the most secure application space launch or cancer treatment we cannot afford any bugs we cannot afford any possible ways of tampering with the data so we need to validate both on the client side and on the server side and everything just needs to be fully secure so if i go ahead and find the correct user and i edit a note for example this one right this is the note which we can see on the screen this is the red note but when i edit it over here for example i will make one of the to do items to be empty so it's no longer going to say learn about socrates but it's going to say basically nothing so it's going to be empty and i update the field now when i go over to the app i can see invalid note please contact support details for nerds value failure string empty felt value empty string basically so as you can see we just cannot even see the invalid node in our ui and technically what we could do then is create some sort of a reporting system where if we click on this invalid node in the ui it would open up some support client or for example it would send an email to the application support team with the id of the failed note for example so if we are building a fully secure app this is the way to go now i have reverted the name back to learn about socrates and just like that we can again fully and properly see the node in the ui because there are no errors so let's go ahead and implement this kind of a validation system for entities as a whole so we're going to start off in the to do item entity because it's simpler and we want to create a member which is going to be a get only property called failure option the problem is that we are inside a freezed data class and there are some kv ads which you need to know about when you want to add a custom function or a getter to a freeze data class or to a freeze union that caveat is that you have to get rid of this mixing syntax instead you are going to implement the underscore dollar sign class which is generated and also you need to provide a empty default constructor so to do item and since we do not want it to be accessible from outside the to-do item package we're going to make it package private with an underscore now we are talking and we can add our field or property just fine the way that we are going to report possible failures of the whole entity is by returning an option which will hold a value failure holding dynamic we don't really care about what is inside the failure we can make it dynamic but we really do care about the actual failure being present and it's going to be a get only property failure option and we just basically want to return either some if there is some sort of a failure present among the value objects held inside the entity or we are going to return none if all of the value objects are valid over here inside the to-do item entity it's going to be very simple because we have really just one validated value object and that is the to do name we really do not have to worry about unique id technically we could also include the unique id in the validation thing but as you can see over here in the definition of unique id it just cannot possibly be invalid because we never use the left side of either so we just know it's always going to be valid that's why we can leave it out so what do we want to return here name dot and technically we could do something like value and then we could do fold and if there is some sort of a failure so we are inside the left side of either so if left arrives which is a f failure then we simply know that the whole entity is not valid so we are going to return sum some failure and pass in the actual failure f so we return option which is a sum failure in our case we can ignore the right value which in this case is just a string because we are operating on a name which is holding a string and in case everything is valid we are going to return none so if everything is valid we return option none failure so no failure and again if you want to check out this code at your own pace you can get it from the link in the video description and this is good enough for this simple class once we get into validating the whole note entity you are going to see that this kind of an approach may be problematic and we are going to fix it but for now let's take a look at this squiggly line under the to-do item it says that we should sort unnamed constructor declarations first so we actually want to ignore this uh linter or this info message so we're going to copy the name of the message go over to analysis options yaml and just paste it here and say ignore and just like that we're going to get rid of that message and we do which is nice now let's do the same validation thing also inside the note entity so again we are going to say implements instead of with implements note we're going to provide the const notes private constructor and we are going to also add the property called failure option let's import darts let's import value failure and let's implement the failure option shall we but over here it's not going to be as simple as with the to do item that's because we have multiple value objects which can be invalid and we need to chain them together and if just single one of these value objects holds an invalid value the whole entity is going to also be invalid so let's go ahead and do what we can right return body is the first validated value object so we are going to say body value and then we're going to say again fold right uh well no we are now going to say fold just as we did inside the to-do item straight away because we need to combine other failures possibly too if you remember in the previous part inside the value objects right here for example in to do name when we were trying to combine multiple validation functions together which also just return either we use something called flat map and i told you that flat map works like a short circuiting if statement where if you have if false and true this last true part is not even going to get evaluated because when the first expression is false the whole end expression is just by definition going to be false too and here we used flat map for it but now we are now going to use flat map because we don't actually want to map anything we don't even really care about the value which is held inside the individual either object we just care about if it's valid or not in other words if it's left or right of either so instead of a flat map function we are just going to use a and then function so let's delete fold and we are going to say and then and provide the next thing which should be included in the validation chain and just like flat map if the first validated value is invalid so it's left then the whole chain will be basically just short circuited it will be skipped and the whole entity will be thus immediately evaluated as invalid so inside this n then we want to provide the next thing which should be validated so that is going to be to-dos and value right this to do that value will tell us for example if the to-do list somehow has more than three items and then technically if this was it we could just say fold and do the same thing as we did inside the to-do item validation so basically if we receive something on the left side some sort of a failure we return that failure from the failure option otherwise if everything is valid we return none which means no failure is present the whole entity is thus valid so we can copy this and paste it over to our note entity but you probably see some problems arising here and that's totally correct we have red squiggly line under to do that value and it says the argument type either value failure kt list to do item kt list to do item being the valid value cannot be assigned to this thing which is dynamic value and also the second either's value failure holds a string not a kt list to do item we don't really care about the types held inside the value failure and we don't even care about the valid values which are on the right side of either here inside this failure option property we just simply want to tell if the whole entity is valid or not so how can we go about ignoring all of these kt lists and strings and just focusing on what's important the left and right of either basically we're going to discard all of the other types which will allow us to use them together and not get any type argument errors the way we can ignore all of these types which we are not interested in is by providing some sort of a mapping inside the value object base class so let's go ahead into core value objects.dart and here we have our default abstract class value object and just like we have for example this is valid getter or method actually we are going to add a failure or unit getter inside of this getter failure or unit we are going to get rid of all of the detailed types and we are just going to focus on the left and right side of either so it's going to return either for sure and the left side will hold just a value failure which is the universal super class or the super union if you will of all the failures which we have inside value objects so value failure holding dynamic we don't even care about the type of failure we just care about the failure itself and then we can completely and absolutely discard the correct the right value of either by saying that it's unit okay so from here we can now just return value dot fold and inside this fold we are going to get rid of all of the non-important types so we are going to return just a cast it left value failure dynamic so basically we return the same value which has been passed in but it's being passed in as value failure let's say string and it's coming out as value failure dynamic so we just get rid of this type parameter and then whenever something is correct on the right side of either we want to return it as a unit so if this comes in this t-type generic type is a string again or it's a kt list we're going to get rid of that type information by just saying that it's a unit so not return but right unit okay and just like that we have gotten rid of all of the things which prevent us from using different value objects in one validation chain so now we can go ahead into the note.dart and instead of saying body dot value we are going to say body dot failure or unit and again to do failure or unit and as you can see we have gotten rid of the errors which were present here because now we are always operating on value failure dynamic and unit and no matter which value object we validate its types for validation in this validation chain are going to be just the same and while we were doing this failure or unit property conversion and these failure option getters it may have been too abstract for you but now that you see the outcome of it hopefully you understand why we did what we did a while ago and if you need to feel free to re-watch the previous few minutes and you are going to grasp it much better so we are validating the body and also the to-do's list but we are only validating the to-do's list as list three meaning that if the to-do's list has more than three items it's going to be invalid but we also want to validate all of the actual to-do items which are held inside the list not just the length of the list so that's why we are going to add another and then function call and inside of there we are going to validate all of the individual to do items this is going to get a bit lengthy but it's definitely worth it so we're going to say to-do's and we want to get them or crash the app and by this time we know that get or crash will definitely not crash the app because by the virtue of previously calling to do's failure of unit we know that if we get to the next and then call the to do's have to be valid because if they weren't we would not even get to this next and then chained call because we would have short-circuited the validation chain just like with the and expressions in an if statement it's the same thing so that's why we can afford to call get or crash without having nightmares about it so once we have the actual to-dos the kt list of to-do items now we want to get hold of the to do items failure option and in order to sort of extract something from a list of items we can use the map function and we want to map the items of the list the to do items so let's say to do item and extract the to do items failure option like this now when is the whole to do item in valid it's invalid when the failure option is sum in other words when this thing has run if there is some value in this failure option it means that the whole to do item is invalid this means that we only care about the values of sum so we are going to go ahead and say filter this is by the way the same thing as calling where function on the regular dart list so we are going to filter by a predicate which will say that the failure option o is sum so what this is going to do is that we're going to have only the failed to do items in this kt list returned by the filter method so we now have inside this kt list only the failed to do items how can we tell if all of the values held inside the list of to-do items are invalid well i will first write the code and then explain it we want to say get or else on the index of zero and if we cannot get this zero index meaning that there is no element present then we're going to return none okay so what are we doing here with this get or else well if we cannot get the zeroth item from this filtered list which should contain only the failed to do items that means that there are no failed to do items present which in its logical conclusion means that all of the to do items are valid or maybe there are even no to-do items to begin with in which case of course the whole list is valid because no to do items means valid notes don't necessarily have to have any to-do's i will actually paste the text here for future reference the comments so you can come back to this later on from the code which you can grab from the link in the video description and once we have all of this done what can we do with all of these none and some values well we can again use our trusty fold method and if the none value arrives that means that our whole list of to-do items holds only valid to do items so we are going to return right unit why write unit well because our failure or units have the right value being a unit that's why we return right unit and in another case that is when at least one element inside the list of to-do items is invalid we are going to return that value failure so left and let's rename the a parameter to f so left f okay i know it's tough and i know that it might currently fry your brain because it surely did fry mine when i was trying to explain it it's uh really something to grasp this bunch of code but what are we basically doing we get the kt list of to-do items and then we extract the failure option from each and every to-do item next up we get only the actual failed to-do items from this list or we at least try to get only the failed to-do items from that list and then we basically check are there any failed to do items inside the list if there are we return left with the value failure present inside of there if there are none failed to do items present we return right unit which signifies that everything is valid and then lastly from this whole chain of short-circuiting uh validation calls with and then let's call it like that we return some if there is a failure or we return none if there is no failure and just like that we have created the ability to validate all of the value objects held inside an entity at once be sure to check out the code from the link in the video description and also if you are serious about becoming a great flower developer who can build real apps for clients or at the job go to flutter.education link is also in the video description to get the top curated flower news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best flower resources delivered weekly right into your inbox and if you don't want to miss more tutorials like this which are for the most part not going to be as intense as this one be sure to subscribe to this channel and also join notification squad by hitting the bell button to make sure you grow your flutter skills because here on resocoder i am determined to provide you with the best tutorials and resources so that you will become an in-demand flutter developer if this video helped you with this sort of a validation and all that give it a like and also share it with our developers if you want them to fry their brains 2. leave a comment if you have anything to say and see you in the next video [Music] you
Info
Channel: Reso Coder
Views: 6,811
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, flutter firebase, flutter firestore, flutter firebase auth, flutter firestore tutorial, flutter firebase tutorial, flutter architecture, flutter architecture patterns, flutter domain driven design, flutter ddd, flutter database, flutter todo app, flutter todo app tutorial, flutter todo app firebase, flutter app tutorial, flutter app example, flutter clean architecture, flutter bloc
Id: myFgLD4zI3o
Channel Id: undefined
Length: 43min 25sec (2605 seconds)
Published: Wed Jun 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.