Skip to content

me-zo/architecture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 

Repository files navigation

Application Architecture

The architecture that I follow my applications is based on two completely different architectures

  1. The Onion Architecture similar to the open source .NET application nopcommerce
  2. The Clean Architecture Course which is based on This Blog by Uncle Bob and is made by Reso Coder

Now these two architectures are similar in one aspect which is that they both aim to accomplish a Loosely Coupled Testable Code, and I am all about that.

Project Structure

├── lib
|   ├── app
│   │   ├── app_theme
│   │   │   ├── styles
|   |   |   └── themes.dart
|   |   └── localization
|   |   |   ├── resources
|   |   |   └── resources.dart
│   │   └── app.dart
|   ├── core    --> this layer containes classes that can be used throughout the app
|   |   ├── common
|   |   |   ├── models
|   |   |   └── widgets
|   |   ├── dependency_registrar
|   |   |   ├── feature_dependencies
|   |   |   └── dependencies.dart
|   |   ├── errors
|   |   |   ├── errors.dart
|   |   |   └── error_handler.dart
|   |   ├── fixtures
|   |   ├── helpers
|   |   ├── cache
|   |   └── network
|   ├── data 
|   |   ├── entities    --> models to communicate with databases grouped by relevance
|   |   ├── dtos    --> models to communicate with APIs grouped by relevance
|   |   ├── repositories    --> uses classes from core to get data from data sources
|   |   |   └── *    --> sample repository
|   |   |       ├── *_repository.dart   --> abstract class
|   |   |       └── *_repository_impl.dart --> its default implementation
|   |   └── Shared_preferences  --> app-wide Notifiers such as settings, and permissions 
|   ├── features    --> containes a list of features
|   |   └── home    --> sample feature
|   |   |   ├── domain    
|   |   |   |   ├── models    --> models that communicate data between service and UI
|   |   |   |   └── service    --> uses classes from core and data to present in UI
|   |   |   |       ├── home_service.dart   --> abstract class
|   |   |   |       └── home_service_impl.dart --> its default implementation
|   |   |   └── presentation  
|   |   |       ├── manager    --> a cubit/bloc/provider plus a function_home.dart for further refactoring
|   |   |       ├── screens    --> screens inside a feature (each screen in a single file unless it containes a common widget from multiple features)
|   |   |       └── home_page.dart    --> a widget that has a route name (basically an enterance to the feature that can be used in other features)
|   |   └── route_generator.dart    --> to navigate between features
│   └── main.dart
├── pubspec.lock
├── pubspec.yaml

The Dependency Rule

following The Blog by Uncle Bob

The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.
The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle. That includes, functions, classes. variables, or any other named software entity.
By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generate by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles.

The Core Layer

As noted above in the Project Structure this layer can be accessed by the entire application and here are few examples of this:

  1. An HTTP Client that handles http calls => used in data layer
  2. A Common helper that uses regex expressions to validate Strings => used in presentation layer

The Data Layer

Following the Project Structure this layer is reponsible for dealing with data sources such as Local/Remote Databases, and APIs through using classes from the core layer only and example of that: Lets say Here we are getting data from a local database and as you can see we are returning an entity so when this method is used we have to fill or map it to a model object in order to pass it through the Domain to the presentation layer.

The Features Layer

This is the outmost layer in the application it is a combination of the domain and the presentation layers which leads me to the feature based development side of the application.

Feature Based Development

Noted in the Clean Architecture Course Provided By Reso Coder feature based development allows us to have an application that is Open To Expansion. What do I mean by this ? Well as an application grows the development pace usually slows down due to the complication increase in the code so the solution we came up with was to seperate related parts of the application together in features giving us more flexiblity so that we can add more features without having to warry about references and other complication in other words following the Open-Closed Principle this leads us to a Stable Productivity as denoted by Uncle Bob in Lesson 3 of Clean Code

Why Develop This "ResoOnion" :) Architecture ?

As you may have noticed I kept refering to a few resources that i believe are trying to achieve the same goal as I do.

  • From my experience (developing apps containing 10+ features) the Clean Architecture Course have proved to be quiet slow and incomplete for few reasons:
  1. every feature has all three layers and this nigates the DRY (Don't Repeat yourself) principle. Lets say we have two features calling the same data source but process the data differently this way you would either have to make one feature depend on another or duplicate the code in the data source which made lifting the Data Layer up more reasonable.
  2. every time you want to process an input or view an output you have to create a use case class and use its call method only this might not sound like a big deal but trust me it becomes a nightmare pretty quickly so it made sense to replace it by directly calling the service associated with the feature.
  3. entities were replaced by models to avoid confusion when dealing with databases and models where replaced by DTOs(for data connecting with APIs) and Entities(for data connecting with Databases), plus other changes that just made sense.

Samples

  1. E-Invoice QR Code Reader (Works Locally with Local Database)
  2. Movies Flutter App (Connects to the Internet with an API )

Note: This architecture should work with any object-oriented Language not just dart i just happened to have an implementation in dart so Please feel free to share with me an Implementation in other languages that should be interesting

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published