Flutter TDD Clean Architecture Course [4] - Data Layer Overview & Models

แชร์
ฝัง
  • เผยแพร่เมื่อ 8 พ.ย. 2024

ความคิดเห็น • 95

  • @JeremyConnor
    @JeremyConnor 5 ปีที่แล้ว +9

    I like that you've moved the JSON behaviour out of the entity layer, that makes a lot of sense.

  • @abderrahmansettani9843
    @abderrahmansettani9843 5 ปีที่แล้ว +25

    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.

  • @JonesDTaylor
    @JonesDTaylor 4 ปีที่แล้ว +7

    25:48 no need to add 'as num' at line 13 if you are working with Dart 2.1 and above.

  • @Waseek69Ahmad
    @Waseek69Ahmad 2 ปีที่แล้ว +1

    This series is GOLD

  • @stheo9084
    @stheo9084 4 ปีที่แล้ว +3

    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 .

    • @karemmohamed890
      @karemmohamed890 3 ปีที่แล้ว

      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.

  • @Kemorave
    @Kemorave 2 ปีที่แล้ว

    This is the best series on internet

  • @volodymyrbobyr5256
    @volodymyrbobyr5256 4 ปีที่แล้ว +3

    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

  • @ivanyoed
    @ivanyoed 3 ปีที่แล้ว +1

    Top tier course. Thanks a lot Reso Coder.

  • @wardsuleiman1640
    @wardsuleiman1640 3 ปีที่แล้ว +2

    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 !!

  • @josecoverlessons
    @josecoverlessons 5 ปีที่แล้ว

    I really appreciate this man!!! you are doing the public a service, I will be refactoring all my code to follow your guidelines

  • @sandromaglione
    @sandromaglione 5 ปีที่แล้ว +4

    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?

  • @ercuesy
    @ercuesy 4 ปีที่แล้ว +3

    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!

  • @tomasbaran985
    @tomasbaran985 9 หลายเดือนก่อน

    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.

  • @cosmindumbrava7365
    @cosmindumbrava7365 5 ปีที่แล้ว +3

    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?

  • @raulisesg
    @raulisesg 5 ปีที่แล้ว +1

    You are great!, I hope this series of videos will end soon, to have a complete overview of TDD.
    You could write a book ;)

  • @pathakvivek7865
    @pathakvivek7865 5 ปีที่แล้ว +1

    Very nice tutorial again as always. Thank you so much! Waiting for widget test.

  • @realThinkingPoker
    @realThinkingPoker 3 ปีที่แล้ว

    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.

  • @mehdiparsaei1867
    @mehdiparsaei1867 3 ปีที่แล้ว

    You have to make a abstract class Mapper
    Then your Model have to implement Mapper
    Mapper have two main method
    toModel
    fromModel

  • @erkinkurt6799
    @erkinkurt6799 3 ปีที่แล้ว +3

    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
      @alfredotorrespons5305 3 ปีที่แล้ว +1

      I'm having the same doubt, if you found an elegant solution please let me know.

    • @erkinkurt6799
      @erkinkurt6799 3 ปีที่แล้ว +1

      @@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.

  • @albanr8028
    @albanr8028 3 ปีที่แล้ว

    Thank you so much for this series !

  • @CarlosPerez-zz5ij
    @CarlosPerez-zz5ij 2 ปีที่แล้ว

    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?

  • @matthewtrent1981
    @matthewtrent1981 2 ปีที่แล้ว

    What do you do when you need to access the same entity and model from multiple features? (great vids btw!)

  • @saadahmed1662
    @saadahmed1662 5 ปีที่แล้ว +2

    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

  • @amilismurfs
    @amilismurfs 3 ปีที่แล้ว

    This tutorial is awesome. Thanks :)

  • @d-apps2699
    @d-apps2699 2 ปีที่แล้ว

    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?

  • @uDropper
    @uDropper 10 หลายเดือนก่อน

    Since all the models have some basic methods, would it be valid to create an abstract class to serve as an model interface?

  • @mohammedelfatih8018
    @mohammedelfatih8018 4 ปีที่แล้ว

    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

  • @nr152522
    @nr152522 5 ปีที่แล้ว +4

    If our model classes already extend a class, how would we handle this? E.g. 'UserModel extends Table' (from Flutter Moor lib).

    • @ResoCoder
      @ResoCoder  5 ปีที่แล้ว +5

      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.

    • @nr152522
      @nr152522 5 ปีที่แล้ว +1

      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!

  • @kindalame9894
    @kindalame9894 ปีที่แล้ว

    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?

  • @TheJaniable
    @TheJaniable 8 หลายเดือนก่อน

    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.

  • @pedrodelacruz2369
    @pedrodelacruz2369 3 ปีที่แล้ว

    Excelent content

  • @bhautikgajera6383
    @bhautikgajera6383 8 หลายเดือนก่อน

    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

  • @gbplayzone
    @gbplayzone 5 ปีที่แล้ว

    Very nice Course!!! Thanks man!

  • @PalDorogi
    @PalDorogi 4 ปีที่แล้ว

    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.

  • @batuhankrbb
    @batuhankrbb 3 ปีที่แล้ว

    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?

  • @psybitcoin
    @psybitcoin 4 ปีที่แล้ว

    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?

  • @earGO
    @earGO 4 ปีที่แล้ว

    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.

  • @liorpolak1391
    @liorpolak1391 3 ปีที่แล้ว

    Great

  • @luisbaltodano1941
    @luisbaltodano1941 4 ปีที่แล้ว

    Hi, why should be use a factory construc in this case?

  • @eduardorabanal2803
    @eduardorabanal2803 5 ปีที่แล้ว

    great video as always, thanks a lot

  • @qingcaish
    @qingcaish 4 ปีที่แล้ว

    Microsoft eShopOnWeb project show an every good example of clean architecture.

  • @MrAmG17
    @MrAmG17 ปีที่แล้ว

    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

  • @yashpaneliya1362
    @yashpaneliya1362 3 ปีที่แล้ว

    the NumberTriviaRepository in domain layer is created just to write test for usecases, right?

  • @Rubentuation
    @Rubentuation 5 ปีที่แล้ว +1

    Thanks mate!

  • @luisyaurimartinez7952
    @luisyaurimartinez7952 3 ปีที่แล้ว +2

    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();
    }

  • @dawidniegrebecki2205
    @dawidniegrebecki2205 4 ปีที่แล้ว

    Great Video!1

  • @gabrielpigatto2016
    @gabrielpigatto2016 4 ปีที่แล้ว

    for those who are getting a error in json.decode at 19:15 just use JsonCodec.decode

  • @ShadowInfest
    @ShadowInfest 5 ปีที่แล้ว +1

    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?

    • @ShadowInfest
      @ShadowInfest 5 ปีที่แล้ว +4

      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?

  • @lucasmarinho5888
    @lucasmarinho5888 4 ปีที่แล้ว

    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='...."

  • @psybitcoin
    @psybitcoin 4 ปีที่แล้ว

    How to write tests for example an API that returns lists of text for multiple numbers?

  • @theopee4760
    @theopee4760 4 ปีที่แล้ว

    How will you handle a complex list with this.

  • @anirutkamchai4174
    @anirutkamchai4174 5 ปีที่แล้ว +1

    Can you use provider instead bloc :)

    • @ResoCoder
      @ResoCoder  5 ปีที่แล้ว +5

      I'm using provider With Bloc 😉

  • @纪亚荣
    @纪亚荣 5 ปีที่แล้ว

    How can I compose the TDD Clean Architecture with Redux in a Project, like a React Project

  • @SEOTADEO
    @SEOTADEO 2 ปีที่แล้ว

  • @pascalgehring7815
    @pascalgehring7815 3 ปีที่แล้ว +2

    Does anyone know how to get his aaa Test snippet?

    • @abdullahalasif2110
      @abdullahalasif2110 3 ปีที่แล้ว +3

      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

    • @pascalgehring7815
      @pascalgehring7815 3 ปีที่แล้ว

      @@abdullahalasif2110 Thanks :)

    • @abdullahalasif2110
      @abdullahalasif2110 3 ปีที่แล้ว +1

      You are welcome.

  • @jesselima_dev
    @jesselima_dev 5 ปีที่แล้ว

    Done!!! :D

  • @Djtroyan4eg
    @Djtroyan4eg 4 ปีที่แล้ว +1

    I have an error in test like Expected:
    Actual:

    • @jassjass1244
      @jassjass1244 4 ปีที่แล้ว +2

      facing the same problem . have you solved it?
      Expected: NumberTriviaModel:
      Actual: NumberTriviaModel:

    • @Djtroyan4eg
      @Djtroyan4eg 4 ปีที่แล้ว

      @@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

    • @peterirving9458
      @peterirving9458 4 ปีที่แล้ว +3

      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()

    • @Djtroyan4eg
      @Djtroyan4eg 4 ปีที่แล้ว

      @@peterirving9458 it is correct, when I convert objects into json string it is working correctly, so it is same

    • @peterthompson6909
      @peterthompson6909 4 ปีที่แล้ว

      @@peterirving9458 yep, that was my problem - thanks for the good dose of sensible :)

  • @SpellOdyssey
    @SpellOdyssey 3 ปีที่แล้ว

    fromJson doesn't work !! test is not working it shows error and I can't figure it out

    • @adriano_souza
      @adriano_souza 3 ปีที่แล้ว +1

      to me is toJson. Did you fix it?

  • @adriano_souza
    @adriano_souza 3 ปีที่แล้ว

    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'

    • @skaryus
      @skaryus 3 ปีที่แล้ว

      Have you solved the problem?

    • @adriano_souza
      @adriano_souza 3 ปีที่แล้ว +3

      @@skaryus yes man! it's because I forgot :super() in NumberTriviaModel

    • @skaryus
      @skaryus 3 ปีที่แล้ว

      @@adriano_souza All right. Keep working 👍

  • @tahamalas1322
    @tahamalas1322 5 ปีที่แล้ว +1

    Can't we use BuiltValue in the data layer for the serialization and deserialization?

    • @YomenChannel
      @YomenChannel 5 ปีที่แล้ว

      Im using built value. When you use it, I don't see the point in testing 'toJson' and 'fromJson' methods :)

    • @tahamalas1322
      @tahamalas1322 5 ปีที่แล้ว

      @@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

  • @FooBarMightBeGreen
    @FooBarMightBeGreen 5 ปีที่แล้ว +3

    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

    • @kevinhorasia3298
      @kevinhorasia3298 ปีที่แล้ว

      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

    • @FooBarMightBeGreen
      @FooBarMightBeGreen ปีที่แล้ว

      @@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.

  • @aytunch
    @aytunch 5 ปีที่แล้ว

    imple.... men.....tations 😜

  • @mehdiparsaei1867
    @mehdiparsaei1867 3 ปีที่แล้ว

    Fixtures?!!!
    I did not hear that.
    Use "dummy_data" instead of "mixtures" for your folder name.

  • @justinandrewhampton
    @justinandrewhampton 4 ปีที่แล้ว

    "computery writing of exponents" 🤣
    th-cam.com/video/keaTZ9M_U1A/w-d-xo.html