Flutter Clean Architecture With TDD | BLoC | Cubit

Flutter Clean Architecture With TDD | BLoC | Cubit

    Clean architecture helps you maintain your code and it's really suitable for large projects and best for scalability. Flutter beginners get difficult time to understand and implement it. And adding BLoC and Cubit with it makes it more difficult. Take a BLoC and TDD with clear architecture course.

    Riverpod Clean Architecture Course

    This tutorial is not for beginners. You should have at least 6 months experience in Flutter

    Here I am gonna explain step by step to understand Clean architecture and also cover TDD at the end. Clean architecture has three layers. This could be your ultimate project or folder structure of Flutter app.

    Clean architecture itself follow something called SOLID.

    Three layers are Presentation layer, Domain layer and Data layer. Look at the flow them how they are called. The below picture show bidirectional flow of the layer communications.

    Domain layer

    Domain layer contains the business logic of our application. But this is not BLoC business logic. Strongly suggest to write your code from domain layer.

    In general, domain layer works with presentation layer. Domain layer is triggered by an events from presentation layer. These events could be a button press or API calling.

    Domain does not depend on anyone. Presentation layer finds domain layer to work with.

    First let's a look at this layer and folder structure

    Here you can see that have entities, repos and usescases folder. First we should create entities. Entities hold the blue print of our data model which we will pass around for a certain features or screens or pages.

    After that we create repository or repos. Repositories contains abstract classes or interface. They are the rules of a particular feature or screen. These classes define what a particular feature should do.

    These classes contain methods signature. So the signatue defines what a feature should do.

    When presentation layer communicates with domain layer, presentation layer first reach out to usecases folder in domain layer.

    From the name it implies that, usecases tells you when to use them. It means what methods are defined there. 

    Usecases This sub layer contains tunnel between presentation and domain layer. In general, this is only tunnel between presentation layer and domain layer to communicate.

    Here you see how we reached out from our AuthBloc to SignIn class. AuthBloc belongs to presentation layer but it reaches for SignIn class in the usecases folder. 

    After that usecases reaches to repo which has AuthRepo. AuthRepo is an abstract class and it is implemented by the data layer.

    This usecases layer should only contain a class or methods and helper related logic or function.

    Usecases layer should be very independent and should not take anything outside of Domain layer.

    Data layer

    Data layer is for fetching data from outside world to app. Data layer depends on domain layer. If you delete domain layer, data layer will get error. But the opposite is not true. In general data layer contains three below folders.

    1. datasources
    2. models
    3. repos

    Since data layer works with external resources and fetch data, it also throws exceptions if necessary. We used dartz package to handle the success or failure.

    Data layer contains models, and these models may extend the entities of the domain layer. In our models in data layer we will have toJson, fromJson, copyWith method like these.

    What ever is defined in the domain layer repositories, data layer repositories would implement them. So repositories here depend on data source of this layer. Data source would be taken from external server or local storage.

    Presentation layer

    Presentation layer may include your bloc, views, utils, and widgets. This layer mostly depends on other layer.

    How the layer may look like see the picture below

    In general, in widgets folder you will put the reusable classes or files. Utils folder contains things like special widgets like styles, colors and things like that.

    bloc folder is the most important one. It contains your state, event and bloc. They are at the heart of the state management. 

    And views folder actual screen which the users see. And the classes in this folder connects and contains every other classes in the presentation layer.

    Ultimately, views file would contain bloc and bloc itself would contain event and state. The bloc would reach out to domain layer first when an user interaction happens.

    The above picture should give you how the views inside presentation layer works. Even though it's one way from the arrow, but it should also work the opposite if you receive data from outside world.

    In general the bloc in presentation layer would trigger the usecases of domain layer. And then the usecases would trigger the repositories in domain layer to data layer repository. Remember data layer's repositories are the implementation of the domain layer repositories(they are just abstract classes).

    And then data layer's repositories would find the data source and get data back to the usecases of domain layer.

    Then domain layer would feed data back to the bloc. And bloc will show the data on the view. 

    Let's take another look. This might help how you understand the basic flow. The below diagram shows how the basic flow starts from Presentation layer to the domain layer to the data layer. This is uni directional.

    Q & A

    ###  Where does the domain layer sit?

    ==> It sits between data and presentation layer.

    ###  How many sub direcotry does the domain layer have?

    ==> It will have three sub directories. 

    ###  What's the first thing in domain layer?

    ==> It's the entities folder. It would contain the blue print of the data coming from server. It's like our data structure.

    ###  What does the domain layer's repository do?

    ==> Repositories contain contract between data layer and domain layer.

    ###  How are the contracts defined?

    ==> They are defined using interfaces or abstract classes. 

    ###  How are domain layers usecases and repository connected?

    ==>  Usescases depend on the repositories.

    ###  What principle does domain layer's usecases follow?

    ==>  They follow SRP(Single Responsibility Principle) principle.

    ### In TDD, what do you test from the domain layer?

    ==> We test the usecases of domain layer.

    ### what else do usecases do?

    ==> They carry out the operations of repository.

    ### What are models in data layer?

    ==>  They are like entities with extra features.

    ### How does domain layer connects to data layer?

    ==>  Domain layer's repos are implemented in data layer.

    ### What are the repos of data layer?

    ==>  These repos are connected from the repos of the domain layer.

    ###What is the datasources folder in data layer?

    ==>  Datasources folder's dart files implement the repos of data layer.  This is the actual of implementation that's get triggerd from usecases of domain layer.

    ==>  They are the implementation of the domain layer's repo. Domain layer's repos are abstract classes.

    ### How does presentation layer reaches to domain layer?

    ==>  Presentation layer does it through usecases. Usecases use something called callable() method in dart to reach to the repos of domain layer.

    A simple demo of clean architecture

    Other BLoC and TDD Clean Architecture related questions are covered here.

    SOLID Principle

    Clean architecture embodies S-O-L-I-D principle.

    Here S stands for Single Responsibility Principle or SRP. Here in every module is responsible for doing only one task. That's why clean architecture has so much code. 

    Here O stands for Open Close Principle or OCP. It basically means every module or sub layer are open to new extension, which means you can easily add new code without disturbing the architecture.

    It means you or your team members should be able to add new functionalities to an existing software system without changing the existing code

    L for Liskov Substitution Principle or LSP. It means child class could replace parent class. It's totally object oriented principle. It's about inheritance and getting properties and fields from parent class.

    I for Interface Segregation Principle or ISP. It means interfaces are not forced to be used by clients. 

    D for Dependency Inversion Principle or DIP. It means you should create more interfaces and they should be able to work with new dependency without breaking the old one. It strictly connects with ISP. To follow DIP you must first follow ISP.

    We will talk more about S-L-O-I-P in future of this tutorial. 


    Recommended posts

    Recent posts