What's the difference between a DTO, a Model, and an Entity in Clean Architecture?
Short Answer
An Entity is a pure business object living in the domain layer with no knowledge of JSON or databases; a Model (or DTO) lives in the data layer, knows how to (de)serialize from a specific data source, and gets converted into an Entity before crossing into the domain layer.
Entities represent 'what the business cares about' — a User entity might just have id, name, email, with no fromJson/toJson, since the domain layer shouldn't know or care where data comes from. A Model lives in the data layer, mirrors the exact shape of an API response or database row, and knows how to serialize/deserialize that specific format.
The repository implementation converts a Model into an Entity (often via a toEntity() method) before returning it to domain/presentation layers — this is what lets you swap a REST API for GraphQL, or change a database schema, without rippling into business logic.
Code Example
// Data layer
class UserModel {
final String id, name, email;
UserModel.fromJson(Map<String, dynamic> json)
: id = json['id'], name = json['name'], email = json['email'];
UserEntity toEntity() => UserEntity(id: id, name: name, email: email);
}
// Domain layer — no JSON knowledge at all
class UserEntity {
final String id, name, email;
const UserEntity({required this.id, required this.name, required this.email});
}Common Mistakes
- ×Passing Models directly up into domain/presentation layers instead of converting to Entities first, leaking data-layer concerns upward.
- ×Creating a separate Entity and identical Model for every project regardless of whether the API shape ever differs from the domain shape.
Related Questions
What is Clean Architecture and how does it apply to Flutter?
Clean Architecture separates an app into independent layers — typically presentation, domain, and data — where inner layers (business logic) never depend on outer layers (UI, frameworks, databases), so business rules can be tested and reused independently of Flutter itself.
What is the Repository pattern?
The Repository pattern puts a single abstraction in front of however data is actually fetched or stored — network, local cache, database — so the rest of the app talks to one consistent interface and doesn't care where the data comes from.