Clean Architecture Clean Architecture in english Software Architecture Software Development

Clean Architecture Data Sources: Part 05

February 8, 2026 · khokanuzzamankhokan@gmail.com

Clean Architecture Data Sources: Part 05

Data Sources: Connecting Your App to the Outside World

In our previous article, we introduced the Repository as a gateway. But where does that gateway lead? Today, we explore Clean Architecture Data Sources—the actual endpoints where your app talks to the internet or the phone’s storage.

What are Data Sources?

A Data Source is the lowest level of your Data Layer. Its only job is to perform the “CRUD” (Create, Read, Update, Delete) operations on a specific platform. Generally, we divide these into two categories:

  1. Remote Data Source: Handles network requests (e.g., calling a REST API using http or dio).
  2. Local Data Source: Handles local storage (e.g., SQLite, Hive, or SharedPreferences).

Why separate them from the Repository?

You might wonder, “Why not just put the API call inside the Repository Implementation?” The answer lies in the Single Responsibility Principle.

The Repository’s job is to decide which data to show (e.g., “Check local cache first, then fetch from remote”). The Data Source’s job is to get that data.

Key Benefits:

  • Library Independence: If you want to switch from the http package to dio, You only change the Data Source. Your Repository and Use Cases stay the same.
  • Error Handling: You can catch low-level network errors (like a 404 or 500) at the Data Source level and convert them into custom “Exceptions” that your app understands.
  • Cleaner Testing: You can test your network logic independently of your business logic.

Practical Code Example

Let’s implement a Remote Data Source for our user profile feature.

Step 1: The Interface (The Contract)

// Data Layer: data_sources/user_remote_data_source.dart
abstract class UserRemoteDataSource {
  Future<UserModel> getUserFromApi(String id);
}

Step 2: The Implementation

This is where we use our favorite HTTP client to fetch the raw data.

// Data Layer: data_sources/user_remote_data_source_impl.dart
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
  final HttpClient client; 

  UserRemoteDataSourceImpl(this.client);

  @override
  Future<UserModel> getUserFromApi(String id) async {
    final response = await client.get('https://api.example.com/users/$id');

    if (response.statusCode == 200) {
      // We return a Model here, not an Entity!
      return UserModel.fromJson(response.data);
    } else {
      throw ServerException();
    }
  }
}

Conclusion

By isolating your Clean Architecture Data Sources, you create a “plug-and-play” system. Your app becomes robust because its core logic doesn’t care about the messy details of status codes or database queries.

In the next part, we will discuss Mappers—the crucial translators that turn these “Models” into the “Entities” our Domain layer loves.

To understand the foundational principles of this layer, I highly recommend reading Uncle Bob’s Original Blog on Clean Architecture, where the concept was first introduced to the software engineering community.

Share:

Leave a Reply

Your email address will not be published. Required fields are marked *