Full width home advertisement

Post Page Advertisement [Top]

 Most developers overcomplicate clean architecture.

They create layers before features.
They build repositories before logic exists.
They create files for future problems.

Instead, let’s build one small but real feature.

A dark mode toggle.

It looks small.
But it is very practical.
And it helps you truly understand how clean architecture works.

In this guide, we will build this feature step by step.
We will place each piece in the correct layer.
And understand why it belongs there.

By the end, you will not just have a toggle.
You will understand how to structure features properly.






Watch step-by-step video down below:

Step 1 — Start With an Empty Project

Create a new project with an empty Compose activity.

Name it something simple like:

Dark Mode Clean Architecture

Remove boilerplate code.
Remove unnecessary scaffolds.

Start clean.


Step 2 — Create Only the Main Layers

Before writing any feature logic, create four packages:

  • data

  • domain

  • presentation

  • di

That’s it.

No repositories yet.
No use cases yet.
Just structure.





Clean architecture has three core layers:

  • Presentation

  • Domain

  • Data

DI is just wiring.


Step 3 — Build the UI First (Presentation Layer)

Inside the presentation layer:

Create:

  • screens/home

  • HomeScreen

  • HomeState

  • HomeAction

  • HomeViewModel

The HomeScreen contains:

  • A title

  • A label “Dark Mode”

  • A Switch

At this stage, it only toggles UI state.

No persistence yet.

This is important.

You build UI behavior first.
Then connect logic.






Step 4 — Add State and Action

State represents what changes on screen.

HomeState:

  • isDarkModeEnabled: Boolean

Action represents what user does.

HomeAction:

  • OnDarkModeToggled(Boolean)

The ViewModel:

  • Holds StateFlow

  • Exposes state

  • Handles onAction

When the switch changes, state updates.

Now the UI reacts.

This is clean presentation logic.


Step 5 — Make It Persistent (Domain Layer)

Right now, if you close the app, dark mode resets.

So we move to domain.

Create:

  • model/ThemeSetting

  • repository/ThemeRepository

  • usecase/GetThemeSettingUseCase

  • usecase/UpdateThemeSettingUseCase

Domain defines:

  • What the app needs

  • Not how it works

ThemeRepository is an interface.

It defines:

  • getThemeSetting()

  • updateThemeSetting()

No implementation here.

Just rules.






Step 6 — Implement in Data Layer

Now we move to data.

Here we implement:

  • ThemeRepositoryImpl

  • PreferenceDataSource

  • DTO models

Data layer uses:

SharedPreferences

Important concept:

Data models and Domain models are not the same.

Even if they look similar.

Data layer works with DTO.
Domain works with pure business model.

This separation keeps flexibility.

If storage changes later, domain does not break.


In repository implementation we convert data model into domain as seen in above screenshot.


Step 7 — Handle Coroutine Cancellation Properly

Inside repository implementation:

Always rethrow CancellationException.

Many developers forget this.

If you catch all exceptions blindly, coroutines will not cancel properly.

Clean architecture also means correct coroutine handling.


Step 8 — Wire Everything With Dependency Injection

Now connect everything using DI.

Use Koin.

Initialize:

  • SharedPreferences

  • PreferenceDataSource

  • ThemeRepositoryImpl

  • UseCases

  • ViewModel

DI connects:

Data → Domain → Presentation

No layer directly knows implementation details.



Step 9 — Test the Feature

Run the app.

Turn on Dark Mode.
Close the app.
Open it again.

Dark mode stays enabled.

Now you have:

  • One screen

  • One ViewModel

  • Two use cases

  • One repository

  • One data source

Nothing extra.


The Real Lesson

Architecture should grow with features.

Not before features.

We did not create:

  • Multiple repositories

  • Unused abstractions

  • Fake future layers

We built one real feature.

And the architecture formed naturally around it.


Final Thoughts

Clean architecture is not about folders.

It is about responsibility.

  • Presentation handles UI

  • Domain handles business rules

  • Data handles persistence

  • DI wires everything

Build small.
Build real.
Let architecture evolve with your app.

If you want the starter blueprint used for projects like this, keep a reusable structure template and start every project from there.

Download starter blueprint: https://codingreel.gumroad.com/l/clean-arch-cr

Clean architecture is not scary.

It is structured thinking.

And it becomes simple once you build it feature by feature.

No comments:

Post a Comment

Share your thoughts ...

Bottom Ad [Post Page]