Architecture Learnings Part #3 {What is in a Domain?}

Hitesh Das
5 min readJul 10, 2020

In the last two articles we read about how to model a Model and how Model changes can make a View to react. If you have not read the first two parts yet, I would recommend you to read them first to get an overview of this Architecture Learnings series.

In this article, we will read about the heart of Architecture Design. i.e Domain. We will also focus on on the design principles while defining the Domain layer.

So, what is in a Domain …

In simple words, Domain layer is where your business rules and logic resides. The Domain layer implements business logic to be provided to the application or presentation layer.

So, while designing the Domain layer of your project, following design principles must be followed.

  1. Stick to a design standard.
  2. Should be Platform Agnostic.
  3. Keep away technical implementation details.

Sticking to a design standard makes a project looks like a unique unit to all that are involved in its day to day development and maintenance. A uniform design standard makes your code more readable and manageable. Also, it boosts interoperability and reduces integration efforts when a new feature is plugged in.

Domain entities should be Platform Agnostic. They should not be coupled to any process definition or platform; the objects created by Domain or Domain objects should be potentially reusable across all platforms.

Domain Layer = Platform Agnostic

A common error while addressing a business problem, is to put technology concepts into the Domain layer. For example, a database. Database is just a persistent representation of Domain entities. A Domain entity does not exist because it is the ORM of a database table! UI technologies, data persistence in general, and vendor platforms are top layers or components used for the scope of a project. Keeping away technical implementation details while designing the Domain layer helps in intrinsically agnostic design.

Domain Layer ≠ Technology’s details

Now, that we know how to design the Domain layer, let’s discuss the classification of the Domain layer.

  1. Domain Entities — They represents the Business objects, Attributes and their Relationships. e.g a LinkedInPost, Article etc.
  2. Domain Services — This gives an abstraction for certain features that can be managed differently depending on the environment that will use the Domain layer. e.g Tracking, Logging, Storage etc…
  3. Domain Logic — This represents the implementation of logic linked to the business objects, such as validation rules or aggregation of different business objects with some business strategies. Let’s call this an UseCase.

Now let’s try to design a Domain layer with a simple example.

“Load a list of articles with some user information in each article”

Which network client will I use to make the request ? I will use my favourite database to store the Post and User information… How will UI look like ? etc etc…

A lot of such questions, and probably many technical solutions might come across our mind and we may jump to the solution too. Quite first common thoughts and tendency as a smart IT guy we often have!

Remember, Principle #3 we should keep away technical implementation details while designing the Domain layer.

So, let’s start…

Strategy — By defining a correct and strict dependency rules we design our Domain not to have any dependency on any other layers. i.e Presentation and Data Layers. Due to number of dependencies to any Platform Library the Domain Layer should be a pure native module.(can be written in pure Java or Kotlin language)

Defining our Domain Entities — From the problem statement, we can define two entities here viz. User and Article, which can be easily identified by their unique ids and relations between them.

data class User(val userId: String, val name: String) data class Article(val articleId: String, val title: String, val userId: String)

Defining the Abstractions — The Repositories. Let’s call them an ArticleRepository and a UserRepository. Both of them will be defined as interfaces. Domain do not depend on Data . Its data that implements the abstractions to give real implementations.

interface ArtileRepository {  fun get(): List<Article>}interface UserRepository {  fun get(): List<User>}

And, finally the

Domain Logic — The UseCase. Let’s call it an ArticleListUseCase that uses both ArticleRepository and UserRepository to create a combined object with article and user details.

data class ArticleWithUserName(val userName: String, val title: String)class ArticleListUseCase(private val userRepository: UserRepository, private val articleRepository: ArticleRepository) { fun get(): List<ArticleWithUserName> { val userList = userRepository.get()  val articleList = articleRepository.get()  // Some Busineess Logic to combine both the lists.  return combineList(userList, articleList)}

( You can definitely fetch the data asynchronously from the repositories using Rx or Coroutines)

Voila! , we created our Domain layer for the given problem statement. The list of articles generated by our Domain layer above is intrinsically agnostic and could be now displayed in Android, iOS, Web or even Terminal.

Now it’s time to introduce Uncle Bob’s clean architecture diagram.

Application and Data Layers are outer layers since they are only implementations and can be easily replaced. They do not constitute the core of the business problem. It’s the Domain that represents the core of our program.

Layers that lie outwards on the circle are prone to change. Hence, solution driven by Presentation or Data layer is susceptible to changes and it makes it hard to to replace or bridge with different sources in future.

Always aim for a Domain driven design that will scale as your application grows in future.

Conclusion

In this article, we saw the importance of the Domain layer in architecture. Also, for those who haven’t tried Clean Architecture yet, the introduction of the Domain layer will definitely avoid fat Presentation layers. The Presentation Layer will only call Domain logic and updates the View Model to which our View will react. Thus, improving the readability, pluggability, debuggability and testability of the application.

In the next part of the architecture learning series, we will compare different architecture models MVC — MVP — MVVM — MVI.

Stay tuned…

--

--

Hitesh Das

Mobile Apps Engineering "When we share, we open doors to a new beginning”