The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
DTO ,据我所知,是ORM设计模式的基石,我简直”崇拜”它。但让我们直接来说吧:DTO只是一种耻辱,而发明它的人是错的。他的所作所为没有任何借口。
顺便说一下,据我所知,他的名字是Martin Fowler。也许他不是DTO的唯一发明者,但他使其合法化并推荐使用。但是,毫无疑问,他是错的。
面向对象编程的关键思想是隐藏数据在对象之后。这个思想有一个名字:封装。在面向对象编程中,数据不应该是可见的。对象只能访问它们封装的数据,而不能访问其他对象封装的数据。对于这个原则,没有争议—这就是面向对象编程的全部。
然而,DTO完全违背了这个原则。
让我们看一个实际的例子。假设这是一个从某个RESTful API获取JSON文档并返回DTO的服务,然后我们可以将其存储在数据库中:
Book book = api.loadBookById(123);
database.saveNewBook(book);
我猜这就是loadBookById()
方法内部会发生的事情:
Book loadBookById(int id) {
JsonObject json = /* Load it from RESTful API */
Book book = new Book();
book.setISBN(json.getString("isbn"));
book.setTitle(json.getString("title"));
book.setAuthor(json.getString("author"));
return book;
}
我是对的吗?我敢打赌我是对的。这对我来说已经很恶心了。无论如何,让我们继续。这很可能会发生在saveNewBook()
方法中(我使用纯JDBC)。
void saveNewBook(Book book) {
Statement stmt = connection.prepareStatement(
"INSERT INTO book VALUES (?, ?, ?)"
);
stmt.setString(1, book.getISBN());
stmt.setString(2, book.getTitle());
stmt.setString(3, book.getAuthor());
stmt.execute();
}
这个Book
是数据传输对象设计模式的一个经典例子。它只是在两段代码、两个过程之间传递数据。book
对象非常笨拙。它只知道…什么也不做。实际上,它根本不是一个对象,而是一个被动且贫血的数据结构。
正确的设计是什么?有几种选择。例如,我认为这个看起来不错:
Book book = api.bookById(123);
book.save(database);
这是在bookById()
函数中发生的事情:
Book bookById(int id) {
return new JsonBook(
/* RESTful API access point */
);
}
这是在 Book.save()
中发生的事情:
void save(Database db) {
JsonObject json = /* Load it from RESTful API */
db.createBook(
json.getString("isbn"),
json.getString("title"),
json.getString("author")
);
}
如果书籍的JSON中有许多其他参数,而这些参数无法很好地作为单个createBook()
方法的参数,则会发生什么情况?这样怎么样呢:
void save(Database db) {
db.create()
.withISBN(json.getString("isbn"))
.withTitle(json.getString("title"))
.withAuthor(json.getString("author"))
.deploy();
}
有很多其他选择。但主要的观点是数据永远不会逸出对象book
。一旦对象被实例化,数据对任何其他人来说都不可见或无法访问。我们只能要求我们的对象保存自己或将自己打印到某种媒介上,但我们永远无法从中获取任何数据。
DTO的概念本身就是错误的,因为它将面向对象的代码变成了过程式代码。我们有操作数据的过程,而DTO只是那些数据的容器。不要以那种方式思考,也不要这样做。
附注:DTO还有一些其他名称:业务对象,领域对象(不在DDD中),实体对象,JavaBeans。
Translated by ChatGPT gpt-3.5-turbo/36 on 2023-10-01 at 08:13