Kotlin 如何将业务逻辑与表示分离?

Kotlin 如何将业务逻辑与表示分离?,kotlin,Kotlin,假设我有以下课程: 数据类电子邮件(val id:String, val from:String, val to:String, val cc:List=listOf(), val bcc:List=listOf(), val标题:字符串?=“”, val消息:字符串?=“”, val评估:Int?=0) 我有不同格式的数据,json、txt、csv等 我想为每种格式制作一个导入器。第一个选项是添加与数据格式一样多的伴随对象。 问题是该类的API会被不必要的细节弄得乱七八糟,特别是如果导入者在

假设我有以下课程:

数据类电子邮件(val id:String,
val from:String,
val to:String,
val cc:List=listOf(),
val bcc:List=listOf(),
val标题:字符串?=“”,
val消息:字符串?=“”,
val评估:Int?=0)
我有不同格式的数据,json、txt、csv等

我想为每种格式制作一个导入器。第一个选项是添加与数据格式一样多的伴随对象。 问题是该类的API会被不必要的细节弄得乱七八糟,特别是如果导入者在最终返回电子邮件对象之前会进行一些预处理的话

换句话说,我想将业务逻辑与表示分离

  • 我真的需要这么做吗?我来自其他语言,最佳实践可能会从一种语言变为另一种语言

  • 如果是,最好的方法是什么。我想要一个链接到一些著名库中的实现

  • 谢谢

  • 我真的需要这么做吗?我来自其他语言,最佳实践可能会从一种语言变为另一种语言
  • 我认为这可以归结为偏好。在我看来,最好不要在域模型中包含序列化相关信息。原因是:

    • 它真的不属于那里。正如您在问题中所说,添加所有这些映射逻辑会使
      Email
      类变得混乱
    • 更改CSV或JSON解析器可能会迫使您也更改
      Email
      类中的映射逻辑,从而生成代码
    一个干净的方法是使用扩展函数。您可以选择在本地使用它们,或者将它们放在同伴对象中。后一个选项仍然会使用映射逻辑使数据类混乱

    因此,例如,如果您有一个
    CsvEmailImporter
    类,那么您可以编写一个私有函数,将CSV文件中的一行转换为
    Email
    对象:

    class CsvEmailImporter:EmailImporter{
    覆盖有趣的导入(源:InputStream):列表{
    val emails=source.bufferedReader()
    .lineSequence()
    .drop(1)//不包括csv头
    .map{it.toEmail()}
    托利斯先生()
    回复电子邮件
    }
    private fun String.toEmail():电子邮件{
    //将CSV文件中的一行映射到电子邮件对象
    }
    }
    
    请注意,在本例中,映射函数对
    CsvEmailImporter
    是私有的。这意味着我们不必修改
    Email
    类本身。这也意味着你不能从其他任何地方访问或看到它

  • 如果是,最好的方法是什么。我想要一个链接到一些著名库中的实现
  • 我不知道这里是否有“最佳方式”,但我从一个流行的漫画阅读器应用程序中找到了。 在本例中,有一个顶级函数将
    Manga
    对象转换为
    MangaInfo
    对象。此函数可以从外部访问,类似于将其放入同伴对象中


    我建议您尝试不同的方法,看看哪些方法最适合您和您的代码库。

    谢谢您的详细回答!我很想知道你关于将序列化从域模型中分离出来的观点。你为什么认为这是个好主意?@QueenofSpades我应该在我最初的回答中加入一些理由。我已经更新了它并包含了两个理由:-让我们考虑第二个论点。为什么进口商可以改变?1.解析完全相同但方式不同的数据,比如用
    循环更改
    for
    。对于这种更改,我们只会在同伴对象位于
    Email
    类中时触摸它。变化就在数据本身,比如说现在我的文件有了我喜欢解析的新字段。例如,如果我的文件现在有一个关于电子邮件发送日期的信息,那么在这两种情况下我都需要更改解析器和
    email
    类(无论解析器是独立的还是在一个伴随对象中),我觉得我遗漏了什么。你能举一个特别的例子说明这种分离会从中受益吗?谢谢