Skip to content

vannt1991/flutter-recipes-project

Repository files navigation

Clean architecture flutter app

A clean architecture recipes app, made with Recipes and Flutter sdk.

The main goal is to build readble, maintainable, testable, and high-quality flutter app using test-driven-design styled architecture.

You can learn how to implement the architecture here: TDD Clean Architecture for Flutter

Screenshots

Technologies

Architecture

  • Test-driven-design

  • Clean architecture Clean Architecture

  • Call follow Call follow

   

Real Implementation

===================

To materialize the architectural decisions and to make it more useful to our team, we’ve started to choose flutter packages to suit our needs, following the philosophy of using as fewer third-party packages as possible.

- To implement UseCases as the Business Logic Components of the application, we felt that the natural decision was the Bloc package, as it is a mature, robust, and well-known solution for state management in Flutter context, and it is easy to test as well.

- To represent Bloc states and events, Models and Entities, we’ve decided to use Freezed package, as it is an elegant and easy solution to implement sealed classes, union types and data classes as it is not available by default in Dart (yet!). It’s based in code generation and it has ready-to-use integration with Json_serializable package that we’ve decided to use to deal with serialization.

- To deal with dependency injection we’ve decided to use a simple service locator: Kiwi, we can replace with GetIt and define a simple set of rules-of-thumb to keep consistency over project’s development and maintenance life cycles. Rules-of-Thumb:

— If a class depends on another, it must be passed at instantiation by constructor and the instance control should be made by the service locator.

— Dependency injection setup for a module/feature should be split in each feature (each feature/module will contain its own file explicitly defining its dependency injection setup).

— The service locator should never be referenced in a place other than a constructor call.

- To deal with internationalization we’ve decided to use pure Object Oriented Programming, and keep all Strings of the application as static constants of an implementation of an abstract class to be defined.

- To deal with navigation we’ve decided to use the Flutters native Navigator, as it poses as a complete solution, and with the arrival of Get Router, we think that it is an elegant declarative solution to deal with navigation. But we can easily switch to flutter navigator following this guide https://api.flutter.dev/flutter/widgets/Navigator-class.html, and on production, i prefer using native flutter navigator to navigation and router pages.

- To deal with http requests we’ve decided to use Dio package as it is a better option than the native Flutter solution presenting good features like Interceptors, base options like headers, base url etc., and is a well known and popular solution. Then we made a wrapper over the client to model errors and responses into our system context.

- To persist sensitive local data we’ve decided to use the package flutter_secure_storage because it is a popular and performative solution when there isn’t the need of storing complex data.

- To storage data structure with offline mode we've decided to use to hive database and can easily replace with sqflite or sembast are good choice via injection.

- To multi-language we decided to using flutter localization and i18n packages.

We’ve defined helper classes/types to deal with the Result of actions, the Result type (generic Freezed union type that has two types: a Success and a Failure), the RequestStatus type (generic Freezed union type that has four types: Idle, Loading, Succeeded, Failed) to help dealing with the visual response of requests, the AppError (abstract class that is implemented in each relevant particular error type), and to help with forms, the Maybe type (generic Freezed union type that has two types: Nothing and Just) used in the definition of FormField type (generic Freezed data class containing the name of the field and the Maybe instance representing the actual possible inputted value to the form field).

Front-end

  • Flutter SDK
  • GetX (navigation service, dependencies manager, ui components)
  • Bloc / Cubit / GetX (state managment)

Back-end

  • SQLite
  • Sembast
  • Hive
  • Recipes

Step to Run App

Make sure you have the latest version of Flutter installed

Open terminal and run this command to generate code:

flutter packages pub get && flutter pub run build_runner build --delete-conflicting-outputs && flutter gen-l10n

Step 2: Open folder lib/main.dart and select to run \

For testing

1, We have Unit testing all logic at test folder. we can simple execute it via command:

flutter test --machine --coverage > tests.output

See more here: https://docs.flutter.dev/cookbook/testing/unit/introduction

2, We have integration test at test_driver folder. To run the tests execute following command:

flutter drive --target=test_driver/app.dart

See more here: https://medium.com/@rishabhv1509/flutter-driver-84d54d1d19e6

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages