This is a project that demonstrates how to implement a clean code architecture in Flutter using the Business Logic Component (BloC) pattern and a Test-Driven Development (TDD) approach.
The project is structured according to the principles of clean architecture, with separate layers for presentation, application, domain, and infrastructure. The presentation layer is implemented using Flutter, while the other layers are platform-independent.
The BloC pattern is used to manage the application state and business logic. Each screen in the app has its own BloC, which is responsible for handling user input and updating the UI. The BloCs communicate with the domain layer to perform business logic and with the infrastructure layer to access external services and data sources.
The TDD approach is used to ensure that the code is robust, reliable, and maintainable. Each feature is developed incrementally, with tests written before the code. This helps catch bugs early and ensures that the code is testable, which makes it easier to refactor and maintain over time.
The project includes examples of how to implement common features in Flutter using the BloC pattern, such as navigation, form validation, and data fetch. It also includes unit tests for each feature, demonstrating how to write tests using the Flutter testing framework and the Mockito library.
To get started with the project, simply clone the repository and run flutter run
in the project directory. You can also run the tests using the flutter test
command.
Clean Code Architecture Theory: https://www.freecodecamp.org/news/a-quick-introduction-to-clean-architecture-990c014448d2/
-
Every "feature" of the app, like getting some interesting trivia about a number, will be divided into 3 layers - presentation, domain and data.
-
Presentation:
- This is the stuff you're used to from "unclean" Flutter architecture.
- You obviously need widgets to display something on the screen. These widgets then dispatch events to the state management and listen for states.
-
Domain:
- Domain is the inner layer which shouldn't be susceptible to the whims of changing data sources or porting our app to Angular Dart.
- It will contain only the core business logic (use cases) and business objects (entities). It should be totally independent of every other layer.
- Use Cases are classes which encapsulate all the business logic of a particular use case of the app (e.g. GetConcreteNumberTrivia or GetRandomNumberTrivia).
-
Data:
- The data layer consists of a Repository implementation (the contract comes from the domain layer) and data sources - one is usually for getting remote (API) data and the other for caching that data.
- Repository is where you decide if you return fresh or cached data, when to cache it and so on.
- Domain
- Entities: Business objects (entities) that our application will use
- Repositories: Contracts(abstract classes) is defined in
Domain
, knowing that the actual implementation of the Repository in theData
layer will fullfill this contract. - Usecases: Containes only business logics
- Data:
- Datasources: this one is usually for getting remote (API) data and the other for caching that data. Here we have remote datasource and local datasource. In Simple terms this is the API of your application
- Models: This is that transforming raw data (e.g JSON) into Dart objects requires some JSON conversion code. We create Model classes which extend
Entities
and add some specific functionality (toJson, fromJson) or additional fields, like database ID, for example. Simple words, Blueprint of the data our app will work with - Repositories: Repository implementation (the contract comes from the
Domain
layer). This is a place to even fine tune the data, i.e filter, sort, clean and all last moment changes before sending data to business logic layer
- Presentation:
- Bloc: TODO
- Pages: TODO
- Widgets: TODO
Please raise a small PR