我正在使用ASP.NET MVC开发基于Web的应用程序。我正在尝试使用丰富的领域模型,而不是瘦/贫血的模型。
我已经按照Onion体系结构对解决方案进行了建模。不同的项目如下:
****数据访问是使用dapper完成的,IDbContext是2个简单命令,查询接口的包装。我已经将每个查询隔离为单独的类。
为了讨论起见,我仅使用该应用程序的一小部分。
我有一个版本化的文档库,其中包含文档以及其他元数据,例如标签,权限等
我的文档对象的简化模型如下所示
我希望在域对象中定义操作,因为每个操作中都涉及业务逻辑。让我以“删除”作为操作。该操作需要执行
As shown in above example, I would need the database context to complete this operation. The way I have currently thinking if modeling is to have the domain object have IDbContext, which can execute the queries exposed.
In my controller class I call the domain objects and perform the operations.
I am not sure if passing the IDbContext in the domain object is ok? If not what are the better ways to model this?
I am not convinced in having a separate service layer because 1) Controller act as first layer of service layer for most of the cases 2) Service layer is just duplicating the same methods from domain to another class
Let me know how I can better this design.
Injecting the IDbContext
like that brakes the main principle of the Domain model which should be responsible for business logic ONLY while retrieving and storing your domain entities is the responsibility of the infrastructure layer. Yes you inject it by interface, hiding the actual implementation but it makes you domain model aware of some storage.
Also the steps from above required to delete a Document
doesn't entierly belong to the Document object. Let's consider the first step with user permissions and the following cases:
For the first case there might not be a connection between a user and a document to remove. Admin users are just allowed to do anything. It's like a classical example with two bank accounts and an operation to tranfer money which involves both accounts but is not their responsibility. This is when Domain services come into place. Please don't confuse them with Service layer services. Domain services are part of the domain model and responsible for business logic only.
So if I were you, I would create a new Domain service with DeleteDocument
method. This should do the first three steps from above accepting User
and Document
as parameters. The fourth step should be done by your repository. Not sure what you mean by saying
I didn’t see too much value in adding repositories
but from domain model perspective you already have one it's the IDbContext
. I assume you meant some pattern to implement repository or separate repository for each entity. In the long run your pseudo code in the controller should be the following:
var user = bdContext<User>.SelectById(userId);
var document = bdContext<Document>.SelectById(docId);
var docService = new DocumentService();
docService.DeleteDocument(document, user); // Throw exception here if deletion is not allowed
bdContext<Document>.Delete(document);
If you expect you need this logic in many places of you application you can just wrap it up in a Service layer service.
I suggest reading Eric Evans book on DDD if you want to learn more about Domain modeling. This discusses the meaning of entities, value objects, domain services, etc. in detail.
ANSWER TO THE COMMENT: Not really, the domain services are part of the domain, so both implementation and interface are part of the domain as well. The fact that two or more objects have to interact with each other is not enough for creating a domain service. Let's consider a flight booking system as an example. You have a Flight
entity with different properties such as DepartureCity
, ArrivalCity
. Flight
entity should also have a reference to a list of seats. Seat
could be a separate entity as well with such properties as Class
(business, economy, etc.), Type
(isle, row, middle), etc. So booking a seat requires interacting with different entites, such as Flight
and Seat
but we don't need a domain service here. As by nature Seat
property makes no sense if not considered as a child object of a Flight
. It's even very unlikely you would ever have a case to query a Seat
entity from out of the Flight
context. So reserving a Seat
is responsibility of the Flight
entity here and it's ok to place the reserving logic to the Flight
class. Please note it's just an example to try and explain when we need to create domain services, a real system could be modeled completely another way. So just try following these three basic steps to decide whether or not you need a domain service:
- The operation performed by the Service refers to a domain concept which does not naturally belong to an Entity or Value Object.
- The operation performed refers to other objects in the domain.
- The operation is stateless.
我正在从应用程序/服务层而非域/业务层的控制器访问dbcontext。域模型仅处理业务逻辑,它不应该知道任何持久性逻辑,从上面的示例中您可以看到DocumentService没有dbcontext的引用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句