Applying clean architecture to a react codebase brings lots of benefits, most of them you can find by simple googling what's clean architecture and what should we adopt architectural patterns.
One advantage that strikes me is having business rules isolated from framework specific things. This means that our core logic is not coupled to React, React Native, Express, etc...
This gives you enough flexibility to, for example, move specific parts of the application to a backend, change libraries without too much pain, test once and reuse as many times as you want, share code between React and React native applications, among others.
This is a realistic approach, what I mean by that is: It's simple enough to be applicable and Robust enough to have it in a production environment.
Although I have greatly simplified it, for educational purposes, I believe that this example is of great value to get you started with applying architectural patterns and adapting them to your own needs.
I've been pretty busy lately, so I'll write as much as possible.
I'll write three blog posts explaining better saying What is Clean Architecture, Why adopt it and how.
Portuguese version of How to implement clean architecture for React codebases can be found HERE
The nomenclature may vary, but the concept behind this architectural pattern is: the domain dictates how tools should be organized and not the other way around. What I mean by that is that we should organize our codebase around the business rules and not around the frameworks we use to achieve business rules. The diagram above shows how the dependency rule works, the inner circles must not know about the outer circles. That is, there cannot be an import of a use case within an entity, or import of a framework within a use case. Another important rule is: entities and use cases should not rely on external libraries. The explanation is simple, the core of our application must be robust enough and malleable enough to meet the demands of the business without needing any external intervention. If by chance, an essential part of the application core MUST BE an external dependency. Dependency needs to be modeled following dependency inversion principle.
- Entity: Application independent business rules
- Interactor: Application especific business rules
- Adapter: Glue code from/to interactors and presenter, most of the time implementing a framework specific behaviour. e. g.: We have to connect interactor with react container, to do so, we have to connect interactor with redux (framework) and then connect redux to container components.
- Presenter: Maps data from/to adapter to/from components.
- Components: Simplest possible unit of presentation. Any mapping, conversion, MUST be done by presenter.
Talk is cheap, don't you think? That's why I'm sharing two sample apps to facilitate your digestion.
A great advantage of following clean architecture is having all business logic self-contained and closer, in a readable way.
Take a look at core/entities/
and core/useCases/
folders and see for yourself.
Counter app is a simple example of how to apply clean architecture to react world, it uses only synchronous actions and has no external dependencies.
It contains a single business rule:
- The counter can not be negative and can not be greater than 10.
Authentication app is a simple example, but no to simple, of how to apply clean architecture to a realistic scenario. It contains some shared business rules:
- Users must have a valid email.
- Users password cannot contains anything but numbers and letters.
- Users name must have full name, and it has to be lower case.
- The App cannot sign up two users with same email address.
- The app must use an external dependency to persist user register.
This repository contains 2 examples of how to implement react following clean architecture, both follow same folder structure which represents diagram showed above.
./counter
├── core
│ └── lib
│ ├── adapters
│ │ └── redux
│ ├── entities
│ ├── frameworks
│ └── useCases
├── native
│ └── src
│ ├── components
│ └── stylesheets
└── web
└── src
├── assets
├── components
└── stylesheets
Note: frameworks folder is basically framework setup to have it available to the adapters.
run npm install
under the project you'd like to run, and then run npm start
.
There's an issue related to how yarn/npm symlink file dependencies on windows. Due to this issue, you should first go under the core
module and run npm install
and npm run build
. This will make the core
module ready to be installed on the other modules.
- Clean Architecture: a craftsman's guide to software structure and design
- The clean architecture
- Agility and Architecture
- Github
- Presentational and Container Components
- Microsoft for provide a typescript react native starter kit.
- Will Monk for provide a typescript react starter kit.
If something looks odd, don't hesitate to reach me out or opening an issue.