Consider below is the business use case shared by a business team on which this sample application is built :
- Receive request to create a new Loan (car/housing)
- Check if customer is fraud or not
- if fraud, don't create a new loan, respond with error
- if not fraud, create a new Loan
- Save the loan to DataStore
- Respond with Loan information
- Entities - The place where our enterprise business rules resides (NOT a layer with just plain old java object having getters & setters - rather the actual behaviours/functions is encapsulated, if following DDD this is the place where the domain concepts resides)
- UseCases - The place where our application business rules resides, which controls the dance of Entities
- InterfaceAdapters - The place where implementation for database, http call , interfaces defined in UseCase resides
- Drivers - The place where all the independent components are stitched together to form an application (web)
- Functional-tests - The place where all high-level functional(business use cases) integration tests reside
- Integration-tests - The place where all technical (database/rest integration, retries, timeout etc.) integration tests reside
Clear boundaries defined :
- Entities doesn't know anything about its outer circles (i.e UseCases, InterfaceAdapters, configurations layer).
- UseCases doesn't know anything about its outer circles (i.e InterfaceAdapters, configurations layer), but knows about its inner circles (i.e Entities)
- InterfaceAdapters doesn't know anything about its outer circles (i.e Drivers), but knows about its inner circles (i.e Entities, UseCases layer)
- Drivers doesn't know anything about Functional-test/Integration-test, but knows about its inner circles (i.e InterfaceAdapters, Entities, UseCases layer)
- Functional-tests know every layer
- Integration-tests know every layer
- Entities & UseCases layers are central and every other layers support them - which means our application is purely driven by business aspects and not from technical perspective
- Easy maintenance -
- Separation of concerns of,
- business vs technical
- framework dependent vs framework in-dependent
- unit tests vs integration tests vs functional tests
- Separation of concerns of,
- Refactor friendly - Easy to refactor applications (consider scenarios of getting rid of frameworks like reactor/springboot, and this can be done without affecting the domain layers )
- Independent of external interactions - Changes in the external http contract or database doesn't affect the Entities & UseCases (unless its required to update the domain with business logics)
- Evolving architecture -
- Domain is evolved free from the external dependencies
- The rate at which the entity/usecases evolve (more frequent ?) as compared to interfaceadapters/drivers (less frequent ?) are totally different.
Development flow :
This application is used for demo purpose, hence exhaustive test cases/exception handling etc are not covered in the applications.
https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/