Flutter TDD Clean Architecture Course [2] – Entities & Use Cases

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

/u/MRresoMC , a question regarding your videos. I believe my question is the most relevant under your 2nd video. A couple of statements from your video/article:

  1. You mention that the dependency/call flow is from presentation -> domain -> data.
  2. Repository contracts are defined in domain layer.
  3. Repository implementations are in data layer

This allows for a total independence of the domain layer,

Indeed that sounds good. There is 1 technical problem I'm facing: let's assume that GetConcreteNumberTrivia use case requires a complex type as it's parameter (because of the number of parameters). That means the method signature should look like so: NumberTriviaRepository#getConcreteNumberTrivia(SomeComplexRequestType param).

Since dependency flow is from domain to data layer, I'd have to define SomeComplexRequestType in data layer to make sure that I don't violate rule 1 (repo implementation is in data layer and data layer can't depend on domain). However, if I do so, the domain layer will not be fully encapsulated, I violate the big advantage of the proposed architecture "total independence of the domain layer".

So, my question: if you have to deal with complex data types, what do you recommend, where should they be defined?

👍︎︎ 1 👤︎︎ u/daniel-vh 📅︎︎ Sep 08 2019 🗫︎ replies
Captions
in the first part you learn the core concepts of clean architecture as it pertains to flour we also created a bunch of empty folders which you can see on the side right now for presentation domain and that this is for the number trivia app we are building and now it's time to start filling in these empty folders with actual code of course using test-driven development Oh [Music] welcome to resell coder where you're getting prepared for real app development by building better faster more stable apps so subscribe and hit the bell if you want to grow your coding skills so of course whenever you are building an app you should start with the UI and user experience first but I've done that homework for you as you've seen in the previous tutorial the app looks something like this the actual coding process though will happen from the inner most stable layers and will progress toward the outer layers so in the case of clean architecture as it was proposed by Uncle Bob we can see that we should start from the domain layer particularly from entities so we're going to create an entity right now before we do that though before we can create an entity for the number trivia we have to add some packages over to pop spec yamo because we are gonna be using quite a lot of packages to make things easier for us of course and with that I have to tell you to make sure you check out the written tutorial from the link in the description where you can find all of the code written in this video all of the links and all of that good stuff and go through this lesson at your own pace this pub spec yamo file is one of the few things which i am going to just copy and paste over on video so that i don't bore you to death so let's just delete all of these unnecessary comments which is clutter up the pub spec yamo file and then the dependencies and dev dependencies will be the following so we have get it which is the service locator I've added all of the dependencies right now so that we later do not have to come back to this Yambol file and just lose time on that so we have get it then we have waterblock for state management equatable for value equality then we are going to touch on some functional programming concepts then for a remote API we have connectivity and HTTP packages of course and for local cache we are going to be using just simple shared preferences as for dev dependencies these are the ones which do not get packaged together with your app once you build it we have flutter test this was here even before I think by default and then we have mojito for creating mocks we are going to get to all of this as we progress forward with this tutorial but just so that you have all of the packages already present we've added them over here and I'm just going to delete all of the other comments so that they don't clutter up pop spec and here we go the pub spec diamo file is completely finished alright so let's now move on to creating the actual entity the first question we have to ask ourselves is what kind of data will the number trivia operate with well of course with number trivia entities so we can create a new file under the domain entities let's call it number trivia the dart of course and now we have to take a look at the JSON response from the API because based on that response we are going to model our class here so if you go to numbers API dot-com 4/32 or some other number and then question mark JSON so it's a query parameter you will obtain the following response and of course this link is also available from the written tutorial so this is the response which we will be operating with throughout our and we need to model our number trivia entity so that it can contain this kind of data so what do we actually really need from this JSON object well we need the text obviously because that's the core so to say functionality of our number trivia app we are also going to store the number but then we have two interesting fields which are found and type we are now gonna need those at all because found is completely irrelevant for our case and the type will be always trivia and why is found completely irrelevant well if I search for a number other than 42 so for example some complete gibberish wrong number which doesn't have any entry in the numbers API and search for that you can see that found is false but we still obtain some kind of a reasonable response that this is an uninteresting numbers so we can still display even this message to the user in the app we do not need to worry at all whether or not the number was found so the bottom line is that we need text and number fields to map to properties in our app so let's create a class number trivia which will extend equitable and let's import equatable here this is so that value equality is made simple because by default dart supports only referential equality so even two objects which contain completely the same data will not be equal unless they are referencing to the same point in memory with equatable this is completely changed when two objects contain the same values the same data they will be equal and we do not need to override equal operator or hash code anything like that equatable does that for us so it saves us a bunch of boilerplate and now we need to store the text and number so final string text and then final int number and of course we need to put them into constructors so we can just hit control that at least in vs code and create constructor for all of these fields here but we're not is going to have this kind of a constructor with unnamed arguments we want to have them named and of course we are going to make them required so we need to import meta package so meta dot dart and let's just make this required and also this one will be required here and we mustn't forget to pass these over to the super constructor because equitable needs to know which property is to make equality happen on so we are going to pass them in as a list so we pass in text and also number to the super constructor which is equatable and you may have noticed that we didn't do any test driven development here that's because this class is really it doesn't have any logic there is nothing to test so that's why we aren't writing any tests for this number trivia entity should you have any logic inside your entity you will write test even for entity but that's not the case with this one alright now let's talk about use cases they are aware the business logic gets executed and sure there won't be much logic in the number trivia app because all a use case will do is to get data from a repository so just so you can see that here we go with the diagram we have use case here it will get data from the repository and they will communicate together through these entities and we have created just one such entity called number trivia a few moments ago and we're going to have to use cases in our finished app get concrete number trivia and get random bird trivia by looking at this diagram as I've already said you know that use cases get data from repositories and then they pass that data which in this case are entities over to the presentation logic holders and to the whole presentation layer so it kind of makes sense that when a use case is communicate with repositories the repository should return an entity right but because we have to allow for asynchronous operations we're going to wrap this entity which in this case is number trivia into a future but that's not the actual case of what we are going to do we have to think about error handling as well because is it the best choice to let exceptions freely propagate having to remember and when you have to remember something you know that that's not cool we have to remember to catch them somewhere else in the code if we let exceptions just nicely propagate at their own peril I do not think that this is the best choice instead we want to catch exceptions as early as possible inside the repository here and then return failure objects from the repository methods so unlike exceptions you will not have to try and catch all of these exceptions you will have failure objects which are returned as regular objects return types from methods there will be no special error flow nothing like that it will be just like a regular data flow without any kind of try catch finally blocks in the rest of the app from the repository upwards so to recap repository and the ten subsequently use cases will return both number trivia objects and also they will return failure objects from their methods so how is something like that possible how can we return number trivia or fail from the same method welcome functional programming and that's why we have imported the darts package over to our app this functional programming darts package allows us to simply use an either type while I will not pretend that I am some functional programming pro at least not yet you don't need to know any really advanced stuff about functional programming either speaking of either the either type which is a functional programming concept will allow us to return either number trivia or failure which we are going to create next obviously we still do not have any failure classes so let's define them right now we are going to create an error subfolder under core and this will hold failures Dart and the failure here will be really only a simple class it will be abstract actually because then later on we are going to create some concrete implementations of failure objects and again we are not writing this in test-driven development manner because there is nothing to test in an abstract class so this will be abstract class failure let's again extend equatable so that the class is extending failure later on should they have any fields like message or some error code or something like that their equality will be able to be checked based on those fields so for that to use equatable in this abstract base class we have to have a constructor here which will accept a list of properties which will equal Const dynamic which will be a empty list and then we will pass this list of properties over to the super constructor this is nothing really to worry about this is just what's going on with this dart analyzer this is just simply the way that things work with equatable so we pass in properties over to the super constructor and again this is only an abstract class we are going to create concrete classes in the next part of this course then as you hopefully remember from the last part and as is signified by this diagram here a repository from which a use case gets its data is both inside the domain layer and inside data layer as well at the same time or to be more precise the definition of a repository or as we are going to call it the repositories contract is present in the domain layer this upper half of this gradient is pink or wood is discover whatever and then the concrete implementation of a repository this green side of the gradient is in the data layer this will allow for total independence of the domain layer but there is also another benefit which we haven't talked about yet and that is testability that's right testability and separation of concerns go together extremely well and this is the absolute beauty of clean architecture because it really complements test-driven development because without really architecture you cannot even test anything because spaghetti code believe it or not cannot be tested how will this allow for better testing well writing a contract for a repository in this case it will be an abstract repository class will allow us to write tests test-driven development style of course for the use cases even without having an implementation of the repository something like this is called and we're of course going to get to that later on for now let's create the so-called contract of the repository inside the domain folder under repositories let's create a new file number trivia repository the dart and inside of here will have an abstract class number trivia repository and this class will have the following interface we want to have two methods here one for getting concrete number trivia for which we have to pass in a number and don't worry I will come back to the return types in just a bit so get concrete number trivia in number if I could write number and then of course it's going to have get random number trivia which will not have any parameters so let's just rename concrete to random and what is going to be its return type well we are going to use that either type which I have described previously so let's go bit by bit it will of course still return a future because it will be an asynchronous operation to get the concrete or random number trivia from the repository and subsequently from the data sources and what's interesting is the type which the future will wrap it will be either which comes from the darts package so let's import that and then either gets two type parameters one is left so L and R for right of course and the left side is always for this kind of error handling the failure so let's import failure here and the right side is always the success kind of data so in this case it will be the entity number trivia and we of course need to import even that right over here and then this return type will be the same forged random number trivia we will cover this in greater detail later on how to actually work with this either type but for now just know that this function this method will return either a failure which is the left side or number trivia which is the right side and this way we do not have to deal with catching exceptions anywhere else in the app then in the repository which will convert the exceptions into failures and let's use the nifty little extension for vs code to fix import so they will be in the relative manner okay although this part is getting quite long and information-packed already I do not really want to leave you hanging so we are finally going to write some tests while implementing the get concrete number trivia use case and in the next part we are gonna add the get random number trivia use case so definitely stay tuned for that and subscribe to this channel if you do not want to miss it and also hit the bell button so that you will get notified about all the new videos as is the case with test-driven development we are going to write the test before writing the production code so this will ensure that we aren't gonna add a bunch of unneeded functionality this is the yagna principle you ain't gonna need it which is one of the most powerful things about test-driven development because it forces you to really think about what you write because you really do not want to test unnecessary logic it even doesn't make sense you cannot write unnecessary logic with test-driven development because you really just do not even think about writing something for future proofing your code and that is the perfect thing about test-driven development so let's get right to it getting the test in dart apps happens inside the test folder we have a widget test here we can delete that right now so move to trash and usually what we are going to do to is that the test folder structure follows the production code folder structure so we are going to create all of these folders so core will go here then also new folder features inside the features folder will be another folder called number trivia and right now we are going to write only the use case so the domain folder would be enough to create here but we are going to create all of the other folders as well so also data and then presentation just so that we have everything we need for future lessons so we have data domain presentation inside domain we are going to have the use cases folder and this is where we are going to write our first test tests in dart are always named the same way as is the production code file but we append tests to the end so because the production code file will be called get concrete number trivia the test will be called get concrete number trivia test the dirt and again you can get all of this code from the written tutorial which is available from the link in the video description writing the test requires a bit of a setup we know that the use case should get its data from the number trivia repository for which we currently have only the contract the abstract class because we have only the abstract class we're going to mock it so that we can add some functionality to it only for this test and mocking something also allows us to check whether or not some methods have been called on that object and overall it really allows for nice testing experience so without further ado let's create a class Mach number trivia repository which will extend mark which comes from the maketo the dart package and then it will of course implement first it needs to implement the number trivia repository let's import even that so extending this new class with mock allows us to market of course and then we implement the interface from the number to be a repository abstract class let's now also import the flutter test package so flutter test dot dar will go here and now we have to think about how will the use case which we currently do not even have a file for and that is perfectly fine with DES driven development how will the use case operate with the repository well of course it's going to get that repository passed in through the constructor so that later on we can use the gated package to do some nice dependency injection thingies this is called loose coupling and loose coupling is absolutely crucial for test-driven development because without loose coupling you cannot test anything basically and to pass this marked version of a repository into the now Nadia existent use case we're going to use a method called setup which is available for every test that you write in dart and the setup method runs before every single test so let's first create void main because all of the tests run inside this main method and then we have the setup method here in which we are going to initialize all the objects we need but first we actually have to create the variables in which the objects in question will be stored so what do we want to have here well the now Nadia existent get concrete number trivial use case so we are going to just call it use case and then also the Mach number trivia repository will be stored here so that we can then later on get it and do some mocking on this instance so inside setup we're going to first initialize or instantiate to be precise the Mach number trivia repository so just let's create a new instance just like that and then we're going to also instantiate the use case so get concrete number trivia use kids will be instantiated and the Mach number to your repository will be passed in of course it doesn't make any sense to continue with writing the test because currently it doesn't even compile so even before writing the actual test we can do another step in the test-driven development because we have arrived in the red face TDD works in red green refactor phases red face is obvious because we have red squiggly lines so we have to pick something in the red face and now we want to arrive into the green face and then later on we'll refactor and we are gonna arrive into the green phase which is without errors by creating the actual gate concrete number trivia class so let's create it under domain use cases here so new file get concrete number trivia dad art and this will be just a simple class for now get concrete number trivia and it will accept a final number trivia repository called repository into its constructor so once we import it and create constructor for missing fields and fix import so that they are relative this is the kind of class we have now and this is perfectly enough for this test to not complain anymore about non-existent get concrete number trivia use case and I probably have a typo here of course get concrete so we have to rename that concrete now we are talking so now we can import it over to the test file and we don't have any errors of course we haven't tested anything else so let's move on right on to that the nature of our numbered trivia app is really simple so there will not be a lot to test here in the use case because really all it will do is to just get the number trivia data from the repository and that's basically about it it will just get the entity or the failure of course from the repository to start writing a test you can either just write test and then write should get trivia for number from the repository or I have a nice little snake which I have created myself and that is a a a test which is the arranged act and assert test so this test should get trivia for the number from the repository and now of course we have already the repository instance present in here which is the mocked instance of the repository but we do not have the trivia and we do not have a number so let's create these variables we want to have final T number which is the test number which we are going to try to get from the repository so the number is equal to just one and then final the number trivia it's equal to a new instance of number trivia this is what is going to be returned from the mocked class we're going to get to all of this in just a little while so number trivia we want to have a regular instance of it here so it accepts a number which will be the T number or we can actually just pass one in here it doesn't really matter and then the text will be again it doesn't matter what the text is so now in the arrange phase of this test what we want to do is to provide some functionality to the mocked instance of the repository so when and this is really nice the syntax that is here because you can really read it as an English sentence and it will all make sense so when Mach number trivia repository get concrete number trivia is called on it with any argument so it doesn't matter whether or not the number is one or two or three it can be really anything so any is a matter then answer because it's asynchronous so you cannot call then return but you have to call then answer and the answer will be asynchronous and what do we want to answer well the return type of get concrete number trivia is an either and the right side of the either type is number trivia and the left side is failure well in the test it doesn't really matter what we return we can return really either failure or the number trivia in this case let's return the number trivia so we want to return the right side of the eater type this is how we really use it and then later on you can also check whether or not the side of the returned object is left or right if it's left you know that it's a failure if it's right you know that it's a successful object returned so right let's import darts here we wanna return right T number trivia so to go through this again when the Mach number should be our repository get concrete number trivia method is called with any argument any number then always answer with the success response so to say so the right side of the either with number trivia contained inside of it all of this is available from the written tutorials so definitely if you want to learn at your own pace check that out from the link in the video description now we move on to the act phase of the test which is usually really simple so we just want to store the result of calling the use case and we wanna call the use case which is asynchronous so we're gonna call a wait use case that executes and of course there is no such method yet because we have not implemented it because we are doing test-driven development so we want to call execute on that use case and pass in the number the number here now comes the third part of test so what do we want to check for well we expect that the result of the execute method on the use case will really be the same thing as was just returned from the Mach number trivia repository because again the stuff that use case does is really simple it just gets the data from the repository and in the case of numbers trivia app it doesn't do anything more than that so therefore we expect the result to be right and inside of it we expect that there will be T number trivia present and then we also want to verify using the makita package we want to verify that Mach number three our repositories get concrete number trivia was called with the number this is pretty important because imagine that we pass in the T number into the use case so just to make it more visually concrete let's pass in number twenty but somehow in the use case some smart guy decided that he will always pass the number 42 over to get concrete number trivia in the repository if we did not have this verification here we would find out about it of course because the response would be not correct but this verification adds another layer of protection to our code against these kinds of errors which do not just pass the correct arguments to the methods of the dependencies of the use case or any other class there is so let's again revert back to T number and finally we are just going to verify no more interactions are happening on the Mach number trivia repository because once we call execute the use case should not do anything more with the repository there is a no point in even running this test because it's not gonna run since it doesn't even compile we have a compilation error here that execute is not present on the use case this test really acts like a documentation for the functionality which we are about to implement so let's jump right into that we're gonna go to get concrete number trivia and start writing the implementation of execute method so it will return future either which contains failure or number trivia so we need to import all of these types over here once we give this method name execute so let's import darts let's import failures and let's import number trivia now based on the test we know that execute method should take in a number which is a named parameter so therefore we know what we need to do it will have a named required of course so we need to import meta also method add dart required number which is an integer and it's going to just call the repository that get concrete number trivia with the number and of course we need to return a weight whatever was gotten from the repository so this function needs to be itself asynchronous all right so this is the implementation for the execute method and now all we need to do is to run the test I have a handy shortcut keyboard shortcut for running all of the dart tests so I will show you how to do that just go to if you are using vs code of course in IntelliJ this would be completely different but in vs code go to file preferences keyboard shortcuts and now search for dart run all tests and for this command just set some key binding I have shift alt and left square bracket so once you have this shortcut you can run all of the tests with shift alt and left square bracket we have only one test of course and it's going to pass so should get trivia for the number from the repository this is only a simple test that's because the functionality of the gate can't read number trivia use case is also simple but a test so now we can be confident in our code and the other way to run a test is to go over to the bugging tab here in vs coal now tap on this configure or fix launch the JSON gear icon ignore that net if something like that pops up and we want to add configuration so dart run all tests all right and with this configuration present in the launch JSON file you can now select dart run all tests from the drop-down in the debug tab of vs code so once you do that you can run all tests even by clicking this green start debugging button and again it will pass because the same test was run again in the next start we are going to add another use case for getting the random number trivia and also we are going to refactor this code and also the new use cases code so that it will be more robust so definitely stay tuned for that and if you don't want to miss the next part and also more to Reles like this definitely subscribe to this channel and also join the notification squad by hitting the bell button to make sure you grow your flatterer coding skills because here on reso coder I am determined to provide you with the best app development tutorials and resources out there if this video helped you with understanding at least just a bit test-driven development process and do not worry we are going to write many many more tests throughout this series give this video a like and also share it with our developers who are surely benefit from it as well leave a comment if you have anything to say any questions regarding this test-driven development I will try to answer them to my best ability follow me on Instagram I go under the name reso coder everywhere so that you get some behind-the-scenes news from what I'm currently doing and see you Internet [Music]
Info
Channel: Reso Coder
Views: 65,473
Rating: 4.9718461 out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, clean architecture, software development, flutter clean ui, flutter clean architecture, flutter clean code, flutter testing tutorial, flutter tdd, flutter test driven development, flutter crash course, flutter course, flutter, flutter tutorial, flutter dependency injection, flutter state management, flutter bloc library, flutter unit test, flutter mvp, flutter mvvm
Id: lPkWX8xFthE
Channel Id: undefined
Length: 40min 22sec (2422 seconds)
Published: Thu Aug 29 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.