Application Structure

Application Structures

The folder structure of a project is very important. It helps you to organize your project in a better way. It also helps you to understand the project structure easily.

In this guide, we will discuss the folder structure of a project.

Minimal structure

The minimal structure proposed by the project consists of a simple source folder containing your business code. The bin folder is used to use the hmr within your application during the development phase; so you should not delete it.

├── bin
│ └── main.dart
├── lib
│ ├── events
│ └── commands
├── pubspec.yaml
└── .env

N-tier structure

When you're developing increasingly complex applications, you generally lose readability and maintainability and maintainability if you don't focus on a stable, future-proof software architecture.

One approach we recommend is the module-based architecture. This involves dividing your application into several business modules that are independent of each other.

We recommend the following structure.

├── assets
│ ├── image1.png
│ └── image2.png
├── bin
│ └── main.dart
├── lib
│ ├── commons
│ │ ├── helper.dart
│ │ └── api.dart
│ │
│ ├── module 1
│ │ ├── events
│ │ ├── commands
│ │ └── provider.dart
│ │
│ └── module 2
│ ├── events
│ ├── commands
│ └── provider.dart
├── pubspec.yaml
└── .env

To simplify the management of your modules, we recommend that you create a provider.dart file within each which will serve as the entry point for each module.

import 'package:mineral/api.dart';
final class Provider extends Provider {
final MineralClientContract _client;
Provider(this._client) {}
}

Layered architecture

When we talk about modular architecture, we quickly come to hexagonal architecture. This architecture allows you to decouple the different parts of your application according to their core business and responsibility within it.

We recommend the following approach.

├── bin
│ └── main.dart
├── lib
│ ├── ui
│ │ ├── events
│ │ │ ├── ready_event.dart
│ │ │ └── message_create_event.dart
│ │ │
│ │ └── commands
│ │ └── foo_command.dart
│ │
│ ├── services
│ │ └── foo_service.dart
│ │
│ ├── data
│ │ ├── models
│ │ └── repositories
│ │
│ └── provider.dart
├── pubspec.yaml
└── .env

The above structure is an example that we recommend to help you adopt a modular, scalable and maintainable architecture by decoupling the different parts of your application as much as possible.

However, it will not always suit your business needs and will need to be adapted accordingly.

  • ui: Contains the various parts of your application which are related to your business, including events and commands.
  • services: Contains the services which allow you to manipulate the data in your application; they will generally be used from the ui.
  • data: Contains the DTOs and repositories that allow you to manipulate the data in your application. An example of use is the use of a remote REST service to which you need to make HTTP calls.
  • provider: The entry point of your module who's call under the main file.

Hexagonal architecture

When we talk about modular architecture, we quickly come to hexagonal architecture. This architecture allows you to decouple the different parts of your application according to their core business and responsibility within it.

We recommend the following approach.

├── bin
│ └── main.dart
├── lib
│ └── application
│ │ └── tickets
│ │ ├── commands
│ │ ├── events
│ │ └── ticket_provider.dart
│ │
│ ├── domain
│ │ └── tickets
│ │ ├── entities
│ │ ├── repositories
│ │ ├── dtos
│ │ └── contracts
│ │
│ └── infrastructure
│ └── tickets
│ ├── repositories
│ └── dtos
├── pubspec.yaml
└── .env

The previous structure is an example of an implementation based on hexagonal architecture. business context from the rest of the application or external services in order to make it more testable but also to remove any dependency on external services.

  • bin: Contains the entry point of your application.
  • application: Contains the various parts of your application which are related to your business, including events, commands, states or any mineral component.
  • domain: Contains the entities, DTOs, repositories, contracts that allow you to manipulate the data in your application. He contains the business logic of your application and must not depend on anything other than itself.
  • infrastructure: Contains implementations that must interact with external services such as APIs, BDDs and queues. Each implementation must implement a contract defined in the domain.

You can find a sample implementation of this architecture here