The domain layer is an *optional* layer that sits between the UI layer and the
data layer.
![When it is included, the optional domain layer provides dependencies to
the UI layer and depends on the data layer.](https://developer.android.com/static/topic/libraries/architecture/images/mad-arch-domain-overview.png) **Figure 1.** The domain layer's role in app architecture.

The domain layer is responsible for encapsulating complex business logic, or
simple business logic that is reused by multiple ViewModels. This layer is
optional because not all apps will have these requirements. You should only use
it when needed-for example, to handle complexity or favor reusability.
| **Note:** The term "domain layer" is used in other software architectures, such as "clean" architecture, and has a different meaning there. Don't confuse the definition of "domain layer" defined in the Android official architecture guidance with other definitions you may have read elsewhere. There may be subtle but important differences.

A domain layer provides the following benefits:

- It avoids code duplication.
- It improves readability in classes that use domain layer classes.
- It improves the testability of the app.
- It avoids large classes by allowing you to split responsibilities.

To keep these classes simple and lightweight, each use case should only have
responsibility over a single functionality, and they should not contain mutable
data. You should instead handle mutable data in your UI or data layers.
**Note:** The recommendations and best practices present in this page can be applied to a broad spectrum of apps to allow them to scale, improve quality and robustness, and make them easier to test. However, you should treat them as guidelines and adapt them to your requirements as needed.  

## Naming conventions in this guide

In this guide, use cases are named after the single action they're responsible
for. The convention is as follows:

*verb in present tense* + *noun/what (optional)* + *UseCase*.

For example: `FormatDateUseCase`, `LogOutUserUseCase`,
`GetLatestNewsWithAuthorsUseCase`, or `MakeLoginRequestUseCase`.

## Dependencies

In a typical app architecture, use case classes fit between ViewModels from the
UI layer and repositories from the data layer. This means that use case classes
usually depend on repository classes, and they communicate with the UI layer the
same way repositories do---using either callbacks (for Java) or coroutines (for
Kotlin). To learn more about this, see the [data layer
page](https://developer.android.com/jetpack/guide/data-layer).

For example, in your app, you might have a use case class that fetches data from
a news repository and an author repository, and combines them:  

    class GetLatestNewsWithAuthorsUseCase(
      private val newsRepository: NewsRepository,
      private val authorsRepository: AuthorsRepository
    ) { /* ... */ }

Because use cases contain reusable logic, they can also be used by other use
cases. It's normal to have multiple levels of use cases in the domain layer. For
example, the use case defined in the example below can make use of the
`FormatDateUseCase` use case if multiple classes from the UI layer rely on time
zones to display the proper message on the screen:  

    class GetLatestNewsWithAuthorsUseCase(
      private val newsRepository: NewsRepository,
      private val authorsRepository: AuthorsRepository,
      private val formatDateUseCase: FormatDateUseCase
    ) { /* ... */ }

![GetLatestNewsWithAuthorsUseCase depends on repository classes from the
data layer, but it also depends on FormatDataUseCase, another use case class
that is also in the domain layer.](https://developer.android.com/static/topic/libraries/architecture/images/mad-arch-domain-usecase-deps.png) **Figure 2.** Example dependency graph for a use case that depends on other use cases.

## Call use cases in Kotlin

In Kotlin, you can make use case class instances callable as functions by
defining the `invoke()` function with the `operator` modifier. See the following
example:  

    class FormatDateUseCase(userRepository: UserRepository) {

        private val formatter = SimpleDateFormat(
            userRepository.getPreferredDateFormat(),
            userRepository.getPreferredLocale()
        )

        operator fun invoke(date: Date): String {
            return formatter.format(date)
        }
    }

In this example, the `invoke()` method in `FormatDateUseCase` allows you to
call instances of the class as if they were functions. The `invoke()` method is
not restricted to any specific signature---it can take any number of parameters
and return any type. You can also overload `invoke()` with different signatures
in your class. You'd call the use case from the example above as follows:  

    class MyViewModel(formatDateUseCase: FormatDateUseCase) : ViewModel() {
        init {
            val today = Calendar.getInstance()
            val todaysDate = formatDateUseCase(today)
            /* ... */
        }
    }

To learn more about the `invoke()` operator, see the [Kotlin
docs](https://kotlinlang.org/docs/operator-overloading.html#invoke-operator).

## Lifecycle

Use cases don't have their own lifecycle. Instead, they're scoped to the class
that uses them. This means that you can call use cases from classes in the UI
layer, from services, or from the `Application` class itself. Because use cases
shouldn't contain mutable data, you should create a new instance of a use case
class every time you pass it as a dependency.

## Threading

Use cases from the domain layer must be *main-safe*; in other words, they must
be safe to call from the main thread. If use case classes perform long-running
blocking operations, they are responsible for moving that logic to the
appropriate thread. However, before doing that, check if those blocking
operations would be better placed in other layers of the hierarchy. Typically,
complex computations happen in the data layer to encourage reusability or
caching. For example, a resource-intensive operation on a big list is better
placed in the data layer than in the domain layer if the result needs to be
cached to reuse it on multiple screens of the app.

The following example shows a use case that performs its work on a background
thread:  

    class MyUseCase(
        private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
    ) {

        suspend operator fun invoke(...) = withContext(defaultDispatcher) {
            // Long-running blocking operations happen on a background thread.
        }
    }

## Common tasks

This section describes how to perform common domain layer tasks.

### Reusable simple business logic

You should encapsulate repeatable business logic present in the UI layer in a
use case class. This makes it easier to apply any changes everywhere the logic
is used. It also allows you to test the logic in isolation.

Consider the `FormatDateUseCase` example described earlier. If your business
requirements regarding date formatting change in the future, you only need to
change code in one centralized place.
| **Note:** In some cases, logic that can exist in use cases could instead be part of static methods in `Util` classes. However, the latter is discouraged because `Util` classes are often hard to find and their functionality is hard to discover. Furthermore, use cases can share common functionality such as threading and error handling in base classes that can benefit larger teams at scale.

### Combine repositories

In a news app, you might have `NewsRepository` and `AuthorsRepository` classes
that handle news and author data operations respectively. The `Article` class
that `NewsRepository` exposes only contains the name of the author, but you want
to display more information about the author on the screen. Author information
can be obtained from the `AuthorsRepository`.
![GetLatestNewsWithAuthorsUseCase depends on two different repository
classes from the data layer: NewsRepository and AuthorsRepository.](https://developer.android.com/static/topic/libraries/architecture/images/mad-arch-domain-multiple-repos.png) **Figure 3.** Dependency graph for a use case that combines data from multiple repositories.

Because the logic involves multiple repositories and can become complex, you
create a `GetLatestNewsWithAuthorsUseCase` class to abstract the logic out of
the ViewModel and make it more readable. This also makes the logic easier to
test in isolation, and reusable in different parts of the app.  

    /**
     * This use case fetches the latest news and the associated author.
     */
    class GetLatestNewsWithAuthorsUseCase(
      private val newsRepository: NewsRepository,
      private val authorsRepository: AuthorsRepository,
      private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
    ) {
        suspend operator fun invoke(): List<ArticleWithAuthor> =
            withContext(defaultDispatcher) {
                val news = newsRepository.fetchLatestNews()
                val result: MutableList<ArticleWithAuthor> = mutableListOf()
                // This is not parallelized, the use case is linearly slow.
                for (article in news) {
                    // The repository exposes suspend functions
                    val author = authorsRepository.getAuthor(article.authorId)
                    result.add(ArticleWithAuthor(article, author))
                }
                result
            }
    }

The logic maps all items in the `news` list; so even though the data layer is
main-safe, this work shouldn't block the main thread because you don't know how
many items it'll process. That's why the use case moves the work to a background
thread using the default dispatcher.
| **Note:** The [Room library](https://developer.android.com/training/data-storage/room) lets you query [relationships](https://developer.android.com/training/data-storage/room/relationships) between different entities in a database. If the database is the [source of
| truth](https://developer.android.com/jetpack/guide/data-layer#source-of-truth), you can create a query that does all that work for you. In that case, it's better to create a repository class like `NewsWithAuthorsRepository` instead of a use case.

## Other consumers

Apart from the UI layer, the domain layer can be reused by other classes such as
services and the `Application` class. Furthermore, if other platforms such as TV
or Wear share codebase with the mobile app, their UI layer can also reuse use
cases to get all the aforementioned benefits of the domain layer.

## Data layer access restriction

One other consideration when implementing the domain layer is whether you should
still allow direct access to the data layer from the UI layer, or force
everything through the domain layer.
![UI layer cannot access data layer directly, it must go through the Domain layer](https://developer.android.com/static/topic/libraries/architecture/images/mad-arch-domain-data-access-restriction.png) **Figure 4.** Dependency graph showing UI layer being denied access to the data layer.

An advantage of making this restriction is that it stops your UI from bypassing
domain layer logic, for example, if you are performing analytics logging on each
access request to the data layer.

However, the **potentially significant disadvantage** is that it forces you to
add use cases even when they are just simple function calls to the data layer,
which can add complexity for little benefit.

A good approach is to add use cases only when required. If you find that your UI
layer is accessing data through use cases almost exclusively, it may
make sense to *only* access data this way.

Ultimately, the decision to restrict access to the data layer comes down to your
individual codebase, and whether you prefer strict rules or a more flexible
approach.

## Testing

[General testing guidance](https://developer.android.com/training/testing) applies when testing the domain
layer. For other UI tests, developers typically use fake repositories, and it's
good practice to use fake repositories when testing the domain layer as well.

## Samples

The following Google samples demonstrate the use of the domain layer.
Go explore them to see this guidance in practice:

## Recommended for you

- Note: link text is displayed when JavaScript is off
- [Data layer](https://developer.android.com/topic/architecture/data-layer)
- [UI State production](https://developer.android.com/topic/architecture/ui-layer/state-production)