I think value object should not have business logic.
That maybe confused other programmers.
for exmaple,
public class PersonVO {
private String name;
private int age;
public void somethingBusinessLogic() {
// Do very complecated logic -> Using Reflection, Conversion
}
}
If i use this VO, have to look vo logic how to work.
many of programmers put their business logic inside of VO.
I wonder what is best practice?
It depends on what architecture you are using in application. If you have layered architecture:
Service layer should have business logic
Data layer is responsible for CRUD operation and this layer should be very simple. This layer should not have any logic, except base CRUD logic. Model classes should not have any logic as ORM prevents you from having logic in model classes.
UI layer should be responsible only for presentation and deal with DTOs or ViewModels
Read more about other architectures here in this beautiful answer
Related
I have my code first, SQL data models (using EF Core 1.1) that are used to model my schema/tables. However I also have domain objects which are partial or full mapped versions of these SQL data models, in essence they sort of have the same shape as the SQL data models.
Now I would like to know what is the best way to handle cascading updates when you have complex objects being altered outside of the context of its tracked context. When you consider that all my domain operations do not take place on the tracked entity, they take place on the domain object.
In Short, This is what I am trying to achieve.
1) Read entity from database.
2) Map entity to domain object.
3) Apply updates to domain object.
4) Map domain object back to entity.
5) Apply database update on mapped entity which results in the entity and its associated relative entities to be updated.
By the way the entities and domain object have the typical many to one relationships that one might run into. What is the best way to go about doing this?
What is the best way to go about doing this?
I think the best way to go about this is to avoid the problem in the first place by using an framework that is flexible enough to allow mapping the domain objects directly to the database without too many compromise in order to avoid having to model an explicit persistence model in code.
in essence they sort of have the same shape as the SQL data models
If you think about it means you would have the same impedance mismatch between your domain model (object model) and relational DB model than between your domain model and the explicit persistence model.
Still, there is an elegant way to perform the mapping which Vaughn Vernon describes in Modeling Aggregates with DDD and Entity Framework. Basically, it boils down to store state in explicit state objects which are bags of getters/setters that are encapsulated and maintained by real domain objects. These state objects are then mapped with EF.
E.g. taken from the above linked article
public class Product {
public Product(
TenantId tenantId,
ProductId productId,
ProductOwnerId productOwnerId,
string name,
string description) {
State = new ProductState();
State.ProductKey = tenantId.Id + ":" + productId.Id;
State.ProductOwnerId = productOwnerId;
State.Name = name;
State.Description = description;
State.BacklogItems = new List<ProductBacklogItemState>();
}
internal Product(ProductState state) {
State = state;
}
...
}
Could my domain model reference my repository interfaces? or better yet, containing my repositories definitions?
I ask because I was thinking about what I read on the limbo of internet that says that a model shouldn't know about its persistence, but I think if the repository exists due the model, I mean, to handle specific needs of its model, why not the model project define it?
Is it a problem/ bad design if I do the following?
public interface ISomethingThatNeedToBeAprovedRepository
{
void Save(SomethingThatNeedToBeAproved somethingThatNeedToBeAproved);
}
public class SomethingThatNeedToBeAproved
{
public int Status {get;set;}
public string Reason {get;set;}
public ISomethingThatNeedToBeAprovedRepository Repository{ get; set;}
public void Aprove(status, reason)
{
DoSomeAsserts();
Status = status;
Reason = reason;
Repository.save(this);
}
}
Yes, it can!
At given point you need to persist your aggregate so a repository is needed. I use to take IRepository inside my domain model, while infratructure details of Repository in another project.
No, it will be a bad design.
The domain model (this domain layer) should totally be independent of any other layer.
The repository interface and implementation should refer to the domain model to save and perform storage operations.
The answer is really it depends.
As #marianoc84 said, at some point, the application would really need to concern about persistence. The question here, is the particular domain model needs a concern about data persistence?
If it does, then it is make sense to put a repository inside the model.
On other side, having the repository inside 'may' makes unit test more challenging, and just be aware that generally speaking, the domain model could be distributed anywhere to pretty much up to application layer.
However, if the model does not really need to concern about persistence, then you don't really need a repository inside. The persistence could be done on other places such as having an 'ApprovalServices' which in this case, there could be several A, B, C, D and E that could be approved and have this to be persisted.
I'm looking for some advice on how much I should be concerned around avoiding the anemic domain model. We are just starting on DDD and are struggling with analysis paralysis regarding simple design decisions. The latest point we are sticking on is where certain business logic belongs, for example we have an Order object, which has properties like Status etc. Now say I have to perform a command like UndoLastStatus because someone made a mistake with an order, this is not as simple as just changing the Status as other information has to be logged and properties changed. Now in the real world this is a pure administration task. So the way I see it I have two options I can think of:
Option 1: Add the method to order so something like Order.UndoLastStatus(), whilst this kinda make sense, it doesn't really reflect the domain. Also Order is the primary object in the system and if everything involving the order is placed in the order class things could get out of hand.
Option 2: Create a Shop object, and with that have different services which represent differant roles. So I might have Shop.AdminService, Shop.DispatchService, and Shop.InventoryService. So in this case I would have Shop.AdminService.UndoLastStatus(Order).
Now the second option we have something which reflects the domain much more, and would allow developers to talk to business experts about similar roles that actually exists. But its also heading toward an anemic model. Which would be the better way to go in general?
Option 2 would lead to procedural code for sure.
Might be easier to develop, but much harder to maintain.
Now in the real world this is a pure administration task
"Administration" tasks should be private and invoked through public, fully "domain`ish" actions. Preferably - still written in easy to understand code that is driven from domain.
As I see it - problem is that UndoLastStatus makes little sense to domain expert.
More likely they are talking about making, canceling and filling orders.
Something along these lines might fit better:
class Order{
void CancelOrder(){
Status=Status.Canceled;
}
void FillOrder(){
if(Status==Status.Canceled)
throw Exception();
Status=Status.Filled;
}
static void Make(){
return new Order();
}
void Order(){
Status=Status.Pending;
}
}
I personally dislike usage of "statuses", they are automatically shared to everything that uses them - i see that as unnecessary coupling.
So I would have something like this:
class Order{
void CancelOrder(){
IsCanceled=true;
}
void FillOrder(){
if(IsCanceled) throw Exception();
IsFilled=true;
}
static Order Make(){
return new Order();
}
void Order(){
IsPending=true;
}
}
For changing related things when order state changes, best bet is to use so called domain events.
My code would look along these lines:
class Order{
void CancelOrder(){
IsCanceled=true;
Raise(new Canceled(this));
}
//usage of nested classes for events is my homemade convention
class Canceled:Event<Order>{
void Canceled(Order order):base(order){}
}
}
class Customer{
private void BeHappy(){
Console.WriteLine("hooraay!");
}
//nb: nested class can see privates of Customer
class OnOrderCanceled:IEventHandler<Order.Canceled>{
void Handle(Order.Canceled e){
//caveat: this approach needs order->customer association
var order=e.Source;
order.Customer.BeHappy();
}
}
}
If Order grows too huge, You might want to check out what bounded contexts are (as Eric Evans says - if he had a chance to wrote his book again, he would move bounded contexts to the very beginning).
In short - it's a form of decomposition driven by domain.
Idea is relatively simple - it is OK to have multiple Orders from different viewpoints aka contexts.
E.g. - Order from Shopping context, Order from Accounting context.
namespace Shopping{
class Order{
//association with shopping cart
//might be vital for shopping but completely irrelevant for accounting
ShoppingCart Cart;
}
}
namespace Accounting{
class Order{
//something specific only to accounting
}
}
But usually enough domain itself avoids complexity and is easily decomposable if You listen to it closely enough. E.g. You might hear from experts terms like OrderLifeCycle, OrderHistory, OrderDescription that You can leverage as anchors for decomposition.
NB: Keep in mind - I got zero understanding about Your domain.
It's quite likely that those verbs I'm using are completely strange to it.
I would be guided by the GRASP principles. Apply the Information Expert design principle, that is you should assign the responsibility to the class that naturally has the most information required to fulfill the change.
In this case, since changing the order status involves other entities, I would make each of these low-level domain objects support a method to apply the change with respect to itself. Then also use a domain service layer as you describe in option 2, that abstracts the whole operation, spanning multiple domain objects as needed.
Also see the Facade pattern.
I think having a method like UndoLastStatus on the Order class feels a bit wrong because the reasons for its existence are in a sense outside of the scope of an order. On the other hand, having a method which is responsible for changing the status of an order, Order.ChangeStatus, fits nicely as a domain model. The status of an order is a proper domain concept and changing that status should be done through the Order class, since it owns the data associated with an order status - it is the responsibility of the Order class to keep itself consistent and in a proper state.
Another way to think of it is that the Order object is what's persisted to the database and it is the 'last stop' for all changes applied to an Order. It is easier to reason about what a valid state for an order might be from the perspective of an Order rather than from the perspective of an external component. This is what DDD and OOP are all about, making it easier for humans to reason about code. Furthermore, access to private or protected members may be required to execute a state change, in which case having the method be on the order class is a better option. This is one of the reasons why anemic domain models are frowned upon - they shift the responsibility of keeping state consistent away from the owning class, thereby breaking encapsulation among other things.
One way to implement a more specific operation such as UndoLastStatus would be to create an OrderService which exposes the domain and is how external components operate upon the domain. Then you can create a simple command object like this:
class UndoLastStatusCommand {
public Guid OrderId { get; set; }
}
An the OrderService would have a method to process that command:
public void Process(UndoLastStatusCommand command) {
using (var unitOfWork = UowManager.Start()) {
var order = this.orderRepository.Get(command.OrderId);
if (order == null)
throw some exception
// operate on domain to undo last status
unitOfWork.Commit();
}
}
So now the domain model for Order exposes all of the data and behavior that correspond to an Order, but the OrderService, and the service layer in general, declare the different kind of operations that are performed on an order and expose the domain for utilization by external components, such as the presentation layer.
Also consider looking into the concept of domain events which considers anemic domain models and ways of improving them.
It sounds like you are not driving this domain from tests. Take a look at the work of Rob Vens, especially his work on exploratory modeling, time inversion and active-passive.
i've read a blog about DDD from Matt Petters
and according and there it is said that we create a repository (interface) for each entity and after that we create a RepositoryFactory that is going to give instances (declared as interfaces) of repositories
is this how project are done using DDD ?
i mean, i saw projects that i thought that they use DDD but they were calling each repository directly, there was no factory involved
and also
why do we need to create so much repository classes, why not use something like
public interface IRepository : IDisposable
{
T[] GetAll();
T[] GetAll(Expression<Func> filter);
T GetSingle(Expression<Func> filter);
T GetSingle(Expression<Func> filter, List<Expression<Func>> subSelectors);
void Delete(T entity);
void Add(T entity);
int SaveChanges();
}
i guess it could be something with violating the SOLID principles, or something else ?
There are many different ways of doing it. There's is not single 'right' way of doing it. Most people prefer a Repository per Entity because it lets them vary Domain Services in a more granular way. This definitely fits the 'S' in SOLID.
When it comes to factories, they should only be used when they add value. If all they do is to wrap a new operation, they don't add value.
Here are some scenarios in which factories add value:
Abtract Factories lets you vary Repository implementations independently of client code. This fits well with the 'L' in SOLID, but you could also achieve the same effect by using DI to inject the Repository into the Domain Service that requires it.
When the creation of an object in itself is such a complex operation (i.e. in involves much more than just creating a new instance) that it is best encapsulated behind an API.
I have implemented the command side of DDD using the domain model and repositories, but how do I implement the query side?
Do I create an entirely new domain model for the UI, and where is this kept in the project structure...in the domain layer, the UI layer, etc?
Also, what do I use as my querying mechanism, do I create new repositories specifically for the UI domain objects, something other than repositories, or something else?
From my understanding of CQRS you would create a set a DTOs that fulfil the requirements of the user interface screens or applications that may need to consume them.
Where this exists in the project is based on the requirements as it would depend if you were going to expose these DTOs via web services.
In which case I wouldn't put it in the Web Layer but rather in the Application layer or a dedicated Façade layer.
Then you would have a read only repository or data access layer which populates the DTOs directly. I think that the Query side of things should be optimized for read performance in which case direct queries/stored procedures on database views or tables and SqlDataReaders would do the best job here. But it would definitely be worth abstracting this access behind an interface so you can add a cached implementation later down the track.
If you're using an ORM and want to map from your Domain Entities to the DTOs then you could have a generic QueryRepository which has methods which take an ISpecification or similar construct for defining your queries then a DtoAssembler object for creating the Dtos from your Domain objects.
Then have an implementation has a first class object for each of the queries you are going to perform.
Here's a fairly contrived example but I hope it gives you an idea.
public interface ISpecification<T>
{
Expression<Func<T, bool>> Predicate { get; }
}
public class ActiveCustomersSpecification : ISpecification<Customer>
{
private Expression<Func<Customer, bool>> predicate;
public ActiveCustomersSpecification()
{
predicate = c => c.IsActive;
}
#region ISpecicfication<Customer> Members
public Expression<Func<Customer, bool>> Predicate
{
get { return predicate; }
}
#endregion
}
public interface IQueryRepository<T>
{
IQueryable<T> GetQuery(ISpecification<T> specification);
IEnumerable<T> FindAllBy(ISpecification<T> specification);
}
public class CustomerDtoAssembler
{
public CustomerDto AssembleFrom(Customer customer)
{
var customerDto = new CustomerDto
{
Id = customer.Id
};
return customerDto;
}
}
I think willbt has given you a really good starting point.
I would add that if you do opt to continue to use the ORM as the data-access strategy for queries you would be well-advised to consider defining a fetching strategy tailored to the data you expect you'll need to access (I'm thinking specifically about NHibernate here, by the way). What this means is you can decide whether to lazy-load or to eager-load the objects and collections associated with a particular Aggregate Root object.
The NCommon project by Ritesh Rao offers an excellent (work in progress) demonstration of how to define a different fetching strategy for different purposes.
Ritesh explains it really well in his blog.
Go ahead and have a look at the source:
here's the IFetchingStrategy interface
and this shows the use of fetching strategies in a unit test
In the test 'Repository_For_Uses_Registered_Fetching_Strategies' the call to
NHRepository<Order>().For<NHRepositoryTests>()
...causes the fetching strategies registered against the NHRepositoryTests class to be used, and therefore the OrderItems and Products will be eager loaded without messing about with NHibernate mapping configurations.