AWS Serverless Refactoring Series: How to Move to Clean Architecture?
This is Part 1 of the AWS Serverless Refactoring Series, where I refactor the default AWS Serverless Application template to a more maintainable and easy to extend architecture.
Separate projects help separate concerns.
Clean Architecture is a popular way to organize code and separate projects. It has different names like Onion Architecture, Hexagonal Architecture, Ports and Adapters, etc.
They all have the same goal! Separating the software into layers and thereby separating concerns.
Dependencies in Clean Architecture all point inwards. The outer layer code can know (or reference) the inner layer code (or DLL). The code in the inner layer cannot know anything about the outer layer code.
Functions.cs class currently handles mixed concerns. It interacts with the AWS Infrastructure, Creates Domain Objects, and saves them to an external DynamoDB database.
To refactor the project template into the Clean Architecture, let’s first add two projects.
- MyApplication.Domain → Holds all Domain-related logic
- MyApplication.Infrastructure → Holds Infrastructure-related logic. e.g. DynamoDB
Following the diagram above, the Domain project is at the core of everything. Hence it does not have any other dependencies.
MyApplication.Infrastructure project has a dependency on the Domain project. The Domain project defines the interfaces to interact with the Infrastructure. It is an example of Dependency Inversion Principle.
Dependency Inversion Principle states that Higher Level Modules should not depend on Lower Level Modules
Whenever the Dependency Inversion Principle is applied, the interface ownership also gets reversed. The client owns the interface when this happens.
Implementations for these interfaces are in the Infrastructure project. Hence it takes in a dependency of the Domain.
[MyApplication.Host](http://myapplication.Host) project depends on both the Infrastructure and Domain projects. It is the Composition Root.
*A Composition Root is the unique location in the application, where the modules are composed together.*
The Composition Root is the appropriate place to set up Dependency Injection Container. It needs references to all projects to set up the dependencies.
Blog.cs currently acts as a Data Transfer Object (DTO).It only has data properties and does not have any behavior.
Since this application is about Blogs, let’s move this class into the Domain Project.
Let’s add it to the Entities folder.
Blog.cs under the Host project and update the namespaces across the solution.
This being a Refactoring example, I will not change any existing functionality of the application. However, as you find functionality realted to Blog, move them to this class.
We have the basic structure required for our AWS Serverless application.
In the next post, we will start extracting the functionality from
Functions.cs class and moving it across to these new projects.