关注点分离 - DAO、DTO 和 BO

8

我有一个DAO、DTO和BO。下面的代码是结果:

// Instantiate a new user repository.
UserRepository rep = new UserRepository();

// Retrieve user by ID (returns DTO) and convert to business object.
User user = rep.GetById(32).ToBusiness<User>();

// Perform business logic.
user.ResetPassword();
user.OtherBusinessLogic("test");
user.FirstName = "Bob";

// Convert business object back to a DTO to save to the database.
rep.Save(user.ToDataTransfer<Data.DTO.User>());

所以我试图分离关注点,但我想要摆脱这段代码中的“converts”。在业务逻辑层中(DTO层不知道业务逻辑层),“converts”实际上作为扩展对象存储。DTO本身仅存储数据,没有任何业务逻辑。UserRepository调用DAO,并在GetById结束时使用AutoMapper从DAO映射到DTO。“converts”(ToBusiness和ToDataTransfer)正如它们描述的那样。
我的一位同事认为我可能需要一个业务库,但认为这可能有点笨重。你有什么想法吗?
3个回答

9

我唯一困惑的地方是为什么需要调用 ToBusiness<User>()ToDataTransfer<Data.DTO.User>() 方法。

仓库(Repository)的职责是处理数据管理。它应该隐藏实现细节(以及业务对象和数据对象之间的转换)。

UserRepository 应该返回一个不需要任何类型转换的 User

UserRepository 也应该能够持久化一个 User,无需进行类型转换。

如果所有类型转换都由仓库处理,则代码会更加简洁,如下所示:

UserRepository rep = new UserRepository();

User user = rep.GetById(32);

// Do Work Here

rep.Save(user);

1
你建议不使用DTO对象,而是直接跳过去使用业务对象吗?关于更干净的代码——我完全同意——这就是我试图通过关注责任分离来实现的。 - Josh Barker
Justin,如果我说错了,请纠正我,但我认为Justin没有建议不使用DTO,而是建议隐藏它。仓储库将调用DTO和BO之间的转换方法,这样当您编写正常的业务功能时,您永远不需要看到或知道DTO。 - rayd09

5
我通过创建业务服务层来解决这个问题。这样,我可以通过业务服务层访问功能,业务服务层使用查询DAL并返回DTO的存储库。 DTO由DAL填充,并帮助将数据传输到业务层(转换为业务对象)。
因此,图表如下:
DAL-> Repository(返回DTO)-> Service(返回BO)
它运行得非常好,我能够在Service层中放置业务逻辑,从而将其与Repository本身抽象化。示例代码:
// UserService uses UserRepository internally + any additional business logic.
var service = new UserService();
var user = service.GetById(32);

user.ResetPassword();
user.OtherBusinessLogic("test");
user.FirstName = "Bob";

service.Save(user);

1

这是我第一次看到将DTO转换为BO,通常我会将DTO发送给BO类或方法进行消费。当BO完成并希望保存对DTO的修改时,它将其发送到DAL并使其持久化。


谢谢您的回复。如果您能提供任何示例代码,那将非常有帮助。 - Josh Barker
我同意这个观点。你应该取回你的业务对象,如果需要转换为DTO,则可以使用AutoMapper等工具进行转换。 - Keith Rousseau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接