Opinionated example of how you can apply SOLID principles and CA to UI Web development. Based on Uncle Bob Martin Clean Architecture and Functional Design books.
You will see UseCases, Entities, Presenters, Controllers, inverted dependencies etc.
And TESTS of course - simple, fast Developer tests (as Kent Beck commanded).
(experiment: copy pasted tests just to make plenty of them and ran)
Used mocha/chai
for testing (you prefer jest
- you are my enemy).
The examples are not intended to be "true" FP, since true FP is readable only to chosen ones.
The examples are not intended to be "true" OOP. Because... because!
The intent is make it conceivable to everyone.
Caution
VERY DRAMATICALLY SUPER IMPORTANT NOTE:
If you don't like something - I don't care...
If you have better ideas (unlikely) - create a PR and prepare to fight.
The project contains core module and it's integration to the different ui frameworks, like react, angular, vue etc. There is also pure native example.
It showcases how you can split business logic not only from view, but also from framework(!) and even platform (yes there is react-native integration).
- Usecases and Entities can be found in core (order, order-list). There are also simple presenters examples.
- Simple inverted dependency examples are in core/src/dummy-dependencies.
- More complex presenter example is here.
- Usecases and entities are written in procedural style. On UpdateOrderList usecase example you can see alternative FP or OOP style. Style doesn't really matter.
Note
For holding state the Atom is used.
It really doesn't matter what you are using under the hood.
You just need some util to rerender view when presentation changes by a UseCase.
It can be existing tool or you can implement yours, the bestest and perfect one.
Note
UI is primitive, because I'm not going to waste time on styles; only structure and use cases matter.
But your are welcome to PR better styles.
Caution
Not all examples are already integrated. Why? Because you didn't pay me for that.
To run example locally, clone repo, then navigate to example you are interested in (i.e. packages/react-example
). Then:
npm i
npm start
See instructions in terminal.
Rough UML diagram of the project architecture:
Note that all arrows cross the App boundary inwards. This means everything is dependent on business logic.
This is acheived by Dependency Inversion.
This allows easy testing, since any inverted dependency can be substituted by a test double.
Also there is no need to render markup and simulate events for executing a UseCase. It can be simply called from the test suite.
Workflow diagram of the abstraction interactions:
- [abstractionName]? means abstraction can be omitted for some reason. e.g. controller can be so simple and degenerate that it would be unreasonable to abstract it from a framework.
- "framework controller" means a file where you usually bind view to the data and handlers.
e.g.
.jsx
file where you write functional component for React or[name].component.ts
file for Angular. In this project for consistency between frameworks those files are placed to the[component-name]
folder and calledindex.[js|ts|jsx|vue]
In this example I implement part of backoffice for the online store. I do not intend to cover all edge cases and implement fully functional online store admin app. I intend to implement practical example of several parts just as a showcase. The following user stories will give you an idea of what is covered.
User should see list of the orders (first page) and total order count.
Each order should contain id, created date, customer name, sum, payment status, fulfillment status.
While loading the orders, user should see some indication of that.
User should be able to open the order to see its details.
User should be able to remove order from the list.
Removal should be confirmed by user.
While removing, user should not be able to interact with the order.
User should be able to load next batch of the orders
(It might be infinite scroll or pagination, doesn't really matter)
User should be able to refresh order list in order to see current order data
User see all order details.
User should be able to change allowed fields.
For now those are: payment status, fulfillments status, shipping address.
User should be able to save changed order.
User should be able to close order.
Closing should be confirmed by user.