Reputation: 129
There are lots of information on how to connect an entity in the domain layer to a model in the data layer. In Dart, the model usually extends the entity. All the tutorials I saw, only have plain, easy entities.
But for a single nested entity there is nothing.
Just an example:
An entity Address
.
class Address {
String city;
Address(this.city)
}
An Entity User
:
class User{
String name;
Address addr;
User(this.city, this.address)
}
How will the data models look like in the data layer? And how are they connected? How and where would you implement a copyWith method of the User? Needs to be called in a UseCase. I read that one should map the Address-Entity to a Adress-Model.
But if that is needed for such a single data model, how would this look like if you have several data models and even more nested?
Also, I read that clean architecture make sense in big projects. But then it becomes even worse. So, is there any good, smart solution? Is it really worth separating models and entities? Is clean architecture a theory? Only applicable to small toy apps? Does clean architecture solve non-existent problems? In the past in C# most of the time you would have services, models, viewmodels and views (and of course nested in features).
I would like to adopt clean architecture, but it seems that it causes more problems than solving real world problems.
Maybe I saw wrong implementations of clean architecture. The idea of separation between data. business logic, and views is a very good one - but not new at all.
Upvotes: 0
Views: 483
Reputation: 129
I tried to follow the comment, but I think I did not get it completely. This is because my first priority is to model the real world. In the example, there are only properties of simple data types in a class, so it does not reflect my use case.
So in Dart I would currently implement it as follow:
In the domain layer:
class Address {
String city;
Address({
required this.city,
});
}
class User {
String name;
Address addr;
User({
required this.name,
required this.addr,
});
}
In the data layer:
class AddressModel extends Address {
AddressModel({required super.city});
AddressModel copyWith({String? city,}) {
return AddressModel(city: city ?? this.city,);
}
}
class UserModel extends User {
UserModel({required super.name, required super.addr});
UserModel copyWith({String? name, Address? addr,}) {
return UserModel(
name: name ?? this.name,
addr: addr ?? this.addr,);
}
}
So in the data level I will always extend the class of the domain level. Hence the UserModel in the data layer references an address defined in the domain level.
In a Usecase I need to create the address of a User by passing a AddressModel (possible, because the data layer classes extend the resp. domain layer classes.. So, there is a direct link from domain to data level. I saw this already in one tutorial. I.e.:
AdressModel address = ...
String name = ...
User user = User(name, address);
Bottom line:
In C# there can be a similar solution.
Anyway, thank you for your ideas and the link to the blog.
Upvotes: 0
Reputation: 370
It is very difficult to answer briefly. Clean architecture contains many aspects and important notions from my view is the word Dependency. I let you looking here in Uncle Bob post https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
What I can confirm is that you don't have to follow clean architecture 100% if the project you are solving is very small. But what you can do is adopt certain aspects that, in my view, are best practices in software development and help you achieve a better design. Better design means simple to understand and modify, even for the original developer when you return to your code after a while.
About the point of Entity and Data model: if you look to the responsibility of each one you will discover that if you use one class to do the 2 jobs you will mix responsibilities.
I explain:
Data model is a representation on how you store some data. a data model may be a:
public class UserData
{
public int Id {get; set;}
public string Name {get; set;}
public int CryptedPassword {get; set;}
public string Hash {get; set;}
}
a simple object with no behavior that change when you change the data representation.
Entity is more complex. It may represent the user properties and behavior. It depends on which programming style you are adopting. An example of User entity may be:
public class User
{
public int Id {get; set;}
public string Name {get; set;}
// May be you are not in need to see password here if authentification was implemented in another layer
// And only need to have a property filled somewhere in the code
public bool IsSignedIn {get; set;}
// Some other properties which you never store may be because they are computed
public double Rating => ComputeRating();
// May be some behavior, may be you put them in some domain services (it depends)
public void DoWork()
{
...
}
private double ComputeRating(IRatingCalculator ratingCalculator, ...)
{
...
}
}
If you use the same reasoning a UserView is not supposed to follow the User structure. May be it will be
public class UserView
{
public string Name {get; set;}
public int Stars {get; set;} // Rating converted to stars number
}
which is returned with an Api that return a UserApiResult
public class UserApiResult
{
public int Id {get; set;}
public string Name {get; set;}
public double Rating {get; set;}
}
So the idea here is to have the habit of keeping each object in its context of usage (scope, layer) and not to mix things up.
You will need some mapper/converter to switch from one to the another object sure thing and this is the cost to pay. Each solution have a cost.
But really this is nothing compared to the problem that it will solve and hours of understanding that you need to waste when you start to change code later to add a new feature.
Personally, I see someone using a Domain object (User here) as an Api result (UserApiResult) or data model (UserData), as someone using a list to store a simple integer and even worse. So I will make an effort to read the code and search to discover a simple reality :)
Upvotes: 0