有很多关于如何将领域层中的实体连接到数据层中的模型的信息。 在 Dart 中,模型通常扩展实体。我看到的所有教程都只有简单、简单的实体。
但是对于单个嵌套实体来说什么都没有。
举个例子: 一个实体
Address
。
class Address {
String city;
Address(this.city)
}
一个实体
User
:
class User{
String name;
Address addr;
User(this.city, this.address)
}
数据层中的数据模型会是什么样子?它们是如何连接的? 您将如何以及在哪里实现 User 的 copyWith 方法?需要在UseCase中调用。我读到应该将地址实体映射到地址模型。
但是,如果这样一个单一的数据模型需要这样做,那么如果您有多个数据模型甚至更多嵌套的数据模型,这会是什么样子?
此外,我读到干净的架构在大型项目中很有意义。但随后情况会变得更糟。 那么,有什么好的、聪明的解决方案吗?模型和实体真的值得分离吗? 干净的建筑是一种理论吗?只适用于小玩具应用?干净的架构能解决不存在的问题吗?过去,在 C# 中,大多数时候您都会有服务、模型、视图模型和视图(当然还有嵌套在功能中)。
我想采用干净的架构,但似乎它造成的问题比解决现实世界的问题更多。
也许我看到了干净架构的错误实现。数据之间分离的想法。业务逻辑和视图是非常好的 - 但一点也不新鲜。
很难简单地回答。 干净的架构包含很多方面,在我看来,重要的概念是“依赖”这个词。我让你看鲍勃叔叔的帖子 https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html 我可以确认的是,如果您要解决的项目非常小,您不必 100% 遵循干净的架构。 但你可以做的是采用某些方面,在我看来,这些方面是软件开发的最佳实践,可以帮助你实现更好的设计。 更好的设计意味着易于理解和修改,即使对于原始开发人员来说,当您在一段时间后返回代码时也是如此。
关于实体和数据模型的要点:如果您查看每个模型的职责,您会发现,如果您使用一个类来完成 2 项工作, 将混合职责。
我解释一下:
数据模型是如何存储某些数据的表示。 数据模型可能是:
public class UserData
{
public int Id {get; set;}
public string Name {get; set;}
public int CryptedPassword {get; set;}
public string Hash {get; set;}
}
一个简单的对象,当您更改数据表示时,其行为不会发生变化。
实体更加复杂。它可以代表用户属性和行为。这取决于您采用哪种编程风格。 用户实体的示例可能是:
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, ...)
{
...
}
}
如果您使用相同的推理,则 UserView 不应遵循 User 结构。也许会是这样
public class UserView
{
public string Name {get; set;}
public int Stars {get; set;} // Rating converted to stars number
}
它与返回 UserApiResult 的 Api 一起返回
public class UserApiResult
{
public int Id {get; set;}
public string Name {get; set;}
public double Rating {get; set;}
}
因此,这里的想法是养成将每个对象保留在其使用上下文(范围、层)中的习惯,而不是混淆事物。
您将需要一些映射器/转换器来从一个对象切换到另一个对象,这是肯定的,这就是要支付的成本。 每个解决方案都有成本。
但实际上,与它将解决的问题以及当您稍后开始更改代码以添加新功能时需要浪费的时间理解相比,这根本不算什么。
就我个人而言,我看到有人使用 Domain 对象(此处为 User)作为 Api 结果(UserApiResult)或数据模型(UserData),就像有人使用列表来 存储一个简单的整数甚至更糟。所以我会努力阅读代码并搜索以发现一个简单的现实:)