Thanks man damn I've been waiting for it keep it coming this is the best flutter well-made series on TH-cam !
4 ปีที่แล้ว +4
Superb stuff indeed! One note though on fixture_reader.dart file. When you run your tests locally, this will work, but if you try to use some kind of ci tool, your tests will fail. This is because ci tools need relative path. You can add a try/catch pattern here to avoid it. I change it to this: import 'dart:io'; String fixture(String name) { String jsonString; try { jsonString = File('test/fixtures/$name').readAsStringSync(); } catch (e) { jsonString = File('../test/fixtures/$name').readAsStringSync(); } return jsonString; } Hope this helps someone.
Correct me if I am wrong but you planned the implementation of fromJson in order to accept large double numbers from the API . By converting numbers to num and then to int you cannot be sure that your code will not break in a larger number(i.e. 10^40) which is bigger than int predefined limits from the api. Generally your tutorial is great by the way .
numbersapi can also return `null` for the number, which it counts as "infinity" in order to find all possible responses, api documentation should probably be consulted
I have a question: What are the reasons for the Model classes to extends the Entity classes? I tried to apply this concept in my project and came to a dead end, so I had to relay on Models to feed my UI with data. So I was wondering if there any obvious reasons for this approach? I would like to share a snippet of my code, but that would be inappropriate here. Finally, I would like to thank you for the great effort you put in your courses. Keep the goodies coming !!
In the written tutorial you say that in this example we do not need a Mapper class for the conversion logic. Can you explain how you would implement a Mapper class in this project if you need to add one?
Hi Matej, thank you for sharing your fantastic videos. I really learn a lot. Question: would it be possible for you to make a video on how to test Firebase interface in terms of documents and collections messaging back and forth? Thanks!
Rather than expanding the model like so (22:40): factory NumberTriviaModel. fromJson(Map json) { return NumberTriviaModel( text: json[ 'text'], number: json[ 'number'], ); } I would consider putting the conversion in core/utils/conversion_utils.dart: class ConversionUtils{ static NumberTriviaModel jsonToNumberTriviaModel(Map json)=>NumberTriviaModel( text: json[ 'text'], number: json[ 'number'], ); } Then when testing it, using it like so: final result = ConversionUtils.jsonToNumberTriviaModel(jsonMap); This way provides better separation of concerns, aligns with the single responsibility principle, and offers greater maintainability and potential for reuse.
I just waited for this 4 course :) Good job! But I have one question: Extending abstract UseCase we can end with many UseCase classes (for example if we add some CRUD operations). Can we have specific UseCase classes with more methods? How would we handle the output, input interfaces in this case?
When I use expect(tNumberTriviaModel, isA()); it returns: Expected: Actual: NumberTriviaModel: Which: is not an instance of 'NumberTrivia' Not sure if isA is expected to use as checking the parent class.
With this separation how would you implement JSON Serializable. Since, we need to introduce json serializable annotations into entity class because properties will be there. We are coupling json serializable package to our domain layer. Which is bad according to plug in plug out situations. So what do you think?
@@alfredotorrespons5305 You can create DTOs which uses json serializable and have toDomain methods. At the end of the day you will have domain entities and dtos. However, it’s a design choice actually. If flutter/dart dies, Json serializable will die also. So it makes sense to use it inside domain layer.
Hey there, u talked about dependency inversion, here u extended entity class which is domain layer by model class which is data layer, so what about dependency inversion in this case??. Shouldnt u make entity contract and place it in core package, this contract should be implemented by entity class and model class, di would be achieved as both entity nd model will depend on abstract class and a separate package... Please explain this if im wrong
You said that the entity should be independent from anything, but you are using a package inside the class, Equatable, I am not sure it a good idea. Plus you are using dartz (Either) inside the domain too. Could you please explain more about it?
Thank u Reso Coder, I have a question suppose the data source am using is firestore, the response will be document instead of json, so how should apply the same concepts
That would probably be the perfect occasion to use separate Mapper classes. Basically just a static method which takes in JSON string and outputs some object.
Reso Coder actually, that’s exactly what I’ve done. It kind of feels wrong code having the domain and data classes essentially duplicated. I liked your solution of extending the domain class. So for now, mapping it is. Loving the tutorials, keep up the great work!
What was the reason for referencing the fixtures by the file name instead of the variable name? Is it just so that the variable name doesn't matter, or not to add another import?
How would you follow this concept, if the project is using a generator like swagger_dart_code_generator or Amplify to generate model classes? In this case, it seems to me that we will always need a mapper between model and entity, and also, we'll keep having to manually update our mapper and entities each time there is a change in the generated models. Having worked on an agile project with hundreds of model classes generated from an OpenAPI file, this seem to be a lot of extra work.
Hello Can we make use case for other purpose other then fetching data from API For example suppose I have XYZ page in that page has one button when button press it's make some calculations result of that calculation require state change so I want to make that calculation logic separate from presentation layer can we do that ???? because suppose I have to change my state management approach in that case I don't bothering to that kind of business logics
Hi Reso Coder, where would you convert an integer stored in db to a money class used in the ui? As Clean architecture confuses me (have some experience in DDD). I am asking because your entity is a subclass of model, meaning the number and the text has same type, while in my case they would be different. Thx in advance.
If I was working on a login feature, how what would I do? For example, using Firebase: after login we receive a FirebaseUser. What entities should I create? What the model should do?
Just in case someone is stuck with error running this outside VScode. If you have this error when trying to use code for fixture reader provided, FileSystemException: Cannot open file, path = 'test/fixtures/trivia.json' (OS Error: No such file or directory, errno = 2) use this code instead import 'dart:io'; String fixture(String name) { var dir = Directory.current.path; if (dir.endsWith('/test')) { dir = dir.replaceAll('/test', ''); } return File('$dir/test/fixtures/$name').readAsStringSync(); } it appears, that VSCode dev env is different from CLI or, say, IntelliJ (that I use), so that's more "general" solution.
26:18 casting number as num is actually very bad. It introduces a modified behaviour that should in probably show an error message for user. example : user enters 1.1 expecting to get an answer of 1.1 but this .toInt() conversion returns that he entered 1 with the message of 1.1
A los que les funciona la lectura del JSON, pueden usar este código remplazando todo fixture_reader.dart : String fixture(String name) { var dir = Directory.current.path; dir = dir.replaceAll('\\', '/'); if (dir.endsWith('/test')) { dir = dir.replaceAll('/test', ''); } return File('$dir/test/fixtures/$name').readAsStringSync(); }
I have one question. I use the moor library and the generator for it. My models are created by it and extend DataClass. So I can't extend it with my entities... I tried it with Mixins but that just threw errors or wanted to make my entity class abstract which is not correct. Should I just change the tests to check if it is a subclass of DataClass or is there another clean solution?
Sorry for asking the same question, saw it in the comments. But I don't get it really at the moment. Is there any example (link, github whatever or a nice video) where I can try to understand how I can solve this with a Mapping?
How works model extends entity that contains a List? In my case, show me a error: "....('void Function(List)') isn't a valid override of 'ResultMovieDetailsEntity.ratings='...."
For the Custom 'aaa' Test Snippet : In vscode : 1. Press ctrl/cmd + shift + p 2. Type "configure user snippets" 3. select "Dart" 4. In Dart.json file , at the end just before the last '}' symbol paste the following code: "triple_a_test":{ "prefix": "aaa", "body": [ "test(", "\t'should $1',", "\t()async {", "\t\t// arrange", "\t\t$2", "\t\t// act", "\t\t$3", "\t\t// assert", "\t\t$4", "\t},", ");" ], } save it and now whenever you type 'aaa' you'll get the same
@@jassjass1244 no, it it because even if objects have same properties, they're not same instances... So in my case I'm converting objects into json and then compare them
check and see what the text and the number values in the JSON mock objects are, I fixed the error making the json text match the tNumberTriviaModel in the first line of main()
Hi Everyone! Can somebody help me? I don't know why, but the last test fail (toJson), rewrite many times, but I guess is not a typo. It's because null safety? Message Error: Expected: {'text': 'Test text', 'number': 1} Actual: {'text': null, 'number': null} Which: at location ['text'] is instead of 'Test text'
Nice videos. Though, did you realize that by simplifying the double case to just 1.0 you totally ended up fixing likely a non issue (assuming the api really always returns Integers) and actually masking the real problem? The problem is the numbers are way too large to be contained in ints and the real fix would be to use a suitable datatype in the first place. Your ints are now overflowing and the doubles are reduced to some entirely different garbage values making no sense e.g. 1e+40 ==> 10000000000000000000000000000000000000000.0.toInt() == 9223372036854775807
Good point, I don't know if there is any different before and after dart updates with int range limit, but now according to dart documentation int range in dart is between -2^53 and 2^53, includes some integers larger than 2^63
@@kevinhorasia3298 you are describing how "ints" work in JS (which doesn't have true ints, but instead uses floats for ints too). These limits ofc apply to Dart web too. Max precise int value there is just 9007199254740991, which is even less.
I like that you've moved the JSON behaviour out of the entity layer, that makes a lot of sense.
Thanks man damn I've been waiting for it keep it coming this is the best flutter well-made series on TH-cam !
Superb stuff indeed!
One note though on fixture_reader.dart file. When you run your tests locally, this will work, but if you try to use some kind of ci tool, your tests will fail. This is because ci tools need relative path. You can add a try/catch pattern here to avoid it.
I change it to this:
import 'dart:io';
String fixture(String name) {
String jsonString;
try {
jsonString = File('test/fixtures/$name').readAsStringSync();
} catch (e) {
jsonString = File('../test/fixtures/$name').readAsStringSync();
}
return jsonString;
}
Hope this helps someone.
nice!
25:48 no need to add 'as num' at line 13 if you are working with Dart 2.1 and above.
This series is GOLD
Correct me if I am wrong but you planned the implementation of fromJson in order to accept large double numbers from the API . By converting numbers to num and then to int you cannot be sure that your code will not break in a larger number(i.e. 10^40) which is bigger than int predefined limits from the api. Generally your tutorial is great by the way .
No he was just covering an edge case which that can exist a number (1e+40) which the compiler will store as a double also it should be an int.
This is the best series on internet
numbersapi can also return `null` for the number, which it counts as "infinity"
in order to find all possible responses, api documentation should probably be consulted
great comment
Top tier course. Thanks a lot Reso Coder.
I have a question:
What are the reasons for the Model classes to extends the Entity classes?
I tried to apply this concept in my project and came to a dead end, so I had to relay on Models to feed my UI with data.
So I was wondering if there any obvious reasons for this approach?
I would like to share a snippet of my code, but that would be inappropriate here.
Finally, I would like to thank you for the great effort you put in your courses.
Keep the goodies coming !!
I really appreciate this man!!! you are doing the public a service, I will be refactoring all my code to follow your guidelines
In the written tutorial you say that in this example we do not need a Mapper class for the conversion logic.
Can you explain how you would implement a Mapper class in this project if you need to add one?
Hi Matej, thank you for sharing your fantastic videos. I really learn a lot. Question: would it be possible for you to make a video on how to test Firebase interface in terms of documents and collections messaging back and forth? Thanks!
Rather than expanding the model like so (22:40):
factory NumberTriviaModel. fromJson(Map json) {
return NumberTriviaModel(
text: json[ 'text'],
number: json[ 'number'],
);
}
I would consider putting the conversion in core/utils/conversion_utils.dart:
class ConversionUtils{
static NumberTriviaModel jsonToNumberTriviaModel(Map json)=>NumberTriviaModel(
text: json[ 'text'],
number: json[ 'number'],
);
}
Then when testing it, using it like so:
final result = ConversionUtils.jsonToNumberTriviaModel(jsonMap);
This way provides better separation of concerns, aligns with the single responsibility principle, and offers greater maintainability and potential for reuse.
I just waited for this 4 course :) Good job! But I have one question: Extending abstract UseCase we can end with many UseCase classes (for example if we add some CRUD operations). Can we have specific UseCase classes with more methods? How would we handle the output, input interfaces in this case?
You are great!, I hope this series of videos will end soon, to have a complete overview of TDD.
You could write a book ;)
Very nice tutorial again as always. Thank you so much! Waiting for widget test.
When I use
expect(tNumberTriviaModel, isA());
it returns:
Expected:
Actual: NumberTriviaModel:
Which: is not an instance of 'NumberTrivia'
Not sure if isA is expected to use as checking the parent class.
You have to make a abstract class Mapper
Then your Model have to implement Mapper
Mapper have two main method
toModel
fromModel
With this separation how would you implement JSON Serializable. Since, we need to introduce json serializable annotations into entity class because properties will be there. We are coupling json serializable package to our domain layer. Which is bad according to plug in plug out situations. So what do you think?
I'm having the same doubt, if you found an elegant solution please let me know.
@@alfredotorrespons5305 You can create DTOs which uses json serializable and have toDomain methods. At the end of the day you will have domain entities and dtos.
However, it’s a design choice actually. If flutter/dart dies, Json serializable will die also. So it makes sense to use it inside domain layer.
Thank you so much for this series !
Thank you so much man, great video! I have a question: What do you do when you need to access the same entity and model from multiple features?
Do you find the answer?
What do you do when you need to access the same entity and model from multiple features? (great vids btw!)
Hey there, u talked about dependency inversion, here u extended entity class which is domain layer by model class which is data layer, so what about dependency inversion in this case??.
Shouldnt u make entity contract and place it in core package, this contract should be implemented by entity class and model class, di would be achieved as both entity nd model will depend on abstract class and a separate package...
Please explain this if im wrong
This tutorial is awesome. Thanks :)
You said that the entity should be independent from anything, but you are using a package inside the class, Equatable, I am not sure it a good idea. Plus you are using dartz (Either) inside the domain too. Could you please explain more about it?
Since all the models have some basic methods, would it be valid to create an abstract class to serve as an model interface?
Thank u Reso Coder, I have a question suppose the data source am using is firestore, the response will be document instead of json, so how should apply the same concepts
If our model classes already extend a class, how would we handle this? E.g. 'UserModel extends Table' (from Flutter Moor lib).
That would probably be the perfect occasion to use separate Mapper classes. Basically just a static method which takes in JSON string and outputs some object.
Reso Coder actually, that’s exactly what I’ve done. It kind of feels wrong code having the domain and data classes essentially duplicated. I liked your solution of extending the domain class. So for now, mapping it is. Loving the tutorials, keep up the great work!
What was the reason for referencing the fixtures by the file name instead of the variable name? Is it just so that the variable name doesn't matter, or not to add another import?
How would you follow this concept, if the project is using a generator like swagger_dart_code_generator or Amplify to generate model classes? In this case, it seems to me that we will always need a mapper between model and entity, and also, we'll keep having to manually update our mapper and entities each time there is a change in the generated models.
Having worked on an agile project with hundreds of model classes generated from an OpenAPI file, this seem to be a lot of extra work.
Excelent content
Hello Can we make use case for other purpose other then fetching data from API
For example
suppose I have XYZ page
in that page has one button when button press
it's make some calculations
result of that calculation require state change
so I want to make that calculation logic separate from presentation layer
can we do that ????
because suppose I have to change my state management approach in that case I don't bothering to that kind of business logics
Very nice Course!!! Thanks man!
Hi Reso Coder, where would you convert an integer stored in db to a money class used in the ui? As Clean architecture confuses me (have some experience in DDD). I am asking because your entity is a subclass of model, meaning the number and the text has same type, while in my case they would be different. Thx in advance.
What if we want to show double when double comes from json and show int when int comes from json? Should we create 2 model classes?
If I was working on a login feature, how what would I do? For example, using Firebase: after login we receive a FirebaseUser. What entities should I create? What the model should do?
Just in case someone is stuck with error running this outside VScode.
If you have this error when trying to use code for fixture reader provided,
FileSystemException: Cannot open file, path = 'test/fixtures/trivia.json' (OS Error: No such file or directory, errno = 2)
use this code instead
import 'dart:io';
String fixture(String name) {
var dir = Directory.current.path;
if (dir.endsWith('/test')) {
dir = dir.replaceAll('/test', '');
}
return File('$dir/test/fixtures/$name').readAsStringSync();
}
it appears, that VSCode dev env is different from CLI or, say, IntelliJ (that I use), so that's more "general" solution.
Great
Hi, why should be use a factory construc in this case?
great video as always, thanks a lot
Microsoft eShopOnWeb project show an every good example of clean architecture.
26:18 casting number as num is actually very bad. It introduces a modified behaviour that should in probably show an error message for user. example : user enters 1.1 expecting to get an answer of 1.1 but this .toInt() conversion returns that he entered 1 with the message of 1.1
the NumberTriviaRepository in domain layer is created just to write test for usecases, right?
Thanks mate!
A los que les funciona la lectura del JSON, pueden usar este código remplazando todo fixture_reader.dart :
String fixture(String name) {
var dir = Directory.current.path;
dir = dir.replaceAll('\\', '/');
if (dir.endsWith('/test')) {
dir = dir.replaceAll('/test', '');
}
return File('$dir/test/fixtures/$name').readAsStringSync();
}
Great Video!1
for those who are getting a error in json.decode at 19:15 just use JsonCodec.decode
I have one question. I use the moor library and the generator for it. My models are created by it and extend DataClass. So I can't extend it with my entities... I tried it with Mixins but that just threw errors or wanted to make my entity class abstract which is not correct. Should I just change the tests to check if it is a subclass of DataClass or is there another clean solution?
Sorry for asking the same question, saw it in the comments. But I don't get it really at the moment. Is there any example (link, github whatever or a nice video) where I can try to understand how I can solve this with a Mapping?
How works model extends entity that contains a List? In my case, show me a error: "....('void Function(List)') isn't a valid override of 'ResultMovieDetailsEntity.ratings='...."
How to write tests for example an API that returns lists of text for multiple numbers?
How will you handle a complex list with this.
Can you use provider instead bloc :)
I'm using provider With Bloc 😉
How can I compose the TDD Clean Architecture with Redux in a Project, like a React Project
♥
Does anyone know how to get his aaa Test snippet?
For the Custom 'aaa' Test Snippet :
In vscode :
1. Press ctrl/cmd + shift + p
2. Type "configure user snippets"
3. select "Dart"
4. In Dart.json file ,
at the end just before the last '}' symbol paste the following code:
"triple_a_test":{
"prefix": "aaa",
"body": [
"test(",
"\t'should $1',",
"\t()async {",
"\t\t// arrange",
"\t\t$2",
"\t\t// act",
"\t\t$3",
"\t\t// assert",
"\t\t$4",
"\t},",
");"
],
}
save it and now whenever you type 'aaa' you'll get the same
@@abdullahalasif2110 Thanks :)
You are welcome.
Done!!! :D
I have an error in test like Expected:
Actual:
facing the same problem . have you solved it?
Expected: NumberTriviaModel:
Actual: NumberTriviaModel:
@@jassjass1244 no, it it because even if objects have same properties, they're not same instances... So in my case I'm converting objects into json and then compare them
check and see what the text and the number values in the JSON mock objects are, I fixed the error making the json text match the tNumberTriviaModel in the first line of main()
@@peterirving9458 it is correct, when I convert objects into json string it is working correctly, so it is same
@@peterirving9458 yep, that was my problem - thanks for the good dose of sensible :)
fromJson doesn't work !! test is not working it shows error and I can't figure it out
to me is toJson. Did you fix it?
Hi Everyone! Can somebody help me? I don't know why, but the last test fail (toJson), rewrite many times, but I guess is not a typo. It's because null safety?
Message Error:
Expected: {'text': 'Test text', 'number': 1}
Actual: {'text': null, 'number': null}
Which: at location ['text'] is instead of 'Test text'
Have you solved the problem?
@@skaryus yes man! it's because I forgot :super() in NumberTriviaModel
@@adriano_souza All right. Keep working 👍
Can't we use BuiltValue in the data layer for the serialization and deserialization?
Im using built value. When you use it, I don't see the point in testing 'toJson' and 'fromJson' methods :)
@@YomenChannel Yes I definitely agree, but the problem is the model can't be derivative of the entity.. So we can't return the model as an entity
Nice videos. Though, did you realize that by simplifying the double case to just 1.0 you totally ended up fixing likely a non issue (assuming the api really always returns Integers) and actually masking the real problem? The problem is the numbers are way too large to be contained in ints and the real fix would be to use a suitable datatype in the first place. Your ints are now overflowing and the doubles are reduced to some entirely different garbage values making no sense e.g. 1e+40 ==> 10000000000000000000000000000000000000000.0.toInt() == 9223372036854775807
Good point, I don't know if there is any different before and after dart updates with int range limit, but now according to dart documentation int range in dart is between -2^53 and 2^53, includes some integers larger than 2^63
@@kevinhorasia3298 you are describing how "ints" work in JS (which doesn't have true ints, but instead uses floats for ints too). These limits ofc apply to Dart web too. Max precise int value there is just 9007199254740991, which is even less.
imple.... men.....tations 😜
Fixtures?!!!
I did not hear that.
Use "dummy_data" instead of "mixtures" for your folder name.
"computery writing of exponents" 🤣
th-cam.com/video/keaTZ9M_U1A/w-d-xo.html