我想知道如何在这些“模式”之间做出选择--如果我没有使用正确的术语,请原谅我--当我不得不处理来自前面的复杂对象时,请原谅。
Simple意味着数据结构和逻辑之间的分离,如下所示:
class Post(val title: String, val content: String)
class CreatePost(private val repository: Repository) {
fun invoke(post: Post) = repository.savePost(title = post.title, content = post.content)
}Bean也具有可以执行逻辑的函数,
class Post(private val title: String, private val content: String) {
fun save(repository: Repository) = repository.savePost(title = title, content = content)
}
class CreatePost(private val repository: Repository) {
fun invoke(post: Post) = post.save(repository)
}一方面,第一种方法更简单,但第二种方法提供了一些优点:
另一方面:
作为另一种选择,我可以看到这种方法:
class CreatePost(private val title: String, private val content: String) {
fun invoke(repository: Repository) = repository.savePost(title = title, content = content)
}我的控制器只需要调用:
@RestController
class CreatePostResource(private val repository: Repository) {
@PostMapping
fun createPost(createPost: CreatePost) = createPost.invoke(repository)
}这似乎是最相关的方法,但有什么坏处吗?我想我不应该是第一个问自己这些问题的人。
发布于 2022-07-19 10:58:11
面向对象,在其最基本的,也许有点粗糙的定义,是数据和它的逻辑的结合。因此,将数据和逻辑分离违背了面向对象的本质。
这本身并不意味着“好”或“坏”明显。我认为你的“优势”部分是相当公平的。我要补充的是,第二点基本上就是我所说的“可维护性”。能够将事物(数据和逻辑)添加到某物中,而不需要跟踪它的使用地点和方式。让事情在一起发生变化。
现在让我们谈谈你的缺点:
代码流更复杂。
这是James在DCI中提出的论点。在OO中,您通常不会在一个地方看到“事务脚本”,也不会看到整个用例的命令脚本。
Coplien,您和许多其他人认为这对可维护性是有害的。
我想说,这种意见可能源于“失控”的感觉。将真正的责任委托给对象,会使你无法对发生的事情进行微观管理。有些人认为这种“失控”等同于较少的可维护性。
其实正好相反。通过委派责任,你确保没有认知过载,没有巨大的“主控制脚本”或“上帝对象”控制一切。这就产生了可维护性。
用例命名约定似乎不那么相关,因为CreatePost实际上不执行任何逻辑,只调用另一个函数。
我也认为这是一个积极的方面。不应该有一个名为CreatePost的对象。对象不是脚本,它们是东西。CreatePost显然不是一个“东西”,它是一个伪装的过程。
没有分离的关注点。
这取决于你说的是什么意思,你想要分离哪些问题。我想将业务关注点与技术关注点分开。第一个版本分离技术关注点,第二个版本区分业务关注点。
由于我通常关注业务特性和bug,需求、票通常(并不总是)是用业务语言编写的,因此我认为基于业务关注点的分离更有意义。YMMV
https://softwareengineering.stackexchange.com/questions/439892
复制相似问题