Reader small image

You're reading from  Kickstart Modern Android Development with Jetpack and Kotlin

Product typeBook
Published inMay 2022
Reading LevelBeginner
PublisherPackt
ISBN-139781801811071
Edition1st Edition
Languages
Right arrow
Author (1)
Catalin Ghita
Catalin Ghita
author image
Catalin Ghita

Catalin Ghita is a Udemy Instructor and an Android Engineer proficient in Native Android Development, while also being active in Cross-platform development with React-Native and Flutter. He successfully built, deployed, and maintained huge scalable apps with millions of downloads and active users for industry giants like Burger King, Carrefour or Bankinter. He is designated to architect huge applications into scalable, maintainable and testable form and shapes. As the owner of the Coding Troops blog and Udemy instructor, he wrote articles and taught courses reaching tens of thousands of students, thereby exposing and clarifying concepts and subtleties on hot topics in Android.
Read more about Catalin Ghita

Right arrow

Chapter 8: Getting Started with Clean Architecture in Android

In this chapter, we're continuing our journey of improving the architectural design of the Restaurants application.

More specifically, we will try to adopt some design decisions from the well-known Clean Architecture. Clean Architecture is a software design philosophy that tries to create projects with the best level of the following:

  • Separation of concerns
  • Testability
  • Independence of frameworks or libraries used in peripheral layers, such as the UI or Model layer

By doing so, Clean Architecture tries to allow the business parts of our applications to adapt to changing technologies and interfaces.

Clean Architecture is a very broad and complex topic, so, in this chapter, we will try to focus only on establishing a better separation of concerns by separating existing layers even further, but more importantly, by defining a new layer called the Domain layer.

In this chapter, we will on...

Technical requirements

Building Compose-based Android projects for this chapter usually requires your day-to-day tools. However, to follow along smoothly, make sure you have the following:

  • The Arctic Fox 2020.3.1 version of Android Studio. You can also use a newer Android Studio version or even Canary builds, but note that the IDE interface and other generated code files might differ from the ones used throughout this book.
  • Kotlin 1.6.10 or a newer plugin installed in Android Studio
  • The Restaurants app code from the previous chapter

The starting point for this chapter is represented by the Restaurants application developed in the previous chapter. If you haven't followed the implementation from the previous chapter, access the starting point for this chapter by navigating to the Chapter_07 directory of the repository and importing the Android project titled chapter_7_restaurants_app.

To access the solution code for this chapter, navigate to the Chapter_08...

Defining the Domain layer with Use Cases

So far, we've talked about the Presentation layer (with UI and presentation logic) and the Model layer (with data logic). Yet, apart from these two layers, most of the time, applications also encapsulate a different type of logic, different from UI, presentation, or data logic.

To identify this type of logic, we must first acknowledge that most applications have a dedicated business scope – for example, a food delivery application could have the business scope of taking orders and generating revenue for the stakeholder. The stakeholder is the entity interested in the business, such as the company that owns the restaurant chain.

Such applications can contain business rules imposed by the stakeholders that can vary from minimum order amounts, custom availability ranges for certain restaurants, or predefined time frames for different delivery charges; the list could go on. We can refer to such business rules that are dictated...

Separating the Domain model from Data models

Inside the Domain layer, apart from Use Cases, another essential business component in our app is the Domain model component. The Domain model components are those classes that represent core business data or concepts used throughout the application.

Note

Since the Domain models reside inside the Domain layer, they should be agnostic of any third-party library or dependency – ideally, they should be pure Java or Kotlin classes.

For example, in our Restaurants app, the core entity used throughout the app (retrieved, updated, and displayed) is the Restaurant data class, which contains data such as title and description.

If we think about it, our Restaurants app's core business entity is represented by the restaurant itself: that's what the application is about, so it's only natural that we would consider the Restaurant class as a business entity.

Note

In Clean Architecture, Domain model classes are often...

Creating a package structure

Our Restaurants app has come a long way. As we tried to separate responsibilities and concerns as much as possible, new classes emerged – quite a few actually.

If we have a look on the left of Android Studio, on the Project tab, we have an overview of the classes we've defined in our project.

Figure 8.5 – Project structure without any package structuring strategy

It's clear that our project has no folder structure at all – all files and classes are tossed around inside the restaurantsapp root package.

Note

The name of the root package might differ if you selected a different name for your app.

Because we've opted to throw any new class inside the root package, it's difficult to have clear visibility over the project. Our approach is similar to adding dozens of files and assets on the desktop of our PC – in time, it becomes impossible to find anything on the screen.

To...

Decoupling the Compose-based UI layer from ViewModel

Our UI layer (represented by the composable functions) is tightly coupled to the ViewModel. This is natural, since the screen composables instantiate their own ViewModel to do the following:

  • Obtain the UI state and consume it
  • Pass events (such as clicking on a UI item) up to the ViewModel

As an example, we can see how the RestaurantsScreen() composable uses an instance of RestaurantsViewModel:

@Composable
fun RestaurantsScreen(onItemClick: (id: Int) -> Unit) {
    val viewModel: RestaurantsViewModel = viewModel()
    val state = viewModel.state.value
    Box(…) { … }
}

The problem with our approach is that if we want to later test the UI layer, then, inside the test, the RestaurantsScreen composable will instantiate RestaurantsViewModel, which in turn will get data from Use Case classes, which in turn will trigger heavy I/O work...

Summary

In this chapter, we have dipped our toes into Clean Architecture in Android. We started by understanding a bit about what Clean Architecture means and some of the best ways we can achieve this in our Restaurants app, while also covering the main benefits of following such a software design philosophy.

We started with Clean Architecture in the first section, where we defined the Domain layer with Use Cases, and continued refactoring in the second section, where we separated the Domain model from Data models.

Then, we improved the architecture of the app by creating a package structure and by decoupling the Compose-based UI layer from the ViewModel classes even further.

In the next chapter, we will continue our journey of improving the architecture of our application by adopting dependency injection.

Further reading

Clean Architecture is a very complex subject, and one chapter is simply not enough to cover it. However, one of the most important concepts that Clean Architecture brings is the Dependency Rule. The Dependency Rule states that within a project, dependencies can only point inward.

To understand what the Dependency Rule is about, let's visualize the layer dependencies of our Restaurants app through a simplified version of concentric circles. Each concentric circle represents different areas of software with their corresponding layer dependencies (and libraries).

Figure 8.7 – The Dependency Rule with layers and components

This representation dictates that implementation details should be placed in outer circles (just as Compose is an implementation detail of the UI layer or Retrofit is an implementation detail for the Data layer), while business policies (Use Cases from the Domain layer) are placed within the inner circle.

The...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Kickstart Modern Android Development with Jetpack and Kotlin
Published in: May 2022Publisher: PacktISBN-13: 9781801811071
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Catalin Ghita

Catalin Ghita is a Udemy Instructor and an Android Engineer proficient in Native Android Development, while also being active in Cross-platform development with React-Native and Flutter. He successfully built, deployed, and maintained huge scalable apps with millions of downloads and active users for industry giants like Burger King, Carrefour or Bankinter. He is designated to architect huge applications into scalable, maintainable and testable form and shapes. As the owner of the Coding Troops blog and Udemy instructor, he wrote articles and taught courses reaching tens of thousands of students, thereby exposing and clarifying concepts and subtleties on hot topics in Android.
Read more about Catalin Ghita