假设我有以下课程:
data class Email(val id:String,
val from:String,
val to:String,
val cc: List<String> =listOf(),
val bcc: List<String> = listOf(),
val title: String?="",
val message:String?="",
val evaluation:Int?=0)
我有不同格式的数据,json、txt、csv 等。
我想为每种格式制作一个导入器。第一个选项是添加与数据格式一样多的伴随对象。 问题是类的 API 会被不必要的细节弄得杂乱无章,尤其是如果导入器在最终返回电子邮件对象之前会做一些预处理。
换句话说,我想将业务逻辑与表示分离。
我真的需要这样做吗?我来自其他语言,最佳实践可能会从一种语言更改为另一种语言。
如果是这样,最好的方法是什么。我想要一个指向知名库中一些实现的链接。
谢谢。
答案 0 :(得分:1)
我认为这归结为偏好。 IMO 最好不要在域模型中包含序列化相关信息。原因是:
Email
类变得混乱。Email
类中的映射逻辑,从而使您的代码 more coupled。一个干净的方法是使用扩展函数。您可以选择在本地使用它们或将它们放在伴生对象中。后一个选项仍然会使您的数据类与映射逻辑混乱。
例如,如果您有一个 CsvEmailImporter
类,那么您可以编写一个私有函数,将 CSV 文件中的一行转换为 Email
对象:
class CsvEmailImporter : EmailImporter {
override fun import(source: InputStream): List<Email> {
val emails = source.bufferedReader()
.lineSequence()
.drop(1) // don't include the csv header
.map { it.toEmail() }
.toList()
return emails
}
private fun String.toEmail(): Email {
// map a line in the CSV file to an Email object
}
}
注意在这个例子中我们的映射函数是如何私有的 CsvEmailImporter
。这意味着我们不必修改 Email
类本身。这也意味着您无法从其他任何地方访问或查看它。
我不知道这里是否有“最佳方法”,但我从一个流行的漫画阅读器应用程序中找到了 this example。
在这种情况下,有一个顶级函数可以将 Manga
对象转换为 MangaInfo
对象。该函数可从外部访问,类似于将其放入伴生对象中。
我建议尝试不同的方法,看看哪种方法最适合您和您的代码库。